Added SPIRV-Tools.
This commit is contained in:
parent
03b7659b37
commit
172b7c506b
1
3rdparty/glslang/SPIRV/GlslangToSpv.cpp
vendored
1
3rdparty/glslang/SPIRV/GlslangToSpv.cpp
vendored
@ -7007,6 +7007,7 @@ void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsign
|
||||
// optimizer.RegisterPass(CreateCommonUniformElimPass());
|
||||
}
|
||||
optimizer.RegisterPass(CreateAggressiveDCEPass());
|
||||
optimizer.RegisterLegalizationPasses();
|
||||
|
||||
if (!optimizer.Run(spirv.data(), spirv.size(), &spirv))
|
||||
return;
|
||||
|
89
3rdparty/spirv-tools/.appveyor.yml
vendored
Normal file
89
3rdparty/spirv-tools/.appveyor.yml
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
# Windows Build Configuration for AppVeyor
|
||||
# http://www.appveyor.com/docs/appveyor-yml
|
||||
|
||||
# version format
|
||||
version: "{build}"
|
||||
|
||||
# The most recent compiler gives the most interesting new results.
|
||||
# Put it first so we get its feedback first.
|
||||
os:
|
||||
- Visual Studio 2017
|
||||
- Visual Studio 2013
|
||||
|
||||
platform:
|
||||
- x64
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
- Release
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
# Travis advances the master-tot tag to current top of the tree after
|
||||
# each push into the master branch, because it relies on that tag to
|
||||
# upload build artifacts to the master-tot release. This will cause
|
||||
# double testing for each push on Appveyor: one for the push, one for
|
||||
# the tag advance. Disable testing tags.
|
||||
skip_tags: true
|
||||
|
||||
clone_depth: 1
|
||||
|
||||
matrix:
|
||||
fast_finish: true # Show final status immediately if a test fails.
|
||||
exclude:
|
||||
- os: Visual Studio 2013
|
||||
configuration: Debug
|
||||
|
||||
# scripts that run after cloning repository
|
||||
install:
|
||||
# Install ninja
|
||||
- set NINJA_URL="https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-win.zip"
|
||||
- appveyor DownloadFile %NINJA_URL% -FileName ninja.zip
|
||||
- 7z x ninja.zip -oC:\ninja > nul
|
||||
- set PATH=C:\ninja;%PATH%
|
||||
|
||||
before_build:
|
||||
- git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers.git external/spirv-headers
|
||||
- git clone --depth=1 https://github.com/google/googletest.git external/googletest
|
||||
- git clone --depth=1 https://github.com/google/effcee.git external/effcee
|
||||
- git clone --depth=1 https://github.com/google/re2.git external/re2
|
||||
# Set path and environment variables for the current Visual Studio version
|
||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" (call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64)
|
||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64)
|
||||
|
||||
build:
|
||||
parallel: true # enable MSBuild parallel builds
|
||||
verbosity: minimal
|
||||
|
||||
build_script:
|
||||
- mkdir build && cd build
|
||||
- cmake -GNinja -DSPIRV_BUILD_COMPRESSION=ON -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DCMAKE_INSTALL_PREFIX=install -DRE2_BUILD_TESTING=OFF ..
|
||||
- ninja install
|
||||
|
||||
test_script:
|
||||
- ctest -C %CONFIGURATION% --output-on-failure --timeout 300
|
||||
|
||||
after_test:
|
||||
# Zip build artifacts for uploading and deploying
|
||||
- cd install
|
||||
- 7z a SPIRV-Tools-master-windows-"%PLATFORM%"-"%CONFIGURATION%".zip *\*
|
||||
|
||||
artifacts:
|
||||
- path: build\install\*.zip
|
||||
name: artifacts-zip
|
||||
|
||||
deploy:
|
||||
- provider: GitHub
|
||||
auth_token:
|
||||
secure: TMfcScKzzFIm1YgeV/PwCRXFDCw8Xm0wY2Vb2FU6WKlbzb5eUITTpr6I5vHPnAxS
|
||||
release: master-tot
|
||||
description: "Continuous build of the latest master branch by Appveyor and Travis CI"
|
||||
artifact: artifacts-zip
|
||||
draft: false
|
||||
prerelease: false
|
||||
force_update: true
|
||||
on:
|
||||
branch: master
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
5
3rdparty/spirv-tools/.clang-format
vendored
Normal file
5
3rdparty/spirv-tools/.clang-format
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
DerivePointerAlignment: false
|
||||
...
|
15
3rdparty/spirv-tools/.gitignore
vendored
Normal file
15
3rdparty/spirv-tools/.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/build*
|
||||
.ycm_extra_conf.py*
|
||||
compile_commands.json
|
||||
/external/googletest
|
||||
/external/SPIRV-Headers
|
||||
/external/spirv-headers
|
||||
/external/effcee
|
||||
/external/re2
|
||||
/TAGS
|
||||
/.clang_complete
|
||||
/utils/clang-format-diff.py
|
||||
|
||||
# Vim
|
||||
[._]*.s[a-w][a-z]
|
||||
*~
|
133
3rdparty/spirv-tools/.travis.yml
vendored
Normal file
133
3rdparty/spirv-tools/.travis.yml
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
# Linux Build Configuration for Travis
|
||||
|
||||
language: cpp
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
# Use Ubuntu 14.04 LTS (Trusty) as the Linux testing environment.
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: IoR/Xe9E+NnLAeI23WrmUsGQn5rocz+XRYUk+BbaoKiIRYm4q72GKyypRoOGLu7wImOXFSvnN/dpdnqIpx4W0NfsSvNdlXyhDy+wvT1kzTt77dJGnkGZTZ2SBOtC9AECLy4sqM9HG0rYRR6WfXcnP2GlrE5f2aF07aISQbOUsQMvyyhtCmVAzIigK1zIUto5I0pNenvo/Y+ur+mEvTh+FtaoDIGepCbZlCc+OxqRXwXNlI7mDXbzLPmTB1FWTGsrZdRX8czF9tN9Y+T79DQjB4Lcyyeow8yU9NBVlgzZJcp1xI0UIskRT8gVrXmBYL2dMeHnDQuhxjEg9n7jfr3ptA9rgwMaSsgdaLwuBXgtPuqVgUYDpE1cP8WI8q38MXX0I6psTs/WHu+z+5UwfjzpPOHmGdVt48o8ymFTapvD5Cf1+uJyk73QkyStnPIdBF1N9Yx5sD7HN28K6/Ro12sCCePHUZ9Uz1DdZI6XxkgCNKNwao0csAyvODxD6Ee43mkExtviB8BJY5jWLIMTdGhgEGH2sRqils8IDW0p8AOTPM4UC7iA7hdg3pA+XMvBHvP9ixsY7tuB+yR2AfnFaSw2DVbwI5GgFdFMNHXYuL+9V9Wuh3keBKYQT/Hy1YvxjQ/t9UouYHqEsyVFUl3R4lEAM9+qSRsRu+EKmcSO2QtCsWc=
|
||||
matrix:
|
||||
# Each line is a set of environment variables set before a build.
|
||||
# Thus each line represents a different build configuration.
|
||||
- BUILD_TYPE=RelWithDebInfo
|
||||
- BUILD_TYPE=Debug
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
# Additional build using Android NDK with android-cmake
|
||||
- env: BUILD_ANDROID_CMAKE=ON
|
||||
# Additional build using Android NDK with Android.mk
|
||||
- env: BUILD_ANDROID_MK=ON
|
||||
# Additional check over format
|
||||
- env: CHECK_FORMAT=ON
|
||||
exclude:
|
||||
# Skip GCC builds on macOS.
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
|
||||
cache:
|
||||
apt: true
|
||||
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
before_install:
|
||||
- if [[ "$BUILD_ANDROID_CMAKE" == "ON" ]] || [[ "$BUILD_ANDROID_MK" == "ON" ]]; then
|
||||
git clone --depth=1 https://github.com/urho3d/android-ndk.git $HOME/android-ndk;
|
||||
export ANDROID_NDK=$HOME/android-ndk;
|
||||
git clone --depth=1 https://github.com/taka-no-me/android-cmake.git $HOME/android-cmake;
|
||||
export TOOLCHAIN_PATH=$HOME/android-cmake/android.toolchain.cmake;
|
||||
fi
|
||||
- if [[ "$CHECK_FORMAT" == "ON" ]]; then
|
||||
curl -L http://llvm.org/svn/llvm-project/cfe/trunk/tools/clang-format/clang-format-diff.py -o utils/clang-format-diff.py;
|
||||
fi
|
||||
|
||||
before_script:
|
||||
- git clone --depth=1 https://github.com/KhronosGroup/SPIRV-Headers external/spirv-headers
|
||||
- git clone --depth=1 https://github.com/google/googletest external/googletest
|
||||
- git clone --depth=1 https://github.com/google/effcee external/effcee
|
||||
- git clone --depth=1 https://github.com/google/re2 external/re2
|
||||
|
||||
script:
|
||||
# Due to the limitation of Travis platform, we cannot start too many concurrent jobs.
|
||||
# Otherwise GCC will panic with internal error, possibility because of memory issues.
|
||||
# ctest with the current tests doesn't profit from using more than 4 threads.
|
||||
- export NPROC=4
|
||||
- mkdir build && cd build
|
||||
- if [[ "$BUILD_ANDROID_MK" == "ON" ]]; then
|
||||
export BUILD_DIR=$(pwd);
|
||||
mkdir ${BUILD_DIR}/libs;
|
||||
mkdir ${BUILD_DIR}/app;
|
||||
$ANDROID_NDK/ndk-build -C ../android_test NDK_PROJECT_PATH=.
|
||||
NDK_LIBS_OUT=${BUILD_DIR}/libs
|
||||
NDK_APP_OUT=${BUILD_DIR}/app -j${NPROC};
|
||||
elif [[ "$BUILD_ANDROID_CMAKE" == "ON" ]]; then
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_PATH}
|
||||
-DANDROID_NATIVE_API_LEVEL=android-9
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DANDROID_ABI="armeabi-v7a with NEON"
|
||||
-DSPIRV_BUILD_COMPRESSION=ON
|
||||
-DSPIRV_SKIP_TESTS=ON ..;
|
||||
make -j${NPROC};
|
||||
elif [[ "$CHECK_FORMAT" == "ON" ]]; then
|
||||
cd ..;
|
||||
./utils/check_code_format.sh;
|
||||
else
|
||||
cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DSPIRV_BUILD_COMPRESSION=ON -DCMAKE_INSTALL_PREFIX=install ..;
|
||||
make -j${NPROC} install;
|
||||
ctest -j${NPROC} --output-on-failure --timeout 300;
|
||||
fi
|
||||
|
||||
after_success:
|
||||
# Create tarball for deployment
|
||||
- if [[ "${CC}" == "clang" && "${BUILD_ANDROID_MK}" != "ON" && "${BUILD_ANDROID_CMAKE}" != "ON" && "${CHECK_FORMAT}" != "ON" ]]; then
|
||||
cd install;
|
||||
export TARBALL=SPIRV-Tools-master-${TRAVIS_OS_NAME}-${BUILD_TYPE}.zip;
|
||||
find . -print | zip -@ ${TARBALL};
|
||||
fi
|
||||
|
||||
before_deploy:
|
||||
# Tag the current master top of the tree as "master-tot".
|
||||
# Travis CI relies on the tag name to push to the correct release.
|
||||
- git config --global user.name "Travis CI"
|
||||
- git config --global user.email "builds@travis-ci.org"
|
||||
- git tag -f master-tot
|
||||
- git push -q -f https://${spirvtoken}@github.com/KhronosGroup/SPIRV-Tools --tags
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key: ${spirvtoken}
|
||||
on:
|
||||
branch: master
|
||||
condition: ${CC} == clang && ${BUILD_ANDROID_MK} != ON && ${BUILD_ANDROID_CMAKE} != ON && ${CHECK_FORMAT} != ON
|
||||
file: ${TARBALL}
|
||||
skip_cleanup: true
|
||||
overwrite: true
|
||||
|
||||
notifications:
|
||||
email:
|
||||
recipients:
|
||||
- andreyt@google.com
|
||||
- antiagainst@google.com
|
||||
- awoloszyn@google.com
|
||||
- dneto@google.com
|
||||
- ehsann@google.com
|
||||
- qining@google.com
|
||||
on_success: change
|
||||
on_failure: always
|
315
3rdparty/spirv-tools/Android.mk
vendored
Normal file
315
3rdparty/spirv-tools/Android.mk
vendored
Normal file
@ -0,0 +1,315 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
SPVTOOLS_OUT_PATH=$(if $(call host-path-is-absolute,$(TARGET_OUT)),$(TARGET_OUT),$(abspath $(TARGET_OUT)))
|
||||
SPVHEADERS_LOCAL_PATH := $(LOCAL_PATH)/external/spirv-headers
|
||||
|
||||
SPVTOOLS_SRC_FILES := \
|
||||
source/assembly_grammar.cpp \
|
||||
source/binary.cpp \
|
||||
source/diagnostic.cpp \
|
||||
source/disassemble.cpp \
|
||||
source/ext_inst.cpp \
|
||||
source/enum_string_mapping.cpp \
|
||||
source/extensions.cpp \
|
||||
source/id_descriptor.cpp \
|
||||
source/libspirv.cpp \
|
||||
source/name_mapper.cpp \
|
||||
source/opcode.cpp \
|
||||
source/operand.cpp \
|
||||
source/parsed_operand.cpp \
|
||||
source/print.cpp \
|
||||
source/software_version.cpp \
|
||||
source/spirv_endian.cpp \
|
||||
source/spirv_target_env.cpp \
|
||||
source/spirv_validator_options.cpp \
|
||||
source/table.cpp \
|
||||
source/text.cpp \
|
||||
source/text_handler.cpp \
|
||||
source/util/bit_stream.cpp \
|
||||
source/util/parse_number.cpp \
|
||||
source/util/string_utils.cpp \
|
||||
source/util/timer.cpp \
|
||||
source/val/basic_block.cpp \
|
||||
source/val/construct.cpp \
|
||||
source/val/function.cpp \
|
||||
source/val/instruction.cpp \
|
||||
source/val/validation_state.cpp \
|
||||
source/validate.cpp \
|
||||
source/validate_adjacency.cpp \
|
||||
source/validate_arithmetics.cpp \
|
||||
source/validate_atomics.cpp \
|
||||
source/validate_barriers.cpp \
|
||||
source/validate_bitwise.cpp \
|
||||
source/validate_builtins.cpp \
|
||||
source/validate_capability.cpp \
|
||||
source/validate_cfg.cpp \
|
||||
source/validate_composites.cpp \
|
||||
source/validate_conversion.cpp \
|
||||
source/validate_datarules.cpp \
|
||||
source/validate_decorations.cpp \
|
||||
source/validate_derivatives.cpp \
|
||||
source/validate_ext_inst.cpp \
|
||||
source/validate_id.cpp \
|
||||
source/validate_image.cpp \
|
||||
source/validate_instruction.cpp \
|
||||
source/validate_layout.cpp \
|
||||
source/validate_literals.cpp \
|
||||
source/validate_logicals.cpp \
|
||||
source/validate_primitives.cpp \
|
||||
source/validate_type_unique.cpp
|
||||
|
||||
SPVTOOLS_OPT_SRC_FILES := \
|
||||
source/opt/aggressive_dead_code_elim_pass.cpp \
|
||||
source/opt/basic_block.cpp \
|
||||
source/opt/block_merge_pass.cpp \
|
||||
source/opt/build_module.cpp \
|
||||
source/opt/cfg.cpp \
|
||||
source/opt/cfg_cleanup_pass.cpp \
|
||||
source/opt/ccp_pass.cpp \
|
||||
source/opt/common_uniform_elim_pass.cpp \
|
||||
source/opt/compact_ids_pass.cpp \
|
||||
source/opt/composite.cpp \
|
||||
source/opt/const_folding_rules.cpp \
|
||||
source/opt/constants.cpp \
|
||||
source/opt/copy_prop_arrays.cpp \
|
||||
source/opt/dead_branch_elim_pass.cpp \
|
||||
source/opt/dead_insert_elim_pass.cpp \
|
||||
source/opt/dead_variable_elimination.cpp \
|
||||
source/opt/decoration_manager.cpp \
|
||||
source/opt/def_use_manager.cpp \
|
||||
source/opt/dominator_analysis.cpp \
|
||||
source/opt/dominator_tree.cpp \
|
||||
source/opt/eliminate_dead_constant_pass.cpp \
|
||||
source/opt/eliminate_dead_functions_pass.cpp \
|
||||
source/opt/feature_manager.cpp \
|
||||
source/opt/flatten_decoration_pass.cpp \
|
||||
source/opt/fold.cpp \
|
||||
source/opt/folding_rules.cpp \
|
||||
source/opt/fold_spec_constant_op_and_composite_pass.cpp \
|
||||
source/opt/freeze_spec_constant_value_pass.cpp \
|
||||
source/opt/function.cpp \
|
||||
source/opt/if_conversion.cpp \
|
||||
source/opt/inline_pass.cpp \
|
||||
source/opt/inline_exhaustive_pass.cpp \
|
||||
source/opt/inline_opaque_pass.cpp \
|
||||
source/opt/insert_extract_elim.cpp \
|
||||
source/opt/instruction.cpp \
|
||||
source/opt/instruction_list.cpp \
|
||||
source/opt/ir_context.cpp \
|
||||
source/opt/ir_loader.cpp \
|
||||
source/opt/licm_pass.cpp \
|
||||
source/opt/local_access_chain_convert_pass.cpp \
|
||||
source/opt/local_redundancy_elimination.cpp \
|
||||
source/opt/local_single_block_elim_pass.cpp \
|
||||
source/opt/local_single_store_elim_pass.cpp \
|
||||
source/opt/local_ssa_elim_pass.cpp \
|
||||
source/opt/loop_descriptor.cpp \
|
||||
source/opt/loop_peeling.cpp \
|
||||
source/opt/loop_unroller.cpp \
|
||||
source/opt/loop_unswitch_pass.cpp \
|
||||
source/opt/loop_utils.cpp \
|
||||
source/opt/mem_pass.cpp \
|
||||
source/opt/merge_return_pass.cpp \
|
||||
source/opt/module.cpp \
|
||||
source/opt/optimizer.cpp \
|
||||
source/opt/pass.cpp \
|
||||
source/opt/pass_manager.cpp \
|
||||
source/opt/private_to_local_pass.cpp \
|
||||
source/opt/propagator.cpp \
|
||||
source/opt/redundancy_elimination.cpp \
|
||||
source/opt/remove_duplicates_pass.cpp \
|
||||
source/opt/replace_invalid_opc.cpp \
|
||||
source/opt/scalar_analysis.cpp \
|
||||
source/opt/scalar_analysis_simplification.cpp \
|
||||
source/opt/scalar_replacement_pass.cpp \
|
||||
source/opt/set_spec_constant_default_value_pass.cpp \
|
||||
source/opt/simplification_pass.cpp \
|
||||
source/opt/ssa_rewrite_pass.cpp \
|
||||
source/opt/strength_reduction_pass.cpp \
|
||||
source/opt/strip_debug_info_pass.cpp \
|
||||
source/opt/strip_reflect_info_pass.cpp \
|
||||
source/opt/type_manager.cpp \
|
||||
source/opt/types.cpp \
|
||||
source/opt/unify_const_pass.cpp \
|
||||
source/opt/value_number_table.cpp \
|
||||
source/opt/workaround1209.cpp
|
||||
|
||||
# Locations of grammar files.
|
||||
#
|
||||
# TODO(dneto): Build a single set of tables that embeds versioning differences on
|
||||
# a per-item basis. That must happen before SPIR-V 1.4, etc.
|
||||
# https://github.com/KhronosGroup/SPIRV-Tools/issues/1195
|
||||
SPV_CORE10_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.0/spirv.core.grammar.json
|
||||
SPV_CORE11_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.1/spirv.core.grammar.json
|
||||
SPV_CORE12_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.2/spirv.core.grammar.json
|
||||
SPV_COREUNIFIED1_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/unified1/spirv.core.grammar.json
|
||||
SPV_CORELATEST_GRAMMAR=$(SPV_COREUNIFIED1_GRAMMAR)
|
||||
SPV_GLSL_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.2/extinst.glsl.std.450.grammar.json
|
||||
SPV_OPENCL_GRAMMAR=$(SPVHEADERS_LOCAL_PATH)/include/spirv/1.2/extinst.opencl.std.100.grammar.json
|
||||
# TODO(dneto): I expect the DebugInfo grammar file to eventually migrate to SPIRV-Headers
|
||||
SPV_DEBUGINFO_GRAMMAR=$(LOCAL_PATH)/source/extinst.debuginfo.grammar.json
|
||||
|
||||
define gen_spvtools_grammar_tables
|
||||
$(call generate-file-dir,$(1)/core.insts-1.0.inc)
|
||||
$(1)/core.insts-1.0.inc $(1)/operand.kinds-1.0.inc $(1)/glsl.std.450.insts.inc $(1)/opencl.std.insts.inc: \
|
||||
$(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
$(SPV_CORE10_GRAMMAR) \
|
||||
$(SPV_GLSL_GRAMMAR) \
|
||||
$(SPV_OPENCL_GRAMMAR) \
|
||||
$(SPV_DEBUGINFO_GRAMMAR)
|
||||
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
--spirv-core-grammar=$(SPV_CORE10_GRAMMAR) \
|
||||
--extinst-glsl-grammar=$(SPV_GLSL_GRAMMAR) \
|
||||
--extinst-opencl-grammar=$(SPV_OPENCL_GRAMMAR) \
|
||||
--extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
|
||||
--core-insts-output=$(1)/core.insts-1.0.inc \
|
||||
--glsl-insts-output=$(1)/glsl.std.450.insts.inc \
|
||||
--opencl-insts-output=$(1)/opencl.std.insts.inc \
|
||||
--operand-kinds-output=$(1)/operand.kinds-1.0.inc
|
||||
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.0 : instructions & operands <= grammar JSON files"
|
||||
$(1)/core.insts-1.1.inc $(1)/operand.kinds-1.1.inc: \
|
||||
$(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
$(SPV_CORE11_GRAMMAR) \
|
||||
$(SPV_DEBUGINFO_GRAMMAR)
|
||||
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
--spirv-core-grammar=$(SPV_CORE11_GRAMMAR) \
|
||||
--extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
|
||||
--core-insts-output=$(1)/core.insts-1.1.inc \
|
||||
--operand-kinds-output=$(1)/operand.kinds-1.1.inc
|
||||
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.1 : instructions & operands <= grammar JSON files"
|
||||
$(1)/core.insts-1.2.inc $(1)/operand.kinds-1.2.inc: \
|
||||
$(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
$(SPV_CORE12_GRAMMAR) \
|
||||
$(SPV_DEBUGINFO_GRAMMAR)
|
||||
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
--spirv-core-grammar=$(SPV_CORE12_GRAMMAR) \
|
||||
--extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
|
||||
--core-insts-output=$(1)/core.insts-1.2.inc \
|
||||
--operand-kinds-output=$(1)/operand.kinds-1.2.inc
|
||||
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.2 : instructions & operands <= grammar JSON files"
|
||||
$(1)/core.insts-unified1.inc $(1)/operand.kinds-unified1.inc: \
|
||||
$(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
$(SPV_COREUNIFIED1_GRAMMAR) \
|
||||
$(SPV_DEBUGINFO_GRAMMAR)
|
||||
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
--spirv-core-grammar=$(SPV_COREUNIFIED1_GRAMMAR) \
|
||||
--extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
|
||||
--core-insts-output=$(1)/core.insts-unified1.inc \
|
||||
--operand-kinds-output=$(1)/operand.kinds-unified1.inc
|
||||
@echo "[$(TARGET_ARCH_ABI)] Grammar v1.3 (from unified1) : instructions & operands <= grammar JSON files"
|
||||
$(LOCAL_PATH)/source/opcode.cpp: $(1)/core.insts-1.0.inc $(1)/core.insts-1.1.inc $(1)/core.insts-1.2.inc $(1)/core.insts-unified1.inc
|
||||
$(LOCAL_PATH)/source/operand.cpp: $(1)/operand.kinds-1.0.inc $(1)/operand.kinds-1.1.inc $(1)/operand.kinds-1.2.inc $(1)/operand.kinds-unified1.inc
|
||||
$(LOCAL_PATH)/source/ext_inst.cpp: \
|
||||
$(1)/glsl.std.450.insts.inc \
|
||||
$(1)/opencl.std.insts.inc \
|
||||
$(1)/debuginfo.insts.inc \
|
||||
$(1)/spv-amd-gcn-shader.insts.inc \
|
||||
$(1)/spv-amd-shader-ballot.insts.inc \
|
||||
$(1)/spv-amd-shader-explicit-vertex-parameter.insts.inc \
|
||||
$(1)/spv-amd-shader-trinary-minmax.insts.inc
|
||||
endef
|
||||
$(eval $(call gen_spvtools_grammar_tables,$(SPVTOOLS_OUT_PATH)))
|
||||
|
||||
|
||||
define gen_spvtools_lang_headers
|
||||
# Generate language-specific headers. So far we only generate C headers
|
||||
# $1 is the output directory.
|
||||
# $2 is the base name of the header file, e.g. "DebugInfo".
|
||||
# $3 is the grammar file containing token definitions.
|
||||
$(call generate-file-dir,$(1)/$(2).h)
|
||||
$(1)/$(2).h : \
|
||||
$(LOCAL_PATH)/utils/generate_language_headers.py \
|
||||
$(3)
|
||||
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_language_headers.py \
|
||||
--extinst-name=$(2) \
|
||||
--extinst-grammar=$(3) \
|
||||
--extinst-output-base=$(1)/$(2)
|
||||
@echo "[$(TARGET_ARCH_ABI)] Generate language specific header for $(2): headers <= grammar"
|
||||
$(LOCAL_PATH)/source/ext_inst.cpp: $(1)/$(2).h
|
||||
endef
|
||||
# We generate language-specific headers for DebugInfo
|
||||
$(eval $(call gen_spvtools_lang_headers,$(SPVTOOLS_OUT_PATH),DebugInfo,$(SPV_DEBUGINFO_GRAMMAR)))
|
||||
|
||||
|
||||
define gen_spvtools_vendor_tables
|
||||
$(call generate-file-dir,$(1)/$(2).insts.inc)
|
||||
$(1)/$(2).insts.inc : \
|
||||
$(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
$(LOCAL_PATH)/source/extinst.$(2).grammar.json
|
||||
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
--extinst-vendor-grammar=$(LOCAL_PATH)/source/extinst.$(2).grammar.json \
|
||||
--vendor-insts-output=$(1)/$(2).insts.inc
|
||||
@echo "[$(TARGET_ARCH_ABI)] Vendor extended instruction set: $(2) tables <= grammar"
|
||||
$(LOCAL_PATH)/source/ext_inst.cpp: $(1)/$(2).insts.inc
|
||||
endef
|
||||
# Vendor extended instruction sets, with grammars from SPIRV-Tools source tree.
|
||||
SPV_NONSTANDARD_EXTINST_GRAMMARS=$(foreach F,$(wildcard $(LOCAL_PATH)/source/extinst.*.grammar.json),$(patsubst extinst.%.grammar.json,%,$(notdir $F)))
|
||||
$(foreach E,$(SPV_NONSTANDARD_EXTINST_GRAMMARS),$(eval $(call gen_spvtools_vendor_tables,$(SPVTOOLS_OUT_PATH),$E)))
|
||||
|
||||
define gen_spvtools_enum_string_mapping
|
||||
$(call generate-file-dir,$(1)/extension_enum.inc.inc)
|
||||
$(1)/extension_enum.inc $(1)/enum_string_mapping.inc: \
|
||||
$(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
$(SPV_CORELATEST_GRAMMAR)
|
||||
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_grammar_tables.py \
|
||||
--spirv-core-grammar=$(SPV_CORELATEST_GRAMMAR) \
|
||||
--extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
|
||||
--extension-enum-output=$(1)/extension_enum.inc \
|
||||
--enum-string-mapping-output=$(1)/enum_string_mapping.inc
|
||||
@echo "[$(TARGET_ARCH_ABI)] Generate enum<->string mapping <= grammar JSON files"
|
||||
# Generated header extension_enum.inc is transitively included by table.h, which is
|
||||
# used pervasively. Capture the pervasive dependency.
|
||||
$(foreach F,$(SPVTOOLS_SRC_FILES) $(SPVTOOLS_OPT_SRC_FILES),$(LOCAL_PATH)/$F ) \
|
||||
: $(1)/extension_enum.inc
|
||||
$(LOCAL_PATH)/source/enum_string_mapping.cpp: $(1)/enum_string_mapping.inc
|
||||
endef
|
||||
$(eval $(call gen_spvtools_enum_string_mapping,$(SPVTOOLS_OUT_PATH)))
|
||||
|
||||
define gen_spvtools_build_version_inc
|
||||
$(call generate-file-dir,$(1)/dummy_filename)
|
||||
$(1)/build-version.inc: \
|
||||
$(LOCAL_PATH)/utils/update_build_version.py \
|
||||
$(LOCAL_PATH)/CHANGES
|
||||
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/update_build_version.py \
|
||||
$(LOCAL_PATH) $(1)/build-version.inc
|
||||
@echo "[$(TARGET_ARCH_ABI)] Generate : build-version.inc <= CHANGES"
|
||||
$(LOCAL_PATH)/source/software_version.cpp: $(1)/build-version.inc
|
||||
endef
|
||||
$(eval $(call gen_spvtools_build_version_inc,$(SPVTOOLS_OUT_PATH)))
|
||||
|
||||
define gen_spvtools_generators_inc
|
||||
$(call generate-file-dir,$(1)/dummy_filename)
|
||||
$(1)/generators.inc: \
|
||||
$(LOCAL_PATH)/utils/generate_registry_tables.py \
|
||||
$(SPVHEADERS_LOCAL_PATH)/include/spirv/spir-v.xml
|
||||
@$(HOST_PYTHON) $(LOCAL_PATH)/utils/generate_registry_tables.py \
|
||||
--xml=$(SPVHEADERS_LOCAL_PATH)/include/spirv/spir-v.xml \
|
||||
--generator-output=$(1)/generators.inc
|
||||
@echo "[$(TARGET_ARCH_ABI)] Generate : generators.inc <= spir-v.xml"
|
||||
$(LOCAL_PATH)/source/opcode.cpp: $(1)/generators.inc
|
||||
endef
|
||||
$(eval $(call gen_spvtools_generators_inc,$(SPVTOOLS_OUT_PATH)))
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := SPIRV-Tools
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/include \
|
||||
$(LOCAL_PATH)/source \
|
||||
$(LOCAL_PATH)/external/spirv-headers/include \
|
||||
$(SPVTOOLS_OUT_PATH)
|
||||
LOCAL_EXPORT_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/include
|
||||
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -Werror
|
||||
LOCAL_SRC_FILES:= $(SPVTOOLS_SRC_FILES)
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := SPIRV-Tools-opt
|
||||
LOCAL_C_INCLUDES := \
|
||||
$(LOCAL_PATH)/include \
|
||||
$(LOCAL_PATH)/source \
|
||||
$(LOCAL_PATH)/external/spirv-headers/include \
|
||||
$(SPVTOOLS_OUT_PATH)
|
||||
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -Werror
|
||||
LOCAL_STATIC_LIBRARIES:=SPIRV-Tools
|
||||
LOCAL_SRC_FILES:= $(SPVTOOLS_OPT_SRC_FILES)
|
||||
include $(BUILD_STATIC_LIBRARY)
|
483
3rdparty/spirv-tools/CHANGES
vendored
Normal file
483
3rdparty/spirv-tools/CHANGES
vendored
Normal file
@ -0,0 +1,483 @@
|
||||
Revision history for SPIRV-Tools
|
||||
|
||||
v2018.3-dev 2018-04-06
|
||||
- General:
|
||||
- Support SPV_EXT_descriptor_indexing
|
||||
- Support SPV_GOOGLE_decorate_string
|
||||
- Support SPV_GOOGLE_hlsl_functionality1
|
||||
- Support SPV_NV_shader_subgroup_partitioned
|
||||
- Use "unified1" grammar from SPIRV-Headers
|
||||
- Simplify support for new extensions. Assembler, disassembler, and simple validation
|
||||
support is automatic if new tokens are introduced with appropriate extension
|
||||
attributes in the "unified1" SPIR-V core grammar.
|
||||
- Disassembler: Emit more digits on floating point, to reliably reproduce all
|
||||
significand bits. (Use std::max_digits10 instead of std::digits10)
|
||||
- Optimizer:
|
||||
- Add --strip-reflect
|
||||
- Add --time-report
|
||||
- Merge-return now works with structured control flow.
|
||||
- New (faster) SSA rewriter to convert local loads and stores to SSA IDs and phis.
|
||||
Can replace load/store elimination passes.
|
||||
- Fix instruction folding case: insertion that feeds and extract, when the extract
|
||||
remains.
|
||||
- Copy propagate arrays, in simple cases.
|
||||
- Better handling of OpImageTexelPointer
|
||||
- Add loop peeling internal utility.
|
||||
- Initial utilities for scalar evolution.
|
||||
- Validator:
|
||||
- Check Vulkan built-in variables
|
||||
- Check Vulkan-specific atomic result type rule.
|
||||
- Relax control barrier check for SPIR-V 1.3. Fixes #1427
|
||||
- Check OpPhi.
|
||||
- Stop checking sizes derived from spec-constants.
|
||||
- Re-enable checks for OpUConvert.
|
||||
- Fixes:
|
||||
#898: Linker properly removes FuncParamAttr from imported symbols.
|
||||
#924, #1174: Fix handling of decoration groups in optimizer, linker.
|
||||
#1404: Don't optimize away the compute compute workgroup size constant.
|
||||
#1407: Remove a bad assertion
|
||||
#1456: Fix bug in SSA rewriter related to variables updated in loops.
|
||||
|
||||
v2018.2 2018-03-07
|
||||
- General:
|
||||
- Support SPIR-V 1.3 and Vulkan 1.1.
|
||||
- Default target environment is now SPIR-V 1.3. For command-line tools,
|
||||
use the --target-env option to override the default. Examples:
|
||||
# Generate a SPIR-V 1.0 binary instead of SPIR-V 1.3
|
||||
spirv-as --target-env spv1.0 a.spvasm -o a.spv
|
||||
spirv-as --target-env vulkan1.0 a.spvasm -o a.spv
|
||||
# Validate as Vulkan 1.0
|
||||
spirv-val --target-env vulkan1.0 a.spv
|
||||
- Support SPV_GOOGLE_decorate_string and SPV_GOOGLE_hlsl_functionality1
|
||||
- Fixes:
|
||||
- Fix Android.mk build. Compilation was failing due to missing definitions of
|
||||
SpvCapabilityFloat16ImageAMD and other enumerated values.
|
||||
- Optimizer: Avoid generating duplicate names when merging types.
|
||||
- #1375: Validator: SPV_AMD_gpu_shaer_half_float implicitly allows declaration
|
||||
of the 16-bit floating point type.
|
||||
- #1376: Optimizer: Avoid folding half-precision float.
|
||||
|
||||
v2018.1 2018-03-02
|
||||
- General:
|
||||
- Support Visual Studio 2013 again. (Continue support for VS 2015 and VS 2017.)
|
||||
- Support building SPIRV-Tools as a shared library.
|
||||
- Improve the HLSL legalization optimization recipe. #1311
|
||||
- Optimizer:
|
||||
- General speedups.
|
||||
- Remove generic dead code elimination functionality from transforms:
|
||||
--eliminate-local-single-block
|
||||
--eliminate-local-single-store
|
||||
--eliminate-local-multi-store
|
||||
To recover the previous behaviour, a recipe using those transforms should now
|
||||
also invoke the --eliminate-dead-code-aggressive transform.
|
||||
- Improve folding, including coverage for floating point, OpSelect, and arithmetic
|
||||
with non-trivial constant operands.
|
||||
- Add loop-invariant code motion pass.
|
||||
- Add loop-unrolling pass, for honouring unroll hits.
|
||||
- Add loop-unswitch pass.
|
||||
- Add instruction simplification pass.
|
||||
- Aggressive dead code elimination: Understands capability hierarchy when finding
|
||||
instructions it can eliminate (combinators). (PR #1268)
|
||||
- CCP can now fold floating point arithmetic. #1311
|
||||
- Validator:
|
||||
- Validate barrier instructions.
|
||||
- Check Vulkan-specific rules for atomics.
|
||||
- Check Vulkan prohibition of Location or Component decorations on BuiltIn variables.
|
||||
- Linker:
|
||||
- Add --verify-ids option
|
||||
- Add option to allow a resulting module to be partially linked.
|
||||
- Handle OpModuleProcessed (instructions in SPIR-V layout section 7c)
|
||||
- Fixes:
|
||||
- #1265: Optimizer: Fix use-after free bug in if-conversion. (Fix object lifecycle bug
|
||||
in type manager.)
|
||||
- #1282: Fix new warnings found by GCC 8.0.1.
|
||||
- #1285: Optimizer: Fix random failures during inlining. (Dangling references in DefUseManager)
|
||||
- #1295: Optimizer: Fix incorrect handling of Phi nodes in CCP.
|
||||
- #1300: Fix CCP: avoid bad CCP transitions and unsettled values.
|
||||
- #1304: Avoid static-duration variables of class type (with constructors).
|
||||
- #1323: Fix folding of an insert composite feeding a composite extract.
|
||||
- #1339: Fix CCP: Handle OpConstantNull boolean values as conditions.
|
||||
- #1341: DCEInst: Keep atomic instructions (and some others with side effects).
|
||||
- #1354: Don't fold integer division.
|
||||
- #1357: Support OpConstantNull in folding.
|
||||
- #1361: CCP: Fix handling of non-constant module-scope values
|
||||
|
||||
v2018.0 2018-02-02
|
||||
- General
|
||||
- VisualStudio 2013 is no longer supported. VisualStudio 2015 is supported.
|
||||
- Use "include/unified1" directory from SPIRV-Headers. Requires recent SPIRV-Headers source.
|
||||
- Disassembler: spirv-dis adds --color option to force color disassembly.
|
||||
- Optimizer:
|
||||
- Add pass to eliminate dead insertions.
|
||||
- Aggressive dead code elimination now removes OpSwitch constructs.
|
||||
- Block merging occurs in more cases.
|
||||
- Add driver workaround transform: replace OpUnreachable with harmless branch to merge.
|
||||
- Improve instruction folding framework.
|
||||
- Add loop analysis.
|
||||
- Add scalar replacement of aggregates to size-optimization recipe.
|
||||
- Add pass to replace instructions invalid for a shader stage, with a harmless value.
|
||||
This changes the semantics of the program! Not for general use!
|
||||
- Rearragne and add passes to performance-optimization recipe, to produce better results.
|
||||
- Validator:
|
||||
- Validate OpenCL extended instructions.
|
||||
- Shaders can't perform atomics on floats.
|
||||
- Validate memory semantics values in atomics.
|
||||
- Validate instruction-adjacency constraints, e.g. OpPhi predecessors, merge instructions
|
||||
immediately precede branches.
|
||||
- Fixes:
|
||||
- PR 1198: Optimizer: Fix CCP in presence of matrix constants.
|
||||
- #1199: Optimizer: Fix CCP: don't propagate spec constants.
|
||||
- #1203: Optimizer: Fix common uniform elim bug introduced by refactoring.
|
||||
- #1210: Optimizer: Aggressive dead code elimination: Fix 'break' identification.
|
||||
- #1212: Optimizer: Aggressive dead code elimination: Was skipping too many instructions.
|
||||
- #1214: Optimizer: Aggressive dead code elimination: Fix infinite loop.
|
||||
- #1228: Optimizer: Fix CCP: Handling of varying Phi nodes; was resulting in infinite loop.
|
||||
- #1245: Optimizer: Dead branch elimination: Avoid a null pointer dereference.
|
||||
- #1250: Optimizer: Dead branch elimination: Avoid spuriously reporting a change.
|
||||
|
||||
v2017.3 2018-01-12
|
||||
- General:
|
||||
- Support DebugInfo extended instruction set, targeted at OpenCL environments.
|
||||
See the SPIR-V Registry.
|
||||
- Generate a SPIRV-Tools.pc file for pkg-config.
|
||||
- Optimizer:
|
||||
- Progress for legalization of code generated from HLSL (issue #1118):
|
||||
- Add --legalize-hlsl option to run transforms used to transform intermediate
|
||||
code generated by HLSL to SPIR-V for Vulkan compilers. Those compilers
|
||||
normally run these transforms automatically. This option is used for developing
|
||||
those transforms.
|
||||
- Add Private-to-Function variable conversion for modules with logical
|
||||
addressing.
|
||||
- Add --ccp: SSA Conditional Constant Propagation (CCP)
|
||||
- Add --print-all to show disassembly for each optimization pass.
|
||||
- Internal: Add loop descriptors and post-order tree iterator.
|
||||
- Generalized dead branch elimination
|
||||
- Aggressive dead code elimination (ADCE) now removes dead functions and
|
||||
module-scope variables.
|
||||
- Vector extract/insert elimination now optimizes through some cases of
|
||||
VectorShuffle, and GLSL.std.450 Mix extended instruction.
|
||||
- Validator:
|
||||
- Add validation for GLSL.std.450 extended instruction set.
|
||||
- Check out of bounds composite accesses, where that's statically computable.
|
||||
Fixes #1112.
|
||||
- Check upper bits of literal numbers that aren't a multiple of 32-bits wide.
|
||||
- More validation of primitive instructions
|
||||
- Add optional "relaxed" checking logical addressing mode to permit some
|
||||
cases of pointer-to-pointer. Contributes to HLSL legalization (issue #1118).
|
||||
- Fixes:
|
||||
#1100: Validator: Image operand Sample can be used with OpImageSparseFetch,
|
||||
OpImageSparseRead.
|
||||
#1108: Remove duplicates transform was incorrectly removing non-duplicate
|
||||
decorations.
|
||||
#1111: Optimizer's type manager could reference deleted memory.
|
||||
#1112: Fix decoration equality check, e.g. it is now symmetric.
|
||||
#1129: Validator now disallows Dim=SupbassData for OpImageSparseRead.
|
||||
#1143: Fix CCP: Was generating incorrect code for loops.
|
||||
#1153: Fix CCP crash.
|
||||
#1154: Optimizer's internal instruction-to-block mappings were sometimes
|
||||
inconsistent.
|
||||
#1159: Fix CCP infinite loop.
|
||||
#1168: Fix dead branch elimination intermittently generating incorrect code.
|
||||
Fixes https://github.com/KhronosGroup/glslang/issues/1205
|
||||
#1186: Fix validation of PackDouble2x32 and UnpackDouble2x32
|
||||
|
||||
v2017.2 2017-12-15
|
||||
- General:
|
||||
- Support OpenCL 1.2, 2.0 target environments, including embedded profiles
|
||||
- Add CONTRIBUTING.md
|
||||
- Fix exit status code for spirv-link
|
||||
- Disassember: Enable emitting ANSI colour codes to a string
|
||||
- Library avoids polluting global namespace. The libraries can export C and C++
|
||||
symbols starting with "spv", or in a C++ namespace. Add a test for this.
|
||||
- Linux release builds include debug information, for easier profiling
|
||||
- Build bots no longer test VisualStudio 2013
|
||||
- Testing dependency RE2 requires VisualStudio 2015 or later
|
||||
- Build bots check code formatting
|
||||
- Optimizer:
|
||||
- Add --skip-validation to spirv-opt
|
||||
- Add dominance tree analysis
|
||||
- Add generic value propagation engine
|
||||
- Add global redundancy elimination within a function
|
||||
- Add scalar replacement of function-scope variables of composite type
|
||||
- Aggressive dead code elimination: Remove empty loops
|
||||
- Killing an instruction notifies the IRContext
|
||||
- IRContext::KillInst deletes the instruction
|
||||
- Move CFG analysis to IRContext
|
||||
- Add constant manager
|
||||
- Fix: Don't consider derivative instructions as combinators.
|
||||
- Fix: Don't delete an instruction twice in local dead-code-elimination
|
||||
- Fix: Don't consider derivative instructions as combinators.
|
||||
- Validator:
|
||||
- Finish checking of image instructions (Section 3.32.10)
|
||||
- Check sparse image instructions
|
||||
- Check OpTypeImage, OpTypeSampleImage
|
||||
- Check composite instructions (Section 3.32.12)
|
||||
- Check atomic instructions (Section 3.32.18)
|
||||
- Check OpEmitStreamVertex, OpEndStreamPrimitive instructions
|
||||
- Re-enable validation of OpCopyObject
|
||||
- OpKill, image ImplicitLod and QueryLod instructions can only be used in Fragment
|
||||
shaders.
|
||||
- Fixes for image instruction validation:
|
||||
- Lod image operand only usable with ExplicitLod and OpImageFetch
|
||||
- ExplicitLod Lod image operand must be float scalar
|
||||
- OpImageFectch Lod image operand must be int scalar
|
||||
- OpImageGather component operand must be 32-bits (integer scalar)
|
||||
- OpImageQuerySizeLod Lod must be integer scalar
|
||||
- Fixes:
|
||||
#622: Remove names and decorations when inlining
|
||||
#989: Aggressive dead code elim: Don't optimize away live breaks from a loop
|
||||
#991: Fix validation of SPV_AMD_shader_ballot
|
||||
#1004: Use after free of an instruction, in remove-duplicates transform
|
||||
#1007: OpImageRead not required to return 4-component vector
|
||||
#1009: OpImageRead can return scalar int/float types
|
||||
#1011: OpImageWrite should allow scalar int/float texel types
|
||||
#1012: Fix validat Dref type check
|
||||
#1017: Load-store elimination considers variable initializations
|
||||
#1034: Fix Windows debug build: operator< should be a weak ordering
|
||||
#1083: Inlining: Set parent (function) for each inlined basic block.
|
||||
#1075: Aggressive dead code elimination: Was leaving dangling references to
|
||||
removed blocks.
|
||||
|
||||
v2017.1 2017-11-23
|
||||
- Update README with details on the public_spirv_tools_dev@khronos.org mailing list.
|
||||
- General:
|
||||
- Automatically deploy built artifacts to GitHub Releases
|
||||
- Add a Linker (module combiner). Under development.
|
||||
- Add Android.mk for Android NDK builds.
|
||||
- Add the 'effcee' library as an optional dependency for use in tests.
|
||||
Eventually it will be a required dependency, once downstream projects have
|
||||
a chance to adjust. Requires 're2' library.
|
||||
- Avoid static-duration variables of class type (with constructors).
|
||||
- Hack around bugs in gcc-4.8.1 template handling
|
||||
- Faster opcode lookup
|
||||
- Validator:
|
||||
- Recognize extensions listed on SPIR-V registry,
|
||||
through #25 SPV_AMD_shader_fragment_mask
|
||||
- Validator issues an info message when it sees an unrecognized extension.
|
||||
- Type check basic arithmetic operations
|
||||
- Type check carry/extended arithmetic operations
|
||||
- Type check vector arithmetic operations
|
||||
- Type check Relational and Logical instructions
|
||||
- Type check Bit instructions
|
||||
- Check type uniqueness rules
|
||||
- Check conversion instructions
|
||||
- Check image instructions
|
||||
- Check derivative instructions
|
||||
- Check OpVectorShuffle
|
||||
- Check OpBranchConditional
|
||||
- OpModuleProcessed is only allowed after debug names section and before annotations
|
||||
section.
|
||||
- Checks the right kind of return is called for each function (void or non-void).
|
||||
- Add option to relax type check when storing structs (--relax-store-struct)
|
||||
- Optimizer:
|
||||
- Refactoring internal representation of the module, including:
|
||||
- IRContext: owns a module and manages analyses
|
||||
- Instructions are owned by intrusive lists, and have unique IDs
|
||||
- BasicBlock owns its instruction list.
|
||||
- DefUseManager: change representation of uses, for faster processing
|
||||
on large modules.
|
||||
- Add high level recipes: -O, -Os, and -Oconfig
|
||||
Recipes for -O and -Os are under development.
|
||||
- Add eliminate-dead-function transform
|
||||
- Add strength reduction transform: For now, convert multiply by power of 2
|
||||
to a bit shift.
|
||||
- Add CFG cleanup transform
|
||||
- Add removal of dead module-scope variables
|
||||
- Add merge-return transform for modules without structured control flow
|
||||
- Add redundancy elimination within a basic block (local value numbering)
|
||||
- Extract-insert elimination:
|
||||
- Recognize the case where the first instruction in the sequence is an
|
||||
OpCompositeConstruct or OpConstantComposite
|
||||
- Handle some cases of nested structs
|
||||
- Dead branch elimination now can eliminate entire selection constructs
|
||||
when all arms are dead.
|
||||
- Compressing codec:
|
||||
- Updated algorithm to 1.01, 1.02, 1.03
|
||||
- Not built by default. Use -DSPIRV_BUILD_COMPRESSION=ON to build.
|
||||
- Codec can be parameterized by a customized model.
|
||||
- Fixes:
|
||||
#728: Fix decoration of inlined functions
|
||||
#798: spirv-as should fail when given unrecognized long option
|
||||
#800: Inliner: Fix inlining function into header of multi-block loop
|
||||
#824: Eliminate-local-multi-store: Fix a crash
|
||||
#826: Elimiante-local-multi-store: Fix a crash
|
||||
#827: Fix crash when compact-ids transform runs before another transform.
|
||||
#834: Add Cmake option to build the compressing codec. Off by default.
|
||||
#911: Fix classification of Line and NoLine instructions
|
||||
|
||||
v2017.0 2017-09-01
|
||||
- Update README to describe that assembler, disassembler, and binary parser support
|
||||
are based on grammar files from the SPIRV-Headers repository.
|
||||
|
||||
v2016.7 2017-09-01
|
||||
- Add SPIR-V 1.2
|
||||
- OpenCL 2.2 support is now based on SPIR-V 1.2
|
||||
- Support AMD extensions in assembler, disassembler:
|
||||
SPV_AMD_gcn_shader
|
||||
SPV_AMD_shader_ballot
|
||||
SPV_AMD_shader_explicit_vertex_parameter
|
||||
SPV_AMD_shader_trinary_minmax
|
||||
SPV_AMD_gpu_shader_half_float
|
||||
SPV_AMD_texture_gather_bias_lod
|
||||
SPV_AMD_gpu_shader_int16
|
||||
- Optimizer: Add support for:
|
||||
- Inline all function calls in entry points.
|
||||
- Flatten decoration groups. Fixes #602
|
||||
- Id compaction (minimize Id bound). Fixes #624
|
||||
- Eliminate redundant composite insert followed by extract
|
||||
- Simplify access chains to local variables
|
||||
- Eliminate local variables with a single store, if possible
|
||||
- Eliminate local variables with a several stores, if possible
|
||||
- Eliminate loads and stores in same block to local variables
|
||||
- Eliminate redundant insert/extract to composite values
|
||||
- Aggressive dead instruction elimination
|
||||
- Eliminate dead branches
|
||||
- Merge blocks when the second can only be preceded by the first
|
||||
- Eliminate ommon uniform loads
|
||||
- Assembler: Add option to preserve numeric ids. Fixes #625
|
||||
- Add build target spirv-tools-vimsyntax to generate spvasm.vim, a SPIR-V
|
||||
assembly syntax file for Vim.
|
||||
- Version string: Allow overriding of wall clock timestamp with contents
|
||||
of environment variable SOURCE_DATE_EPOCH.
|
||||
- Validator implements relaxed rules for SPV_KHR_16bit_storage.
|
||||
- CMake installation rules use GNUInstallDirs. For example, libraries
|
||||
will be installed into a lib64 directory if that's the norm for the
|
||||
current system.
|
||||
- Fixes:
|
||||
#500: Parameterize validator limit checks
|
||||
#508: Support compilation under CYGWIN
|
||||
#517: Fix validation when continue (or case) contstruct is also the head of a
|
||||
nested control construct.
|
||||
#551: If a merge block is reachable, it must be *strictly* dominated by its
|
||||
header.
|
||||
#548: Validator: Error when the reserved OpImageSparseSampleProj* opcodes
|
||||
are used.
|
||||
#611: spvtools::Optimizer was failing to save the module to the output
|
||||
binary vector when all passes succeded without changes.
|
||||
#629: The inline-entry-points-all optimization could generate invalidly
|
||||
structured code when the inlined function had early returns.
|
||||
#697: Optimizer's Instruction::ForEachInId method was skipping semantics-id
|
||||
and scope-id.
|
||||
#755: Inliner: Fix inlining of callee with single Return appearing before
|
||||
the end of the function.
|
||||
#776: Fix dead branch elimination in presence of complex but dead control
|
||||
flow.
|
||||
#781: SPV_KHR_variable_pointers allows duplicate pointer types
|
||||
#782: Inliner: Fix remapping of non-label forward references in callee
|
||||
#787: Inliner: Fix remapping of inlined entry block when called from
|
||||
single block loop.
|
||||
#790: Inliner: Fix remapping of inlined entry block when callee has
|
||||
multiple returns.
|
||||
|
||||
v2016.6 2016-12-13
|
||||
- Published the C++ interface for assembling, disassembling, validation, and
|
||||
optimization.
|
||||
- Support SPV_KHR_shader_draw_parameters in assembler, disassembler, parser.
|
||||
- Validator:
|
||||
- Add validator API accepting raw binary words
|
||||
- Increased coverage:
|
||||
- Checks "Data rules" in Universal Validation Rules, section 2.16.1
|
||||
- WIP: Universal Limits.
|
||||
- The minimum mandated upper bounds are checked.
|
||||
- TODO: Parameterize the validator to allow larger limits accepted by
|
||||
a more than minimally capable implementation.
|
||||
- OpSampledImage checks
|
||||
- OpConstantComposite checks
|
||||
- Id bound check
|
||||
- Disasssembler:
|
||||
- Generates friendly GLSL-based names for more builtin variables
|
||||
- Generates friendly names for numeric OpConstant values
|
||||
- Vendor tool info extracted from SPIR-V XML registry file.
|
||||
- Fixes issues:
|
||||
#429: Validator: Allow OpTypeForwardPointer and OpTypeStruct to reference
|
||||
undefined IDs
|
||||
#482: Validator: OpVariable initializer can be an ID of a module-scope variable
|
||||
|
||||
v2016.5 2016-09-16
|
||||
- Support SPV_KHR_shader_ballot in assembler, disassembler, parser.
|
||||
- Disassembler: Generate friendly names for built-in variables.
|
||||
- Partial fixes:
|
||||
#359: Add Emacs helper for automatically diassembling/assembling a SPIR-V
|
||||
binary on file load/save.
|
||||
- Fixes:
|
||||
#414: Validator: Allow OpUndef for composite constants
|
||||
#415: Validator: Phi can use its own value in some cases.
|
||||
|
||||
v2016.4 2016-09-01
|
||||
- Relicensed under Apache 2.0
|
||||
- Add optimization passes (in API and spirv-opt command)
|
||||
- Fold spec constants defined with OpSpecConstantOp and
|
||||
OpSpecConstantComposite to normal constants with fixed value(s).
|
||||
- Fixes issues:
|
||||
#318: Relicensed under Apache 2.0
|
||||
|
||||
v2016.3 2016-08-24
|
||||
- Add target environment enums for OpenCL 2.1, OpenCL 2.2,
|
||||
OpenGL 4.0, OpenGL 4.1, OpenGL 4.2, OpenGL 4.3, OpenGL 4.5.
|
||||
- Add spirv-cfg, an experimental tool to dump the control flow graph
|
||||
as a GraphiViz "dot" graph
|
||||
- Add optimization pass: Eliminate dead constants.
|
||||
- Add spirv-lesspipe.sh filter utility
|
||||
- Fixes issues:
|
||||
#288: Check def-use dominance rules for OpPhi (variable,parent) operands
|
||||
#339: Allow OpUndef in types-constants-global-vars section, as required
|
||||
by SPIR-V 1.0 Rev7, 1.1 Rev 3.
|
||||
#340: Avoid race on mkdir during build
|
||||
#365: Relax PointSize, ClipDistance, CullDistance capability check in all
|
||||
environments not just Vulkan 1.0.
|
||||
|
||||
v2016.2 2016-08-05
|
||||
- Validator is incomplete
|
||||
- Checks ID use block is dominated by definition block
|
||||
- Add optimization passes (in API and spirv-opt command)
|
||||
- Strip debug info instructions
|
||||
- Freeze spec constant to their default values
|
||||
- Allow INotEqual as operation for OpSpecConstantOp
|
||||
- Fixes bugs:
|
||||
#270: validator: crash when continue construct is unreachable
|
||||
#279: validator: infinite loop when analyzing some degenerate control
|
||||
flow graphs
|
||||
#286: validator: don't incorrectly generate def-use error for
|
||||
(variable,parent) parameters to OpPhi
|
||||
#290: disassembler: never generate bare % for an identifier
|
||||
#295: validator: def-use dominance check should ignore unreachable uses
|
||||
#276: validator: allow unreachable continue constructs
|
||||
#297: validator: allow an unreachable block to branch to a reachable
|
||||
merge block
|
||||
|
||||
v2016.1 2016-07-19
|
||||
- Fix https://github.com/KhronosGroup/SPIRV-Tools/issues/261
|
||||
Turn off ClipDistance and CullDistance capability checks for Vulkan.
|
||||
- The disassembler can emit friendly names based on debug info (OpName
|
||||
instructions), and will infer somewhat friendly names for most types.
|
||||
This is turned on by default for the spirv-dis command line tool.
|
||||
- Updated to support SPIR-V 1.1 rev 2
|
||||
- Input StorageClass, Sampled1D capability, and SampledBuffer capability
|
||||
do not require Shader capability anymore.
|
||||
|
||||
v2016.0 2016-07-04
|
||||
|
||||
- Adds v<year>.<index> versioning, with "-dev" indicating
|
||||
work in progress. The intent is to more easly report
|
||||
and summarize functionality when SPIRV-Tools is incorporated
|
||||
in downstream projects.
|
||||
|
||||
- Summary of functionality (See the README.md for more):
|
||||
- Supports SPIR-V 1.1 Rev 1
|
||||
- Supports SPIR-V 1.0 Rev 5
|
||||
- Supports GLSL std450 extended instructions 1.0 Rev 3
|
||||
- Supports OpenCL extended instructions 1.0 Rev 2
|
||||
- Assembler, disassembler are complete
|
||||
- Supports floating point widths of 16, 32, 64 bits
|
||||
- Supports integer widths up to 64 bits
|
||||
- Validator is incomplete
|
||||
- Checks capability requirements in most cases
|
||||
- Checks module layout constraints
|
||||
- Checks ID use-definition ordering constraints,
|
||||
ignoring control flow
|
||||
- Checks some control flow graph rules
|
||||
- Optimizer is introduced, with few available transforms.
|
||||
- Supported on Linux, OSX, Android, Windows
|
||||
|
||||
- Fixes bugs:
|
||||
- #143: OpenCL pow and pown arguments
|
268
3rdparty/spirv-tools/CMakeLists.txt
vendored
Normal file
268
3rdparty/spirv-tools/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,268 @@
|
||||
# Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
if (POLICY CMP0048)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
endif()
|
||||
if (POLICY CMP0054)
|
||||
# Avoid dereferencing variables or interpret keywords that have been
|
||||
# quoted or bracketed.
|
||||
# https://cmake.org/cmake/help/v3.1/policy/CMP0054.html
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
project(spirv-tools)
|
||||
enable_testing()
|
||||
set(SPIRV_TOOLS "SPIRV-Tools")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||
add_definitions(-DSPIRV_LINUX)
|
||||
set(SPIRV_TIMER_ENABLED ON)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
|
||||
add_definitions(-DSPIRV_WINDOWS)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "CYGWIN")
|
||||
add_definitions(-DSPIRV_WINDOWS)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
||||
add_definitions(-DSPIRV_MAC)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
|
||||
add_definitions(-DSPIRV_ANDROID)
|
||||
set(SPIRV_TIMER_ENABLED ON)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
|
||||
add_definitions(-DSPIRV_FREEBSD)
|
||||
else()
|
||||
message(FATAL_ERROR "Your platform '${CMAKE_SYSTEM_NAME}' is not supported!")
|
||||
endif()
|
||||
|
||||
if (${SPIRV_TIMER_ENABLED})
|
||||
add_definitions(-DSPIRV_TIMER_ENABLED)
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
message(STATUS "No build type selected, default to Debug")
|
||||
set(CMAKE_BUILD_TYPE "Debug")
|
||||
endif()
|
||||
|
||||
option(SKIP_SPIRV_TOOLS_INSTALL "Skip installation" ${SKIP_SPIRV_TOOLS_INSTALL})
|
||||
if(NOT ${SKIP_SPIRV_TOOLS_INSTALL})
|
||||
set(ENABLE_SPIRV_TOOLS_INSTALL ON)
|
||||
endif()
|
||||
|
||||
option(SPIRV_BUILD_COMPRESSION "Build SPIR-V compressing codec" OFF)
|
||||
|
||||
option(SPIRV_WERROR "Enable error on warning" ON)
|
||||
if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
||||
set(COMPILER_IS_LIKE_GNU TRUE)
|
||||
endif()
|
||||
if(${COMPILER_IS_LIKE_GNU})
|
||||
set(SPIRV_WARNINGS -Wall -Wextra -Wnon-virtual-dtor -Wno-missing-field-initializers)
|
||||
|
||||
option(SPIRV_WARN_EVERYTHING "Enable -Weverything" ${SPIRV_WARN_EVERYTHING})
|
||||
if(${SPIRV_WARN_EVERYTHING})
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(SPIRV_WARNINGS ${SPIRV_WARNINGS}
|
||||
-Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded)
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(SPIRV_WARNINGS ${SPIRV_WARNINGS} -Wpedantic -pedantic-errors)
|
||||
else()
|
||||
message(STATUS "Unknown compiler ${CMAKE_CXX_COMPILER_ID}, "
|
||||
"so SPIRV_WARN_EVERYTHING has no effect")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${SPIRV_WERROR})
|
||||
set(SPIRV_WARNINGS ${SPIRV_WARNINGS} -Werror)
|
||||
endif()
|
||||
elseif(MSVC)
|
||||
set(SPIRV_WARNINGS -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS /wd4800)
|
||||
|
||||
if(${SPIRV_WERROR})
|
||||
set(SPIRV_WARNINGS ${SPIRV_WARNINGS} /WX)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/source)
|
||||
|
||||
option(SPIRV_COLOR_TERMINAL "Enable color terminal output" ON)
|
||||
if(${SPIRV_COLOR_TERMINAL})
|
||||
add_definitions(-DSPIRV_COLOR_TERMINAL)
|
||||
endif()
|
||||
|
||||
option(SPIRV_LOG_DEBUG "Enable excessive debug output" OFF)
|
||||
if(${SPIRV_LOG_DEBUG})
|
||||
add_definitions(-DSPIRV_LOG_DEBUG)
|
||||
endif()
|
||||
|
||||
if (DEFINED SPIRV_TOOLS_EXTRA_DEFINITIONS)
|
||||
add_definitions(${SPIRV_TOOLS_EXTRA_DEFINITIONS})
|
||||
endif()
|
||||
|
||||
function(spvtools_default_compile_options TARGET)
|
||||
target_compile_options(${TARGET} PRIVATE ${SPIRV_WARNINGS})
|
||||
|
||||
if (${COMPILER_IS_LIKE_GNU})
|
||||
target_compile_options(${TARGET} PRIVATE
|
||||
-std=c++11 -fno-exceptions -fno-rtti)
|
||||
target_compile_options(${TARGET} PRIVATE
|
||||
-Wall -Wextra -Wno-long-long -Wshadow -Wundef -Wconversion
|
||||
-Wno-sign-conversion)
|
||||
# For good call stacks in profiles, keep the frame pointers.
|
||||
if(NOT "${SPIRV_PERF}" STREQUAL "")
|
||||
target_compile_options(${TARGET} PRIVATE -fno-omit-frame-pointer)
|
||||
endif()
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(SPIRV_USE_SANITIZER "" CACHE STRING
|
||||
"Use the clang sanitizer [address|memory|thread|...]")
|
||||
if(NOT "${SPIRV_USE_SANITIZER}" STREQUAL "")
|
||||
target_compile_options(${TARGET} PRIVATE
|
||||
-fsanitize=${SPIRV_USE_SANITIZER})
|
||||
endif()
|
||||
else()
|
||||
target_compile_options(${TARGET} PRIVATE
|
||||
-Wno-missing-field-initializers)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
# Specify /EHs for exception handling. This makes using SPIRV-Tools as
|
||||
# dependencies in other projects easier.
|
||||
target_compile_options(${TARGET} PRIVATE /EHs)
|
||||
endif()
|
||||
|
||||
# For MinGW cross compile, statically link to the C++ runtime.
|
||||
# But it still depends on MSVCRT.dll.
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
if (${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
|
||||
set_target_properties(${TARGET} PROPERTIES
|
||||
LINK_FLAGS -static -static-libgcc -static-libstdc++)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if(NOT COMMAND find_host_package)
|
||||
macro(find_host_package)
|
||||
find_package(${ARGN})
|
||||
endmacro()
|
||||
endif()
|
||||
if(NOT COMMAND find_host_program)
|
||||
macro(find_host_program)
|
||||
find_program(${ARGN})
|
||||
endmacro()
|
||||
endif()
|
||||
|
||||
find_host_package(PythonInterp)
|
||||
|
||||
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||
macro(spvtools_check_symbol_exports TARGET)
|
||||
add_test(NAME spirv-tools-symbol-exports-${TARGET}
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
${spirv-tools_SOURCE_DIR}/utils/check_symbol_exports.py "$<TARGET_FILE:${TARGET}>")
|
||||
endmacro()
|
||||
else()
|
||||
macro(spvtools_check_symbol_exports TARGET)
|
||||
message("Skipping symbol exports test for ${TARGET}")
|
||||
endmacro()
|
||||
endif()
|
||||
|
||||
# Defaults to OFF if the user didn't set it.
|
||||
option(SPIRV_SKIP_EXECUTABLES
|
||||
"Skip building the executable and tests along with the library"
|
||||
${SPIRV_SKIP_EXECUTABLES})
|
||||
option(SPIRV_SKIP_TESTS
|
||||
"Skip building tests along with the library" ${SPIRV_SKIP_TESTS})
|
||||
if ("${SPIRV_SKIP_EXECUTABLES}")
|
||||
set(SPIRV_SKIP_TESTS ON)
|
||||
endif()
|
||||
|
||||
# Defaults to ON. The checks can be time consuming.
|
||||
# Turn off if they take too long.
|
||||
option(SPIRV_CHECK_CONTEXT "In a debug build, check if the IR context is in a valid state." ON)
|
||||
if (${SPIRV_CHECK_CONTEXT})
|
||||
add_definitions(-DSPIRV_CHECK_CONTEXT)
|
||||
endif()
|
||||
|
||||
add_subdirectory(external)
|
||||
|
||||
if (TARGET effcee)
|
||||
add_definitions(-DSPIRV_EFFCEE)
|
||||
endif()
|
||||
|
||||
add_subdirectory(source)
|
||||
add_subdirectory(tools)
|
||||
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(examples)
|
||||
|
||||
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/spirv-tools/libspirv.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/spirv-tools/libspirv.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/spirv-tools/optimizer.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/spirv-tools/linker.hpp
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_INCLUDEDIR}/spirv-tools/)
|
||||
endif(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||
|
||||
if (NOT "${SPIRV_SKIP_TESTS}")
|
||||
add_test(NAME spirv-tools-copyrights
|
||||
COMMAND ${PYTHON_EXECUTABLE} utils/check_copyright.py
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
set(SPIRV_LIBRARIES "-lSPIRV-Tools -lSPIRV-Tools-link -lSPIRV-Tools-opt")
|
||||
set(SPIRV_SHARED_LIBRARIES "-lSPIRV-Tools-shared")
|
||||
if(SPIRV_BUILD_COMPRESSION)
|
||||
set(SPIRV_LIBRARIES "${SPIRV_LIBRARIES} -lSPIRV-Tools-comp")
|
||||
endif(SPIRV_BUILD_COMPRESSION)
|
||||
|
||||
# Build pkg-config file
|
||||
# Use a first-class target so it's regenerated when relevant files are updated.
|
||||
add_custom_target(spirv-tools-pkg-config ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCHANGES_FILE=${CMAKE_CURRENT_SOURCE_DIR}/CHANGES
|
||||
-DTEMPLATE_FILE=${CMAKE_CURRENT_SOURCE_DIR}/cmake/SPIRV-Tools.pc.in
|
||||
-DOUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/SPIRV-Tools.pc
|
||||
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
|
||||
-DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR}
|
||||
-DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR}
|
||||
-DSPIRV_LIBRARIES=${SPIRV_LIBRARIES}
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/write_pkg_config.cmake
|
||||
DEPENDS "CHANGES" "cmake/SPIRV-Tools.pc.in" "cmake/write_pkg_config.cmake")
|
||||
add_custom_target(spirv-tools-shared-pkg-config ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DCHANGES_FILE=${CMAKE_CURRENT_SOURCE_DIR}/CHANGES
|
||||
-DTEMPLATE_FILE=${CMAKE_CURRENT_SOURCE_DIR}/cmake/SPIRV-Tools-shared.pc.in
|
||||
-DOUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/SPIRV-Tools-shared.pc
|
||||
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
|
||||
-DCMAKE_INSTALL_LIBDIR=${CMAKE_INSTALL_LIBDIR}
|
||||
-DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR}
|
||||
-DSPIRV_SHARED_LIBRARIES=${SPIRV_SHARED_LIBRARIES}
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/write_pkg_config.cmake
|
||||
DEPENDS "CHANGES" "cmake/SPIRV-Tools-shared.pc.in" "cmake/write_pkg_config.cmake")
|
||||
|
||||
# Install pkg-config file
|
||||
if (ENABLE_SPIRV_TOOLS_INSTALL)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/SPIRV-Tools.pc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/SPIRV-Tools-shared.pc
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
endif()
|
189
3rdparty/spirv-tools/CONTRIBUTING.md
vendored
Normal file
189
3rdparty/spirv-tools/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
# Contributing to SPIR-V Tools
|
||||
|
||||
## For users: Reporting bugs and requesting features
|
||||
|
||||
We organize known future work in GitHub projects. See [Tracking SPIRV-Tools work
|
||||
with GitHub
|
||||
projects](https://github.com/KhronosGroup/SPIRV-Tools/blob/master/projects.md)
|
||||
for more.
|
||||
|
||||
To report a new bug or request a new feature, please file a GitHub issue. Please
|
||||
ensure the bug has not already been reported by searching
|
||||
[issues](https://github.com/KhronosGroup/SPIRV-Tools/issues) and
|
||||
[projects](https://github.com/KhronosGroup/SPIRV-Tools/projects). If the bug has
|
||||
not already been reported open a new one
|
||||
[here](https://github.com/KhronosGroup/SPIRV-Tools/issues/new).
|
||||
|
||||
When opening a new issue for a bug, make sure you provide the following:
|
||||
|
||||
* A clear and descriptive title.
|
||||
* We want a title that will make it easy for people to remember what the
|
||||
issue is about. Simply using "Segfault in spirv-opt" is not helpful
|
||||
because there could be (but hopefully aren't) multiple bugs with
|
||||
segmentation faults with different causes.
|
||||
* A test case that exposes the bug, with the steps and commands to reproduce
|
||||
it.
|
||||
* The easier it is for a developer to reproduce the problem, the quicker a
|
||||
fix can be found and verified. It will also make it easier for someone
|
||||
to possibly realize the bug is related to another issue.
|
||||
|
||||
For feature requests, we use
|
||||
[issues](https://github.com/KhronosGroup/SPIRV-Tools/issues) as well. Please
|
||||
create a new issue, as with bugs. In the issue provide
|
||||
|
||||
* A description of the problem that needs to be solved.
|
||||
* Examples that demonstrate the problem.
|
||||
|
||||
## For developers: Contributing a patch
|
||||
|
||||
Before we can use your code, you must sign the [Khronos Open Source Contributor
|
||||
License Agreement](https://cla-assistant.io/KhronosGroup/SPIRV-Tools) (CLA),
|
||||
which you can do online. The CLA is necessary mainly because you own the
|
||||
copyright to your changes, even after your contribution becomes part of our
|
||||
codebase, so we need your permission to use and distribute your code. We also
|
||||
need to be sure of various other things -- for instance that you'll tell us if
|
||||
you know that your code infringes on other people's patents. You don't have to
|
||||
sign the CLA until after you've submitted your code for review and a member has
|
||||
approved it, but you must do it before we can put your code into our codebase.
|
||||
|
||||
See
|
||||
[README.md](https://github.com/KhronosGroup/SPIRV-Tools/blob/master/README.md)
|
||||
for instruction on how to get, build, and test the source. Once you have made
|
||||
your changes:
|
||||
|
||||
* Ensure the code follows the [Google C++ Style
|
||||
Guide](https://google.github.io/styleguide/cppguide.html). Running
|
||||
`clang-format -style=file -i [modified-files]` can help.
|
||||
* Create a pull request (PR) with your patch.
|
||||
* Make sure the PR description clearly identified the problem, explains the
|
||||
solution, and references the issue if applicable.
|
||||
* If your patch completely fixes bug 1234, the commit message should say
|
||||
`Fixes https://github.com/KhronosGroup/SPIRV-Tools/issues/1234`
|
||||
When you do this, the issue will be closed automatically when the commit
|
||||
goes into master. Also, this helps us update the [CHANGES](CHANGES) file.
|
||||
* Watch the continuous builds to make sure they pass.
|
||||
* Request a code review.
|
||||
|
||||
The reviewer can either approve your PR or request changes. If changes are
|
||||
requested:
|
||||
|
||||
* Please add new commits to your branch, instead of amending your commit.
|
||||
Adding new commits makes it easier for the reviewer to see what has changed
|
||||
since the last review.
|
||||
* Once you are ready for another round of reviews, add a comment at the
|
||||
bottom, such as "Ready for review" or "Please take a look" (or "PTAL"). This
|
||||
explicit handoff is useful when responding with multiple small commits.
|
||||
|
||||
After the PR has been reviewed it is the job of the reviewer to merge the PR.
|
||||
Instructions for this are given below.
|
||||
|
||||
## For maintainers: Reviewing a PR
|
||||
|
||||
The formal code reviews are done on GitHub. Reviewers are to look for all of the
|
||||
usual things:
|
||||
|
||||
* Coding style follows the [Google C++ Style
|
||||
Guide](https://google.github.io/styleguide/cppguide.html)
|
||||
* Identify potential functional problems.
|
||||
* Identify code duplication.
|
||||
* Ensure the unit tests have enough coverage.
|
||||
|
||||
When looking for functional problems, there are some common problems reviewers
|
||||
should pay particular attention to:
|
||||
|
||||
* Does the code work for both Shader (Vulkan and OpenGL) and Kernel (OpenCL)
|
||||
scenarios? The respective SPIR-V dialects are slightly different.
|
||||
* Changes are made to a container while iterating through it. You have to be
|
||||
careful that iterators are not invalidated or that elements are not skipped.
|
||||
* C++11 and VS2013. We generally assume that we have a C++11 compliant
|
||||
compiler. However, on Windows, we still support Visual Studio 2013, which is
|
||||
not fully C++11 compliant. See
|
||||
[here](https://msdn.microsoft.com/en-us/library/hh567368.aspx). In
|
||||
particular, note that it does not provide default move-constructors or
|
||||
move-assignments for classes. In general, r-value references do not work the
|
||||
way you might assume they do.
|
||||
* For SPIR-V transforms: The module is changed, but the analyses are not
|
||||
updated. For example, a new instruction is added, but the def-use manager is
|
||||
not updated. Later on, it is possible that the def-use manager will be used,
|
||||
and give wrong results.
|
||||
|
||||
## For maintainers: Merging a PR
|
||||
|
||||
We intend to maintain a linear history on the GitHub master branch, and the
|
||||
build and its tests should pass at each commit in that history. A linear
|
||||
always-working history is easier to understand and to bisect in case we want to
|
||||
find which commit introduced a bug.
|
||||
|
||||
### Initial merge setup
|
||||
|
||||
The following steps should be done exactly once (when you are about to merge a
|
||||
PR for the first time):
|
||||
|
||||
* It is assumed that upstream points to
|
||||
[git@github.com](mailto:git@github.com):KhronosGroup/SPIRV-Tools.git or
|
||||
https://github.com/KhronosGroup/SPIRV-Tools.git.
|
||||
|
||||
* Find out the local name for the main github repo in your git configuration.
|
||||
For example, in this configuration, it is labeled `upstream`.
|
||||
|
||||
```
|
||||
git remote -v
|
||||
[ ... ]
|
||||
upstream https://github.com/KhronosGroup/SPIRV-Tools.git (fetch)
|
||||
upstream https://github.com/KhronosGroup/SPIRV-Tools.git (push)
|
||||
```
|
||||
|
||||
* Make sure that the `upstream` remote is set to fetch from the `refs/pull`
|
||||
namespace:
|
||||
|
||||
```
|
||||
git config --get-all remote.upstream.fetch
|
||||
+refs/heads/*:refs/remotes/upstream/*
|
||||
+refs/pull/*/head:refs/remotes/upstream/pr/*
|
||||
```
|
||||
|
||||
* If the line `+refs/pull/*/head:refs/remotes/upstream/pr/*` is not present in
|
||||
your configuration, you can add it with the command:
|
||||
|
||||
```
|
||||
git config --local --add remote.upstream.fetch '+refs/pull/*/head:refs/remotes/upstream/pr/*'
|
||||
```
|
||||
|
||||
### Merge workflow
|
||||
|
||||
The following steps should be done for every PR that you intend to merge:
|
||||
|
||||
* Make sure your local copy of the master branch is up to date:
|
||||
|
||||
```
|
||||
git checkout master
|
||||
git pull
|
||||
```
|
||||
|
||||
* Fetch all pull requests refs:
|
||||
|
||||
```
|
||||
git fetch upstream
|
||||
```
|
||||
|
||||
* Checkout the particular pull request you are going to review:
|
||||
|
||||
```
|
||||
git checkout pr/1048
|
||||
```
|
||||
|
||||
* Rebase the PR on top of the master branch. If there are conflicts, send it
|
||||
back to the author and ask them to rebase. During the interactive rebase be
|
||||
sure to squash all of the commits down to a single commit.
|
||||
|
||||
```
|
||||
git rebase -i master
|
||||
```
|
||||
|
||||
* **Build and test the PR.**
|
||||
|
||||
* If all of the tests pass, push the commit `git push upstream HEAD:master`
|
||||
|
||||
* Close the PR and add a comment saying it was push using the commit that you
|
||||
just pushed. See https://github.com/KhronosGroup/SPIRV-Tools/pull/935 as an
|
||||
example.
|
202
3rdparty/spirv-tools/LICENSE
vendored
Normal file
202
3rdparty/spirv-tools/LICENSE
vendored
Normal file
@ -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.
|
509
3rdparty/spirv-tools/README.md
vendored
Normal file
509
3rdparty/spirv-tools/README.md
vendored
Normal file
@ -0,0 +1,509 @@
|
||||
# SPIR-V Tools
|
||||
|
||||
[![Build Status](https://travis-ci.org/KhronosGroup/SPIRV-Tools.svg?branch=master)](https://travis-ci.org/KhronosGroup/SPIRV-Tools)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/gpue87cesrx3pi0d/branch/master?svg=true)](https://ci.appveyor.com/project/Khronoswebmaster/spirv-tools/branch/master)
|
||||
|
||||
## Overview
|
||||
|
||||
The SPIR-V Tools project provides an API and commands for processing SPIR-V
|
||||
modules.
|
||||
|
||||
The project includes an assembler, binary module parser, disassembler,
|
||||
validator, and optimizer for SPIR-V. Except for the optimizer, all are based
|
||||
on a common static library. The library contains all of the implementation
|
||||
details, and is used in the standalone tools whilst also enabling integration
|
||||
into other code bases directly. The optimizer implementation resides in its
|
||||
own library, which depends on the core library.
|
||||
|
||||
The interfaces have stabilized:
|
||||
We don't anticipate making a breaking change for existing features.
|
||||
|
||||
SPIR-V is defined by the Khronos Group Inc.
|
||||
See the [SPIR-V Registry][spirv-registry] for the SPIR-V specification,
|
||||
headers, and XML registry.
|
||||
|
||||
## Versioning SPIRV-Tools
|
||||
|
||||
See [`CHANGES`](CHANGES) for a high level summary of recent changes, by version.
|
||||
|
||||
SPIRV-Tools project version numbers are of the form `v`*year*`.`*index* and with
|
||||
an optional `-dev` suffix to indicate work in progress. For exampe, the
|
||||
following versions are ordered from oldest to newest:
|
||||
|
||||
* `v2016.0`
|
||||
* `v2016.1-dev`
|
||||
* `v2016.1`
|
||||
* `v2016.2-dev`
|
||||
* `v2016.2`
|
||||
|
||||
Use the `--version` option on each command line tool to see the software
|
||||
version. An API call reports the software version as a C-style string.
|
||||
|
||||
## Supported features
|
||||
|
||||
### Assembler, binary parser, and disassembler
|
||||
|
||||
* Support for SPIR-V 1.0, 1.1, 1.2, and 1.3
|
||||
* Based on SPIR-V syntax described by JSON grammar files in the
|
||||
[SPIRV-Headers](spirv-headers) repository.
|
||||
* Support for extended instruction sets:
|
||||
* GLSL std450 version 1.0 Rev 3
|
||||
* OpenCL version 1.0 Rev 2
|
||||
* Assembler only does basic syntax checking. No cross validation of
|
||||
IDs or types is performed, except to check literal arguments to
|
||||
`OpConstant`, `OpSpecConstant`, and `OpSwitch`.
|
||||
|
||||
See [`syntax.md`](syntax.md) for the assembly language syntax.
|
||||
|
||||
### Validator
|
||||
|
||||
The validator checks validation rules described by the SPIR-V specification.
|
||||
|
||||
Khronos recommends that tools that create or transform SPIR-V modules use the
|
||||
validator to ensure their outputs are valid, and that tools that consume SPIR-V
|
||||
modules optionally use the validator to protect themselves from bad inputs.
|
||||
This is especially encouraged for debug and development scenarios.
|
||||
|
||||
The validator has one-sided error: it will only return an error when it has
|
||||
implemented a rule check and the module violates that rule.
|
||||
|
||||
The validator is incomplete.
|
||||
See the [CHANGES](CHANGES) file for reports on completed work, and
|
||||
the [Validator
|
||||
sub-project](https://github.com/KhronosGroup/SPIRV-Tools/projects/1) for planned
|
||||
and in-progress work.
|
||||
|
||||
*Note*: The validator checks some Universal Limits, from section 2.17 of the SPIR-V spec.
|
||||
The validator will fail on a module that exceeds those minimum upper bound limits.
|
||||
It is [future work](https://github.com/KhronosGroup/SPIRV-Tools/projects/1#card-1052403)
|
||||
to parameterize the validator to allow larger
|
||||
limits accepted by a more than minimally capable SPIR-V consumer.
|
||||
|
||||
|
||||
### Optimizer
|
||||
|
||||
*Note:* The optimizer is still under development.
|
||||
|
||||
Currently supported optimizations:
|
||||
* General
|
||||
* Strip debug info
|
||||
* Specialization Constants
|
||||
* Set spec constant default value
|
||||
* Freeze spec constant
|
||||
* Fold `OpSpecConstantOp` and `OpSpecConstantComposite`
|
||||
* Unify constants
|
||||
* Eliminate dead constant
|
||||
* Code Reduction
|
||||
* Inline all function calls exhaustively
|
||||
* Convert local access chains to inserts/extracts
|
||||
* Eliminate local load/store in single block
|
||||
* Eliminate local load/store with single store
|
||||
* Eliminate local load/store with multiple stores
|
||||
* Eliminate local extract from insert
|
||||
* Eliminate dead instructions (aggressive)
|
||||
* Eliminate dead branches
|
||||
* Merge single successor / single predecessor block pairs
|
||||
* Eliminate common uniform loads
|
||||
* Remove duplicates: Capabilities, extended instruction imports, types, and
|
||||
decorations.
|
||||
|
||||
For the latest list with detailed documentation, please refer to
|
||||
[`include/spirv-tools/optimizer.hpp`](include/spirv-tools/optimizer.hpp).
|
||||
|
||||
For suggestions on using the code reduction options, please refer to this [white paper](https://www.lunarg.com/shader-compiler-technologies/white-paper-spirv-opt/).
|
||||
|
||||
|
||||
### Linker
|
||||
|
||||
*Note:* The linker is still under development.
|
||||
|
||||
Current features:
|
||||
* Combine multiple SPIR-V binary modules together.
|
||||
* Combine into a library (exports are retained) or an executable (no symbols
|
||||
are exported).
|
||||
|
||||
See the [CHANGES](CHANGES) file for reports on completed work, and the [General
|
||||
sub-project](https://github.com/KhronosGroup/SPIRV-Tools/projects/2) for
|
||||
planned and in-progress work.
|
||||
|
||||
### Extras
|
||||
|
||||
* [Utility filters](#utility-filters)
|
||||
* Build target `spirv-tools-vimsyntax` generates file `spvasm.vim`.
|
||||
Copy that file into your `$HOME/.vim/syntax` directory to get SPIR-V assembly syntax
|
||||
highlighting in Vim. This build target is not built by default.
|
||||
|
||||
## Contributing
|
||||
|
||||
The SPIR-V Tools project is maintained by members of the The Khronos Group Inc.,
|
||||
and is hosted at https://github.com/KhronosGroup/SPIRV-Tools.
|
||||
|
||||
Consider joining the `public_spirv_tools_dev@khronos.org` mailing list, via
|
||||
[https://www.khronos.org/spir/spirv-tools-mailing-list/](https://www.khronos.org/spir/spirv-tools-mailing-list/).
|
||||
The mailing list is used to discuss development plans for the SPIRV-Tools as an open source project.
|
||||
Once discussion is resolved,
|
||||
specific work is tracked via issues and sometimes in one of the
|
||||
[projects][spirv-tools-projects].
|
||||
|
||||
(To provide feedback on the SPIR-V _specification_, file an issue on the
|
||||
[SPIRV-Headers][spirv-headers] GitHub repository.)
|
||||
|
||||
See [`projects.md`](projects.md) to see how we use the
|
||||
[GitHub Project
|
||||
feature](https://help.github.com/articles/tracking-the-progress-of-your-work-with-projects/)
|
||||
to organize planned and in-progress work.
|
||||
|
||||
Contributions via merge request are welcome. Changes should:
|
||||
* Be provided under the [Apache 2.0](#license).
|
||||
* You'll be prompted with a one-time "click-through"
|
||||
[Khronos Open Source Contributor License Agreement][spirv-tools-cla]
|
||||
(CLA) dialog as part of submitting your pull request or
|
||||
other contribution to GitHub.
|
||||
* Include tests to cover updated functionality.
|
||||
* C++ code should follow the [Google C++ Style Guide][cpp-style-guide].
|
||||
* Code should be formatted with `clang-format`. Settings are defined by
|
||||
the included [.clang-format](.clang-format) file.
|
||||
|
||||
We intend to maintain a linear history on the GitHub `master` branch.
|
||||
|
||||
### Source code organization
|
||||
|
||||
* `example`: demo code of using SPIRV-Tools APIs
|
||||
* `external/googletest`: Intended location for the
|
||||
[googletest][googletest] sources, not provided
|
||||
* `external/effcee`: Location of [Effcee][effcee] sources, if the `effcee` library
|
||||
is not already configured by an enclosing project.
|
||||
* `external/re2`: Location of [RE2][re2] sources, if the `effcee` library is not already
|
||||
configured by an enclosing project.
|
||||
(The Effcee project already requires RE2.)
|
||||
* `include/`: API clients should add this directory to the include search path
|
||||
* `external/spirv-headers`: Intended location for
|
||||
[SPIR-V headers][spirv-headers], not provided
|
||||
* `include/spirv-tools/libspirv.h`: C API public interface
|
||||
* `source/`: API implementation
|
||||
* `test/`: Tests, using the [googletest][googletest] framework
|
||||
* `tools/`: Command line executables
|
||||
|
||||
Example of getting sources, assuming SPIRV-Tools is configured as a standalone project:
|
||||
|
||||
git clone https://github.com/KhronosGroup/SPIRV-Tools.git spirv-tools
|
||||
git clone https://github.com/KhronosGroup/SPIRV-Headers.git spirv-tools/external/spirv-headers
|
||||
git clone https://github.com/google/googletest.git spirv-tools/external/googletest
|
||||
git clone https://github.com/google/effcee.git spirv-tools/external/effcee
|
||||
git clone https://github.com/google/re2.git spirv-tools/external/re2
|
||||
|
||||
### Tests
|
||||
|
||||
The project contains a number of tests, used to drive development
|
||||
and ensure correctness. The tests are written using the
|
||||
[googletest][googletest] framework. The `googletest`
|
||||
source is not provided with this project. There are two ways to enable
|
||||
tests:
|
||||
* If SPIR-V Tools is configured as part of an enclosing project, then the
|
||||
enclosing project should configure `googletest` before configuring SPIR-V Tools.
|
||||
* If SPIR-V Tools is configured as a standalone project, then download the
|
||||
`googletest` source into the `<spirv-dir>/external/googletest` directory before
|
||||
configuring and building the project.
|
||||
|
||||
*Note*: You must use a version of googletest that includes
|
||||
[a fix][googletest-pull-612] for [googletest issue 610][googletest-issue-610].
|
||||
The fix is included on the googletest master branch any time after 2015-11-10.
|
||||
In particular, googletest must be newer than version 1.7.0.
|
||||
|
||||
### Optional dependency on Effcee
|
||||
|
||||
Some tests depend on the [Effcee][effcee] library for stateful matching.
|
||||
Effcee itself depends on [RE2][re2].
|
||||
|
||||
* If SPIRV-Tools is configured as part of a larger project that already uses
|
||||
Effcee, then that project should include Effcee before SPIRV-Tools.
|
||||
* Otherwise, SPIRV-Tools expects Effcee sources to appear in `external/effcee`
|
||||
and RE2 sources to appear in `external/re2`.
|
||||
|
||||
Currently Effcee is an optional dependency, but soon it will be required.
|
||||
|
||||
## Build
|
||||
|
||||
Instead of building manually, you can also download the binaries for your
|
||||
platform directly from the [master-tot release][master-tot-release] on GitHub.
|
||||
Those binaries are automatically uploaded by the buildbots after successful
|
||||
testing and they always reflect the current top of the tree of the master
|
||||
branch.
|
||||
|
||||
The project uses [CMake][cmake] to generate platform-specific build
|
||||
configurations. Assume that `<spirv-dir>` is the root directory of the checked
|
||||
out code:
|
||||
|
||||
```sh
|
||||
cd <spirv-dir>
|
||||
git clone https://github.com/KhronosGroup/SPIRV-Headers.git external/spirv-headers
|
||||
git clone https://github.com/google/googletest.git external/googletest # optional
|
||||
|
||||
mkdir build && cd build
|
||||
cmake [-G <platform-generator>] <spirv-dir>
|
||||
```
|
||||
|
||||
Once the build files have been generated, build using your preferred
|
||||
development environment.
|
||||
|
||||
### CMake options
|
||||
|
||||
The following CMake options are supported:
|
||||
|
||||
* `SPIRV_COLOR_TERMINAL={ON|OFF}`, default `ON` - Enables color console output.
|
||||
* `SPIRV_SKIP_TESTS={ON|OFF}`, default `OFF`- Build only the library and
|
||||
the command line tools. This will prevent the tests from being built.
|
||||
* `SPIRV_SKIP_EXECUTABLES={ON|OFF}`, default `OFF`- Build only the library, not
|
||||
the command line tools and tests.
|
||||
* `SPIRV_BUILD_COMPRESSION={ON|OFF}`, default `OFF`- Build SPIR-V compressing
|
||||
codec.
|
||||
* `SPIRV_USE_SANITIZER=<sanitizer>`, default is no sanitizing - On UNIX
|
||||
platforms with an appropriate version of `clang` this option enables the use
|
||||
of the sanitizers documented [here][clang-sanitizers].
|
||||
This should only be used with a debug build.
|
||||
* `SPIRV_WARN_EVERYTHING={ON|OFF}`, default `OFF` - On UNIX platforms enable
|
||||
more strict warnings. The code might not compile with this option enabled.
|
||||
For Clang, enables `-Weverything`. For GCC, enables `-Wpedantic`.
|
||||
See [`CMakeLists.txt`](CMakeLists.txt) for details.
|
||||
* `SPIRV_WERROR={ON|OFF}`, default `ON` - Forces a compilation error on any
|
||||
warnings encountered by enabling the compiler-specific compiler front-end
|
||||
option.
|
||||
|
||||
Additionally, you can pass additional C preprocessor definitions to SPIRV-Tools
|
||||
via setting `SPIRV_TOOLS_EXTRA_DEFINITIONS`. For example, by setting it to
|
||||
`/D_ITERATOR_DEBUG_LEVEL=0` on Windows, you can disable checked iterators and
|
||||
iterator debugging.
|
||||
|
||||
## Library
|
||||
|
||||
### Usage
|
||||
|
||||
The internals of the library use C++11 features, and are exposed via both a C
|
||||
and C++ API.
|
||||
|
||||
In order to use the library from an application, the include path should point
|
||||
to `<spirv-dir>/include`, which will enable the application to include the
|
||||
header `<spirv-dir>/include/spirv-tools/libspirv.h{|pp}` then linking against
|
||||
the static library in `<spirv-build-dir>/source/libSPIRV-Tools.a` or
|
||||
`<spirv-build-dir>/source/SPIRV-Tools.lib`.
|
||||
For optimization, the header file is
|
||||
`<spirv-dir>/include/spirv-tools/optimizer.hpp`, and the static library is
|
||||
`<spirv-build-dir>/source/libSPIRV-Tools-opt.a` or
|
||||
`<spirv-build-dir>/source/SPIRV-Tools-opt.lib`.
|
||||
|
||||
* `SPIRV-Tools` CMake target: Creates the static library:
|
||||
* `<spirv-build-dir>/source/libSPIRV-Tools.a` on Linux and OS X.
|
||||
* `<spirv-build-dir>/source/libSPIRV-Tools.lib` on Windows.
|
||||
* `SPIRV-Tools-opt` CMake target: Creates the static library:
|
||||
* `<spirv-build-dir>/source/libSPIRV-Tools-opt.a` on Linux and OS X.
|
||||
* `<spirv-build-dir>/source/libSPIRV-Tools-opt.lib` on Windows.
|
||||
|
||||
#### Entry points
|
||||
|
||||
The interfaces are still under development, and are expected to change.
|
||||
|
||||
There are five main entry points into the library in the C interface:
|
||||
|
||||
* `spvTextToBinary`: An assembler, translating text to a binary SPIR-V module.
|
||||
* `spvBinaryToText`: A disassembler, translating a binary SPIR-V module to
|
||||
text.
|
||||
* `spvBinaryParse`: The entry point to a binary parser API. It issues callbacks
|
||||
for the header and each parsed instruction. The disassembler is implemented
|
||||
as a client of `spvBinaryParse`.
|
||||
* `spvValidate` implements the validator functionality. *Incomplete*
|
||||
* `spvValidateBinary` implements the validator functionality. *Incomplete*
|
||||
|
||||
The C++ interface is comprised of three classes, `SpirvTools`, `Optimizer` and
|
||||
`Linker`, all in the `spvtools` namespace.
|
||||
* `SpirvTools` provides `Assemble`, `Disassemble`, and `Validate` methods.
|
||||
* `Optimizer` provides methods for registering and running optimization passes.
|
||||
* `Linker` provides methods for combining together multiple binaries.
|
||||
|
||||
## Command line tools
|
||||
|
||||
Command line tools, which wrap the above library functions, are provided to
|
||||
assemble or disassemble shader files. It's a convention to name SPIR-V
|
||||
assembly and binary files with suffix `.spvasm` and `.spv`, respectively.
|
||||
|
||||
### Assembler tool
|
||||
|
||||
The assembler reads the assembly language text, and emits the binary form.
|
||||
|
||||
The standalone assembler is the exectuable called `spirv-as`, and is located in
|
||||
`<spirv-build-dir>/tools/spirv-as`. The functionality of the assembler is implemented
|
||||
by the `spvTextToBinary` library function.
|
||||
|
||||
* `spirv-as` - the standalone assembler
|
||||
* `<spirv-dir>/tools/as`
|
||||
|
||||
Use option `-h` to print help.
|
||||
|
||||
### Disassembler tool
|
||||
|
||||
The disassembler reads the binary form, and emits assembly language text.
|
||||
|
||||
The standalone disassembler is the executable called `spirv-dis`, and is located in
|
||||
`<spirv-build-dir>/tools/spirv-dis`. The functionality of the disassembler is implemented
|
||||
by the `spvBinaryToText` library function.
|
||||
|
||||
* `spirv-dis` - the standalone disassembler
|
||||
* `<spirv-dir>/tools/dis`
|
||||
|
||||
Use option `-h` to print help.
|
||||
|
||||
The output includes syntax colouring when printing to the standard output stream,
|
||||
on Linux, Windows, and OS X.
|
||||
|
||||
### Linker tool
|
||||
|
||||
The linker combines multiple SPIR-V binary modules together, resulting in a single
|
||||
binary module as output.
|
||||
|
||||
This is a work in progress.
|
||||
The linker does not support OpenCL program linking options related to math
|
||||
flags. (See section 5.6.5.2 in OpenCL 1.2)
|
||||
|
||||
* `spirv-link` - the standalone linker
|
||||
* `<spirv-dir>/tools/link`
|
||||
|
||||
### Optimizer tool
|
||||
|
||||
The optimizer processes a SPIR-V binary module, applying transformations
|
||||
in the specified order.
|
||||
|
||||
This is a work in progress, with initially only few available transformations.
|
||||
|
||||
* `spirv-opt` - the standalone optimizer
|
||||
* `<spirv-dir>/tools/opt`
|
||||
|
||||
### Validator tool
|
||||
|
||||
*Warning:* This functionality is under development, and is incomplete.
|
||||
|
||||
The standalone validator is the executable called `spirv-val`, and is located in
|
||||
`<spirv-build-dir>/tools/spirv-val`. The functionality of the validator is implemented
|
||||
by the `spvValidate` library function.
|
||||
|
||||
The validator operates on the binary form.
|
||||
|
||||
* `spirv-val` - the standalone validator
|
||||
* `<spirv-dir>/tools/val`
|
||||
|
||||
### Control flow dumper tool
|
||||
|
||||
The control flow dumper prints the control flow graph for a SPIR-V module as a
|
||||
[GraphViz](http://www.graphviz.org/) graph.
|
||||
|
||||
This is experimental.
|
||||
|
||||
* `spirv-cfg` - the control flow graph dumper
|
||||
* `<spirv-dir>/tools/cfg`
|
||||
|
||||
### Utility filters
|
||||
|
||||
* `spirv-lesspipe.sh` - Automatically disassembles `.spv` binary files for the
|
||||
`less` program, on compatible systems. For example, set the `LESSOPEN`
|
||||
environment variable as follows, assuming both `spirv-lesspipe.sh` and
|
||||
`spirv-dis` are on your executable search path:
|
||||
```
|
||||
export LESSOPEN='| spirv-lesspipe.sh "%s"'
|
||||
```
|
||||
Then you page through a disassembled module as follows:
|
||||
```
|
||||
less foo.spv
|
||||
```
|
||||
* The `spirv-lesspipe.sh` script will pass through any extra arguments to
|
||||
`spirv-dis`. So, for example, you can turn off colours and friendly ID
|
||||
naming as follows:
|
||||
```
|
||||
export LESSOPEN='| spirv-lesspipe.sh "%s" --no-color --raw-id'
|
||||
```
|
||||
|
||||
* [vim-spirv](https://github.com/kbenzie/vim-spirv) - A vim plugin which
|
||||
supports automatic disassembly of `.spv` files using the `:edit` command and
|
||||
assembly using the `:write` command. The plugin also provides additional
|
||||
features which include; syntax highlighting; highlighting of all ID's matching
|
||||
the ID under the cursor; and highlighting errors where the `Instruction`
|
||||
operand of `OpExtInst` is used without an appropriate `OpExtInstImport`.
|
||||
|
||||
* `50spirv-tools.el` - Automatically disassembles '.spv' binary files when
|
||||
loaded into the emacs text editor, and re-assembles them when saved,
|
||||
provided any modifications to the file are valid. This functionality
|
||||
must be explicitly requested by defining the symbol
|
||||
SPIRV_TOOLS_INSTALL_EMACS_HELPERS as follows:
|
||||
```
|
||||
cmake -DSPIRV_TOOLS_INSTALL_EMACS_HELPERS=true ...
|
||||
```
|
||||
|
||||
In addition, this helper is only installed if the directory /etc/emacs/site-start.d
|
||||
exists, which is typically true if emacs is installed on the system.
|
||||
|
||||
Note that symbol IDs are not currently preserved through a load/edit/save operation.
|
||||
This may change if the ability is added to spirv-as.
|
||||
|
||||
|
||||
### Tests
|
||||
|
||||
Tests are only built when googletest is found. Use `ctest` to run all the
|
||||
tests.
|
||||
|
||||
## Future Work
|
||||
<a name="future"></a>
|
||||
|
||||
_See the [projects pages](https://github.com/KhronosGroup/SPIRV-Tools/projects)
|
||||
for more information._
|
||||
|
||||
### Assembler and disassembler
|
||||
|
||||
* The disassembler could emit helpful annotations in comments. For example:
|
||||
* Use variable name information from debug instructions to annotate
|
||||
key operations on variables.
|
||||
* Show control flow information by annotating `OpLabel` instructions with
|
||||
that basic block's predecessors.
|
||||
* Error messages could be improved.
|
||||
|
||||
### Validator
|
||||
|
||||
This is a work in progress.
|
||||
|
||||
### Linker
|
||||
|
||||
* The linker could accept math transformations such as allowing MADs, or other
|
||||
math flags passed at linking-time in OpenCL.
|
||||
* Linkage attributes can not be applied through a group.
|
||||
* Check decorations of linked functions attributes.
|
||||
* Remove dead instructions, such as OpName targeting imported symbols.
|
||||
|
||||
## Licence
|
||||
<a name="license"></a>
|
||||
Full license terms are in [LICENSE](LICENSE)
|
||||
```
|
||||
Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
|
||||
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.
|
||||
```
|
||||
|
||||
[spirv-tools-cla]: https://cla-assistant.io/KhronosGroup/SPIRV-Tools
|
||||
[spirv-tools-projects]: https://github.com/KhronosGroup/SPIRV-Tools/projects
|
||||
[spirv-tools-mailing-list]: https://www.khronos.org/spir/spirv-tools-mailing-list
|
||||
[spirv-registry]: https://www.khronos.org/registry/spir-v/
|
||||
[spirv-headers]: https://github.com/KhronosGroup/SPIRV-Headers
|
||||
[googletest]: https://github.com/google/googletest
|
||||
[googletest-pull-612]: https://github.com/google/googletest/pull/612
|
||||
[googletest-issue-610]: https://github.com/google/googletest/issues/610
|
||||
[effcee]: https://github.com/google/effcee
|
||||
[re2]: https://github.com/google/re2
|
||||
[CMake]: https://cmake.org/
|
||||
[cpp-style-guide]: https://google.github.io/styleguide/cppguide.html
|
||||
[clang-sanitizers]: http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation
|
||||
[master-tot-release]: https://github.com/KhronosGroup/SPIRV-Tools/releases/tag/master-tot
|
12
3rdparty/spirv-tools/android_test/Android.mk
vendored
Normal file
12
3rdparty/spirv-tools/android_test/Android.mk
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_CPP_EXTENSION := .cc .cpp .cxx
|
||||
LOCAL_SRC_FILES:=test.cpp
|
||||
LOCAL_MODULE:=spirvtools_test
|
||||
LOCAL_LDLIBS:=-landroid
|
||||
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -Werror
|
||||
LOCAL_STATIC_LIBRARIES=SPIRV-Tools SPIRV-Tools-opt
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
include $(LOCAL_PATH)/../Android.mk
|
5
3rdparty/spirv-tools/android_test/jni/Application.mk
vendored
Normal file
5
3rdparty/spirv-tools/android_test/jni/Application.mk
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
APP_ABI := all
|
||||
APP_BUILD_SCRIPT := Android.mk
|
||||
APP_STL := gnustl_static
|
||||
APP_PLATFORM := android-9
|
||||
NDK_TOOLCHAIN_VERSION := 4.9
|
22
3rdparty/spirv-tools/android_test/test.cpp
vendored
Normal file
22
3rdparty/spirv-tools/android_test/test.cpp
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <memory>
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
#include "spirv-tools/optimizer.hpp"
|
||||
|
||||
void android_main(struct android_app* /*state*/) {
|
||||
spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_2);
|
||||
spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_2);
|
||||
}
|
12
3rdparty/spirv-tools/cmake/SPIRV-Tools-shared.pc.in
vendored
Normal file
12
3rdparty/spirv-tools/cmake/SPIRV-Tools-shared.pc.in
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
|
||||
Name: SPIRV-Tools
|
||||
Description: Tools for SPIR-V
|
||||
Version: @CURRENT_VERSION@
|
||||
URL: https://github.com/KhronosGroup/SPIRV-Tools
|
||||
|
||||
Libs: -L${libdir} @SPIRV_SHARED_LIBRARIES@
|
||||
Cflags: -I${includedir}
|
12
3rdparty/spirv-tools/cmake/SPIRV-Tools.pc.in
vendored
Normal file
12
3rdparty/spirv-tools/cmake/SPIRV-Tools.pc.in
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
|
||||
Name: SPIRV-Tools
|
||||
Description: Tools for SPIR-V
|
||||
Version: @CURRENT_VERSION@
|
||||
URL: https://github.com/KhronosGroup/SPIRV-Tools
|
||||
|
||||
Libs: -L${libdir} @SPIRV_LIBRARIES@
|
||||
Cflags: -I${includedir}
|
31
3rdparty/spirv-tools/cmake/write_pkg_config.cmake
vendored
Normal file
31
3rdparty/spirv-tools/cmake/write_pkg_config.cmake
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
# Copyright (c) 2017 Pierre Moreau
|
||||
#
|
||||
# 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.
|
||||
|
||||
# First, retrieve the current version from CHANGES
|
||||
file(STRINGS ${CHANGES_FILE} CHANGES_CONTENT)
|
||||
string(
|
||||
REGEX
|
||||
MATCH "v[0-9]+(.[0-9]+)?(-dev)? [0-9]+-[0-9]+-[0-9]+"
|
||||
FIRST_VERSION_LINE
|
||||
${CHANGES_CONTENT})
|
||||
string(
|
||||
REGEX
|
||||
REPLACE "^v([^ ]+) .+$" "\\1"
|
||||
CURRENT_VERSION
|
||||
"${FIRST_VERSION_LINE}")
|
||||
# If this is a development version, replace "-dev" by ".0" as pkg-config nor
|
||||
# CMake support "-dev" in the version.
|
||||
# If it's not a "-dev" version then ensure it ends with ".1"
|
||||
string(REGEX REPLACE "-dev.1" ".0" CURRENT_VERSION "${CURRENT_VERSION}.1")
|
||||
configure_file(${TEMPLATE_FILE} ${OUT_FILE} @ONLY)
|
35
3rdparty/spirv-tools/examples/CMakeLists.txt
vendored
Normal file
35
3rdparty/spirv-tools/examples/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2016 Google Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Add a SPIR-V Tools example. Signature:
|
||||
# add_spvtools_example(
|
||||
# TARGET target_name
|
||||
# SRCS src_file1.cpp src_file2.cpp
|
||||
# LIBS lib_target1 lib_target2
|
||||
# )
|
||||
function(add_spvtools_example)
|
||||
if (NOT ${SPIRV_SKIP_EXECUTABLES})
|
||||
set(one_value_args TARGET)
|
||||
set(multi_value_args SRCS LIBS)
|
||||
cmake_parse_arguments(
|
||||
ARG "" "${one_value_args}" "${multi_value_args}" ${ARGN})
|
||||
|
||||
add_executable(${ARG_TARGET} ${ARG_SRCS})
|
||||
spvtools_default_compile_options(${ARG_TARGET})
|
||||
target_link_libraries(${ARG_TARGET} PRIVATE ${ARG_LIBS})
|
||||
set_property(TARGET ${ARG_TARGET} PROPERTY FOLDER "SPIRV-Tools examples")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
add_subdirectory(cpp-interface)
|
19
3rdparty/spirv-tools/examples/cpp-interface/CMakeLists.txt
vendored
Normal file
19
3rdparty/spirv-tools/examples/cpp-interface/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright (c) 2016 Google Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
add_spvtools_example(
|
||||
TARGET spirv-tools-cpp-example
|
||||
SRCS main.cpp
|
||||
LIBS SPIRV-Tools-opt
|
||||
)
|
64
3rdparty/spirv-tools/examples/cpp-interface/main.cpp
vendored
Normal file
64
3rdparty/spirv-tools/examples/cpp-interface/main.cpp
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// This program demonstrates basic SPIR-V module processing using
|
||||
// SPIRV-Tools C++ API:
|
||||
// * Assembling
|
||||
// * Validating
|
||||
// * Optimizing
|
||||
// * Disassembling
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
#include "spirv-tools/optimizer.hpp"
|
||||
|
||||
int main() {
|
||||
const std::string source =
|
||||
" OpCapability Shader "
|
||||
" OpMemoryModel Logical GLSL450 "
|
||||
" OpSource GLSL 450 "
|
||||
" OpDecorate %spec SpecId 1 "
|
||||
" %int = OpTypeInt 32 1 "
|
||||
" %spec = OpSpecConstant %int 0 "
|
||||
"%const = OpConstant %int 42";
|
||||
|
||||
spvtools::SpirvTools core(SPV_ENV_VULKAN_1_0);
|
||||
spvtools::Optimizer opt(SPV_ENV_VULKAN_1_0);
|
||||
|
||||
auto print_msg_to_stderr = [](spv_message_level_t, const char*,
|
||||
const spv_position_t&, const char* m) {
|
||||
std::cerr << "error: " << m << std::endl;
|
||||
};
|
||||
core.SetMessageConsumer(print_msg_to_stderr);
|
||||
opt.SetMessageConsumer(print_msg_to_stderr);
|
||||
|
||||
std::vector<uint32_t> spirv;
|
||||
if (!core.Assemble(source, &spirv)) return 1;
|
||||
if (!core.Validate(spirv)) return 1;
|
||||
|
||||
opt.RegisterPass(spvtools::CreateSetSpecConstantDefaultValuePass({{1, "42"}}))
|
||||
.RegisterPass(spvtools::CreateFreezeSpecConstantValuePass())
|
||||
.RegisterPass(spvtools::CreateUnifyConstantPass())
|
||||
.RegisterPass(spvtools::CreateStripDebugInfoPass());
|
||||
if (!opt.Run(spirv.data(), spirv.size(), &spirv)) return 1;
|
||||
|
||||
std::string disassembly;
|
||||
if (!core.Disassemble(spirv, &disassembly)) return 1;
|
||||
std::cout << disassembly << "\n";
|
||||
|
||||
return 0;
|
||||
}
|
122
3rdparty/spirv-tools/external/CMakeLists.txt
vendored
Normal file
122
3rdparty/spirv-tools/external/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
# Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
#
|
||||
#
|
||||
# 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.
|
||||
|
||||
if (DEFINED SPIRV-Headers_SOURCE_DIR)
|
||||
# This allows flexible position of the SPIRV-Headers repo.
|
||||
set(SPIRV_HEADER_DIR ${SPIRV-Headers_SOURCE_DIR})
|
||||
else()
|
||||
if (IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/SPIRV-Headers)
|
||||
set(SPIRV_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SPIRV-Headers)
|
||||
else()
|
||||
set(SPIRV_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/spirv-headers)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (IS_DIRECTORY ${SPIRV_HEADER_DIR})
|
||||
set(SPIRV_HEADER_INCLUDE_DIR ${SPIRV_HEADER_DIR}/include PARENT_SCOPE)
|
||||
else()
|
||||
message(FATAL_ERROR
|
||||
"SPIRV-Headers was not found - please checkout a copy under external/.")
|
||||
endif()
|
||||
|
||||
if (NOT ${SPIRV_SKIP_TESTS})
|
||||
# Find gmock if we can. If it's not already configured, then try finding
|
||||
# it in external/googletest.
|
||||
if (TARGET gmock)
|
||||
message(STATUS "Google Mock already configured")
|
||||
else()
|
||||
set(GMOCK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/googletest/googlemock)
|
||||
if(EXISTS ${GMOCK_DIR})
|
||||
if(MSVC)
|
||||
# Our tests use ::testing::Combine. Work around a compiler
|
||||
# detection problem in googletest, where that template is
|
||||
# accidentally disabled for VS 2017.
|
||||
# See https://github.com/google/googletest/issues/1352
|
||||
add_definitions(-DGTEST_HAS_COMBINE=1)
|
||||
endif()
|
||||
if(WIN32)
|
||||
option(gtest_force_shared_crt
|
||||
"Use shared (DLL) run-time lib even when Google Test is built as static lib."
|
||||
ON)
|
||||
endif()
|
||||
add_subdirectory(${GMOCK_DIR} EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
endif()
|
||||
if (TARGET gmock)
|
||||
set(GTEST_TARGETS
|
||||
gtest
|
||||
gtest_main
|
||||
gmock
|
||||
gmock_main
|
||||
)
|
||||
foreach(target ${GTEST_TARGETS})
|
||||
set_property(TARGET ${target} PROPERTY FOLDER GoogleTest)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(SPIRV_ENABLE_EFFCEE ON)
|
||||
if (MSVC)
|
||||
if (MSVC_VERSION LESS 1900)
|
||||
message(STATUS "SPIRV-Tools: Need Visual Studio 2015 or later for Effcee and RE2")
|
||||
set(SPIRV_ENABLE_EFFCEE OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (SPIRV_ENABLE_EFFCEE)
|
||||
# Find Effcee and RE2, for testing.
|
||||
# Optional for now, but eventually we'll make this required.
|
||||
|
||||
# First find RE2, since Effcee depends on it.
|
||||
# If already configured, then use that. Otherwise, prefer to find it under 're2'
|
||||
# in this directory.
|
||||
if (NOT TARGET re2)
|
||||
# If we are configuring RE2, then turn off its testing. It takes a long time and
|
||||
# does not add much value for us. If an enclosing project configured RE2, then it
|
||||
# has already chosen whether to enable RE2 tesitng.
|
||||
set(RE2_BUILD_TESTING OFF CACHE STRING "Run RE2 Tests")
|
||||
if (NOT RE2_SOURCE_DIR)
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/re2)
|
||||
set(RE2_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/re2" CACHE STRING "RE2 source dir" )
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT TARGET effcee)
|
||||
# Expect to find effcee in this directory.
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/effcee)
|
||||
# If we're configuring RE2 (via Effcee), then turn off RE2 testing.
|
||||
if (NOT TARGET re2)
|
||||
set(RE2_BUILD_TESTING OFF)
|
||||
endif()
|
||||
if (MSVC)
|
||||
# SPIRV-Tools uses the shared CRT with MSVC. Tell Effcee to do the same.
|
||||
set(EFFCEE_ENABLE_SHARED_CRT ON)
|
||||
endif()
|
||||
add_subdirectory(effcee)
|
||||
set_property(TARGET effcee PROPERTY FOLDER Effcee)
|
||||
# Turn off warnings for effcee and re2
|
||||
set_property(TARGET effcee APPEND PROPERTY COMPILE_OPTIONS -w)
|
||||
set_property(TARGET re2 APPEND PROPERTY COMPILE_OPTIONS -w)
|
||||
endif()
|
||||
endif()
|
||||
# TODO(dneto): Eventually, require this.
|
||||
endif()
|
||||
if (TARGET effcee)
|
||||
message(STATUS "SPIRV-Tools: Effcee is configured")
|
||||
else()
|
||||
message(STATUS "SPIRV-Tools: Effcee is not configured. Skipping Effcee-based tests.")
|
||||
endif()
|
||||
|
||||
endif()
|
137
3rdparty/spirv-tools/include/generated/DebugInfo.h
vendored
Normal file
137
3rdparty/spirv-tools/include/generated/DebugInfo.h
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and/or associated documentation files (the "Materials"),
|
||||
// to deal in the Materials without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
// and/or sell copies of the Materials, and to permit persons to whom the
|
||||
// Materials are furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Materials.
|
||||
//
|
||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
// STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
// HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
//
|
||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
// IN THE MATERIALS.
|
||||
|
||||
#ifndef SPIRV_EXTINST_DebugInfo_H_
|
||||
#define SPIRV_EXTINST_DebugInfo_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum { DebugInfoVersion = 100, DebugInfoVersion_BitWidthPadding = 0x7fffffff };
|
||||
enum { DebugInfoRevision = 1, DebugInfoRevision_BitWidthPadding = 0x7fffffff };
|
||||
|
||||
enum DebugInfoInstructions {
|
||||
DebugInfoDebugInfoNone = 0,
|
||||
DebugInfoDebugCompilationUnit = 1,
|
||||
DebugInfoDebugTypeBasic = 2,
|
||||
DebugInfoDebugTypePointer = 3,
|
||||
DebugInfoDebugTypeQualifier = 4,
|
||||
DebugInfoDebugTypeArray = 5,
|
||||
DebugInfoDebugTypeVector = 6,
|
||||
DebugInfoDebugTypedef = 7,
|
||||
DebugInfoDebugTypeFunction = 8,
|
||||
DebugInfoDebugTypeEnum = 9,
|
||||
DebugInfoDebugTypeComposite = 10,
|
||||
DebugInfoDebugTypeMember = 11,
|
||||
DebugInfoDebugTypeInheritance = 12,
|
||||
DebugInfoDebugTypePtrToMember = 13,
|
||||
DebugInfoDebugTypeTemplate = 14,
|
||||
DebugInfoDebugTypeTemplateParameter = 15,
|
||||
DebugInfoDebugTypeTemplateTemplateParameter = 16,
|
||||
DebugInfoDebugTypeTemplateParameterPack = 17,
|
||||
DebugInfoDebugGlobalVariable = 18,
|
||||
DebugInfoDebugFunctionDeclaration = 19,
|
||||
DebugInfoDebugFunction = 20,
|
||||
DebugInfoDebugLexicalBlock = 21,
|
||||
DebugInfoDebugLexicalBlockDiscriminator = 22,
|
||||
DebugInfoDebugScope = 23,
|
||||
DebugInfoDebugNoScope = 24,
|
||||
DebugInfoDebugInlinedAt = 25,
|
||||
DebugInfoDebugLocalVariable = 26,
|
||||
DebugInfoDebugInlinedVariable = 27,
|
||||
DebugInfoDebugDeclare = 28,
|
||||
DebugInfoDebugValue = 29,
|
||||
DebugInfoDebugOperation = 30,
|
||||
DebugInfoDebugExpression = 31,
|
||||
DebugInfoDebugMacroDef = 32,
|
||||
DebugInfoDebugMacroUndef = 33,
|
||||
DebugInfoInstructionsMax = 0x7ffffff
|
||||
};
|
||||
|
||||
|
||||
enum DebugInfoDebugInfoFlags {
|
||||
DebugInfoFlagIsProtected = 0x01,
|
||||
DebugInfoFlagIsPrivate = 0x02,
|
||||
DebugInfoFlagIsPublic = 0x03,
|
||||
DebugInfoFlagIsLocal = 0x04,
|
||||
DebugInfoFlagIsDefinition = 0x08,
|
||||
DebugInfoFlagFwdDecl = 0x10,
|
||||
DebugInfoFlagArtificial = 0x20,
|
||||
DebugInfoFlagExplicit = 0x40,
|
||||
DebugInfoFlagPrototyped = 0x80,
|
||||
DebugInfoFlagObjectPointer = 0x100,
|
||||
DebugInfoFlagStaticMember = 0x200,
|
||||
DebugInfoFlagIndirectVariable = 0x400,
|
||||
DebugInfoFlagLValueReference = 0x800,
|
||||
DebugInfoFlagRValueReference = 0x1000,
|
||||
DebugInfoFlagIsOptimized = 0x2000,
|
||||
DebugInfoDebugInfoFlagsMax = 0x7ffffff
|
||||
};
|
||||
|
||||
enum DebugInfoDebugBaseTypeAttributeEncoding {
|
||||
DebugInfoUnspecified = 0,
|
||||
DebugInfoAddress = 1,
|
||||
DebugInfoBoolean = 2,
|
||||
DebugInfoFloat = 4,
|
||||
DebugInfoSigned = 5,
|
||||
DebugInfoSignedChar = 6,
|
||||
DebugInfoUnsigned = 7,
|
||||
DebugInfoUnsignedChar = 8,
|
||||
DebugInfoDebugBaseTypeAttributeEncodingMax = 0x7ffffff
|
||||
};
|
||||
|
||||
enum DebugInfoDebugCompositeType {
|
||||
DebugInfoClass = 0,
|
||||
DebugInfoStructure = 1,
|
||||
DebugInfoUnion = 2,
|
||||
DebugInfoDebugCompositeTypeMax = 0x7ffffff
|
||||
};
|
||||
|
||||
enum DebugInfoDebugTypeQualifier {
|
||||
DebugInfoConstType = 0,
|
||||
DebugInfoVolatileType = 1,
|
||||
DebugInfoRestrictType = 2,
|
||||
DebugInfoDebugTypeQualifierMax = 0x7ffffff
|
||||
};
|
||||
|
||||
enum DebugInfoDebugOperation {
|
||||
DebugInfoDeref = 0,
|
||||
DebugInfoPlus = 1,
|
||||
DebugInfoMinus = 2,
|
||||
DebugInfoPlusUconst = 3,
|
||||
DebugInfoBitPiece = 4,
|
||||
DebugInfoSwap = 5,
|
||||
DebugInfoXderef = 6,
|
||||
DebugInfoStackValue = 7,
|
||||
DebugInfoConstu = 8,
|
||||
DebugInfoDebugOperationMax = 0x7ffffff
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SPIRV_EXTINST_DebugInfo_H_
|
1
3rdparty/spirv-tools/include/generated/build-version.inc
vendored
Normal file
1
3rdparty/spirv-tools/include/generated/build-version.inc
vendored
Normal file
@ -0,0 +1 @@
|
||||
"v2018.3-dev", "SPIRV-Tools v2018.3-dev v2018.2-56-g3020104"
|
410
3rdparty/spirv-tools/include/generated/core.insts-unified1.inc
vendored
Normal file
410
3rdparty/spirv-tools/include/generated/core.insts-unified1.inc
vendored
Normal file
@ -0,0 +1,410 @@
|
||||
static const SpvCapability pygen_variable_caps_Addresses[] = {SpvCapabilityAddresses};
|
||||
static const SpvCapability pygen_variable_caps_AddressesVariablePointersVariablePointersStorageBuffer[] = {SpvCapabilityAddresses, SpvCapabilityVariablePointers, SpvCapabilityVariablePointersStorageBuffer};
|
||||
static const SpvCapability pygen_variable_caps_DerivativeControl[] = {SpvCapabilityDerivativeControl};
|
||||
static const SpvCapability pygen_variable_caps_DeviceEnqueue[] = {SpvCapabilityDeviceEnqueue};
|
||||
static const SpvCapability pygen_variable_caps_FragmentMaskAMD[] = {SpvCapabilityFragmentMaskAMD};
|
||||
static const SpvCapability pygen_variable_caps_Geometry[] = {SpvCapabilityGeometry};
|
||||
static const SpvCapability pygen_variable_caps_GeometryStreams[] = {SpvCapabilityGeometryStreams};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniform[] = {SpvCapabilityGroupNonUniform};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered[] = {SpvCapabilityGroupNonUniformArithmetic, SpvCapabilityGroupNonUniformClustered};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformBallot[] = {SpvCapabilityGroupNonUniformBallot};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformPartitionedNV[] = {SpvCapabilityGroupNonUniformPartitionedNV};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformQuad[] = {SpvCapabilityGroupNonUniformQuad};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformShuffle[] = {SpvCapabilityGroupNonUniformShuffle};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformShuffleRelative[] = {SpvCapabilityGroupNonUniformShuffleRelative};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformVote[] = {SpvCapabilityGroupNonUniformVote};
|
||||
static const SpvCapability pygen_variable_caps_Groups[] = {SpvCapabilityGroups};
|
||||
static const SpvCapability pygen_variable_caps_ImageQuery[] = {SpvCapabilityImageQuery};
|
||||
static const SpvCapability pygen_variable_caps_Kernel[] = {SpvCapabilityKernel};
|
||||
static const SpvCapability pygen_variable_caps_KernelImageQuery[] = {SpvCapabilityKernel, SpvCapabilityImageQuery};
|
||||
static const SpvCapability pygen_variable_caps_LiteralSampler[] = {SpvCapabilityLiteralSampler};
|
||||
static const SpvCapability pygen_variable_caps_Matrix[] = {SpvCapabilityMatrix};
|
||||
static const SpvCapability pygen_variable_caps_NamedBarrier[] = {SpvCapabilityNamedBarrier};
|
||||
static const SpvCapability pygen_variable_caps_PipeStorage[] = {SpvCapabilityPipeStorage};
|
||||
static const SpvCapability pygen_variable_caps_Pipes[] = {SpvCapabilityPipes};
|
||||
static const SpvCapability pygen_variable_caps_Shader[] = {SpvCapabilityShader};
|
||||
static const SpvCapability pygen_variable_caps_SparseResidency[] = {SpvCapabilitySparseResidency};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupBallotKHR[] = {SpvCapabilitySubgroupBallotKHR};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupBufferBlockIOINTEL[] = {SpvCapabilitySubgroupBufferBlockIOINTEL};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupDispatch[] = {SpvCapabilitySubgroupDispatch};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupImageBlockIOINTEL[] = {SpvCapabilitySubgroupImageBlockIOINTEL};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupShuffleINTEL[] = {SpvCapabilitySubgroupShuffleINTEL};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupVoteKHR[] = {SpvCapabilitySubgroupVoteKHR};
|
||||
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_AMD_shader_ballot[] = {libspirv::Extension::kSPV_AMD_shader_ballot};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_AMD_shader_fragment_mask[] = {libspirv::Extension::kSPV_AMD_shader_fragment_mask};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_GOOGLE_decorate_string[] = {libspirv::Extension::kSPV_GOOGLE_decorate_string};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1[] = {libspirv::Extension::kSPV_GOOGLE_hlsl_functionality1};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {libspirv::Extension::kSPV_KHR_shader_ballot};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_subgroup_vote[] = {libspirv::Extension::kSPV_KHR_subgroup_vote};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_NV_shader_subgroup_partitioned[] = {libspirv::Extension::kSPV_NV_shader_subgroup_partitioned};
|
||||
|
||||
static const spv_opcode_desc_t kOpcodeTableEntries[] = {
|
||||
{"Nop", SpvOpNop, 0, nullptr, 0, {}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Undef", SpvOpUndef, 0, nullptr, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SourceContinued", SpvOpSourceContinued, 0, nullptr, 1, {SPV_OPERAND_TYPE_LITERAL_STRING}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Source", SpvOpSource, 0, nullptr, 4, {SPV_OPERAND_TYPE_SOURCE_LANGUAGE, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SourceExtension", SpvOpSourceExtension, 0, nullptr, 1, {SPV_OPERAND_TYPE_LITERAL_STRING}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Name", SpvOpName, 0, nullptr, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_STRING}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MemberName", SpvOpMemberName, 0, nullptr, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_STRING}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"String", SpvOpString, 0, nullptr, 2, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_STRING}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Line", SpvOpLine, 0, nullptr, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Extension", SpvOpExtension, 0, nullptr, 1, {SPV_OPERAND_TYPE_LITERAL_STRING}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ExtInstImport", SpvOpExtInstImport, 0, nullptr, 2, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_STRING}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ExtInst", SpvOpExtInst, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MemoryModel", SpvOpMemoryModel, 0, nullptr, 2, {SPV_OPERAND_TYPE_ADDRESSING_MODEL, SPV_OPERAND_TYPE_MEMORY_MODEL}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"EntryPoint", SpvOpEntryPoint, 0, nullptr, 4, {SPV_OPERAND_TYPE_EXECUTION_MODEL, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_VARIABLE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ExecutionMode", SpvOpExecutionMode, 0, nullptr, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_EXECUTION_MODE}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Capability", SpvOpCapability, 0, nullptr, 1, {SPV_OPERAND_TYPE_CAPABILITY}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeVoid", SpvOpTypeVoid, 0, nullptr, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeBool", SpvOpTypeBool, 0, nullptr, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeInt", SpvOpTypeInt, 0, nullptr, 3, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeFloat", SpvOpTypeFloat, 0, nullptr, 2, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeVector", SpvOpTypeVector, 0, nullptr, 3, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeMatrix", SpvOpTypeMatrix, 1, pygen_variable_caps_Matrix, 3, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeImage", SpvOpTypeImage, 0, nullptr, 9, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DIMENSIONALITY, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT, SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeSampler", SpvOpTypeSampler, 0, nullptr, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeSampledImage", SpvOpTypeSampledImage, 0, nullptr, 2, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeArray", SpvOpTypeArray, 0, nullptr, 3, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeRuntimeArray", SpvOpTypeRuntimeArray, 1, pygen_variable_caps_Shader, 2, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeStruct", SpvOpTypeStruct, 0, nullptr, 2, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeOpaque", SpvOpTypeOpaque, 1, pygen_variable_caps_Kernel, 2, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_STRING}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypePointer", SpvOpTypePointer, 0, nullptr, 3, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_STORAGE_CLASS, SPV_OPERAND_TYPE_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeFunction", SpvOpTypeFunction, 0, nullptr, 3, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeEvent", SpvOpTypeEvent, 1, pygen_variable_caps_Kernel, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeDeviceEvent", SpvOpTypeDeviceEvent, 1, pygen_variable_caps_DeviceEnqueue, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeReserveId", SpvOpTypeReserveId, 1, pygen_variable_caps_Pipes, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeQueue", SpvOpTypeQueue, 1, pygen_variable_caps_DeviceEnqueue, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypePipe", SpvOpTypePipe, 1, pygen_variable_caps_Pipes, 2, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ACCESS_QUALIFIER}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TypeForwardPointer", SpvOpTypeForwardPointer, 1, pygen_variable_caps_Addresses, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_STORAGE_CLASS}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConstantTrue", SpvOpConstantTrue, 0, nullptr, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConstantFalse", SpvOpConstantFalse, 0, nullptr, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Constant", SpvOpConstant, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConstantComposite", SpvOpConstantComposite, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConstantSampler", SpvOpConstantSampler, 1, pygen_variable_caps_LiteralSampler, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConstantNull", SpvOpConstantNull, 0, nullptr, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SpecConstantTrue", SpvOpSpecConstantTrue, 0, nullptr, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SpecConstantFalse", SpvOpSpecConstantFalse, 0, nullptr, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SpecConstant", SpvOpSpecConstant, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SpecConstantComposite", SpvOpSpecConstantComposite, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SpecConstantOp", SpvOpSpecConstantOp, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Function", SpvOpFunction, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_FUNCTION_CONTROL, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FunctionParameter", SpvOpFunctionParameter, 0, nullptr, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FunctionEnd", SpvOpFunctionEnd, 0, nullptr, 0, {}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FunctionCall", SpvOpFunctionCall, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Variable", SpvOpVariable, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_STORAGE_CLASS, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageTexelPointer", SpvOpImageTexelPointer, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Load", SpvOpLoad, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Store", SpvOpStore, 0, nullptr, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CopyMemory", SpvOpCopyMemory, 0, nullptr, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CopyMemorySized", SpvOpCopyMemorySized, 1, pygen_variable_caps_Addresses, 4, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AccessChain", SpvOpAccessChain, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InBoundsAccessChain", SpvOpInBoundsAccessChain, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PtrAccessChain", SpvOpPtrAccessChain, 3, pygen_variable_caps_AddressesVariablePointersVariablePointersStorageBuffer, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ArrayLength", SpvOpArrayLength, 1, pygen_variable_caps_Shader, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GenericPtrMemSemantics", SpvOpGenericPtrMemSemantics, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InBoundsPtrAccessChain", SpvOpInBoundsPtrAccessChain, 1, pygen_variable_caps_Addresses, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Decorate", SpvOpDecorate, 0, nullptr, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DECORATION}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MemberDecorate", SpvOpMemberDecorate, 0, nullptr, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_DECORATION}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DecorationGroup", SpvOpDecorationGroup, 0, nullptr, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupDecorate", SpvOpGroupDecorate, 0, nullptr, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupMemberDecorate", SpvOpGroupMemberDecorate, 0, nullptr, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"VectorExtractDynamic", SpvOpVectorExtractDynamic, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"VectorInsertDynamic", SpvOpVectorInsertDynamic, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"VectorShuffle", SpvOpVectorShuffle, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CompositeConstruct", SpvOpCompositeConstruct, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CompositeExtract", SpvOpCompositeExtract, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CompositeInsert", SpvOpCompositeInsert, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CopyObject", SpvOpCopyObject, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Transpose", SpvOpTranspose, 1, pygen_variable_caps_Matrix, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SampledImage", SpvOpSampledImage, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSampleImplicitLod", SpvOpImageSampleImplicitLod, 1, pygen_variable_caps_Shader, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSampleExplicitLod", SpvOpImageSampleExplicitLod, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSampleDrefImplicitLod", SpvOpImageSampleDrefImplicitLod, 1, pygen_variable_caps_Shader, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSampleDrefExplicitLod", SpvOpImageSampleDrefExplicitLod, 1, pygen_variable_caps_Shader, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSampleProjImplicitLod", SpvOpImageSampleProjImplicitLod, 1, pygen_variable_caps_Shader, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSampleProjExplicitLod", SpvOpImageSampleProjExplicitLod, 1, pygen_variable_caps_Shader, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSampleProjDrefImplicitLod", SpvOpImageSampleProjDrefImplicitLod, 1, pygen_variable_caps_Shader, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSampleProjDrefExplicitLod", SpvOpImageSampleProjDrefExplicitLod, 1, pygen_variable_caps_Shader, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageFetch", SpvOpImageFetch, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageGather", SpvOpImageGather, 1, pygen_variable_caps_Shader, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageDrefGather", SpvOpImageDrefGather, 1, pygen_variable_caps_Shader, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageRead", SpvOpImageRead, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageWrite", SpvOpImageWrite, 0, nullptr, 4, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Image", SpvOpImage, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageQueryFormat", SpvOpImageQueryFormat, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageQueryOrder", SpvOpImageQueryOrder, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageQuerySizeLod", SpvOpImageQuerySizeLod, 2, pygen_variable_caps_KernelImageQuery, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageQuerySize", SpvOpImageQuerySize, 2, pygen_variable_caps_KernelImageQuery, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageQueryLod", SpvOpImageQueryLod, 1, pygen_variable_caps_ImageQuery, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageQueryLevels", SpvOpImageQueryLevels, 2, pygen_variable_caps_KernelImageQuery, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageQuerySamples", SpvOpImageQuerySamples, 2, pygen_variable_caps_KernelImageQuery, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConvertFToU", SpvOpConvertFToU, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConvertFToS", SpvOpConvertFToS, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConvertSToF", SpvOpConvertSToF, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConvertUToF", SpvOpConvertUToF, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UConvert", SpvOpUConvert, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SConvert", SpvOpSConvert, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FConvert", SpvOpFConvert, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"QuantizeToF16", SpvOpQuantizeToF16, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConvertPtrToU", SpvOpConvertPtrToU, 1, pygen_variable_caps_Addresses, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SatConvertSToU", SpvOpSatConvertSToU, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SatConvertUToS", SpvOpSatConvertUToS, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConvertUToPtr", SpvOpConvertUToPtr, 1, pygen_variable_caps_Addresses, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PtrCastToGeneric", SpvOpPtrCastToGeneric, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GenericCastToPtr", SpvOpGenericCastToPtr, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GenericCastToPtrExplicit", SpvOpGenericCastToPtrExplicit, 1, pygen_variable_caps_Kernel, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_STORAGE_CLASS}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Bitcast", SpvOpBitcast, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SNegate", SpvOpSNegate, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FNegate", SpvOpFNegate, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"IAdd", SpvOpIAdd, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FAdd", SpvOpFAdd, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ISub", SpvOpISub, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FSub", SpvOpFSub, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"IMul", SpvOpIMul, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FMul", SpvOpFMul, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UDiv", SpvOpUDiv, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SDiv", SpvOpSDiv, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FDiv", SpvOpFDiv, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UMod", SpvOpUMod, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SRem", SpvOpSRem, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SMod", SpvOpSMod, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FRem", SpvOpFRem, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FMod", SpvOpFMod, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"VectorTimesScalar", SpvOpVectorTimesScalar, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MatrixTimesScalar", SpvOpMatrixTimesScalar, 1, pygen_variable_caps_Matrix, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"VectorTimesMatrix", SpvOpVectorTimesMatrix, 1, pygen_variable_caps_Matrix, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MatrixTimesVector", SpvOpMatrixTimesVector, 1, pygen_variable_caps_Matrix, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MatrixTimesMatrix", SpvOpMatrixTimesMatrix, 1, pygen_variable_caps_Matrix, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"OuterProduct", SpvOpOuterProduct, 1, pygen_variable_caps_Matrix, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Dot", SpvOpDot, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"IAddCarry", SpvOpIAddCarry, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ISubBorrow", SpvOpISubBorrow, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UMulExtended", SpvOpUMulExtended, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SMulExtended", SpvOpSMulExtended, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Any", SpvOpAny, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"All", SpvOpAll, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"IsNan", SpvOpIsNan, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"IsInf", SpvOpIsInf, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"IsFinite", SpvOpIsFinite, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"IsNormal", SpvOpIsNormal, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SignBitSet", SpvOpSignBitSet, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LessOrGreater", SpvOpLessOrGreater, 1, pygen_variable_caps_Kernel, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Ordered", SpvOpOrdered, 1, pygen_variable_caps_Kernel, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Unordered", SpvOpUnordered, 1, pygen_variable_caps_Kernel, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LogicalEqual", SpvOpLogicalEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LogicalNotEqual", SpvOpLogicalNotEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LogicalOr", SpvOpLogicalOr, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LogicalAnd", SpvOpLogicalAnd, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LogicalNot", SpvOpLogicalNot, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Select", SpvOpSelect, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"IEqual", SpvOpIEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"INotEqual", SpvOpINotEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UGreaterThan", SpvOpUGreaterThan, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SGreaterThan", SpvOpSGreaterThan, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UGreaterThanEqual", SpvOpUGreaterThanEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SGreaterThanEqual", SpvOpSGreaterThanEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ULessThan", SpvOpULessThan, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SLessThan", SpvOpSLessThan, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ULessThanEqual", SpvOpULessThanEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SLessThanEqual", SpvOpSLessThanEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FOrdEqual", SpvOpFOrdEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FUnordEqual", SpvOpFUnordEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FOrdNotEqual", SpvOpFOrdNotEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FUnordNotEqual", SpvOpFUnordNotEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FOrdLessThan", SpvOpFOrdLessThan, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FUnordLessThan", SpvOpFUnordLessThan, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FOrdGreaterThan", SpvOpFOrdGreaterThan, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FUnordGreaterThan", SpvOpFUnordGreaterThan, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FOrdLessThanEqual", SpvOpFOrdLessThanEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FUnordLessThanEqual", SpvOpFUnordLessThanEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FOrdGreaterThanEqual", SpvOpFOrdGreaterThanEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FUnordGreaterThanEqual", SpvOpFUnordGreaterThanEqual, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ShiftRightLogical", SpvOpShiftRightLogical, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ShiftRightArithmetic", SpvOpShiftRightArithmetic, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ShiftLeftLogical", SpvOpShiftLeftLogical, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BitwiseOr", SpvOpBitwiseOr, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BitwiseXor", SpvOpBitwiseXor, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BitwiseAnd", SpvOpBitwiseAnd, 0, nullptr, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Not", SpvOpNot, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BitFieldInsert", SpvOpBitFieldInsert, 1, pygen_variable_caps_Shader, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BitFieldSExtract", SpvOpBitFieldSExtract, 1, pygen_variable_caps_Shader, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BitFieldUExtract", SpvOpBitFieldUExtract, 1, pygen_variable_caps_Shader, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BitReverse", SpvOpBitReverse, 1, pygen_variable_caps_Shader, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BitCount", SpvOpBitCount, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DPdx", SpvOpDPdx, 1, pygen_variable_caps_Shader, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DPdy", SpvOpDPdy, 1, pygen_variable_caps_Shader, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Fwidth", SpvOpFwidth, 1, pygen_variable_caps_Shader, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DPdxFine", SpvOpDPdxFine, 1, pygen_variable_caps_DerivativeControl, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DPdyFine", SpvOpDPdyFine, 1, pygen_variable_caps_DerivativeControl, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FwidthFine", SpvOpFwidthFine, 1, pygen_variable_caps_DerivativeControl, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DPdxCoarse", SpvOpDPdxCoarse, 1, pygen_variable_caps_DerivativeControl, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DPdyCoarse", SpvOpDPdyCoarse, 1, pygen_variable_caps_DerivativeControl, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FwidthCoarse", SpvOpFwidthCoarse, 1, pygen_variable_caps_DerivativeControl, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"EmitVertex", SpvOpEmitVertex, 1, pygen_variable_caps_Geometry, 0, {}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"EndPrimitive", SpvOpEndPrimitive, 1, pygen_variable_caps_Geometry, 0, {}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"EmitStreamVertex", SpvOpEmitStreamVertex, 1, pygen_variable_caps_GeometryStreams, 1, {SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"EndStreamPrimitive", SpvOpEndStreamPrimitive, 1, pygen_variable_caps_GeometryStreams, 1, {SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ControlBarrier", SpvOpControlBarrier, 0, nullptr, 3, {SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MemoryBarrier", SpvOpMemoryBarrier, 0, nullptr, 2, {SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicLoad", SpvOpAtomicLoad, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicStore", SpvOpAtomicStore, 0, nullptr, 4, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicExchange", SpvOpAtomicExchange, 0, nullptr, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicCompareExchange", SpvOpAtomicCompareExchange, 0, nullptr, 8, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicCompareExchangeWeak", SpvOpAtomicCompareExchangeWeak, 1, pygen_variable_caps_Kernel, 8, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicIIncrement", SpvOpAtomicIIncrement, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicIDecrement", SpvOpAtomicIDecrement, 0, nullptr, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicIAdd", SpvOpAtomicIAdd, 0, nullptr, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicISub", SpvOpAtomicISub, 0, nullptr, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicSMin", SpvOpAtomicSMin, 0, nullptr, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicUMin", SpvOpAtomicUMin, 0, nullptr, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicSMax", SpvOpAtomicSMax, 0, nullptr, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicUMax", SpvOpAtomicUMax, 0, nullptr, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicAnd", SpvOpAtomicAnd, 0, nullptr, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicOr", SpvOpAtomicOr, 0, nullptr, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicXor", SpvOpAtomicXor, 0, nullptr, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Phi", SpvOpPhi, 0, nullptr, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LoopMerge", SpvOpLoopMerge, 0, nullptr, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LOOP_CONTROL}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SelectionMerge", SpvOpSelectionMerge, 0, nullptr, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SELECTION_CONTROL}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Label", SpvOpLabel, 0, nullptr, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Branch", SpvOpBranch, 0, nullptr, 1, {SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BranchConditional", SpvOpBranchConditional, 0, nullptr, 4, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Switch", SpvOpSwitch, 0, nullptr, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Kill", SpvOpKill, 1, pygen_variable_caps_Shader, 0, {}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Return", SpvOpReturn, 0, nullptr, 0, {}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ReturnValue", SpvOpReturnValue, 0, nullptr, 1, {SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Unreachable", SpvOpUnreachable, 0, nullptr, 0, {}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LifetimeStart", SpvOpLifetimeStart, 1, pygen_variable_caps_Kernel, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LifetimeStop", SpvOpLifetimeStop, 1, pygen_variable_caps_Kernel, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupAsyncCopy", SpvOpGroupAsyncCopy, 1, pygen_variable_caps_Kernel, 8, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupWaitEvents", SpvOpGroupWaitEvents, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupAll", SpvOpGroupAll, 1, pygen_variable_caps_Groups, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupAny", SpvOpGroupAny, 1, pygen_variable_caps_Groups, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupBroadcast", SpvOpGroupBroadcast, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupIAdd", SpvOpGroupIAdd, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupFAdd", SpvOpGroupFAdd, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupFMin", SpvOpGroupFMin, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupUMin", SpvOpGroupUMin, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupSMin", SpvOpGroupSMin, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupFMax", SpvOpGroupFMax, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupUMax", SpvOpGroupUMax, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupSMax", SpvOpGroupSMax, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ReadPipe", SpvOpReadPipe, 1, pygen_variable_caps_Pipes, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"WritePipe", SpvOpWritePipe, 1, pygen_variable_caps_Pipes, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ReservedReadPipe", SpvOpReservedReadPipe, 1, pygen_variable_caps_Pipes, 8, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ReservedWritePipe", SpvOpReservedWritePipe, 1, pygen_variable_caps_Pipes, 8, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ReserveReadPipePackets", SpvOpReserveReadPipePackets, 1, pygen_variable_caps_Pipes, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ReserveWritePipePackets", SpvOpReserveWritePipePackets, 1, pygen_variable_caps_Pipes, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CommitReadPipe", SpvOpCommitReadPipe, 1, pygen_variable_caps_Pipes, 4, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CommitWritePipe", SpvOpCommitWritePipe, 1, pygen_variable_caps_Pipes, 4, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"IsValidReserveId", SpvOpIsValidReserveId, 1, pygen_variable_caps_Pipes, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GetNumPipePackets", SpvOpGetNumPipePackets, 1, pygen_variable_caps_Pipes, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GetMaxPipePackets", SpvOpGetMaxPipePackets, 1, pygen_variable_caps_Pipes, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupReserveReadPipePackets", SpvOpGroupReserveReadPipePackets, 1, pygen_variable_caps_Pipes, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupReserveWritePipePackets", SpvOpGroupReserveWritePipePackets, 1, pygen_variable_caps_Pipes, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupCommitReadPipe", SpvOpGroupCommitReadPipe, 1, pygen_variable_caps_Pipes, 5, {SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GroupCommitWritePipe", SpvOpGroupCommitWritePipe, 1, pygen_variable_caps_Pipes, 5, {SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"EnqueueMarker", SpvOpEnqueueMarker, 1, pygen_variable_caps_DeviceEnqueue, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"EnqueueKernel", SpvOpEnqueueKernel, 1, pygen_variable_caps_DeviceEnqueue, 13, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GetKernelNDrangeSubGroupCount", SpvOpGetKernelNDrangeSubGroupCount, 1, pygen_variable_caps_DeviceEnqueue, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GetKernelNDrangeMaxSubGroupSize", SpvOpGetKernelNDrangeMaxSubGroupSize, 1, pygen_variable_caps_DeviceEnqueue, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GetKernelWorkGroupSize", SpvOpGetKernelWorkGroupSize, 1, pygen_variable_caps_DeviceEnqueue, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GetKernelPreferredWorkGroupSizeMultiple", SpvOpGetKernelPreferredWorkGroupSizeMultiple, 1, pygen_variable_caps_DeviceEnqueue, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RetainEvent", SpvOpRetainEvent, 1, pygen_variable_caps_DeviceEnqueue, 1, {SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ReleaseEvent", SpvOpReleaseEvent, 1, pygen_variable_caps_DeviceEnqueue, 1, {SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CreateUserEvent", SpvOpCreateUserEvent, 1, pygen_variable_caps_DeviceEnqueue, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"IsValidEvent", SpvOpIsValidEvent, 1, pygen_variable_caps_DeviceEnqueue, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SetUserEventStatus", SpvOpSetUserEventStatus, 1, pygen_variable_caps_DeviceEnqueue, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CaptureEventProfilingInfo", SpvOpCaptureEventProfilingInfo, 1, pygen_variable_caps_DeviceEnqueue, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GetDefaultQueue", SpvOpGetDefaultQueue, 1, pygen_variable_caps_DeviceEnqueue, 2, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BuildNDRange", SpvOpBuildNDRange, 1, pygen_variable_caps_DeviceEnqueue, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSparseSampleImplicitLod", SpvOpImageSparseSampleImplicitLod, 1, pygen_variable_caps_SparseResidency, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSparseSampleExplicitLod", SpvOpImageSparseSampleExplicitLod, 1, pygen_variable_caps_SparseResidency, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSparseSampleDrefImplicitLod", SpvOpImageSparseSampleDrefImplicitLod, 1, pygen_variable_caps_SparseResidency, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSparseSampleDrefExplicitLod", SpvOpImageSparseSampleDrefExplicitLod, 1, pygen_variable_caps_SparseResidency, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSparseSampleProjImplicitLod", SpvOpImageSparseSampleProjImplicitLod, 1, pygen_variable_caps_SparseResidency, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, 0xffffffffu},
|
||||
{"ImageSparseSampleProjExplicitLod", SpvOpImageSparseSampleProjExplicitLod, 1, pygen_variable_caps_SparseResidency, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_IMAGE}, 1, 1, 0, nullptr, 0xffffffffu},
|
||||
{"ImageSparseSampleProjDrefImplicitLod", SpvOpImageSparseSampleProjDrefImplicitLod, 1, pygen_variable_caps_SparseResidency, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, 0xffffffffu},
|
||||
{"ImageSparseSampleProjDrefExplicitLod", SpvOpImageSparseSampleProjDrefExplicitLod, 1, pygen_variable_caps_SparseResidency, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_IMAGE}, 1, 1, 0, nullptr, 0xffffffffu},
|
||||
{"ImageSparseFetch", SpvOpImageSparseFetch, 1, pygen_variable_caps_SparseResidency, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSparseGather", SpvOpImageSparseGather, 1, pygen_variable_caps_SparseResidency, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSparseDrefGather", SpvOpImageSparseDrefGather, 1, pygen_variable_caps_SparseResidency, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSparseTexelsResident", SpvOpImageSparseTexelsResident, 1, pygen_variable_caps_SparseResidency, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NoLine", SpvOpNoLine, 0, nullptr, 0, {}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicFlagTestAndSet", SpvOpAtomicFlagTestAndSet, 1, pygen_variable_caps_Kernel, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicFlagClear", SpvOpAtomicFlagClear, 1, pygen_variable_caps_Kernel, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageSparseRead", SpvOpImageSparseRead, 1, pygen_variable_caps_SparseResidency, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_IMAGE}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SizeOf", SpvOpSizeOf, 1, pygen_variable_caps_Addresses, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"TypePipeStorage", SpvOpTypePipeStorage, 1, pygen_variable_caps_PipeStorage, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"ConstantPipeStorage", SpvOpConstantPipeStorage, 1, pygen_variable_caps_PipeStorage, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"CreatePipeFromPipeStorage", SpvOpCreatePipeFromPipeStorage, 1, pygen_variable_caps_PipeStorage, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"GetKernelLocalSizeForSubgroupCount", SpvOpGetKernelLocalSizeForSubgroupCount, 1, pygen_variable_caps_SubgroupDispatch, 7, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"GetKernelMaxNumSubgroups", SpvOpGetKernelMaxNumSubgroups, 1, pygen_variable_caps_SubgroupDispatch, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"TypeNamedBarrier", SpvOpTypeNamedBarrier, 1, pygen_variable_caps_NamedBarrier, 1, {SPV_OPERAND_TYPE_RESULT_ID}, 1, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"NamedBarrierInitialize", SpvOpNamedBarrierInitialize, 1, pygen_variable_caps_NamedBarrier, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"MemoryNamedBarrier", SpvOpMemoryNamedBarrier, 1, pygen_variable_caps_NamedBarrier, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"ModuleProcessed", SpvOpModuleProcessed, 0, nullptr, 1, {SPV_OPERAND_TYPE_LITERAL_STRING}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"ExecutionModeId", SpvOpExecutionModeId, 0, nullptr, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_EXECUTION_MODE}, 0, 0, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,2)},
|
||||
{"DecorateId", SpvOpDecorateId, 0, nullptr, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DECORATION}, 0, 0, 1, pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1, SPV_SPIRV_VERSION_WORD(1,2)},
|
||||
{"GroupNonUniformElect", SpvOpGroupNonUniformElect, 1, pygen_variable_caps_GroupNonUniform, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformAll", SpvOpGroupNonUniformAll, 1, pygen_variable_caps_GroupNonUniformVote, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformAny", SpvOpGroupNonUniformAny, 1, pygen_variable_caps_GroupNonUniformVote, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformAllEqual", SpvOpGroupNonUniformAllEqual, 1, pygen_variable_caps_GroupNonUniformVote, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBroadcast", SpvOpGroupNonUniformBroadcast, 1, pygen_variable_caps_GroupNonUniformBallot, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBroadcastFirst", SpvOpGroupNonUniformBroadcastFirst, 1, pygen_variable_caps_GroupNonUniformBallot, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBallot", SpvOpGroupNonUniformBallot, 1, pygen_variable_caps_GroupNonUniformBallot, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformInverseBallot", SpvOpGroupNonUniformInverseBallot, 1, pygen_variable_caps_GroupNonUniformBallot, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBallotBitExtract", SpvOpGroupNonUniformBallotBitExtract, 1, pygen_variable_caps_GroupNonUniformBallot, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBallotBitCount", SpvOpGroupNonUniformBallotBitCount, 1, pygen_variable_caps_GroupNonUniformBallot, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBallotFindLSB", SpvOpGroupNonUniformBallotFindLSB, 1, pygen_variable_caps_GroupNonUniformBallot, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBallotFindMSB", SpvOpGroupNonUniformBallotFindMSB, 1, pygen_variable_caps_GroupNonUniformBallot, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformShuffle", SpvOpGroupNonUniformShuffle, 1, pygen_variable_caps_GroupNonUniformShuffle, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformShuffleXor", SpvOpGroupNonUniformShuffleXor, 1, pygen_variable_caps_GroupNonUniformShuffle, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformShuffleUp", SpvOpGroupNonUniformShuffleUp, 1, pygen_variable_caps_GroupNonUniformShuffleRelative, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformShuffleDown", SpvOpGroupNonUniformShuffleDown, 1, pygen_variable_caps_GroupNonUniformShuffleRelative, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformIAdd", SpvOpGroupNonUniformIAdd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFAdd", SpvOpGroupNonUniformFAdd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformIMul", SpvOpGroupNonUniformIMul, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFMul", SpvOpGroupNonUniformFMul, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformSMin", SpvOpGroupNonUniformSMin, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformUMin", SpvOpGroupNonUniformUMin, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFMin", SpvOpGroupNonUniformFMin, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformSMax", SpvOpGroupNonUniformSMax, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformUMax", SpvOpGroupNonUniformUMax, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformFMax", SpvOpGroupNonUniformFMax, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBitwiseAnd", SpvOpGroupNonUniformBitwiseAnd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBitwiseOr", SpvOpGroupNonUniformBitwiseOr, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBitwiseXor", SpvOpGroupNonUniformBitwiseXor, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformLogicalAnd", SpvOpGroupNonUniformLogicalAnd, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformLogicalOr", SpvOpGroupNonUniformLogicalOr, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformLogicalXor", SpvOpGroupNonUniformLogicalXor, 2, pygen_variable_caps_GroupNonUniformArithmeticGroupNonUniformClustered, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformQuadBroadcast", SpvOpGroupNonUniformQuadBroadcast, 1, pygen_variable_caps_GroupNonUniformQuad, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformQuadSwap", SpvOpGroupNonUniformQuadSwap, 1, pygen_variable_caps_GroupNonUniformQuad, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupBallotKHR", SpvOpSubgroupBallotKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_ballot, 0xffffffffu},
|
||||
{"SubgroupFirstInvocationKHR", SpvOpSubgroupFirstInvocationKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_ballot, 0xffffffffu},
|
||||
{"SubgroupAllKHR", SpvOpSubgroupAllKHR, 1, pygen_variable_caps_SubgroupVoteKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, 0xffffffffu},
|
||||
{"SubgroupAnyKHR", SpvOpSubgroupAnyKHR, 1, pygen_variable_caps_SubgroupVoteKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, 0xffffffffu},
|
||||
{"SubgroupAllEqualKHR", SpvOpSubgroupAllEqualKHR, 1, pygen_variable_caps_SubgroupVoteKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, 0xffffffffu},
|
||||
{"SubgroupReadInvocationKHR", SpvOpSubgroupReadInvocationKHR, 1, pygen_variable_caps_SubgroupBallotKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_ballot, 0xffffffffu},
|
||||
{"GroupIAddNonUniformAMD", SpvOpGroupIAddNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu},
|
||||
{"GroupFAddNonUniformAMD", SpvOpGroupFAddNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu},
|
||||
{"GroupFMinNonUniformAMD", SpvOpGroupFMinNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu},
|
||||
{"GroupUMinNonUniformAMD", SpvOpGroupUMinNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu},
|
||||
{"GroupSMinNonUniformAMD", SpvOpGroupSMinNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu},
|
||||
{"GroupFMaxNonUniformAMD", SpvOpGroupFMaxNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu},
|
||||
{"GroupUMaxNonUniformAMD", SpvOpGroupUMaxNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu},
|
||||
{"GroupSMaxNonUniformAMD", SpvOpGroupSMaxNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu},
|
||||
{"FragmentMaskFetchAMD", SpvOpFragmentMaskFetchAMD, 1, pygen_variable_caps_FragmentMaskAMD, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, 0xffffffffu},
|
||||
{"FragmentFetchAMD", SpvOpFragmentFetchAMD, 1, pygen_variable_caps_FragmentMaskAMD, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, 0xffffffffu},
|
||||
{"GroupNonUniformPartitionNV", SpvOpGroupNonUniformPartitionNV, 1, pygen_variable_caps_GroupNonUniformPartitionedNV, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_NV_shader_subgroup_partitioned, 0xffffffffu},
|
||||
{"SubgroupShuffleINTEL", SpvOpSubgroupShuffleINTEL, 1, pygen_variable_caps_SubgroupShuffleINTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu},
|
||||
{"SubgroupShuffleDownINTEL", SpvOpSubgroupShuffleDownINTEL, 1, pygen_variable_caps_SubgroupShuffleINTEL, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu},
|
||||
{"SubgroupShuffleUpINTEL", SpvOpSubgroupShuffleUpINTEL, 1, pygen_variable_caps_SubgroupShuffleINTEL, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu},
|
||||
{"SubgroupShuffleXorINTEL", SpvOpSubgroupShuffleXorINTEL, 1, pygen_variable_caps_SubgroupShuffleINTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu},
|
||||
{"SubgroupBlockReadINTEL", SpvOpSubgroupBlockReadINTEL, 1, pygen_variable_caps_SubgroupBufferBlockIOINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu},
|
||||
{"SubgroupBlockWriteINTEL", SpvOpSubgroupBlockWriteINTEL, 1, pygen_variable_caps_SubgroupBufferBlockIOINTEL, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, 0xffffffffu},
|
||||
{"SubgroupImageBlockReadINTEL", SpvOpSubgroupImageBlockReadINTEL, 1, pygen_variable_caps_SubgroupImageBlockIOINTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu},
|
||||
{"SubgroupImageBlockWriteINTEL", SpvOpSubgroupImageBlockWriteINTEL, 1, pygen_variable_caps_SubgroupImageBlockIOINTEL, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, 0xffffffffu},
|
||||
{"DecorateStringGOOGLE", SpvOpDecorateStringGOOGLE, 0, nullptr, 2, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DECORATION}, 0, 0, 1, pygen_variable_exts_SPV_GOOGLE_decorate_string, 0xffffffffu},
|
||||
{"MemberDecorateStringGOOGLE", SpvOpMemberDecorateStringGOOGLE, 0, nullptr, 3, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_DECORATION}, 0, 0, 1, pygen_variable_exts_SPV_GOOGLE_decorate_string, 0xffffffffu}
|
||||
};
|
38
3rdparty/spirv-tools/include/generated/debuginfo.insts.inc
vendored
Normal file
38
3rdparty/spirv-tools/include/generated/debuginfo.insts.inc
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
|
||||
static const spv_ext_inst_desc_t debuginfo_entries[] = {
|
||||
{"DebugInfoNone", 0, 0, nullptr, {SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugCompilationUnit", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeBasic", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypePointer", 3, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_STORAGE_CLASS, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeQualifier", 4, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeArray", 5, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeVector", 6, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypedef", 7, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeFunction", 8, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeEnum", 9, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeComposite", 10, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeMember", 11, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeInheritance", 12, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypePtrToMember", 13, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeTemplate", 14, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeTemplateParameter", 15, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeTemplateTemplateParameter", 16, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugTypeTemplateParameterPack", 17, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugGlobalVariable", 18, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugFunctionDeclaration", 19, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugFunction", 20, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugLexicalBlock", 21, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugLexicalBlockDiscriminator", 22, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugScope", 23, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugNoScope", 24, 0, nullptr, {SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugInlinedAt", 25, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugLocalVariable", 26, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugInlinedVariable", 27, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugDeclare", 28, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugValue", 29, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugOperation", 30, 0, nullptr, {SPV_OPERAND_TYPE_DEBUG_OPERATION, SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugExpression", 31, 0, nullptr, {SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugMacroDef", 32, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_OPTIONAL_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DebugMacroUndef", 33, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
317
3rdparty/spirv-tools/include/generated/enum_string_mapping.inc
vendored
Normal file
317
3rdparty/spirv-tools/include/generated/enum_string_mapping.inc
vendored
Normal file
@ -0,0 +1,317 @@
|
||||
const char* ExtensionToString(Extension extension) {
|
||||
switch (extension) {
|
||||
case Extension::kSPV_AMD_gcn_shader:
|
||||
return "SPV_AMD_gcn_shader";
|
||||
case Extension::kSPV_AMD_gpu_shader_half_float:
|
||||
return "SPV_AMD_gpu_shader_half_float";
|
||||
case Extension::kSPV_AMD_gpu_shader_half_float_fetch:
|
||||
return "SPV_AMD_gpu_shader_half_float_fetch";
|
||||
case Extension::kSPV_AMD_gpu_shader_int16:
|
||||
return "SPV_AMD_gpu_shader_int16";
|
||||
case Extension::kSPV_AMD_shader_ballot:
|
||||
return "SPV_AMD_shader_ballot";
|
||||
case Extension::kSPV_AMD_shader_explicit_vertex_parameter:
|
||||
return "SPV_AMD_shader_explicit_vertex_parameter";
|
||||
case Extension::kSPV_AMD_shader_fragment_mask:
|
||||
return "SPV_AMD_shader_fragment_mask";
|
||||
case Extension::kSPV_AMD_shader_image_load_store_lod:
|
||||
return "SPV_AMD_shader_image_load_store_lod";
|
||||
case Extension::kSPV_AMD_shader_trinary_minmax:
|
||||
return "SPV_AMD_shader_trinary_minmax";
|
||||
case Extension::kSPV_AMD_texture_gather_bias_lod:
|
||||
return "SPV_AMD_texture_gather_bias_lod";
|
||||
case Extension::kSPV_EXT_descriptor_indexing:
|
||||
return "SPV_EXT_descriptor_indexing";
|
||||
case Extension::kSPV_EXT_fragment_fully_covered:
|
||||
return "SPV_EXT_fragment_fully_covered";
|
||||
case Extension::kSPV_EXT_shader_stencil_export:
|
||||
return "SPV_EXT_shader_stencil_export";
|
||||
case Extension::kSPV_EXT_shader_viewport_index_layer:
|
||||
return "SPV_EXT_shader_viewport_index_layer";
|
||||
case Extension::kSPV_GOOGLE_decorate_string:
|
||||
return "SPV_GOOGLE_decorate_string";
|
||||
case Extension::kSPV_GOOGLE_hlsl_functionality1:
|
||||
return "SPV_GOOGLE_hlsl_functionality1";
|
||||
case Extension::kSPV_INTEL_subgroups:
|
||||
return "SPV_INTEL_subgroups";
|
||||
case Extension::kSPV_KHR_16bit_storage:
|
||||
return "SPV_KHR_16bit_storage";
|
||||
case Extension::kSPV_KHR_device_group:
|
||||
return "SPV_KHR_device_group";
|
||||
case Extension::kSPV_KHR_multiview:
|
||||
return "SPV_KHR_multiview";
|
||||
case Extension::kSPV_KHR_post_depth_coverage:
|
||||
return "SPV_KHR_post_depth_coverage";
|
||||
case Extension::kSPV_KHR_shader_atomic_counter_ops:
|
||||
return "SPV_KHR_shader_atomic_counter_ops";
|
||||
case Extension::kSPV_KHR_shader_ballot:
|
||||
return "SPV_KHR_shader_ballot";
|
||||
case Extension::kSPV_KHR_shader_draw_parameters:
|
||||
return "SPV_KHR_shader_draw_parameters";
|
||||
case Extension::kSPV_KHR_storage_buffer_storage_class:
|
||||
return "SPV_KHR_storage_buffer_storage_class";
|
||||
case Extension::kSPV_KHR_subgroup_vote:
|
||||
return "SPV_KHR_subgroup_vote";
|
||||
case Extension::kSPV_KHR_variable_pointers:
|
||||
return "SPV_KHR_variable_pointers";
|
||||
case Extension::kSPV_NVX_multiview_per_view_attributes:
|
||||
return "SPV_NVX_multiview_per_view_attributes";
|
||||
case Extension::kSPV_NV_geometry_shader_passthrough:
|
||||
return "SPV_NV_geometry_shader_passthrough";
|
||||
case Extension::kSPV_NV_sample_mask_override_coverage:
|
||||
return "SPV_NV_sample_mask_override_coverage";
|
||||
case Extension::kSPV_NV_shader_subgroup_partitioned:
|
||||
return "SPV_NV_shader_subgroup_partitioned";
|
||||
case Extension::kSPV_NV_stereo_view_rendering:
|
||||
return "SPV_NV_stereo_view_rendering";
|
||||
case Extension::kSPV_NV_viewport_array2:
|
||||
return "SPV_NV_viewport_array2";
|
||||
case Extension::kSPV_VALIDATOR_ignore_type_decl_unique:
|
||||
return "SPV_VALIDATOR_ignore_type_decl_unique";
|
||||
};
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
bool GetExtensionFromString(const char* str, Extension* extension) {
|
||||
static const char* known_ext_strs[] = { "SPV_AMD_gcn_shader", "SPV_AMD_gpu_shader_half_float", "SPV_AMD_gpu_shader_half_float_fetch", "SPV_AMD_gpu_shader_int16", "SPV_AMD_shader_ballot", "SPV_AMD_shader_explicit_vertex_parameter", "SPV_AMD_shader_fragment_mask", "SPV_AMD_shader_image_load_store_lod", "SPV_AMD_shader_trinary_minmax", "SPV_AMD_texture_gather_bias_lod", "SPV_EXT_descriptor_indexing", "SPV_EXT_fragment_fully_covered", "SPV_EXT_shader_stencil_export", "SPV_EXT_shader_viewport_index_layer", "SPV_GOOGLE_decorate_string", "SPV_GOOGLE_hlsl_functionality1", "SPV_INTEL_subgroups", "SPV_KHR_16bit_storage", "SPV_KHR_device_group", "SPV_KHR_multiview", "SPV_KHR_post_depth_coverage", "SPV_KHR_shader_atomic_counter_ops", "SPV_KHR_shader_ballot", "SPV_KHR_shader_draw_parameters", "SPV_KHR_storage_buffer_storage_class", "SPV_KHR_subgroup_vote", "SPV_KHR_variable_pointers", "SPV_NVX_multiview_per_view_attributes", "SPV_NV_geometry_shader_passthrough", "SPV_NV_sample_mask_override_coverage", "SPV_NV_shader_subgroup_partitioned", "SPV_NV_stereo_view_rendering", "SPV_NV_viewport_array2", "SPV_VALIDATOR_ignore_type_decl_unique" };
|
||||
static const Extension known_ext_ids[] = { Extension::kSPV_AMD_gcn_shader, Extension::kSPV_AMD_gpu_shader_half_float, Extension::kSPV_AMD_gpu_shader_half_float_fetch, Extension::kSPV_AMD_gpu_shader_int16, Extension::kSPV_AMD_shader_ballot, Extension::kSPV_AMD_shader_explicit_vertex_parameter, Extension::kSPV_AMD_shader_fragment_mask, Extension::kSPV_AMD_shader_image_load_store_lod, Extension::kSPV_AMD_shader_trinary_minmax, Extension::kSPV_AMD_texture_gather_bias_lod, Extension::kSPV_EXT_descriptor_indexing, Extension::kSPV_EXT_fragment_fully_covered, Extension::kSPV_EXT_shader_stencil_export, Extension::kSPV_EXT_shader_viewport_index_layer, Extension::kSPV_GOOGLE_decorate_string, Extension::kSPV_GOOGLE_hlsl_functionality1, Extension::kSPV_INTEL_subgroups, Extension::kSPV_KHR_16bit_storage, Extension::kSPV_KHR_device_group, Extension::kSPV_KHR_multiview, Extension::kSPV_KHR_post_depth_coverage, Extension::kSPV_KHR_shader_atomic_counter_ops, Extension::kSPV_KHR_shader_ballot, Extension::kSPV_KHR_shader_draw_parameters, Extension::kSPV_KHR_storage_buffer_storage_class, Extension::kSPV_KHR_subgroup_vote, Extension::kSPV_KHR_variable_pointers, Extension::kSPV_NVX_multiview_per_view_attributes, Extension::kSPV_NV_geometry_shader_passthrough, Extension::kSPV_NV_sample_mask_override_coverage, Extension::kSPV_NV_shader_subgroup_partitioned, Extension::kSPV_NV_stereo_view_rendering, Extension::kSPV_NV_viewport_array2, Extension::kSPV_VALIDATOR_ignore_type_decl_unique };
|
||||
const auto b = std::begin(known_ext_strs);
|
||||
const auto e = std::end(known_ext_strs);
|
||||
const auto found = std::equal_range(
|
||||
b, e, str, [](const char* str1, const char* str2) {
|
||||
return std::strcmp(str1, str2) < 0;
|
||||
});
|
||||
if (found.first == e || found.first == found.second) return false;
|
||||
|
||||
*extension = known_ext_ids[found.first - b];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
const char* CapabilityToString(SpvCapability capability) {
|
||||
switch (capability) {
|
||||
case SpvCapabilityMatrix:
|
||||
return "Matrix";
|
||||
case SpvCapabilityShader:
|
||||
return "Shader";
|
||||
case SpvCapabilityGeometry:
|
||||
return "Geometry";
|
||||
case SpvCapabilityTessellation:
|
||||
return "Tessellation";
|
||||
case SpvCapabilityAddresses:
|
||||
return "Addresses";
|
||||
case SpvCapabilityLinkage:
|
||||
return "Linkage";
|
||||
case SpvCapabilityKernel:
|
||||
return "Kernel";
|
||||
case SpvCapabilityVector16:
|
||||
return "Vector16";
|
||||
case SpvCapabilityFloat16Buffer:
|
||||
return "Float16Buffer";
|
||||
case SpvCapabilityFloat16:
|
||||
return "Float16";
|
||||
case SpvCapabilityFloat64:
|
||||
return "Float64";
|
||||
case SpvCapabilityInt64:
|
||||
return "Int64";
|
||||
case SpvCapabilityInt64Atomics:
|
||||
return "Int64Atomics";
|
||||
case SpvCapabilityImageBasic:
|
||||
return "ImageBasic";
|
||||
case SpvCapabilityImageReadWrite:
|
||||
return "ImageReadWrite";
|
||||
case SpvCapabilityImageMipmap:
|
||||
return "ImageMipmap";
|
||||
case SpvCapabilityPipes:
|
||||
return "Pipes";
|
||||
case SpvCapabilityGroups:
|
||||
return "Groups";
|
||||
case SpvCapabilityDeviceEnqueue:
|
||||
return "DeviceEnqueue";
|
||||
case SpvCapabilityLiteralSampler:
|
||||
return "LiteralSampler";
|
||||
case SpvCapabilityAtomicStorage:
|
||||
return "AtomicStorage";
|
||||
case SpvCapabilityInt16:
|
||||
return "Int16";
|
||||
case SpvCapabilityTessellationPointSize:
|
||||
return "TessellationPointSize";
|
||||
case SpvCapabilityGeometryPointSize:
|
||||
return "GeometryPointSize";
|
||||
case SpvCapabilityImageGatherExtended:
|
||||
return "ImageGatherExtended";
|
||||
case SpvCapabilityStorageImageMultisample:
|
||||
return "StorageImageMultisample";
|
||||
case SpvCapabilityUniformBufferArrayDynamicIndexing:
|
||||
return "UniformBufferArrayDynamicIndexing";
|
||||
case SpvCapabilitySampledImageArrayDynamicIndexing:
|
||||
return "SampledImageArrayDynamicIndexing";
|
||||
case SpvCapabilityStorageBufferArrayDynamicIndexing:
|
||||
return "StorageBufferArrayDynamicIndexing";
|
||||
case SpvCapabilityStorageImageArrayDynamicIndexing:
|
||||
return "StorageImageArrayDynamicIndexing";
|
||||
case SpvCapabilityClipDistance:
|
||||
return "ClipDistance";
|
||||
case SpvCapabilityCullDistance:
|
||||
return "CullDistance";
|
||||
case SpvCapabilityImageCubeArray:
|
||||
return "ImageCubeArray";
|
||||
case SpvCapabilitySampleRateShading:
|
||||
return "SampleRateShading";
|
||||
case SpvCapabilityImageRect:
|
||||
return "ImageRect";
|
||||
case SpvCapabilitySampledRect:
|
||||
return "SampledRect";
|
||||
case SpvCapabilityGenericPointer:
|
||||
return "GenericPointer";
|
||||
case SpvCapabilityInt8:
|
||||
return "Int8";
|
||||
case SpvCapabilityInputAttachment:
|
||||
return "InputAttachment";
|
||||
case SpvCapabilitySparseResidency:
|
||||
return "SparseResidency";
|
||||
case SpvCapabilityMinLod:
|
||||
return "MinLod";
|
||||
case SpvCapabilitySampled1D:
|
||||
return "Sampled1D";
|
||||
case SpvCapabilityImage1D:
|
||||
return "Image1D";
|
||||
case SpvCapabilitySampledCubeArray:
|
||||
return "SampledCubeArray";
|
||||
case SpvCapabilitySampledBuffer:
|
||||
return "SampledBuffer";
|
||||
case SpvCapabilityImageBuffer:
|
||||
return "ImageBuffer";
|
||||
case SpvCapabilityImageMSArray:
|
||||
return "ImageMSArray";
|
||||
case SpvCapabilityStorageImageExtendedFormats:
|
||||
return "StorageImageExtendedFormats";
|
||||
case SpvCapabilityImageQuery:
|
||||
return "ImageQuery";
|
||||
case SpvCapabilityDerivativeControl:
|
||||
return "DerivativeControl";
|
||||
case SpvCapabilityInterpolationFunction:
|
||||
return "InterpolationFunction";
|
||||
case SpvCapabilityTransformFeedback:
|
||||
return "TransformFeedback";
|
||||
case SpvCapabilityGeometryStreams:
|
||||
return "GeometryStreams";
|
||||
case SpvCapabilityStorageImageReadWithoutFormat:
|
||||
return "StorageImageReadWithoutFormat";
|
||||
case SpvCapabilityStorageImageWriteWithoutFormat:
|
||||
return "StorageImageWriteWithoutFormat";
|
||||
case SpvCapabilityMultiViewport:
|
||||
return "MultiViewport";
|
||||
case SpvCapabilitySubgroupDispatch:
|
||||
return "SubgroupDispatch";
|
||||
case SpvCapabilityNamedBarrier:
|
||||
return "NamedBarrier";
|
||||
case SpvCapabilityPipeStorage:
|
||||
return "PipeStorage";
|
||||
case SpvCapabilityGroupNonUniform:
|
||||
return "GroupNonUniform";
|
||||
case SpvCapabilityGroupNonUniformVote:
|
||||
return "GroupNonUniformVote";
|
||||
case SpvCapabilityGroupNonUniformArithmetic:
|
||||
return "GroupNonUniformArithmetic";
|
||||
case SpvCapabilityGroupNonUniformBallot:
|
||||
return "GroupNonUniformBallot";
|
||||
case SpvCapabilityGroupNonUniformShuffle:
|
||||
return "GroupNonUniformShuffle";
|
||||
case SpvCapabilityGroupNonUniformShuffleRelative:
|
||||
return "GroupNonUniformShuffleRelative";
|
||||
case SpvCapabilityGroupNonUniformClustered:
|
||||
return "GroupNonUniformClustered";
|
||||
case SpvCapabilityGroupNonUniformQuad:
|
||||
return "GroupNonUniformQuad";
|
||||
case SpvCapabilitySubgroupBallotKHR:
|
||||
return "SubgroupBallotKHR";
|
||||
case SpvCapabilityDrawParameters:
|
||||
return "DrawParameters";
|
||||
case SpvCapabilitySubgroupVoteKHR:
|
||||
return "SubgroupVoteKHR";
|
||||
case SpvCapabilityStorageBuffer16BitAccess:
|
||||
return "StorageBuffer16BitAccess";
|
||||
case SpvCapabilityUniformAndStorageBuffer16BitAccess:
|
||||
return "UniformAndStorageBuffer16BitAccess";
|
||||
case SpvCapabilityStoragePushConstant16:
|
||||
return "StoragePushConstant16";
|
||||
case SpvCapabilityStorageInputOutput16:
|
||||
return "StorageInputOutput16";
|
||||
case SpvCapabilityDeviceGroup:
|
||||
return "DeviceGroup";
|
||||
case SpvCapabilityMultiView:
|
||||
return "MultiView";
|
||||
case SpvCapabilityVariablePointersStorageBuffer:
|
||||
return "VariablePointersStorageBuffer";
|
||||
case SpvCapabilityVariablePointers:
|
||||
return "VariablePointers";
|
||||
case SpvCapabilityAtomicStorageOps:
|
||||
return "AtomicStorageOps";
|
||||
case SpvCapabilitySampleMaskPostDepthCoverage:
|
||||
return "SampleMaskPostDepthCoverage";
|
||||
case SpvCapabilityFloat16ImageAMD:
|
||||
return "Float16ImageAMD";
|
||||
case SpvCapabilityImageGatherBiasLodAMD:
|
||||
return "ImageGatherBiasLodAMD";
|
||||
case SpvCapabilityFragmentMaskAMD:
|
||||
return "FragmentMaskAMD";
|
||||
case SpvCapabilityStencilExportEXT:
|
||||
return "StencilExportEXT";
|
||||
case SpvCapabilityImageReadWriteLodAMD:
|
||||
return "ImageReadWriteLodAMD";
|
||||
case SpvCapabilitySampleMaskOverrideCoverageNV:
|
||||
return "SampleMaskOverrideCoverageNV";
|
||||
case SpvCapabilityGeometryShaderPassthroughNV:
|
||||
return "GeometryShaderPassthroughNV";
|
||||
case SpvCapabilityShaderViewportIndexLayerEXT:
|
||||
return "ShaderViewportIndexLayerEXT";
|
||||
case SpvCapabilityShaderViewportMaskNV:
|
||||
return "ShaderViewportMaskNV";
|
||||
case SpvCapabilityShaderStereoViewNV:
|
||||
return "ShaderStereoViewNV";
|
||||
case SpvCapabilityPerViewAttributesNV:
|
||||
return "PerViewAttributesNV";
|
||||
case SpvCapabilityFragmentFullyCoveredEXT:
|
||||
return "FragmentFullyCoveredEXT";
|
||||
case SpvCapabilityShaderNonUniformEXT:
|
||||
return "ShaderNonUniformEXT";
|
||||
case SpvCapabilityRuntimeDescriptorArrayEXT:
|
||||
return "RuntimeDescriptorArrayEXT";
|
||||
case SpvCapabilityInputAttachmentArrayDynamicIndexingEXT:
|
||||
return "InputAttachmentArrayDynamicIndexingEXT";
|
||||
case SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT:
|
||||
return "UniformTexelBufferArrayDynamicIndexingEXT";
|
||||
case SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT:
|
||||
return "StorageTexelBufferArrayDynamicIndexingEXT";
|
||||
case SpvCapabilityUniformBufferArrayNonUniformIndexingEXT:
|
||||
return "UniformBufferArrayNonUniformIndexingEXT";
|
||||
case SpvCapabilitySampledImageArrayNonUniformIndexingEXT:
|
||||
return "SampledImageArrayNonUniformIndexingEXT";
|
||||
case SpvCapabilityStorageBufferArrayNonUniformIndexingEXT:
|
||||
return "StorageBufferArrayNonUniformIndexingEXT";
|
||||
case SpvCapabilityStorageImageArrayNonUniformIndexingEXT:
|
||||
return "StorageImageArrayNonUniformIndexingEXT";
|
||||
case SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT:
|
||||
return "InputAttachmentArrayNonUniformIndexingEXT";
|
||||
case SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT:
|
||||
return "UniformTexelBufferArrayNonUniformIndexingEXT";
|
||||
case SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT:
|
||||
return "StorageTexelBufferArrayNonUniformIndexingEXT";
|
||||
case SpvCapabilitySubgroupShuffleINTEL:
|
||||
return "SubgroupShuffleINTEL";
|
||||
case SpvCapabilitySubgroupBufferBlockIOINTEL:
|
||||
return "SubgroupBufferBlockIOINTEL";
|
||||
case SpvCapabilitySubgroupImageBlockIOINTEL:
|
||||
return "SubgroupImageBlockIOINTEL";
|
||||
case SpvCapabilityGroupNonUniformPartitionedNV:
|
||||
return "GroupNonUniformPartitionedNV";
|
||||
case SpvCapabilityMax:
|
||||
assert(0 && "Attempting to convert SpvCapabilityMax to string");
|
||||
return "";
|
||||
};
|
||||
|
||||
return "";
|
||||
}
|
34
3rdparty/spirv-tools/include/generated/extension_enum.inc
vendored
Normal file
34
3rdparty/spirv-tools/include/generated/extension_enum.inc
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
kSPV_AMD_gcn_shader,
|
||||
kSPV_AMD_gpu_shader_half_float,
|
||||
kSPV_AMD_gpu_shader_half_float_fetch,
|
||||
kSPV_AMD_gpu_shader_int16,
|
||||
kSPV_AMD_shader_ballot,
|
||||
kSPV_AMD_shader_explicit_vertex_parameter,
|
||||
kSPV_AMD_shader_fragment_mask,
|
||||
kSPV_AMD_shader_image_load_store_lod,
|
||||
kSPV_AMD_shader_trinary_minmax,
|
||||
kSPV_AMD_texture_gather_bias_lod,
|
||||
kSPV_EXT_descriptor_indexing,
|
||||
kSPV_EXT_fragment_fully_covered,
|
||||
kSPV_EXT_shader_stencil_export,
|
||||
kSPV_EXT_shader_viewport_index_layer,
|
||||
kSPV_GOOGLE_decorate_string,
|
||||
kSPV_GOOGLE_hlsl_functionality1,
|
||||
kSPV_INTEL_subgroups,
|
||||
kSPV_KHR_16bit_storage,
|
||||
kSPV_KHR_device_group,
|
||||
kSPV_KHR_multiview,
|
||||
kSPV_KHR_post_depth_coverage,
|
||||
kSPV_KHR_shader_atomic_counter_ops,
|
||||
kSPV_KHR_shader_ballot,
|
||||
kSPV_KHR_shader_draw_parameters,
|
||||
kSPV_KHR_storage_buffer_storage_class,
|
||||
kSPV_KHR_subgroup_vote,
|
||||
kSPV_KHR_variable_pointers,
|
||||
kSPV_NVX_multiview_per_view_attributes,
|
||||
kSPV_NV_geometry_shader_passthrough,
|
||||
kSPV_NV_sample_mask_override_coverage,
|
||||
kSPV_NV_shader_subgroup_partitioned,
|
||||
kSPV_NV_stereo_view_rendering,
|
||||
kSPV_NV_viewport_array2,
|
||||
kSPV_VALIDATOR_ignore_type_decl_unique
|
19
3rdparty/spirv-tools/include/generated/generators.inc
vendored
Normal file
19
3rdparty/spirv-tools/include/generated/generators.inc
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
{0, "Khronos", "", "Khronos"},
|
||||
{1, "LunarG", "", "LunarG"},
|
||||
{2, "Valve", "", "Valve"},
|
||||
{3, "Codeplay", "", "Codeplay"},
|
||||
{4, "NVIDIA", "", "NVIDIA"},
|
||||
{5, "ARM", "", "ARM"},
|
||||
{6, "Khronos", "LLVM/SPIR-V Translator", "Khronos LLVM/SPIR-V Translator"},
|
||||
{7, "Khronos", "SPIR-V Tools Assembler", "Khronos SPIR-V Tools Assembler"},
|
||||
{8, "Khronos", "Glslang Reference Front End", "Khronos Glslang Reference Front End"},
|
||||
{9, "Qualcomm", "", "Qualcomm"},
|
||||
{10, "AMD", "", "AMD"},
|
||||
{11, "Intel", "", "Intel"},
|
||||
{12, "Imagination", "", "Imagination"},
|
||||
{13, "Google", "Shaderc over Glslang", "Google Shaderc over Glslang"},
|
||||
{14, "Google", "spiregg", "Google spiregg"},
|
||||
{15, "Google", "rspirv", "Google rspirv"},
|
||||
{16, "X-LEGEND", "Mesa-IR/SPIR-V Translator", "X-LEGEND Mesa-IR/SPIR-V Translator"},
|
||||
{17, "Khronos", "SPIR-V Tools Linker", "Khronos SPIR-V Tools Linker"},
|
||||
{18, "Wine", "VKD3D Shader Compiler", "Wine VKD3D Shader Compiler"},
|
86
3rdparty/spirv-tools/include/generated/glsl.std.450.insts.inc
vendored
Normal file
86
3rdparty/spirv-tools/include/generated/glsl.std.450.insts.inc
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
static const SpvCapability pygen_variable_caps_Float64[] = {SpvCapabilityFloat64};
|
||||
static const SpvCapability pygen_variable_caps_InterpolationFunction[] = {SpvCapabilityInterpolationFunction};
|
||||
|
||||
static const spv_ext_inst_desc_t glsl_entries[] = {
|
||||
{"Round", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"RoundEven", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Trunc", 3, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FAbs", 4, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"SAbs", 5, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FSign", 6, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"SSign", 7, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Floor", 8, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Ceil", 9, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Fract", 10, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Radians", 11, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Degrees", 12, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Sin", 13, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Cos", 14, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Tan", 15, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Asin", 16, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Acos", 17, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Atan", 18, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Sinh", 19, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Cosh", 20, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Tanh", 21, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Asinh", 22, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Acosh", 23, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Atanh", 24, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Atan2", 25, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Pow", 26, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Exp", 27, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Log", 28, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Exp2", 29, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Log2", 30, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Sqrt", 31, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"InverseSqrt", 32, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Determinant", 33, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"MatrixInverse", 34, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Modf", 35, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ModfStruct", 36, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FMin", 37, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UMin", 38, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"SMin", 39, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FMax", 40, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UMax", 41, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"SMax", 42, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FClamp", 43, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UClamp", 44, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"SClamp", 45, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FMix", 46, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"IMix", 47, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Step", 48, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"SmoothStep", 49, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Fma", 50, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Frexp", 51, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FrexpStruct", 52, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Ldexp", 53, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"PackSnorm4x8", 54, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"PackUnorm4x8", 55, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"PackSnorm2x16", 56, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"PackUnorm2x16", 57, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"PackHalf2x16", 58, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"PackDouble2x32", 59, 1, pygen_variable_caps_Float64, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UnpackSnorm2x16", 60, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UnpackUnorm2x16", 61, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UnpackHalf2x16", 62, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UnpackSnorm4x8", 63, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UnpackUnorm4x8", 64, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UnpackDouble2x32", 65, 1, pygen_variable_caps_Float64, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Length", 66, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Distance", 67, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Cross", 68, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Normalize", 69, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FaceForward", 70, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Reflect", 71, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Refract", 72, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FindILsb", 73, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FindSMsb", 74, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FindUMsb", 75, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"InterpolateAtCentroid", 76, 1, pygen_variable_caps_InterpolationFunction, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"InterpolateAtSample", 77, 1, pygen_variable_caps_InterpolationFunction, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"InterpolateAtOffset", 78, 1, pygen_variable_caps_InterpolationFunction, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"NMin", 79, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"NMax", 80, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"NClamp", 81, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
166
3rdparty/spirv-tools/include/generated/opencl.std.insts.inc
vendored
Normal file
166
3rdparty/spirv-tools/include/generated/opencl.std.insts.inc
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
|
||||
|
||||
static const spv_ext_inst_desc_t opencl_entries[] = {
|
||||
{"acos", 0, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"acosh", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"acospi", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"asin", 3, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"asinh", 4, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"asinpi", 5, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"atan", 6, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"atan2", 7, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"atanh", 8, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"atanpi", 9, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"atan2pi", 10, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"cbrt", 11, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ceil", 12, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"copysign", 13, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"cos", 14, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"cosh", 15, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"cospi", 16, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"erfc", 17, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"erf", 18, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"exp", 19, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"exp2", 20, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"exp10", 21, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"expm1", 22, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fabs", 23, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fdim", 24, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"floor", 25, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fma", 26, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fmax", 27, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fmin", 28, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fmod", 29, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fract", 30, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"frexp", 31, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"hypot", 32, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ilogb", 33, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ldexp", 34, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"lgamma", 35, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"lgamma_r", 36, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"log", 37, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"log2", 38, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"log10", 39, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"log1p", 40, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"logb", 41, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"mad", 42, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"maxmag", 43, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"minmag", 44, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"modf", 45, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"nan", 46, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"nextafter", 47, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"pow", 48, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"pown", 49, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"powr", 50, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"remainder", 51, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"remquo", 52, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"rint", 53, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"rootn", 54, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"round", 55, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"rsqrt", 56, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"sin", 57, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"sincos", 58, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"sinh", 59, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"sinpi", 60, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"sqrt", 61, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"tan", 62, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"tanh", 63, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"tanpi", 64, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"tgamma", 65, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"trunc", 66, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_cos", 67, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_divide", 68, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_exp", 69, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_exp2", 70, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_exp10", 71, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_log", 72, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_log2", 73, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_log10", 74, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_powr", 75, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_recip", 76, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_rsqrt", 77, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_sin", 78, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_sqrt", 79, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"half_tan", 80, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_cos", 81, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_divide", 82, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_exp", 83, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_exp2", 84, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_exp10", 85, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_log", 86, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_log2", 87, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_log10", 88, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_powr", 89, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_recip", 90, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_rsqrt", 91, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_sin", 92, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_sqrt", 93, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"native_tan", 94, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fclamp", 95, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"degrees", 96, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fmax_common", 97, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fmin_common", 98, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"mix", 99, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"radians", 100, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"step", 101, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"smoothstep", 102, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"sign", 103, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"cross", 104, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"distance", 105, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"length", 106, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"normalize", 107, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fast_distance", 108, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fast_length", 109, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"fast_normalize", 110, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_abs", 141, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_abs_diff", 142, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_add_sat", 143, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_add_sat", 144, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_hadd", 145, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_hadd", 146, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_rhadd", 147, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_rhadd", 148, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_clamp", 149, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_clamp", 150, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"clz", 151, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"ctz", 152, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_mad_hi", 153, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_mad_sat", 154, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_mad_sat", 155, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_max", 156, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_max", 157, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_min", 158, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_min", 159, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_mul_hi", 160, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"rotate", 161, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_sub_sat", 162, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_sub_sat", 163, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_upsample", 164, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_upsample", 165, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"popcount", 166, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_mad24", 167, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_mad24", 168, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"s_mul24", 169, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_mul24", 170, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"vloadn", 171, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"vstoren", 172, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"vload_half", 173, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"vload_halfn", 174, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"vstore_half", 175, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"vstore_half_r", 176, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_NONE}},
|
||||
{"vstore_halfn", 177, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"vstore_halfn_r", 178, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_NONE}},
|
||||
{"vloada_halfn", 179, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"vstorea_halfn", 180, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"vstorea_halfn_r", 181, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_FP_ROUNDING_MODE, SPV_OPERAND_TYPE_NONE}},
|
||||
{"shuffle", 182, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"shuffle2", 183, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"printf", 184, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_VARIABLE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"prefetch", 185, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"bitselect", 186, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"select", 187, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_abs", 201, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_abs_diff", 202, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_mul_hi", 203, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"u_mad_hi", 204, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
744
3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc
vendored
Normal file
744
3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc
vendored
Normal file
@ -0,0 +1,744 @@
|
||||
static const SpvCapability pygen_variable_caps_Addresses[] = {SpvCapabilityAddresses};
|
||||
static const SpvCapability pygen_variable_caps_AtomicStorage[] = {SpvCapabilityAtomicStorage};
|
||||
static const SpvCapability pygen_variable_caps_ClipDistance[] = {SpvCapabilityClipDistance};
|
||||
static const SpvCapability pygen_variable_caps_CullDistance[] = {SpvCapabilityCullDistance};
|
||||
static const SpvCapability pygen_variable_caps_DeviceEnqueue[] = {SpvCapabilityDeviceEnqueue};
|
||||
static const SpvCapability pygen_variable_caps_DeviceGroup[] = {SpvCapabilityDeviceGroup};
|
||||
static const SpvCapability pygen_variable_caps_DrawParameters[] = {SpvCapabilityDrawParameters};
|
||||
static const SpvCapability pygen_variable_caps_FragmentFullyCoveredEXT[] = {SpvCapabilityFragmentFullyCoveredEXT};
|
||||
static const SpvCapability pygen_variable_caps_GenericPointer[] = {SpvCapabilityGenericPointer};
|
||||
static const SpvCapability pygen_variable_caps_Geometry[] = {SpvCapabilityGeometry};
|
||||
static const SpvCapability pygen_variable_caps_GeometryTessellation[] = {SpvCapabilityGeometry, SpvCapabilityTessellation};
|
||||
static const SpvCapability pygen_variable_caps_GeometryShaderPassthroughNV[] = {SpvCapabilityGeometryShaderPassthroughNV};
|
||||
static const SpvCapability pygen_variable_caps_GeometryStreams[] = {SpvCapabilityGeometryStreams};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniform[] = {SpvCapabilityGroupNonUniform};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformClustered[] = {SpvCapabilityGroupNonUniformClustered};
|
||||
static const SpvCapability pygen_variable_caps_GroupNonUniformPartitionedNV[] = {SpvCapabilityGroupNonUniformPartitionedNV};
|
||||
static const SpvCapability pygen_variable_caps_ImageBasic[] = {SpvCapabilityImageBasic};
|
||||
static const SpvCapability pygen_variable_caps_ImageBuffer[] = {SpvCapabilityImageBuffer};
|
||||
static const SpvCapability pygen_variable_caps_ImageBufferShaderNonUniformEXT[] = {SpvCapabilityImageBuffer, SpvCapabilityShaderNonUniformEXT};
|
||||
static const SpvCapability pygen_variable_caps_ImageGatherExtended[] = {SpvCapabilityImageGatherExtended};
|
||||
static const SpvCapability pygen_variable_caps_InputAttachment[] = {SpvCapabilityInputAttachment};
|
||||
static const SpvCapability pygen_variable_caps_InputAttachmentShaderNonUniformEXT[] = {SpvCapabilityInputAttachment, SpvCapabilityShaderNonUniformEXT};
|
||||
static const SpvCapability pygen_variable_caps_Int64[] = {SpvCapabilityInt64};
|
||||
static const SpvCapability pygen_variable_caps_Kernel[] = {SpvCapabilityKernel};
|
||||
static const SpvCapability pygen_variable_caps_KernelGroupNonUniform[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniform};
|
||||
static const SpvCapability pygen_variable_caps_KernelGroupNonUniformSubgroupBallotKHR[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniform, SpvCapabilitySubgroupBallotKHR};
|
||||
static const SpvCapability pygen_variable_caps_KernelGroupNonUniformArithmeticGroupNonUniformBallot[] = {SpvCapabilityKernel, SpvCapabilityGroupNonUniformArithmetic, SpvCapabilityGroupNonUniformBallot};
|
||||
static const SpvCapability pygen_variable_caps_Linkage[] = {SpvCapabilityLinkage};
|
||||
static const SpvCapability pygen_variable_caps_Matrix[] = {SpvCapabilityMatrix};
|
||||
static const SpvCapability pygen_variable_caps_MinLod[] = {SpvCapabilityMinLod};
|
||||
static const SpvCapability pygen_variable_caps_MultiView[] = {SpvCapabilityMultiView};
|
||||
static const SpvCapability pygen_variable_caps_MultiViewport[] = {SpvCapabilityMultiViewport};
|
||||
static const SpvCapability pygen_variable_caps_PerViewAttributesNV[] = {SpvCapabilityPerViewAttributesNV};
|
||||
static const SpvCapability pygen_variable_caps_Pipes[] = {SpvCapabilityPipes};
|
||||
static const SpvCapability pygen_variable_caps_SampleMaskOverrideCoverageNV[] = {SpvCapabilitySampleMaskOverrideCoverageNV};
|
||||
static const SpvCapability pygen_variable_caps_SampleMaskPostDepthCoverage[] = {SpvCapabilitySampleMaskPostDepthCoverage};
|
||||
static const SpvCapability pygen_variable_caps_SampleRateShading[] = {SpvCapabilitySampleRateShading};
|
||||
static const SpvCapability pygen_variable_caps_Sampled1D[] = {SpvCapabilitySampled1D};
|
||||
static const SpvCapability pygen_variable_caps_SampledBuffer[] = {SpvCapabilitySampledBuffer};
|
||||
static const SpvCapability pygen_variable_caps_SampledBufferShaderNonUniformEXT[] = {SpvCapabilitySampledBuffer, SpvCapabilityShaderNonUniformEXT};
|
||||
static const SpvCapability pygen_variable_caps_SampledCubeArray[] = {SpvCapabilitySampledCubeArray};
|
||||
static const SpvCapability pygen_variable_caps_SampledRect[] = {SpvCapabilitySampledRect};
|
||||
static const SpvCapability pygen_variable_caps_Shader[] = {SpvCapabilityShader};
|
||||
static const SpvCapability pygen_variable_caps_ShaderKernel[] = {SpvCapabilityShader, SpvCapabilityKernel};
|
||||
static const SpvCapability pygen_variable_caps_ShaderNonUniformEXT[] = {SpvCapabilityShaderNonUniformEXT};
|
||||
static const SpvCapability pygen_variable_caps_ShaderStereoViewNV[] = {SpvCapabilityShaderStereoViewNV};
|
||||
static const SpvCapability pygen_variable_caps_ShaderViewportIndexLayerNV[] = {SpvCapabilityShaderViewportIndexLayerNV};
|
||||
static const SpvCapability pygen_variable_caps_ShaderViewportMaskNV[] = {SpvCapabilityShaderViewportMaskNV};
|
||||
static const SpvCapability pygen_variable_caps_StencilExportEXT[] = {SpvCapabilityStencilExportEXT};
|
||||
static const SpvCapability pygen_variable_caps_StorageBuffer16BitAccessStorageUniformBufferBlock16[] = {SpvCapabilityStorageBuffer16BitAccess, SpvCapabilityStorageUniformBufferBlock16};
|
||||
static const SpvCapability pygen_variable_caps_StorageImageExtendedFormats[] = {SpvCapabilityStorageImageExtendedFormats};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot[] = {SpvCapabilitySubgroupBallotKHR, SpvCapabilityGroupNonUniformBallot};
|
||||
static const SpvCapability pygen_variable_caps_SubgroupDispatch[] = {SpvCapabilitySubgroupDispatch};
|
||||
static const SpvCapability pygen_variable_caps_Tessellation[] = {SpvCapabilityTessellation};
|
||||
static const SpvCapability pygen_variable_caps_TransformFeedback[] = {SpvCapabilityTransformFeedback};
|
||||
static const SpvCapability pygen_variable_caps_VariablePointersStorageBuffer[] = {SpvCapabilityVariablePointersStorageBuffer};
|
||||
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_AMD_gpu_shader_half_float_fetch[] = {libspirv::Extension::kSPV_AMD_gpu_shader_half_float_fetch};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter[] = {libspirv::Extension::kSPV_AMD_shader_explicit_vertex_parameter};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_AMD_shader_fragment_mask[] = {libspirv::Extension::kSPV_AMD_shader_fragment_mask};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_AMD_shader_image_load_store_lod[] = {libspirv::Extension::kSPV_AMD_shader_image_load_store_lod};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_AMD_texture_gather_bias_lod[] = {libspirv::Extension::kSPV_AMD_texture_gather_bias_lod};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_EXT_descriptor_indexing[] = {libspirv::Extension::kSPV_EXT_descriptor_indexing};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_EXT_fragment_fully_covered[] = {libspirv::Extension::kSPV_EXT_fragment_fully_covered};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_EXT_shader_stencil_export[] = {libspirv::Extension::kSPV_EXT_shader_stencil_export};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_EXT_shader_viewport_index_layer[] = {libspirv::Extension::kSPV_EXT_shader_viewport_index_layer};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1[] = {libspirv::Extension::kSPV_GOOGLE_hlsl_functionality1};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_INTEL_subgroups[] = {libspirv::Extension::kSPV_INTEL_subgroups};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_16bit_storage[] = {libspirv::Extension::kSPV_KHR_16bit_storage};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_device_group[] = {libspirv::Extension::kSPV_KHR_device_group};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_multiview[] = {libspirv::Extension::kSPV_KHR_multiview};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_post_depth_coverage[] = {libspirv::Extension::kSPV_KHR_post_depth_coverage};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_shader_atomic_counter_ops[] = {libspirv::Extension::kSPV_KHR_shader_atomic_counter_ops};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {libspirv::Extension::kSPV_KHR_shader_ballot};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_shader_draw_parameters[] = {libspirv::Extension::kSPV_KHR_shader_draw_parameters};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_storage_buffer_storage_classSPV_KHR_variable_pointers[] = {libspirv::Extension::kSPV_KHR_storage_buffer_storage_class, libspirv::Extension::kSPV_KHR_variable_pointers};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_subgroup_vote[] = {libspirv::Extension::kSPV_KHR_subgroup_vote};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_KHR_variable_pointers[] = {libspirv::Extension::kSPV_KHR_variable_pointers};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_NVX_multiview_per_view_attributes[] = {libspirv::Extension::kSPV_NVX_multiview_per_view_attributes};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_NV_geometry_shader_passthrough[] = {libspirv::Extension::kSPV_NV_geometry_shader_passthrough};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_NV_sample_mask_override_coverage[] = {libspirv::Extension::kSPV_NV_sample_mask_override_coverage};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_NV_shader_subgroup_partitioned[] = {libspirv::Extension::kSPV_NV_shader_subgroup_partitioned};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_NV_stereo_view_rendering[] = {libspirv::Extension::kSPV_NV_stereo_view_rendering};
|
||||
static const libspirv::Extension pygen_variable_exts_SPV_NV_viewport_array2[] = {libspirv::Extension::kSPV_NV_viewport_array2};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_ImageOperandsEntries[] = {
|
||||
{"None", 0x0000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Bias", 0x0001, 1, pygen_variable_caps_Shader, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Lod", 0x0002, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Grad", 0x0004, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConstOffset", 0x0008, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Offset", 0x0010, 1, pygen_variable_caps_ImageGatherExtended, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ConstOffsets", 0x0020, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Sample", 0x0040, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MinLod", 0x0080, 1, pygen_variable_caps_MinLod, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_FPFastMathModeEntries[] = {
|
||||
{"None", 0x0000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NotNaN", 0x0001, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NotInf", 0x0002, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NSZ", 0x0004, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AllowRecip", 0x0008, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Fast", 0x0010, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_SelectionControlEntries[] = {
|
||||
{"None", 0x0000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Flatten", 0x0001, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DontFlatten", 0x0002, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_LoopControlEntries[] = {
|
||||
{"None", 0x0000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Unroll", 0x0001, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DontUnroll", 0x0002, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DependencyInfinite", 0x0004, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"DependencyLength", 0x0008, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,1)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_FunctionControlEntries[] = {
|
||||
{"None", 0x0000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Inline", 0x0001, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DontInline", 0x0002, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Pure", 0x0004, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Const", 0x0008, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_MemorySemanticsEntries[] = {
|
||||
{"None", 0x0000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Relaxed", 0x0000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Acquire", 0x0002, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Release", 0x0004, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AcquireRelease", 0x0008, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SequentiallyConsistent", 0x0010, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UniformMemory", 0x0040, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SubgroupMemory", 0x0080, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"WorkgroupMemory", 0x0100, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CrossWorkgroupMemory", 0x0200, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicCounterMemory", 0x0400, 1, pygen_variable_caps_AtomicStorage, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageMemory", 0x0800, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_MemoryAccessEntries[] = {
|
||||
{"None", 0x0000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Volatile", 0x0001, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Aligned", 0x0002, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Nontemporal", 0x0004, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_KernelProfilingInfoEntries[] = {
|
||||
{"None", 0x0000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CmdExecTime", 0x0001, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_SourceLanguageEntries[] = {
|
||||
{"Unknown", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ESSL", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GLSL", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"OpenCL_C", 3, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"OpenCL_CPP", 4, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"HLSL", 5, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_ExecutionModelEntries[] = {
|
||||
{"Vertex", 0, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TessellationControl", 1, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TessellationEvaluation", 2, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Geometry", 3, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Fragment", 4, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GLCompute", 5, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Kernel", 6, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_AddressingModelEntries[] = {
|
||||
{"Logical", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Physical32", 1, 1, pygen_variable_caps_Addresses, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Physical64", 2, 1, pygen_variable_caps_Addresses, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_MemoryModelEntries[] = {
|
||||
{"Simple", 0, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GLSL450", 1, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"OpenCL", 2, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_ExecutionModeEntries[] = {
|
||||
{"Invocations", 0, 1, pygen_variable_caps_Geometry, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SpacingEqual", 1, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SpacingFractionalEven", 2, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SpacingFractionalOdd", 3, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"VertexOrderCw", 4, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"VertexOrderCcw", 5, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PixelCenterInteger", 6, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"OriginUpperLeft", 7, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"OriginLowerLeft", 8, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"EarlyFragmentTests", 9, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PointMode", 10, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Xfb", 11, 1, pygen_variable_caps_TransformFeedback, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DepthReplacing", 12, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DepthGreater", 14, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DepthLess", 15, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DepthUnchanged", 16, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LocalSize", 17, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LocalSizeHint", 18, 1, pygen_variable_caps_Kernel, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InputPoints", 19, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InputLines", 20, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InputLinesAdjacency", 21, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Triangles", 22, 2, pygen_variable_caps_GeometryTessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InputTrianglesAdjacency", 23, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Quads", 24, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Isolines", 25, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"OutputVertices", 26, 2, pygen_variable_caps_GeometryTessellation, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"OutputPoints", 27, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"OutputLineStrip", 28, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"OutputTriangleStrip", 29, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"VecTypeHint", 30, 1, pygen_variable_caps_Kernel, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ContractionOff", 31, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Initializer", 33, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"Finalizer", 34, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"SubgroupSize", 35, 1, pygen_variable_caps_SubgroupDispatch, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"SubgroupsPerWorkgroup", 36, 1, pygen_variable_caps_SubgroupDispatch, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"SubgroupsPerWorkgroupId", 37, 1, pygen_variable_caps_SubgroupDispatch, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1,2)},
|
||||
{"LocalSizeId", 38, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1,2)},
|
||||
{"LocalSizeHintId", 39, 1, pygen_variable_caps_Kernel, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1,2)},
|
||||
{"PostDepthCoverage", 4446, 1, pygen_variable_caps_SampleMaskPostDepthCoverage, 1, pygen_variable_exts_SPV_KHR_post_depth_coverage, {}, 0xffffffffu},
|
||||
{"StencilRefReplacingEXT", 5027, 1, pygen_variable_caps_StencilExportEXT, 1, pygen_variable_exts_SPV_EXT_shader_stencil_export, {}, 0xffffffffu}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_StorageClassEntries[] = {
|
||||
{"UniformConstant", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Input", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Uniform", 2, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Output", 3, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Workgroup", 4, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CrossWorkgroup", 5, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Private", 6, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Function", 7, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Generic", 8, 1, pygen_variable_caps_GenericPointer, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PushConstant", 9, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicCounter", 10, 1, pygen_variable_caps_AtomicStorage, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Image", 11, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"StorageBuffer", 12, 1, pygen_variable_caps_Shader, 2, pygen_variable_exts_SPV_KHR_storage_buffer_storage_classSPV_KHR_variable_pointers, {}, SPV_SPIRV_VERSION_WORD(1,3)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_DimEntries[] = {
|
||||
{"1D", 0, 1, pygen_variable_caps_Sampled1D, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"2D", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"3D", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Cube", 3, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rect", 4, 1, pygen_variable_caps_SampledRect, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Buffer", 5, 1, pygen_variable_caps_SampledBuffer, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SubpassData", 6, 1, pygen_variable_caps_InputAttachment, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_SamplerAddressingModeEntries[] = {
|
||||
{"None", 0, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ClampToEdge", 1, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Clamp", 2, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Repeat", 3, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RepeatMirrored", 4, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_SamplerFilterModeEntries[] = {
|
||||
{"Nearest", 0, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Linear", 1, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_ImageFormatEntries[] = {
|
||||
{"Unknown", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba32f", 1, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba16f", 2, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R32f", 3, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba8", 4, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba8Snorm", 5, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg32f", 6, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg16f", 7, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R11fG11fB10f", 8, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R16f", 9, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba16", 10, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgb10A2", 11, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg16", 12, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg8", 13, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R16", 14, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R8", 15, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba16Snorm", 16, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg16Snorm", 17, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg8Snorm", 18, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R16Snorm", 19, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R8Snorm", 20, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba32i", 21, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba16i", 22, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba8i", 23, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R32i", 24, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg32i", 25, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg16i", 26, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg8i", 27, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R16i", 28, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R8i", 29, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba32ui", 30, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba16ui", 31, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgba8ui", 32, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R32ui", 33, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rgb10a2ui", 34, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg32ui", 35, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg16ui", 36, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rg8ui", 37, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R16ui", 38, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"R8ui", 39, 1, pygen_variable_caps_StorageImageExtendedFormats, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_ImageChannelOrderEntries[] = {
|
||||
{"R", 0, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"A", 1, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RG", 2, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RA", 3, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RGB", 4, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RGBA", 5, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BGRA", 6, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ARGB", 7, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Intensity", 8, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Luminance", 9, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Rx", 10, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RGx", 11, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RGBx", 12, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Depth", 13, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DepthStencil", 14, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"sRGB", 15, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"sRGBx", 16, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"sRGBA", 17, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"sBGRA", 18, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ABGR", 19, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_ImageChannelDataTypeEntries[] = {
|
||||
{"SnormInt8", 0, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SnormInt16", 1, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UnormInt8", 2, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UnormInt16", 3, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UnormShort565", 4, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UnormShort555", 5, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UnormInt101010", 6, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SignedInt8", 7, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SignedInt16", 8, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SignedInt32", 9, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UnsignedInt8", 10, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UnsignedInt16", 11, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UnsignedInt32", 12, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"HalfFloat", 13, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Float", 14, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UnormInt24", 15, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UnormInt101010_2", 16, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_FPRoundingModeEntries[] = {
|
||||
{"RTE", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RTZ", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RTP", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RTN", 3, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_LinkageTypeEntries[] = {
|
||||
{"Export", 0, 1, pygen_variable_caps_Linkage, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Import", 1, 1, pygen_variable_caps_Linkage, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_AccessQualifierEntries[] = {
|
||||
{"ReadOnly", 0, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"WriteOnly", 1, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ReadWrite", 2, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_FunctionParameterAttributeEntries[] = {
|
||||
{"Zext", 0, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Sext", 1, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ByVal", 2, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Sret", 3, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NoAlias", 4, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NoCapture", 5, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NoWrite", 6, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NoReadWrite", 7, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
|
||||
{"RelaxedPrecision", 0, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SpecId", 1, 2, pygen_variable_caps_ShaderKernel, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Block", 2, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BufferBlock", 3, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RowMajor", 4, 1, pygen_variable_caps_Matrix, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ColMajor", 5, 1, pygen_variable_caps_Matrix, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ArrayStride", 6, 1, pygen_variable_caps_Shader, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MatrixStride", 7, 1, pygen_variable_caps_Matrix, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GLSLShared", 8, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GLSLPacked", 9, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CPacked", 10, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BuiltIn", 11, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_BUILT_IN}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NoPerspective", 13, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Flat", 14, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Patch", 15, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Centroid", 16, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Sample", 17, 1, pygen_variable_caps_SampleRateShading, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Invariant", 18, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Restrict", 19, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Aliased", 20, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Volatile", 21, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Constant", 22, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Coherent", 23, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NonWritable", 24, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NonReadable", 25, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Uniform", 26, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SaturatedConversion", 28, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Stream", 29, 1, pygen_variable_caps_GeometryStreams, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Location", 30, 1, pygen_variable_caps_Shader, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Component", 31, 1, pygen_variable_caps_Shader, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Index", 32, 1, pygen_variable_caps_Shader, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Binding", 33, 1, pygen_variable_caps_Shader, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DescriptorSet", 34, 1, pygen_variable_caps_Shader, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Offset", 35, 1, pygen_variable_caps_Shader, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"XfbBuffer", 36, 1, pygen_variable_caps_TransformFeedback, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"XfbStride", 37, 1, pygen_variable_caps_TransformFeedback, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FuncParamAttr", 38, 1, pygen_variable_caps_Kernel, 0, nullptr, {SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FPRoundingMode", 39, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_FP_ROUNDING_MODE}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FPFastMathMode", 40, 1, pygen_variable_caps_Kernel, 0, nullptr, {SPV_OPERAND_TYPE_FP_FAST_MATH_MODE}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LinkageAttributes", 41, 1, pygen_variable_caps_Linkage, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_LINKAGE_TYPE}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NoContraction", 42, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InputAttachmentIndex", 43, 1, pygen_variable_caps_InputAttachment, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Alignment", 44, 1, pygen_variable_caps_Kernel, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MaxByteOffset", 45, 1, pygen_variable_caps_Addresses, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"AlignmentId", 46, 1, pygen_variable_caps_Kernel, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1,2)},
|
||||
{"MaxByteOffsetId", 47, 1, pygen_variable_caps_Addresses, 0, nullptr, {SPV_OPERAND_TYPE_ID}, SPV_SPIRV_VERSION_WORD(1,2)},
|
||||
{"ExplicitInterpAMD", 4999, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu},
|
||||
{"OverrideCoverageNV", 5248, 1, pygen_variable_caps_SampleMaskOverrideCoverageNV, 0, nullptr, {}, 0xffffffffu},
|
||||
{"PassthroughNV", 5250, 1, pygen_variable_caps_GeometryShaderPassthroughNV, 0, nullptr, {}, 0xffffffffu},
|
||||
{"ViewportRelativeNV", 5252, 1, pygen_variable_caps_ShaderViewportMaskNV, 0, nullptr, {}, 0xffffffffu},
|
||||
{"SecondaryViewportRelativeNV", 5256, 1, pygen_variable_caps_ShaderStereoViewNV, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu},
|
||||
{"NonUniformEXT", 5300, 1, pygen_variable_caps_ShaderNonUniformEXT, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"HlslCounterBufferGOOGLE", 5634, 0, nullptr, 1, pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1, {SPV_OPERAND_TYPE_ID}, 0xffffffffu},
|
||||
{"HlslSemanticGOOGLE", 5635, 0, nullptr, 1, pygen_variable_exts_SPV_GOOGLE_hlsl_functionality1, {SPV_OPERAND_TYPE_LITERAL_STRING}, 0xffffffffu}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = {
|
||||
{"Position", 0, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PointSize", 1, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ClipDistance", 3, 1, pygen_variable_caps_ClipDistance, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CullDistance", 4, 1, pygen_variable_caps_CullDistance, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"VertexId", 5, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InstanceId", 6, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PrimitiveId", 7, 2, pygen_variable_caps_GeometryTessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InvocationId", 8, 2, pygen_variable_caps_GeometryTessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Layer", 9, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ViewportIndex", 10, 1, pygen_variable_caps_MultiViewport, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TessLevelOuter", 11, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TessLevelInner", 12, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TessCoord", 13, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PatchVertices", 14, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FragCoord", 15, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PointCoord", 16, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FrontFacing", 17, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SampleId", 18, 1, pygen_variable_caps_SampleRateShading, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SamplePosition", 19, 1, pygen_variable_caps_SampleRateShading, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SampleMask", 20, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FragDepth", 22, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"HelperInvocation", 23, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NumWorkgroups", 24, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"WorkgroupSize", 25, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"WorkgroupId", 26, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LocalInvocationId", 27, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GlobalInvocationId", 28, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LocalInvocationIndex", 29, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"WorkDim", 30, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GlobalSize", 31, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"EnqueuedWorkgroupSize", 32, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GlobalOffset", 33, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GlobalLinearId", 34, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SubgroupSize", 36, 3, pygen_variable_caps_KernelGroupNonUniformSubgroupBallotKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SubgroupMaxSize", 37, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NumSubgroups", 38, 2, pygen_variable_caps_KernelGroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"NumEnqueuedSubgroups", 39, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SubgroupId", 40, 2, pygen_variable_caps_KernelGroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SubgroupLocalInvocationId", 41, 3, pygen_variable_caps_KernelGroupNonUniformSubgroupBallotKHR, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"VertexIndex", 42, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InstanceIndex", 43, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SubgroupEqMask", 4416, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupEqMaskKHR", 4416, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupGeMask", 4417, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupGeMaskKHR", 4417, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupGtMask", 4418, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupGtMaskKHR", 4418, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupLeMask", 4419, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupLeMaskKHR", 4419, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupLtMask", 4420, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupLtMaskKHR", 4420, 2, pygen_variable_caps_SubgroupBallotKHRGroupNonUniformBallot, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"BaseVertex", 4424, 1, pygen_variable_caps_DrawParameters, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"BaseInstance", 4425, 1, pygen_variable_caps_DrawParameters, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"DrawIndex", 4426, 1, pygen_variable_caps_DrawParameters, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"DeviceIndex", 4438, 1, pygen_variable_caps_DeviceGroup, 1, pygen_variable_exts_SPV_KHR_device_group, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"ViewIndex", 4440, 1, pygen_variable_caps_MultiView, 1, pygen_variable_exts_SPV_KHR_multiview, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"BaryCoordNoPerspAMD", 4992, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu},
|
||||
{"BaryCoordNoPerspCentroidAMD", 4993, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu},
|
||||
{"BaryCoordNoPerspSampleAMD", 4994, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu},
|
||||
{"BaryCoordSmoothAMD", 4995, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu},
|
||||
{"BaryCoordSmoothCentroidAMD", 4996, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu},
|
||||
{"BaryCoordSmoothSampleAMD", 4997, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu},
|
||||
{"BaryCoordPullModelAMD", 4998, 0, nullptr, 1, pygen_variable_exts_SPV_AMD_shader_explicit_vertex_parameter, {}, 0xffffffffu},
|
||||
{"FragStencilRefEXT", 5014, 1, pygen_variable_caps_StencilExportEXT, 1, pygen_variable_exts_SPV_EXT_shader_stencil_export, {}, 0xffffffffu},
|
||||
{"ViewportMaskNV", 5253, 1, pygen_variable_caps_ShaderViewportMaskNV, 0, nullptr, {}, 0xffffffffu},
|
||||
{"SecondaryPositionNV", 5257, 1, pygen_variable_caps_ShaderStereoViewNV, 0, nullptr, {}, 0xffffffffu},
|
||||
{"SecondaryViewportMaskNV", 5258, 1, pygen_variable_caps_ShaderStereoViewNV, 0, nullptr, {}, 0xffffffffu},
|
||||
{"PositionPerViewNV", 5261, 1, pygen_variable_caps_PerViewAttributesNV, 0, nullptr, {}, 0xffffffffu},
|
||||
{"ViewportMaskPerViewNV", 5262, 1, pygen_variable_caps_PerViewAttributesNV, 0, nullptr, {}, 0xffffffffu},
|
||||
{"FullyCoveredEXT", 5264, 1, pygen_variable_caps_FragmentFullyCoveredEXT, 1, pygen_variable_exts_SPV_EXT_fragment_fully_covered, {}, 0xffffffffu}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_ScopeEntries[] = {
|
||||
{"CrossDevice", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Device", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Workgroup", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Subgroup", 3, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Invocation", 4, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_GroupOperationEntries[] = {
|
||||
{"Reduce", 0, 3, pygen_variable_caps_KernelGroupNonUniformArithmeticGroupNonUniformBallot, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InclusiveScan", 1, 3, pygen_variable_caps_KernelGroupNonUniformArithmeticGroupNonUniformBallot, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ExclusiveScan", 2, 3, pygen_variable_caps_KernelGroupNonUniformArithmeticGroupNonUniformBallot, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ClusteredReduce", 3, 1, pygen_variable_caps_GroupNonUniformClustered, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"PartitionedReduceNV", 6, 1, pygen_variable_caps_GroupNonUniformPartitionedNV, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PartitionedInclusiveScanNV", 7, 1, pygen_variable_caps_GroupNonUniformPartitionedNV, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PartitionedExclusiveScanNV", 8, 1, pygen_variable_caps_GroupNonUniformPartitionedNV, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_KernelEnqueueFlagsEntries[] = {
|
||||
{"NoWait", 0, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"WaitKernel", 1, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"WaitWorkGroup", 2, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
|
||||
{"Matrix", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Shader", 1, 1, pygen_variable_caps_Matrix, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Geometry", 2, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Tessellation", 3, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Addresses", 4, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Linkage", 5, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Kernel", 6, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Vector16", 7, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Float16Buffer", 8, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Float16", 9, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Float64", 10, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Int64", 11, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Int64Atomics", 12, 1, pygen_variable_caps_Int64, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageBasic", 13, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageReadWrite", 14, 1, pygen_variable_caps_ImageBasic, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageMipmap", 15, 1, pygen_variable_caps_ImageBasic, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Pipes", 17, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Groups", 18, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DeviceEnqueue", 19, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"LiteralSampler", 20, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"AtomicStorage", 21, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Int16", 22, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TessellationPointSize", 23, 1, pygen_variable_caps_Tessellation, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GeometryPointSize", 24, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageGatherExtended", 25, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"StorageImageMultisample", 27, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UniformBufferArrayDynamicIndexing", 28, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SampledImageArrayDynamicIndexing", 29, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"StorageBufferArrayDynamicIndexing", 30, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"StorageImageArrayDynamicIndexing", 31, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ClipDistance", 32, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"CullDistance", 33, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageCubeArray", 34, 1, pygen_variable_caps_SampledCubeArray, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SampleRateShading", 35, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageRect", 36, 1, pygen_variable_caps_SampledRect, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SampledRect", 37, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GenericPointer", 38, 1, pygen_variable_caps_Addresses, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Int8", 39, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InputAttachment", 40, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SparseResidency", 41, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MinLod", 42, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Sampled1D", 43, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Image1D", 44, 1, pygen_variable_caps_Sampled1D, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SampledCubeArray", 45, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SampledBuffer", 46, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageBuffer", 47, 1, pygen_variable_caps_SampledBuffer, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageMSArray", 48, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"StorageImageExtendedFormats", 49, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"ImageQuery", 50, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"DerivativeControl", 51, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"InterpolationFunction", 52, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"TransformFeedback", 53, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"GeometryStreams", 54, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"StorageImageReadWithoutFormat", 55, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"StorageImageWriteWithoutFormat", 56, 1, pygen_variable_caps_Shader, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"MultiViewport", 57, 1, pygen_variable_caps_Geometry, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SubgroupDispatch", 58, 1, pygen_variable_caps_DeviceEnqueue, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"NamedBarrier", 59, 1, pygen_variable_caps_Kernel, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"PipeStorage", 60, 1, pygen_variable_caps_Pipes, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,1)},
|
||||
{"GroupNonUniform", 61, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformVote", 62, 1, pygen_variable_caps_GroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformArithmetic", 63, 1, pygen_variable_caps_GroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformBallot", 64, 1, pygen_variable_caps_GroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformShuffle", 65, 1, pygen_variable_caps_GroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformShuffleRelative", 66, 1, pygen_variable_caps_GroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformClustered", 67, 1, pygen_variable_caps_GroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"GroupNonUniformQuad", 68, 1, pygen_variable_caps_GroupNonUniform, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupBallotKHR", 4423, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_shader_ballot, {}, 0xffffffffu},
|
||||
{"DrawParameters", 4427, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_draw_parameters, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"SubgroupVoteKHR", 4431, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_subgroup_vote, {}, 0xffffffffu},
|
||||
{"StorageBuffer16BitAccess", 4433, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_16bit_storage, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"StorageUniformBufferBlock16", 4433, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_16bit_storage, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"StorageUniform16", 4434, 2, pygen_variable_caps_StorageBuffer16BitAccessStorageUniformBufferBlock16, 1, pygen_variable_exts_SPV_KHR_16bit_storage, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"UniformAndStorageBuffer16BitAccess", 4434, 2, pygen_variable_caps_StorageBuffer16BitAccessStorageUniformBufferBlock16, 1, pygen_variable_exts_SPV_KHR_16bit_storage, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"StoragePushConstant16", 4435, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_16bit_storage, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"StorageInputOutput16", 4436, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_16bit_storage, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"DeviceGroup", 4437, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_device_group, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"MultiView", 4439, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_multiview, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"VariablePointersStorageBuffer", 4441, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_variable_pointers, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"VariablePointers", 4442, 1, pygen_variable_caps_VariablePointersStorageBuffer, 1, pygen_variable_exts_SPV_KHR_variable_pointers, {}, SPV_SPIRV_VERSION_WORD(1,3)},
|
||||
{"AtomicStorageOps", 4445, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_shader_atomic_counter_ops, {}, 0xffffffffu},
|
||||
{"SampleMaskPostDepthCoverage", 4447, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_post_depth_coverage, {}, 0xffffffffu},
|
||||
{"Float16ImageAMD", 5008, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_gpu_shader_half_float_fetch, {}, 0xffffffffu},
|
||||
{"ImageGatherBiasLodAMD", 5009, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_texture_gather_bias_lod, {}, 0xffffffffu},
|
||||
{"FragmentMaskAMD", 5010, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, {}, 0xffffffffu},
|
||||
{"StencilExportEXT", 5013, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_stencil_export, {}, 0xffffffffu},
|
||||
{"ImageReadWriteLodAMD", 5015, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_shader_image_load_store_lod, {}, 0xffffffffu},
|
||||
{"SampleMaskOverrideCoverageNV", 5249, 1, pygen_variable_caps_SampleRateShading, 1, pygen_variable_exts_SPV_NV_sample_mask_override_coverage, {}, 0xffffffffu},
|
||||
{"GeometryShaderPassthroughNV", 5251, 1, pygen_variable_caps_Geometry, 1, pygen_variable_exts_SPV_NV_geometry_shader_passthrough, {}, 0xffffffffu},
|
||||
{"ShaderViewportIndexLayerEXT", 5254, 1, pygen_variable_caps_MultiViewport, 1, pygen_variable_exts_SPV_EXT_shader_viewport_index_layer, {}, 0xffffffffu},
|
||||
{"ShaderViewportIndexLayerNV", 5254, 1, pygen_variable_caps_MultiViewport, 1, pygen_variable_exts_SPV_NV_viewport_array2, {}, 0xffffffffu},
|
||||
{"ShaderViewportMaskNV", 5255, 1, pygen_variable_caps_ShaderViewportIndexLayerNV, 1, pygen_variable_exts_SPV_NV_viewport_array2, {}, 0xffffffffu},
|
||||
{"ShaderStereoViewNV", 5259, 1, pygen_variable_caps_ShaderViewportMaskNV, 1, pygen_variable_exts_SPV_NV_stereo_view_rendering, {}, 0xffffffffu},
|
||||
{"PerViewAttributesNV", 5260, 1, pygen_variable_caps_MultiView, 1, pygen_variable_exts_SPV_NVX_multiview_per_view_attributes, {}, 0xffffffffu},
|
||||
{"FragmentFullyCoveredEXT", 5265, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_fragment_fully_covered, {}, 0xffffffffu},
|
||||
{"GroupNonUniformPartitionedNV", 5297, 0, nullptr, 1, pygen_variable_exts_SPV_NV_shader_subgroup_partitioned, {}, 0xffffffffu},
|
||||
{"ShaderNonUniformEXT", 5301, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"RuntimeDescriptorArrayEXT", 5302, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"InputAttachmentArrayDynamicIndexingEXT", 5303, 1, pygen_variable_caps_InputAttachment, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"UniformTexelBufferArrayDynamicIndexingEXT", 5304, 1, pygen_variable_caps_SampledBuffer, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"StorageTexelBufferArrayDynamicIndexingEXT", 5305, 1, pygen_variable_caps_ImageBuffer, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"UniformBufferArrayNonUniformIndexingEXT", 5306, 1, pygen_variable_caps_ShaderNonUniformEXT, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"SampledImageArrayNonUniformIndexingEXT", 5307, 1, pygen_variable_caps_ShaderNonUniformEXT, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"StorageBufferArrayNonUniformIndexingEXT", 5308, 1, pygen_variable_caps_ShaderNonUniformEXT, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"StorageImageArrayNonUniformIndexingEXT", 5309, 1, pygen_variable_caps_ShaderNonUniformEXT, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"InputAttachmentArrayNonUniformIndexingEXT", 5310, 2, pygen_variable_caps_InputAttachmentShaderNonUniformEXT, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"UniformTexelBufferArrayNonUniformIndexingEXT", 5311, 2, pygen_variable_caps_SampledBufferShaderNonUniformEXT, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"StorageTexelBufferArrayNonUniformIndexingEXT", 5312, 2, pygen_variable_caps_ImageBufferShaderNonUniformEXT, 1, pygen_variable_exts_SPV_EXT_descriptor_indexing, {}, 0xffffffffu},
|
||||
{"SubgroupShuffleINTEL", 5568, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu},
|
||||
{"SubgroupBufferBlockIOINTEL", 5569, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu},
|
||||
{"SubgroupImageBlockIOINTEL", 5570, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_subgroups, {}, 0xffffffffu}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_DebugInfoFlagsEntries[] = {
|
||||
{"FlagIsProtected", 0x01, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagIsPrivate", 0x02, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagIsPublic", 0x03, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagIsLocal", 0x04, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagIsDefinition", 0x08, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagFwdDecl", 0x10, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagArtificial", 0x20, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagExplicit", 0x40, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagPrototyped", 0x80, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagObjectPointer", 0x100, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagStaticMember", 0x200, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagIndirectVariable", 0x400, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagLValueReference", 0x800, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagRValueReference", 0x1000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"FlagIsOptimized", 0x2000, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_DebugBaseTypeAttributeEncodingEntries[] = {
|
||||
{"Unspecified", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Address", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Boolean", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Float", 4, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Signed", 5, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"SignedChar", 6, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Unsigned", 7, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"UnsignedChar", 8, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_DebugCompositeTypeEntries[] = {
|
||||
{"Class", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Structure", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Union", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_DebugTypeQualifierEntries[] = {
|
||||
{"ConstType", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"VolatileType", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"RestrictType", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t pygen_variable_DebugOperationEntries[] = {
|
||||
{"Deref", 0, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Plus", 1, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Minus", 2, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"PlusUconst", 3, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"BitPiece", 4, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Swap", 5, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Xderef", 6, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"StackValue", 7, 0, nullptr, 0, nullptr, {}, SPV_SPIRV_VERSION_WORD(1, 0)},
|
||||
{"Constu", 8, 0, nullptr, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, SPV_SPIRV_VERSION_WORD(1, 0)}
|
||||
};
|
||||
|
||||
static const spv_operand_desc_group_t pygen_variable_OperandInfoTable[] = {
|
||||
{SPV_OPERAND_TYPE_IMAGE, ARRAY_SIZE(pygen_variable_ImageOperandsEntries), pygen_variable_ImageOperandsEntries},
|
||||
{SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, ARRAY_SIZE(pygen_variable_FPFastMathModeEntries), pygen_variable_FPFastMathModeEntries},
|
||||
{SPV_OPERAND_TYPE_SELECTION_CONTROL, ARRAY_SIZE(pygen_variable_SelectionControlEntries), pygen_variable_SelectionControlEntries},
|
||||
{SPV_OPERAND_TYPE_LOOP_CONTROL, ARRAY_SIZE(pygen_variable_LoopControlEntries), pygen_variable_LoopControlEntries},
|
||||
{SPV_OPERAND_TYPE_FUNCTION_CONTROL, ARRAY_SIZE(pygen_variable_FunctionControlEntries), pygen_variable_FunctionControlEntries},
|
||||
{SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, ARRAY_SIZE(pygen_variable_MemorySemanticsEntries), pygen_variable_MemorySemanticsEntries},
|
||||
{SPV_OPERAND_TYPE_MEMORY_ACCESS, ARRAY_SIZE(pygen_variable_MemoryAccessEntries), pygen_variable_MemoryAccessEntries},
|
||||
{SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO, ARRAY_SIZE(pygen_variable_KernelProfilingInfoEntries), pygen_variable_KernelProfilingInfoEntries},
|
||||
{SPV_OPERAND_TYPE_SOURCE_LANGUAGE, ARRAY_SIZE(pygen_variable_SourceLanguageEntries), pygen_variable_SourceLanguageEntries},
|
||||
{SPV_OPERAND_TYPE_EXECUTION_MODEL, ARRAY_SIZE(pygen_variable_ExecutionModelEntries), pygen_variable_ExecutionModelEntries},
|
||||
{SPV_OPERAND_TYPE_ADDRESSING_MODEL, ARRAY_SIZE(pygen_variable_AddressingModelEntries), pygen_variable_AddressingModelEntries},
|
||||
{SPV_OPERAND_TYPE_MEMORY_MODEL, ARRAY_SIZE(pygen_variable_MemoryModelEntries), pygen_variable_MemoryModelEntries},
|
||||
{SPV_OPERAND_TYPE_EXECUTION_MODE, ARRAY_SIZE(pygen_variable_ExecutionModeEntries), pygen_variable_ExecutionModeEntries},
|
||||
{SPV_OPERAND_TYPE_STORAGE_CLASS, ARRAY_SIZE(pygen_variable_StorageClassEntries), pygen_variable_StorageClassEntries},
|
||||
{SPV_OPERAND_TYPE_DIMENSIONALITY, ARRAY_SIZE(pygen_variable_DimEntries), pygen_variable_DimEntries},
|
||||
{SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE, ARRAY_SIZE(pygen_variable_SamplerAddressingModeEntries), pygen_variable_SamplerAddressingModeEntries},
|
||||
{SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE, ARRAY_SIZE(pygen_variable_SamplerFilterModeEntries), pygen_variable_SamplerFilterModeEntries},
|
||||
{SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT, ARRAY_SIZE(pygen_variable_ImageFormatEntries), pygen_variable_ImageFormatEntries},
|
||||
{SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER, ARRAY_SIZE(pygen_variable_ImageChannelOrderEntries), pygen_variable_ImageChannelOrderEntries},
|
||||
{SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE, ARRAY_SIZE(pygen_variable_ImageChannelDataTypeEntries), pygen_variable_ImageChannelDataTypeEntries},
|
||||
{SPV_OPERAND_TYPE_FP_ROUNDING_MODE, ARRAY_SIZE(pygen_variable_FPRoundingModeEntries), pygen_variable_FPRoundingModeEntries},
|
||||
{SPV_OPERAND_TYPE_LINKAGE_TYPE, ARRAY_SIZE(pygen_variable_LinkageTypeEntries), pygen_variable_LinkageTypeEntries},
|
||||
{SPV_OPERAND_TYPE_ACCESS_QUALIFIER, ARRAY_SIZE(pygen_variable_AccessQualifierEntries), pygen_variable_AccessQualifierEntries},
|
||||
{SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE, ARRAY_SIZE(pygen_variable_FunctionParameterAttributeEntries), pygen_variable_FunctionParameterAttributeEntries},
|
||||
{SPV_OPERAND_TYPE_DECORATION, ARRAY_SIZE(pygen_variable_DecorationEntries), pygen_variable_DecorationEntries},
|
||||
{SPV_OPERAND_TYPE_BUILT_IN, ARRAY_SIZE(pygen_variable_BuiltInEntries), pygen_variable_BuiltInEntries},
|
||||
{SPV_OPERAND_TYPE_SCOPE_ID, ARRAY_SIZE(pygen_variable_ScopeEntries), pygen_variable_ScopeEntries},
|
||||
{SPV_OPERAND_TYPE_GROUP_OPERATION, ARRAY_SIZE(pygen_variable_GroupOperationEntries), pygen_variable_GroupOperationEntries},
|
||||
{SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS, ARRAY_SIZE(pygen_variable_KernelEnqueueFlagsEntries), pygen_variable_KernelEnqueueFlagsEntries},
|
||||
{SPV_OPERAND_TYPE_CAPABILITY, ARRAY_SIZE(pygen_variable_CapabilityEntries), pygen_variable_CapabilityEntries},
|
||||
{SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, ARRAY_SIZE(pygen_variable_DebugInfoFlagsEntries), pygen_variable_DebugInfoFlagsEntries},
|
||||
{SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING, ARRAY_SIZE(pygen_variable_DebugBaseTypeAttributeEncodingEntries), pygen_variable_DebugBaseTypeAttributeEncodingEntries},
|
||||
{SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE, ARRAY_SIZE(pygen_variable_DebugCompositeTypeEntries), pygen_variable_DebugCompositeTypeEntries},
|
||||
{SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER, ARRAY_SIZE(pygen_variable_DebugTypeQualifierEntries), pygen_variable_DebugTypeQualifierEntries},
|
||||
{SPV_OPERAND_TYPE_DEBUG_OPERATION, ARRAY_SIZE(pygen_variable_DebugOperationEntries), pygen_variable_DebugOperationEntries},
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_IMAGE, ARRAY_SIZE(pygen_variable_ImageOperandsEntries), pygen_variable_ImageOperandsEntries},
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS, ARRAY_SIZE(pygen_variable_MemoryAccessEntries), pygen_variable_MemoryAccessEntries},
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER, ARRAY_SIZE(pygen_variable_AccessQualifierEntries), pygen_variable_AccessQualifierEntries}
|
||||
};
|
7
3rdparty/spirv-tools/include/generated/spv-amd-gcn-shader.insts.inc
vendored
Normal file
7
3rdparty/spirv-tools/include/generated/spv-amd-gcn-shader.insts.inc
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
|
||||
static const spv_ext_inst_desc_t spv_amd_gcn_shader_entries[] = {
|
||||
{"CubeFaceIndexAMD", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"CubeFaceCoordAMD", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"TimeAMD", 3, 0, nullptr, {SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
8
3rdparty/spirv-tools/include/generated/spv-amd-shader-ballot.insts.inc
vendored
Normal file
8
3rdparty/spirv-tools/include/generated/spv-amd-shader-ballot.insts.inc
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
|
||||
static const spv_ext_inst_desc_t spv_amd_shader_ballot_entries[] = {
|
||||
{"SwizzleInvocationsAMD", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"SwizzleInvocationsMaskedAMD", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"WriteInvocationAMD", 3, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"MbcntAMD", 4, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
5
3rdparty/spirv-tools/include/generated/spv-amd-shader-explicit-vertex-parameter.insts.inc
vendored
Normal file
5
3rdparty/spirv-tools/include/generated/spv-amd-shader-explicit-vertex-parameter.insts.inc
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
static const spv_ext_inst_desc_t spv_amd_shader_explicit_vertex_parameter_entries[] = {
|
||||
{"InterpolateAtVertexAMD", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
13
3rdparty/spirv-tools/include/generated/spv-amd-shader-trinary-minmax.insts.inc
vendored
Normal file
13
3rdparty/spirv-tools/include/generated/spv-amd-shader-trinary-minmax.insts.inc
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
|
||||
static const spv_ext_inst_desc_t spv_amd_shader_trinary_minmax_entries[] = {
|
||||
{"FMin3AMD", 1, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UMin3AMD", 2, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"SMin3AMD", 3, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FMax3AMD", 4, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UMax3AMD", 5, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"SMax3AMD", 6, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FMid3AMD", 7, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"UMid3AMD", 8, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}},
|
||||
{"SMid3AMD", 9, 0, nullptr, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_NONE}}
|
||||
};
|
586
3rdparty/spirv-tools/include/spirv-tools/libspirv.h
vendored
Normal file
586
3rdparty/spirv-tools/include/spirv-tools/libspirv.h
vendored
Normal file
@ -0,0 +1,586 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SPIRV_TOOLS_LIBSPIRV_H_
|
||||
#define SPIRV_TOOLS_LIBSPIRV_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(SPIRV_TOOLS_SHAREDLIB)
|
||||
#if defined(_WIN32)
|
||||
#if defined(SPIRV_TOOLS_IMPLEMENTATION)
|
||||
#define SPIRV_TOOLS_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define SPIRV_TOOLS_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#if defined(SPIRV_TOOLS_IMPLEMENTATION)
|
||||
#define SPIRV_TOOLS_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define SPIRV_TOOLS_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define SPIRV_TOOLS_EXPORT
|
||||
#endif
|
||||
|
||||
// Helpers
|
||||
|
||||
#define SPV_BIT(shift) (1 << (shift))
|
||||
|
||||
#define SPV_FORCE_16_BIT_ENUM(name) _##name = 0x7fff
|
||||
#define SPV_FORCE_32_BIT_ENUM(name) _##name = 0x7fffffff
|
||||
|
||||
// Enumerations
|
||||
|
||||
typedef enum spv_result_t {
|
||||
SPV_SUCCESS = 0,
|
||||
SPV_UNSUPPORTED = 1,
|
||||
SPV_END_OF_STREAM = 2,
|
||||
SPV_WARNING = 3,
|
||||
SPV_FAILED_MATCH = 4,
|
||||
SPV_REQUESTED_TERMINATION = 5, // Success, but signals early termination.
|
||||
SPV_ERROR_INTERNAL = -1,
|
||||
SPV_ERROR_OUT_OF_MEMORY = -2,
|
||||
SPV_ERROR_INVALID_POINTER = -3,
|
||||
SPV_ERROR_INVALID_BINARY = -4,
|
||||
SPV_ERROR_INVALID_TEXT = -5,
|
||||
SPV_ERROR_INVALID_TABLE = -6,
|
||||
SPV_ERROR_INVALID_VALUE = -7,
|
||||
SPV_ERROR_INVALID_DIAGNOSTIC = -8,
|
||||
SPV_ERROR_INVALID_LOOKUP = -9,
|
||||
SPV_ERROR_INVALID_ID = -10,
|
||||
SPV_ERROR_INVALID_CFG = -11,
|
||||
SPV_ERROR_INVALID_LAYOUT = -12,
|
||||
SPV_ERROR_INVALID_CAPABILITY = -13,
|
||||
SPV_ERROR_INVALID_DATA = -14, // Indicates data rules validation failure.
|
||||
SPV_ERROR_MISSING_EXTENSION = -15,
|
||||
SPV_ERROR_WRONG_VERSION = -16, // Indicates wrong SPIR-V version
|
||||
SPV_FORCE_32_BIT_ENUM(spv_result_t)
|
||||
} spv_result_t;
|
||||
|
||||
// Severity levels of messages communicated to the consumer.
|
||||
typedef enum spv_message_level_t {
|
||||
SPV_MSG_FATAL, // Unrecoverable error due to environment.
|
||||
// Will exit the program immediately. E.g.,
|
||||
// out of memory.
|
||||
SPV_MSG_INTERNAL_ERROR, // Unrecoverable error due to SPIRV-Tools
|
||||
// internals.
|
||||
// Will exit the program immediately. E.g.,
|
||||
// unimplemented feature.
|
||||
SPV_MSG_ERROR, // Normal error due to user input.
|
||||
SPV_MSG_WARNING, // Warning information.
|
||||
SPV_MSG_INFO, // General information.
|
||||
SPV_MSG_DEBUG, // Debug information.
|
||||
} spv_message_level_t;
|
||||
|
||||
typedef enum spv_endianness_t {
|
||||
SPV_ENDIANNESS_LITTLE,
|
||||
SPV_ENDIANNESS_BIG,
|
||||
SPV_FORCE_32_BIT_ENUM(spv_endianness_t)
|
||||
} spv_endianness_t;
|
||||
|
||||
// The kinds of operands that an instruction may have.
|
||||
//
|
||||
// Some operand types are "concrete". The binary parser uses a concrete
|
||||
// operand type to describe an operand of a parsed instruction.
|
||||
//
|
||||
// The assembler uses all operand types. In addition to determining what
|
||||
// kind of value an operand may be, non-concrete operand types capture the
|
||||
// fact that an operand might be optional (may be absent, or present exactly
|
||||
// once), or might occur zero or more times.
|
||||
//
|
||||
// Sometimes we also need to be able to express the fact that an operand
|
||||
// is a member of an optional tuple of values. In that case the first member
|
||||
// would be optional, and the subsequent members would be required.
|
||||
typedef enum spv_operand_type_t {
|
||||
// A sentinel value.
|
||||
SPV_OPERAND_TYPE_NONE = 0,
|
||||
|
||||
// Set 1: Operands that are IDs.
|
||||
SPV_OPERAND_TYPE_ID,
|
||||
SPV_OPERAND_TYPE_TYPE_ID,
|
||||
SPV_OPERAND_TYPE_RESULT_ID,
|
||||
SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, // SPIR-V Sec 3.25
|
||||
SPV_OPERAND_TYPE_SCOPE_ID, // SPIR-V Sec 3.27
|
||||
|
||||
// Set 2: Operands that are literal numbers.
|
||||
SPV_OPERAND_TYPE_LITERAL_INTEGER, // Always unsigned 32-bits.
|
||||
// The Instruction argument to OpExtInst. It's an unsigned 32-bit literal
|
||||
// number indicating which instruction to use from an extended instruction
|
||||
// set.
|
||||
SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
|
||||
// The Opcode argument to OpSpecConstantOp. It determines the operation
|
||||
// to be performed on constant operands to compute a specialization constant
|
||||
// result.
|
||||
SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER,
|
||||
// A literal number whose format and size are determined by a previous operand
|
||||
// in the same instruction. It's a signed integer, an unsigned integer, or a
|
||||
// floating point number. It also has a specified bit width. The width
|
||||
// may be larger than 32, which would require such a typed literal value to
|
||||
// occupy multiple SPIR-V words.
|
||||
SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
|
||||
|
||||
// Set 3: The literal string operand type.
|
||||
SPV_OPERAND_TYPE_LITERAL_STRING,
|
||||
|
||||
// Set 4: Operands that are a single word enumerated value.
|
||||
SPV_OPERAND_TYPE_SOURCE_LANGUAGE, // SPIR-V Sec 3.2
|
||||
SPV_OPERAND_TYPE_EXECUTION_MODEL, // SPIR-V Sec 3.3
|
||||
SPV_OPERAND_TYPE_ADDRESSING_MODEL, // SPIR-V Sec 3.4
|
||||
SPV_OPERAND_TYPE_MEMORY_MODEL, // SPIR-V Sec 3.5
|
||||
SPV_OPERAND_TYPE_EXECUTION_MODE, // SPIR-V Sec 3.6
|
||||
SPV_OPERAND_TYPE_STORAGE_CLASS, // SPIR-V Sec 3.7
|
||||
SPV_OPERAND_TYPE_DIMENSIONALITY, // SPIR-V Sec 3.8
|
||||
SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE, // SPIR-V Sec 3.9
|
||||
SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE, // SPIR-V Sec 3.10
|
||||
SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT, // SPIR-V Sec 3.11
|
||||
SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER, // SPIR-V Sec 3.12
|
||||
SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE, // SPIR-V Sec 3.13
|
||||
SPV_OPERAND_TYPE_FP_ROUNDING_MODE, // SPIR-V Sec 3.16
|
||||
SPV_OPERAND_TYPE_LINKAGE_TYPE, // SPIR-V Sec 3.17
|
||||
SPV_OPERAND_TYPE_ACCESS_QUALIFIER, // SPIR-V Sec 3.18
|
||||
SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE, // SPIR-V Sec 3.19
|
||||
SPV_OPERAND_TYPE_DECORATION, // SPIR-V Sec 3.20
|
||||
SPV_OPERAND_TYPE_BUILT_IN, // SPIR-V Sec 3.21
|
||||
SPV_OPERAND_TYPE_GROUP_OPERATION, // SPIR-V Sec 3.28
|
||||
SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS, // SPIR-V Sec 3.29
|
||||
SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO, // SPIR-V Sec 3.30
|
||||
SPV_OPERAND_TYPE_CAPABILITY, // SPIR-V Sec 3.31
|
||||
|
||||
// Set 5: Operands that are a single word bitmask.
|
||||
// Sometimes a set bit indicates the instruction requires still more operands.
|
||||
SPV_OPERAND_TYPE_IMAGE, // SPIR-V Sec 3.14
|
||||
SPV_OPERAND_TYPE_FP_FAST_MATH_MODE, // SPIR-V Sec 3.15
|
||||
SPV_OPERAND_TYPE_SELECTION_CONTROL, // SPIR-V Sec 3.22
|
||||
SPV_OPERAND_TYPE_LOOP_CONTROL, // SPIR-V Sec 3.23
|
||||
SPV_OPERAND_TYPE_FUNCTION_CONTROL, // SPIR-V Sec 3.24
|
||||
SPV_OPERAND_TYPE_MEMORY_ACCESS, // SPIR-V Sec 3.26
|
||||
|
||||
// The remaining operand types are only used internally by the assembler.
|
||||
// There are two categories:
|
||||
// Optional : expands to 0 or 1 operand, like ? in regular expressions.
|
||||
// Variable : expands to 0, 1 or many operands or pairs of operands.
|
||||
// This is similar to * in regular expressions.
|
||||
|
||||
// Macros for defining bounds on optional and variable operand types.
|
||||
// Any variable operand type is also optional.
|
||||
#define FIRST_OPTIONAL(ENUM) ENUM, SPV_OPERAND_TYPE_FIRST_OPTIONAL_TYPE = ENUM
|
||||
#define FIRST_VARIABLE(ENUM) ENUM, SPV_OPERAND_TYPE_FIRST_VARIABLE_TYPE = ENUM
|
||||
#define LAST_VARIABLE(ENUM) \
|
||||
ENUM, SPV_OPERAND_TYPE_LAST_VARIABLE_TYPE = ENUM, \
|
||||
SPV_OPERAND_TYPE_LAST_OPTIONAL_TYPE = ENUM
|
||||
|
||||
// An optional operand represents zero or one logical operands.
|
||||
// In an instruction definition, this may only appear at the end of the
|
||||
// operand types.
|
||||
FIRST_OPTIONAL(SPV_OPERAND_TYPE_OPTIONAL_ID),
|
||||
// An optional image operand type.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_IMAGE,
|
||||
// An optional memory access type.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
|
||||
// An optional literal integer.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER,
|
||||
// An optional literal number, which may be either integer or floating point.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER,
|
||||
// Like SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER, but optional, and integral.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER,
|
||||
// An optional literal string.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING,
|
||||
// An optional access qualifier
|
||||
SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER,
|
||||
// An optional context-independent value, or CIV. CIVs are tokens that we can
|
||||
// assemble regardless of where they occur -- literals, IDs, immediate
|
||||
// integers, etc.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_CIV,
|
||||
|
||||
// A variable operand represents zero or more logical operands.
|
||||
// In an instruction definition, this may only appear at the end of the
|
||||
// operand types.
|
||||
FIRST_VARIABLE(SPV_OPERAND_TYPE_VARIABLE_ID),
|
||||
SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER,
|
||||
// A sequence of zero or more pairs of (typed literal integer, Id).
|
||||
// Expands to zero or more:
|
||||
// (SPV_OPERAND_TYPE_TYPED_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID)
|
||||
// where the literal number must always be an integer of some sort.
|
||||
SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID,
|
||||
// A sequence of zero or more pairs of (Id, Literal integer)
|
||||
LAST_VARIABLE(SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER),
|
||||
|
||||
// The following are concrete enum types.
|
||||
SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS, // DebugInfo Sec 3.2. A mask.
|
||||
SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING, // DebugInfo Sec 3.3
|
||||
SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE, // DebugInfo Sec 3.4
|
||||
SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER, // DebugInfo Sec 3.5
|
||||
SPV_OPERAND_TYPE_DEBUG_OPERATION, // DebugInfo Sec 3.6
|
||||
|
||||
// This is a sentinel value, and does not represent an operand type.
|
||||
// It should come last.
|
||||
SPV_OPERAND_TYPE_NUM_OPERAND_TYPES,
|
||||
|
||||
SPV_FORCE_32_BIT_ENUM(spv_operand_type_t)
|
||||
} spv_operand_type_t;
|
||||
|
||||
typedef enum spv_ext_inst_type_t {
|
||||
SPV_EXT_INST_TYPE_NONE = 0,
|
||||
SPV_EXT_INST_TYPE_GLSL_STD_450,
|
||||
SPV_EXT_INST_TYPE_OPENCL_STD,
|
||||
SPV_EXT_INST_TYPE_SPV_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER,
|
||||
SPV_EXT_INST_TYPE_SPV_AMD_SHADER_TRINARY_MINMAX,
|
||||
SPV_EXT_INST_TYPE_SPV_AMD_GCN_SHADER,
|
||||
SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT,
|
||||
SPV_EXT_INST_TYPE_DEBUGINFO,
|
||||
|
||||
SPV_FORCE_32_BIT_ENUM(spv_ext_inst_type_t)
|
||||
} spv_ext_inst_type_t;
|
||||
|
||||
// This determines at a high level the kind of a binary-encoded literal
|
||||
// number, but not the bit width.
|
||||
// In principle, these could probably be folded into new entries in
|
||||
// spv_operand_type_t. But then we'd have some special case differences
|
||||
// between the assembler and disassembler.
|
||||
typedef enum spv_number_kind_t {
|
||||
SPV_NUMBER_NONE = 0, // The default for value initialization.
|
||||
SPV_NUMBER_UNSIGNED_INT,
|
||||
SPV_NUMBER_SIGNED_INT,
|
||||
SPV_NUMBER_FLOATING,
|
||||
} spv_number_kind_t;
|
||||
|
||||
typedef enum spv_text_to_binary_options_t {
|
||||
SPV_TEXT_TO_BINARY_OPTION_NONE = SPV_BIT(0),
|
||||
// Numeric IDs in the binary will have the same values as in the source.
|
||||
// Non-numeric IDs are allocated by filling in the gaps, starting with 1
|
||||
// and going up.
|
||||
SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS = SPV_BIT(1),
|
||||
SPV_FORCE_32_BIT_ENUM(spv_text_to_binary_options_t)
|
||||
} spv_text_to_binary_options_t;
|
||||
|
||||
typedef enum spv_binary_to_text_options_t {
|
||||
SPV_BINARY_TO_TEXT_OPTION_NONE = SPV_BIT(0),
|
||||
SPV_BINARY_TO_TEXT_OPTION_PRINT = SPV_BIT(1),
|
||||
SPV_BINARY_TO_TEXT_OPTION_COLOR = SPV_BIT(2),
|
||||
SPV_BINARY_TO_TEXT_OPTION_INDENT = SPV_BIT(3),
|
||||
SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET = SPV_BIT(4),
|
||||
// Do not output the module header as leading comments in the assembly.
|
||||
SPV_BINARY_TO_TEXT_OPTION_NO_HEADER = SPV_BIT(5),
|
||||
// Use friendly names where possible. The heuristic may expand over
|
||||
// time, but will use common names for scalar types, and debug names from
|
||||
// OpName instructions.
|
||||
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES = SPV_BIT(6),
|
||||
SPV_FORCE_32_BIT_ENUM(spv_binary_to_text_options_t)
|
||||
} spv_binary_to_text_options_t;
|
||||
|
||||
// Structures
|
||||
|
||||
// Information about an operand parsed from a binary SPIR-V module.
|
||||
// Note that the values are not included. You still need access to the binary
|
||||
// to extract the values.
|
||||
typedef struct spv_parsed_operand_t {
|
||||
// Location of the operand, in words from the start of the instruction.
|
||||
uint16_t offset;
|
||||
// Number of words occupied by this operand.
|
||||
uint16_t num_words;
|
||||
// The "concrete" operand type. See the definition of spv_operand_type_t
|
||||
// for details.
|
||||
spv_operand_type_t type;
|
||||
// If type is a literal number type, then number_kind says whether it's
|
||||
// a signed integer, an unsigned integer, or a floating point number.
|
||||
spv_number_kind_t number_kind;
|
||||
// The number of bits for a literal number type.
|
||||
uint32_t number_bit_width;
|
||||
} spv_parsed_operand_t;
|
||||
|
||||
// An instruction parsed from a binary SPIR-V module.
|
||||
typedef struct spv_parsed_instruction_t {
|
||||
// An array of words for this instruction, in native endianness.
|
||||
const uint32_t* words;
|
||||
// The number of words in this instruction.
|
||||
uint16_t num_words;
|
||||
uint16_t opcode;
|
||||
// The extended instruction type, if opcode is OpExtInst. Otherwise
|
||||
// this is the "none" value.
|
||||
spv_ext_inst_type_t ext_inst_type;
|
||||
// The type id, or 0 if this instruction doesn't have one.
|
||||
uint32_t type_id;
|
||||
// The result id, or 0 if this instruction doesn't have one.
|
||||
uint32_t result_id;
|
||||
// The array of parsed operands.
|
||||
const spv_parsed_operand_t* operands;
|
||||
uint16_t num_operands;
|
||||
} spv_parsed_instruction_t;
|
||||
|
||||
typedef struct spv_const_binary_t {
|
||||
const uint32_t* code;
|
||||
const size_t wordCount;
|
||||
} spv_const_binary_t;
|
||||
|
||||
typedef struct spv_binary_t {
|
||||
uint32_t* code;
|
||||
size_t wordCount;
|
||||
} spv_binary_t;
|
||||
|
||||
typedef struct spv_text_t {
|
||||
const char* str;
|
||||
size_t length;
|
||||
} spv_text_t;
|
||||
|
||||
typedef struct spv_position_t {
|
||||
size_t line;
|
||||
size_t column;
|
||||
size_t index;
|
||||
} spv_position_t;
|
||||
|
||||
typedef struct spv_diagnostic_t {
|
||||
spv_position_t position;
|
||||
char* error;
|
||||
bool isTextSource;
|
||||
} spv_diagnostic_t;
|
||||
|
||||
// Opaque struct containing the context used to operate on a SPIR-V module.
|
||||
// Its object is used by various translation API functions.
|
||||
typedef struct spv_context_t spv_context_t;
|
||||
|
||||
typedef struct spv_validator_options_t spv_validator_options_t;
|
||||
|
||||
// Type Definitions
|
||||
|
||||
typedef spv_const_binary_t* spv_const_binary;
|
||||
typedef spv_binary_t* spv_binary;
|
||||
typedef spv_text_t* spv_text;
|
||||
typedef spv_position_t* spv_position;
|
||||
typedef spv_diagnostic_t* spv_diagnostic;
|
||||
typedef const spv_context_t* spv_const_context;
|
||||
typedef spv_context_t* spv_context;
|
||||
typedef spv_validator_options_t* spv_validator_options;
|
||||
typedef const spv_validator_options_t* spv_const_validator_options;
|
||||
|
||||
// Platform API
|
||||
|
||||
// Returns the SPIRV-Tools software version as a null-terminated string.
|
||||
// The contents of the underlying storage is valid for the remainder of
|
||||
// the process.
|
||||
SPIRV_TOOLS_EXPORT const char* spvSoftwareVersionString(void);
|
||||
// Returns a null-terminated string containing the name of the project,
|
||||
// the software version string, and commit details.
|
||||
// The contents of the underlying storage is valid for the remainder of
|
||||
// the process.
|
||||
SPIRV_TOOLS_EXPORT const char* spvSoftwareVersionDetailsString(void);
|
||||
|
||||
// Certain target environments impose additional restrictions on SPIR-V, so it's
|
||||
// often necessary to specify which one applies. SPV_ENV_UNIVERSAL means
|
||||
// environment-agnostic SPIR-V.
|
||||
typedef enum {
|
||||
SPV_ENV_UNIVERSAL_1_0, // SPIR-V 1.0 latest revision, no other restrictions.
|
||||
SPV_ENV_VULKAN_1_0, // Vulkan 1.0 latest revision.
|
||||
SPV_ENV_UNIVERSAL_1_1, // SPIR-V 1.1 latest revision, no other restrictions.
|
||||
SPV_ENV_OPENCL_2_1, // OpenCL Full Profile 2.1 latest revision.
|
||||
SPV_ENV_OPENCL_2_2, // OpenCL Full Profile 2.2 latest revision.
|
||||
SPV_ENV_OPENGL_4_0, // OpenGL 4.0 plus GL_ARB_gl_spirv, latest revisions.
|
||||
SPV_ENV_OPENGL_4_1, // OpenGL 4.1 plus GL_ARB_gl_spirv, latest revisions.
|
||||
SPV_ENV_OPENGL_4_2, // OpenGL 4.2 plus GL_ARB_gl_spirv, latest revisions.
|
||||
SPV_ENV_OPENGL_4_3, // OpenGL 4.3 plus GL_ARB_gl_spirv, latest revisions.
|
||||
// There is no variant for OpenGL 4.4.
|
||||
SPV_ENV_OPENGL_4_5, // OpenGL 4.5 plus GL_ARB_gl_spirv, latest revisions.
|
||||
SPV_ENV_UNIVERSAL_1_2, // SPIR-V 1.2, latest revision, no other restrictions.
|
||||
SPV_ENV_OPENCL_1_2, // OpenCL Full Profile 1.2 plus cl_khr_il_program,
|
||||
// latest revision.
|
||||
SPV_ENV_OPENCL_EMBEDDED_1_2, // OpenCL Embedded Profile 1.2 plus
|
||||
// cl_khr_il_program, latest revision.
|
||||
SPV_ENV_OPENCL_2_0, // OpenCL Full Profile 2.0 plus cl_khr_il_program,
|
||||
// latest revision.
|
||||
SPV_ENV_OPENCL_EMBEDDED_2_0, // OpenCL Embedded Profile 2.0 plus
|
||||
// cl_khr_il_program, latest revision.
|
||||
SPV_ENV_OPENCL_EMBEDDED_2_1, // OpenCL Embedded Profile 2.1 latest revision.
|
||||
SPV_ENV_OPENCL_EMBEDDED_2_2, // OpenCL Embedded Profile 2.2 latest revision.
|
||||
SPV_ENV_UNIVERSAL_1_3, // SPIR-V 1.3 latest revision, no other restrictions.
|
||||
SPV_ENV_VULKAN_1_1, // Vulkan 1.1 latest revision.
|
||||
} spv_target_env;
|
||||
|
||||
// SPIR-V Validator can be parameterized with the following Universal Limits.
|
||||
typedef enum {
|
||||
spv_validator_limit_max_struct_members,
|
||||
spv_validator_limit_max_struct_depth,
|
||||
spv_validator_limit_max_local_variables,
|
||||
spv_validator_limit_max_global_variables,
|
||||
spv_validator_limit_max_switch_branches,
|
||||
spv_validator_limit_max_function_args,
|
||||
spv_validator_limit_max_control_flow_nesting_depth,
|
||||
spv_validator_limit_max_access_chain_indexes,
|
||||
} spv_validator_limit;
|
||||
|
||||
// Returns a string describing the given SPIR-V target environment.
|
||||
SPIRV_TOOLS_EXPORT const char* spvTargetEnvDescription(spv_target_env env);
|
||||
|
||||
// Creates a context object. Returns null if env is invalid.
|
||||
SPIRV_TOOLS_EXPORT spv_context spvContextCreate(spv_target_env env);
|
||||
|
||||
// Destroys the given context object.
|
||||
SPIRV_TOOLS_EXPORT void spvContextDestroy(spv_context context);
|
||||
|
||||
// Creates a Validator options object with default options. Returns a valid
|
||||
// options object. The object remains valid until it is passed into
|
||||
// spvValidatorOptionsDestroy.
|
||||
SPIRV_TOOLS_EXPORT spv_validator_options spvValidatorOptionsCreate(void);
|
||||
|
||||
// Destroys the given Validator options object.
|
||||
SPIRV_TOOLS_EXPORT void spvValidatorOptionsDestroy(
|
||||
spv_validator_options options);
|
||||
|
||||
// Records the maximum Universal Limit that is considered valid in the given
|
||||
// Validator options object. <options> argument must be a valid options object.
|
||||
SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetUniversalLimit(
|
||||
spv_validator_options options, spv_validator_limit limit_type,
|
||||
uint32_t limit);
|
||||
|
||||
// Record whether or not the validator should relax the rules on types for
|
||||
// stores to structs. When relaxed, it will allow a type mismatch as long as
|
||||
// the types are structs with the same layout. Two structs have the same layout
|
||||
// if
|
||||
//
|
||||
// 1) the members of the structs are either the same type or are structs with
|
||||
// same layout, and
|
||||
//
|
||||
// 2) the decorations that affect the memory layout are identical for both
|
||||
// types. Other decorations are not relevant.
|
||||
SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetRelaxStoreStruct(
|
||||
spv_validator_options options, bool val);
|
||||
|
||||
// Records whether or not the validator should relax the rules on pointer usage
|
||||
// in logical addressing mode.
|
||||
//
|
||||
// When relaxed, it will allow the following usage cases of pointers:
|
||||
// 1) OpVariable allocating an object whose type is a pointer type
|
||||
// 2) OpReturnValue returning a pointer value
|
||||
SPIRV_TOOLS_EXPORT void spvValidatorOptionsSetRelaxLogicalPointer(
|
||||
spv_validator_options options, bool val);
|
||||
|
||||
// Encodes the given SPIR-V assembly text to its binary representation. The
|
||||
// length parameter specifies the number of bytes for text. Encoded binary will
|
||||
// be stored into *binary. Any error will be written into *diagnostic if
|
||||
// diagnostic is non-null. The generated binary is independent of the context
|
||||
// and may outlive it.
|
||||
SPIRV_TOOLS_EXPORT spv_result_t spvTextToBinary(const spv_const_context context,
|
||||
const char* text,
|
||||
const size_t length,
|
||||
spv_binary* binary,
|
||||
spv_diagnostic* diagnostic);
|
||||
|
||||
// Encodes the given SPIR-V assembly text to its binary representation. Same as
|
||||
// spvTextToBinary but with options. The options parameter is a bit field of
|
||||
// spv_text_to_binary_options_t.
|
||||
SPIRV_TOOLS_EXPORT spv_result_t spvTextToBinaryWithOptions(
|
||||
const spv_const_context context, const char* text, const size_t length,
|
||||
const uint32_t options, spv_binary* binary, spv_diagnostic* diagnostic);
|
||||
|
||||
// Frees an allocated text stream. This is a no-op if the text parameter
|
||||
// is a null pointer.
|
||||
SPIRV_TOOLS_EXPORT void spvTextDestroy(spv_text text);
|
||||
|
||||
// Decodes the given SPIR-V binary representation to its assembly text. The
|
||||
// word_count parameter specifies the number of words for binary. The options
|
||||
// parameter is a bit field of spv_binary_to_text_options_t. Decoded text will
|
||||
// be stored into *text. Any error will be written into *diagnostic if
|
||||
// diagnostic is non-null.
|
||||
SPIRV_TOOLS_EXPORT spv_result_t spvBinaryToText(const spv_const_context context,
|
||||
const uint32_t* binary,
|
||||
const size_t word_count,
|
||||
const uint32_t options,
|
||||
spv_text* text,
|
||||
spv_diagnostic* diagnostic);
|
||||
|
||||
// Frees a binary stream from memory. This is a no-op if binary is a null
|
||||
// pointer.
|
||||
SPIRV_TOOLS_EXPORT void spvBinaryDestroy(spv_binary binary);
|
||||
|
||||
// Validates a SPIR-V binary for correctness. Any errors will be written into
|
||||
// *diagnostic if diagnostic is non-null.
|
||||
SPIRV_TOOLS_EXPORT spv_result_t spvValidate(const spv_const_context context,
|
||||
const spv_const_binary binary,
|
||||
spv_diagnostic* diagnostic);
|
||||
|
||||
// Validates a SPIR-V binary for correctness. Uses the provided Validator
|
||||
// options. Any errors will be written into *diagnostic if diagnostic is
|
||||
// non-null.
|
||||
SPIRV_TOOLS_EXPORT spv_result_t spvValidateWithOptions(
|
||||
const spv_const_context context, const spv_const_validator_options options,
|
||||
const spv_const_binary binary, spv_diagnostic* diagnostic);
|
||||
|
||||
// Validates a raw SPIR-V binary for correctness. Any errors will be written
|
||||
// into *diagnostic if diagnostic is non-null.
|
||||
SPIRV_TOOLS_EXPORT spv_result_t
|
||||
spvValidateBinary(const spv_const_context context, const uint32_t* words,
|
||||
const size_t num_words, spv_diagnostic* diagnostic);
|
||||
|
||||
// Creates a diagnostic object. The position parameter specifies the location in
|
||||
// the text/binary stream. The message parameter, copied into the diagnostic
|
||||
// object, contains the error message to display.
|
||||
SPIRV_TOOLS_EXPORT spv_diagnostic
|
||||
spvDiagnosticCreate(const spv_position position, const char* message);
|
||||
|
||||
// Destroys a diagnostic object. This is a no-op if diagnostic is a null
|
||||
// pointer.
|
||||
SPIRV_TOOLS_EXPORT void spvDiagnosticDestroy(spv_diagnostic diagnostic);
|
||||
|
||||
// Prints the diagnostic to stderr.
|
||||
SPIRV_TOOLS_EXPORT spv_result_t
|
||||
spvDiagnosticPrint(const spv_diagnostic diagnostic);
|
||||
|
||||
// The binary parser interface.
|
||||
|
||||
// A pointer to a function that accepts a parsed SPIR-V header.
|
||||
// The integer arguments are the 32-bit words from the header, as specified
|
||||
// in SPIR-V 1.0 Section 2.3 Table 1.
|
||||
// The function should return SPV_SUCCESS if parsing should continue.
|
||||
typedef spv_result_t (*spv_parsed_header_fn_t)(
|
||||
void* user_data, spv_endianness_t endian, uint32_t magic, uint32_t version,
|
||||
uint32_t generator, uint32_t id_bound, uint32_t reserved);
|
||||
|
||||
// A pointer to a function that accepts a parsed SPIR-V instruction.
|
||||
// The parsed_instruction value is transient: it may be overwritten
|
||||
// or released immediately after the function has returned. That also
|
||||
// applies to the words array member of the parsed instruction. The
|
||||
// function should return SPV_SUCCESS if and only if parsing should
|
||||
// continue.
|
||||
typedef spv_result_t (*spv_parsed_instruction_fn_t)(
|
||||
void* user_data, const spv_parsed_instruction_t* parsed_instruction);
|
||||
|
||||
// Parses a SPIR-V binary, specified as counted sequence of 32-bit words.
|
||||
// Parsing feedback is provided via two callbacks provided as function
|
||||
// pointers. Each callback function pointer can be a null pointer, in
|
||||
// which case it is never called. Otherwise, in a valid parse the
|
||||
// parsed-header callback is called once, and then the parsed-instruction
|
||||
// callback once for each instruction in the stream. The user_data parameter
|
||||
// is supplied as context to the callbacks. Returns SPV_SUCCESS on successful
|
||||
// parse where the callbacks always return SPV_SUCCESS. For an invalid parse,
|
||||
// returns a status code other than SPV_SUCCESS, and if diagnostic is non-null
|
||||
// also emits a diagnostic. If a callback returns anything other than
|
||||
// SPV_SUCCESS, then that status code is returned, no further callbacks are
|
||||
// issued, and no additional diagnostics are emitted.
|
||||
SPIRV_TOOLS_EXPORT spv_result_t spvBinaryParse(
|
||||
const spv_const_context context, void* user_data, const uint32_t* words,
|
||||
const size_t num_words, spv_parsed_header_fn_t parse_header,
|
||||
spv_parsed_instruction_fn_t parse_instruction, spv_diagnostic* diagnostic);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SPIRV_TOOLS_LIBSPIRV_H_
|
174
3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp
vendored
Normal file
174
3rdparty/spirv-tools/include/spirv-tools/libspirv.hpp
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SPIRV_TOOLS_LIBSPIRV_HPP_
|
||||
#define SPIRV_TOOLS_LIBSPIRV_HPP_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
// Message consumer. The C strings for source and message are only alive for the
|
||||
// specific invocation.
|
||||
using MessageConsumer = std::function<void(
|
||||
spv_message_level_t /* level */, const char* /* source */,
|
||||
const spv_position_t& /* position */, const char* /* message */
|
||||
)>;
|
||||
|
||||
// C++ RAII wrapper around the C context object spv_context.
|
||||
class Context {
|
||||
public:
|
||||
// Constructs a context targeting the given environment |env|.
|
||||
//
|
||||
// The constructed instance will have an empty message consumer, which just
|
||||
// ignores all messages from the library. Use SetMessageConsumer() to supply
|
||||
// one if messages are of concern.
|
||||
explicit Context(spv_target_env env);
|
||||
|
||||
// Enables move constructor/assignment operations.
|
||||
Context(Context&& other);
|
||||
Context& operator=(Context&& other);
|
||||
|
||||
// Disables copy constructor/assignment operations.
|
||||
Context(const Context&) = delete;
|
||||
Context& operator=(const Context&) = delete;
|
||||
|
||||
// Destructs this instance.
|
||||
~Context();
|
||||
|
||||
// Sets the message consumer to the given |consumer|. The |consumer| will be
|
||||
// invoked once for each message communicated from the library.
|
||||
void SetMessageConsumer(MessageConsumer consumer);
|
||||
|
||||
// Returns the underlying spv_context.
|
||||
spv_context& CContext();
|
||||
const spv_context& CContext() const;
|
||||
|
||||
private:
|
||||
spv_context context_;
|
||||
};
|
||||
|
||||
// A RAII wrapper around a validator options object.
|
||||
class ValidatorOptions {
|
||||
public:
|
||||
ValidatorOptions() : options_(spvValidatorOptionsCreate()) {}
|
||||
~ValidatorOptions() { spvValidatorOptionsDestroy(options_); }
|
||||
// Allow implicit conversion to the underlying object.
|
||||
operator spv_validator_options() const { return options_; }
|
||||
|
||||
// Sets a limit.
|
||||
void SetUniversalLimit(spv_validator_limit limit_type, uint32_t limit) {
|
||||
spvValidatorOptionsSetUniversalLimit(options_, limit_type, limit);
|
||||
}
|
||||
|
||||
void SetRelaxStructStore(bool val) {
|
||||
spvValidatorOptionsSetRelaxStoreStruct(options_, val);
|
||||
}
|
||||
|
||||
// Records whether or not the validator should relax the rules on pointer
|
||||
// usage in logical addressing mode.
|
||||
//
|
||||
// When relaxed, it will allow the following usage cases of pointers:
|
||||
// 1) OpVariable allocating an object whose type is a pointer type
|
||||
// 2) OpReturnValue returning a pointer value
|
||||
void SetRelaxLogicalPointer(bool val) {
|
||||
spvValidatorOptionsSetRelaxLogicalPointer(options_, val);
|
||||
}
|
||||
|
||||
private:
|
||||
spv_validator_options options_;
|
||||
};
|
||||
|
||||
// C++ interface for SPIRV-Tools functionalities. It wraps the context
|
||||
// (including target environment and the corresponding SPIR-V grammar) and
|
||||
// provides methods for assembling, disassembling, and validating.
|
||||
//
|
||||
// Instances of this class provide basic thread-safety guarantee.
|
||||
class SpirvTools {
|
||||
public:
|
||||
enum {
|
||||
// Default assembling option used by assemble():
|
||||
kDefaultAssembleOption = SPV_TEXT_TO_BINARY_OPTION_NONE,
|
||||
|
||||
// Default disassembling option used by Disassemble():
|
||||
// * Avoid prefix comments from decoding the SPIR-V module header, and
|
||||
// * Use friendly names for variables.
|
||||
kDefaultDisassembleOption = SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
|
||||
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES
|
||||
};
|
||||
|
||||
// Constructs an instance targeting the given environment |env|.
|
||||
//
|
||||
// The constructed instance will have an empty message consumer, which just
|
||||
// ignores all messages from the library. Use SetMessageConsumer() to supply
|
||||
// one if messages are of concern.
|
||||
explicit SpirvTools(spv_target_env env);
|
||||
|
||||
// Disables copy/move constructor/assignment operations.
|
||||
SpirvTools(const SpirvTools&) = delete;
|
||||
SpirvTools(SpirvTools&&) = delete;
|
||||
SpirvTools& operator=(const SpirvTools&) = delete;
|
||||
SpirvTools& operator=(SpirvTools&&) = delete;
|
||||
|
||||
// Destructs this instance.
|
||||
~SpirvTools();
|
||||
|
||||
// Sets the message consumer to the given |consumer|. The |consumer| will be
|
||||
// invoked once for each message communicated from the library.
|
||||
void SetMessageConsumer(MessageConsumer consumer);
|
||||
|
||||
// Assembles the given assembly |text| and writes the result to |binary|.
|
||||
// Returns true on successful assembling. |binary| will be kept untouched if
|
||||
// assembling is unsuccessful.
|
||||
bool Assemble(const std::string& text, std::vector<uint32_t>* binary,
|
||||
uint32_t options = kDefaultAssembleOption) const;
|
||||
// |text_size| specifies the number of bytes in |text|. A terminating null
|
||||
// character is not required to present in |text| as long as |text| is valid.
|
||||
bool Assemble(const char* text, size_t text_size,
|
||||
std::vector<uint32_t>* binary,
|
||||
uint32_t options = kDefaultAssembleOption) const;
|
||||
|
||||
// Disassembles the given SPIR-V |binary| with the given |options| and writes
|
||||
// the assembly to |text|. Returns ture on successful disassembling. |text|
|
||||
// will be kept untouched if diassembling is unsuccessful.
|
||||
bool Disassemble(const std::vector<uint32_t>& binary, std::string* text,
|
||||
uint32_t options = kDefaultDisassembleOption) const;
|
||||
// |binary_size| specifies the number of words in |binary|.
|
||||
bool Disassemble(const uint32_t* binary, size_t binary_size,
|
||||
std::string* text,
|
||||
uint32_t options = kDefaultDisassembleOption) const;
|
||||
|
||||
// Validates the given SPIR-V |binary|. Returns true if no issues are found.
|
||||
// Otherwise, returns false and communicates issues via the message consumer
|
||||
// registered.
|
||||
bool Validate(const std::vector<uint32_t>& binary) const;
|
||||
// |binary_size| specifies the number of words in |binary|.
|
||||
bool Validate(const uint32_t* binary, size_t binary_size) const;
|
||||
// Like the previous overload, but takes an options object.
|
||||
bool Validate(const uint32_t* binary, size_t binary_size,
|
||||
const ValidatorOptions& options) const;
|
||||
|
||||
private:
|
||||
struct Impl; // Opaque struct for holding the data fields used by this class.
|
||||
std::unique_ptr<Impl> impl_; // Unique pointer to implementation data.
|
||||
};
|
||||
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SPIRV_TOOLS_LIBSPIRV_HPP_
|
97
3rdparty/spirv-tools/include/spirv-tools/linker.hpp
vendored
Normal file
97
3rdparty/spirv-tools/include/spirv-tools/linker.hpp
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
// Copyright (c) 2017 Pierre Moreau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SPIRV_TOOLS_LINKER_HPP_
|
||||
#define SPIRV_TOOLS_LINKER_HPP_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "libspirv.hpp"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
class LinkerOptions {
|
||||
public:
|
||||
LinkerOptions()
|
||||
: create_library_(false),
|
||||
verify_ids_(false),
|
||||
allow_partial_linkage_(false) {}
|
||||
|
||||
// Returns whether a library or an executable should be produced by the
|
||||
// linking phase.
|
||||
//
|
||||
// All exported symbols are kept when creating a library, whereas they will
|
||||
// be removed when creating an executable.
|
||||
// The returned value will be true if creating a library, and false if
|
||||
// creating an executable.
|
||||
bool GetCreateLibrary() const { return create_library_; }
|
||||
|
||||
// Sets whether a library or an executable should be produced.
|
||||
void SetCreateLibrary(bool create_library) {
|
||||
create_library_ = create_library;
|
||||
}
|
||||
|
||||
// Returns whether to verify the uniqueness of the unique ids in the merged
|
||||
// context.
|
||||
bool GetVerifyIds() const { return verify_ids_; }
|
||||
|
||||
// Sets whether to verify the uniqueness of the unique ids in the merged
|
||||
// context.
|
||||
void SetVerifyIds(bool verify_ids) { verify_ids_ = verify_ids; }
|
||||
|
||||
// Returns whether to allow for imported symbols to have no corresponding
|
||||
// exported symbols
|
||||
bool GetAllowPartialLinkage() const { return allow_partial_linkage_; }
|
||||
|
||||
// Sets whether to allow for imported symbols to have no corresponding
|
||||
// exported symbols
|
||||
void SetAllowPartialLinkage(bool allow_partial_linkage) {
|
||||
allow_partial_linkage_ = allow_partial_linkage;
|
||||
}
|
||||
|
||||
private:
|
||||
bool create_library_;
|
||||
bool verify_ids_;
|
||||
bool allow_partial_linkage_;
|
||||
};
|
||||
|
||||
// Links one or more SPIR-V modules into a new SPIR-V module. That is, combine
|
||||
// several SPIR-V modules into one, resolving link dependencies between them.
|
||||
//
|
||||
// At least one binary has to be provided in |binaries|. Those binaries do not
|
||||
// have to be valid, but they should be at least parseable.
|
||||
// The functions can fail due to the following:
|
||||
// * The given context was not initialised using `spvContextCreate()`;
|
||||
// * No input modules were given;
|
||||
// * One or more of those modules were not parseable;
|
||||
// * The input modules used different addressing or memory models;
|
||||
// * The ID or global variable number limit were exceeded;
|
||||
// * Some entry points were defined multiple times;
|
||||
// * Some imported symbols did not have an exported counterpart;
|
||||
// * Possibly other reasons.
|
||||
spv_result_t Link(const Context& context,
|
||||
const std::vector<std::vector<uint32_t>>& binaries,
|
||||
std::vector<uint32_t>* linked_binary,
|
||||
const LinkerOptions& options = LinkerOptions());
|
||||
spv_result_t Link(const Context& context, const uint32_t* const* binaries,
|
||||
const size_t* binary_sizes, size_t num_binaries,
|
||||
std::vector<uint32_t>* linked_binary,
|
||||
const LinkerOptions& options = LinkerOptions());
|
||||
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SPIRV_TOOLS_LINKER_HPP_
|
557
3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp
vendored
Normal file
557
3rdparty/spirv-tools/include/spirv-tools/optimizer.hpp
vendored
Normal file
@ -0,0 +1,557 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SPIRV_TOOLS_OPTIMIZER_HPP_
|
||||
#define SPIRV_TOOLS_OPTIMIZER_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "libspirv.hpp"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
// C++ interface for SPIR-V optimization functionalities. It wraps the context
|
||||
// (including target environment and the corresponding SPIR-V grammar) and
|
||||
// provides methods for registering optimization passes and optimizing.
|
||||
//
|
||||
// Instances of this class provides basic thread-safety guarantee.
|
||||
class Optimizer {
|
||||
public:
|
||||
// The token for an optimization pass. It is returned via one of the
|
||||
// Create*Pass() standalone functions at the end of this header file and
|
||||
// consumed by the RegisterPass() method. Tokens are one-time objects that
|
||||
// only support move; copying is not allowed.
|
||||
struct PassToken {
|
||||
struct Impl; // Opaque struct for holding inernal data.
|
||||
|
||||
PassToken(std::unique_ptr<Impl>);
|
||||
|
||||
// Tokens can only be moved. Copying is disabled.
|
||||
PassToken(const PassToken&) = delete;
|
||||
PassToken(PassToken&&);
|
||||
PassToken& operator=(const PassToken&) = delete;
|
||||
PassToken& operator=(PassToken&&);
|
||||
|
||||
~PassToken();
|
||||
|
||||
std::unique_ptr<Impl> impl_; // Unique pointer to internal data.
|
||||
};
|
||||
|
||||
// Constructs an instance with the given target |env|, which is used to decode
|
||||
// the binaries to be optimized later.
|
||||
//
|
||||
// The constructed instance will have an empty message consumer, which just
|
||||
// ignores all messages from the library. Use SetMessageConsumer() to supply
|
||||
// one if messages are of concern.
|
||||
explicit Optimizer(spv_target_env env);
|
||||
|
||||
// Disables copy/move constructor/assignment operations.
|
||||
Optimizer(const Optimizer&) = delete;
|
||||
Optimizer(Optimizer&&) = delete;
|
||||
Optimizer& operator=(const Optimizer&) = delete;
|
||||
Optimizer& operator=(Optimizer&&) = delete;
|
||||
|
||||
// Destructs this instance.
|
||||
~Optimizer();
|
||||
|
||||
// Sets the message consumer to the given |consumer|. The |consumer| will be
|
||||
// invoked once for each message communicated from the library.
|
||||
void SetMessageConsumer(MessageConsumer consumer);
|
||||
|
||||
// Registers the given |pass| to this optimizer. Passes will be run in the
|
||||
// exact order of registration. The token passed in will be consumed by this
|
||||
// method.
|
||||
Optimizer& RegisterPass(PassToken&& pass);
|
||||
|
||||
// Registers passes that attempt to improve performance of generated code.
|
||||
// This sequence of passes is subject to constant review and will change
|
||||
// from time to time.
|
||||
Optimizer& RegisterPerformancePasses();
|
||||
|
||||
// Registers passes that attempt to improve the size of generated code.
|
||||
// This sequence of passes is subject to constant review and will change
|
||||
// from time to time.
|
||||
Optimizer& RegisterSizePasses();
|
||||
|
||||
// Registers passes that attempt to legalize the generated code.
|
||||
//
|
||||
// Note: this recipe is specially for legalizing SPIR-V. It should be used
|
||||
// by compilers after translating HLSL source code literally. It should
|
||||
// *not* be used by general workloads for performance or size improvement.
|
||||
//
|
||||
// This sequence of passes is subject to constant review and will change
|
||||
// from time to time.
|
||||
Optimizer& RegisterLegalizationPasses();
|
||||
|
||||
// Optimizes the given SPIR-V module |original_binary| and writes the
|
||||
// optimized binary into |optimized_binary|.
|
||||
// Returns true on successful optimization, whether or not the module is
|
||||
// modified. Returns false if errors occur when processing |original_binary|
|
||||
// using any of the registered passes. In that case, no further passes are
|
||||
// executed and the contents in |optimized_binary| may be invalid.
|
||||
//
|
||||
// It's allowed to alias |original_binary| to the start of |optimized_binary|.
|
||||
bool Run(const uint32_t* original_binary, size_t original_binary_size,
|
||||
std::vector<uint32_t>* optimized_binary) const;
|
||||
|
||||
// Returns a vector of strings with all the pass names added to this
|
||||
// optimizer's pass manager. These strings are valid until the associated
|
||||
// pass manager is destroyed.
|
||||
std::vector<const char*> GetPassNames() const;
|
||||
|
||||
// Sets the option to print the disassembly before each pass and after the
|
||||
// last pass. If |out| is null, then no output is generated. Otherwise,
|
||||
// output is sent to the |out| output stream.
|
||||
Optimizer& SetPrintAll(std::ostream* out);
|
||||
|
||||
// Sets the option to print the resource utilization of each pass. If |out|
|
||||
// is null, then no output is generated. Otherwise, output is sent to the
|
||||
// |out| output stream.
|
||||
Optimizer& SetTimeReport(std::ostream* out);
|
||||
|
||||
private:
|
||||
struct Impl; // Opaque struct for holding internal data.
|
||||
std::unique_ptr<Impl> impl_; // Unique pointer to internal data.
|
||||
};
|
||||
|
||||
// Creates a null pass.
|
||||
// A null pass does nothing to the SPIR-V module to be optimized.
|
||||
Optimizer::PassToken CreateNullPass();
|
||||
|
||||
// Creates a strip-debug-info pass.
|
||||
// A strip-debug-info pass removes all debug instructions (as documented in
|
||||
// Section 3.32.2 of the SPIR-V spec) of the SPIR-V module to be optimized.
|
||||
Optimizer::PassToken CreateStripDebugInfoPass();
|
||||
|
||||
// Creates a strip-reflect-info pass.
|
||||
// A strip-reflect-info pass removes all reflections instructions.
|
||||
// For now, this is limited to removing decorations defined in
|
||||
// SPV_GOOGLE_hlsl_functionality1. The coverage may expand in
|
||||
// the future.
|
||||
Optimizer::PassToken CreateStripReflectInfoPass();
|
||||
|
||||
// Creates an eliminate-dead-functions pass.
|
||||
// An eliminate-dead-functions pass will remove all functions that are not in
|
||||
// the call trees rooted at entry points and exported functions. These
|
||||
// functions are not needed because they will never be called.
|
||||
Optimizer::PassToken CreateEliminateDeadFunctionsPass();
|
||||
|
||||
// Creates a set-spec-constant-default-value pass from a mapping from spec-ids
|
||||
// to the default values in the form of string.
|
||||
// A set-spec-constant-default-value pass sets the default values for the
|
||||
// spec constants that have SpecId decorations (i.e., those defined by
|
||||
// OpSpecConstant{|True|False} instructions).
|
||||
Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
|
||||
const std::unordered_map<uint32_t, std::string>& id_value_map);
|
||||
|
||||
// Creates a set-spec-constant-default-value pass from a mapping from spec-ids
|
||||
// to the default values in the form of bit pattern.
|
||||
// A set-spec-constant-default-value pass sets the default values for the
|
||||
// spec constants that have SpecId decorations (i.e., those defined by
|
||||
// OpSpecConstant{|True|False} instructions).
|
||||
Optimizer::PassToken CreateSetSpecConstantDefaultValuePass(
|
||||
const std::unordered_map<uint32_t, std::vector<uint32_t>>& id_value_map);
|
||||
|
||||
// Creates a flatten-decoration pass.
|
||||
// A flatten-decoration pass replaces grouped decorations with equivalent
|
||||
// ungrouped decorations. That is, it replaces each OpDecorationGroup
|
||||
// instruction and associated OpGroupDecorate and OpGroupMemberDecorate
|
||||
// instructions with equivalent OpDecorate and OpMemberDecorate instructions.
|
||||
// The pass does not attempt to preserve debug information for instructions
|
||||
// it removes.
|
||||
Optimizer::PassToken CreateFlattenDecorationPass();
|
||||
|
||||
// Creates a freeze-spec-constant-value pass.
|
||||
// A freeze-spec-constant pass specializes the value of spec constants to
|
||||
// their default values. This pass only processes the spec constants that have
|
||||
// SpecId decorations (defined by OpSpecConstant, OpSpecConstantTrue, or
|
||||
// OpSpecConstantFalse instructions) and replaces them with their normal
|
||||
// counterparts (OpConstant, OpConstantTrue, or OpConstantFalse). The
|
||||
// corresponding SpecId annotation instructions will also be removed. This
|
||||
// pass does not fold the newly added normal constants and does not process
|
||||
// other spec constants defined by OpSpecConstantComposite or
|
||||
// OpSpecConstantOp.
|
||||
Optimizer::PassToken CreateFreezeSpecConstantValuePass();
|
||||
|
||||
// Creates a fold-spec-constant-op-and-composite pass.
|
||||
// A fold-spec-constant-op-and-composite pass folds spec constants defined by
|
||||
// OpSpecConstantOp or OpSpecConstantComposite instruction, to normal Constants
|
||||
// defined by OpConstantTrue, OpConstantFalse, OpConstant, OpConstantNull, or
|
||||
// OpConstantComposite instructions. Note that spec constants defined with
|
||||
// OpSpecConstant, OpSpecConstantTrue, or OpSpecConstantFalse instructions are
|
||||
// not handled, as these instructions indicate their value are not determined
|
||||
// and can be changed in future. A spec constant is foldable if all of its
|
||||
// value(s) can be determined from the module. E.g., an integer spec constant
|
||||
// defined with OpSpecConstantOp instruction can be folded if its value won't
|
||||
// change later. This pass will replace the original OpSpecContantOp instruction
|
||||
// with an OpConstant instruction. When folding composite spec constants,
|
||||
// new instructions may be inserted to define the components of the composite
|
||||
// constant first, then the original spec constants will be replaced by
|
||||
// OpConstantComposite instructions.
|
||||
//
|
||||
// There are some operations not supported yet:
|
||||
// OpSConvert, OpFConvert, OpQuantizeToF16 and
|
||||
// all the operations under Kernel capability.
|
||||
// TODO(qining): Add support for the operations listed above.
|
||||
Optimizer::PassToken CreateFoldSpecConstantOpAndCompositePass();
|
||||
|
||||
// Creates a unify-constant pass.
|
||||
// A unify-constant pass de-duplicates the constants. Constants with the exact
|
||||
// same value and identical form will be unified and only one constant will
|
||||
// be kept for each unique pair of type and value.
|
||||
// There are several cases not handled by this pass:
|
||||
// 1) Constants defined by OpConstantNull instructions (null constants) and
|
||||
// constants defined by OpConstantFalse, OpConstant or OpConstantComposite
|
||||
// with value 0 (zero-valued normal constants) are not considered equivalent.
|
||||
// So null constants won't be used to replace zero-valued normal constants,
|
||||
// vice versa.
|
||||
// 2) Whenever there are decorations to the constant's result id id, the
|
||||
// constant won't be handled, which means, it won't be used to replace any
|
||||
// other constants, neither can other constants replace it.
|
||||
// 3) NaN in float point format with different bit patterns are not unified.
|
||||
Optimizer::PassToken CreateUnifyConstantPass();
|
||||
|
||||
// Creates a eliminate-dead-constant pass.
|
||||
// A eliminate-dead-constant pass removes dead constants, including normal
|
||||
// contants defined by OpConstant, OpConstantComposite, OpConstantTrue, or
|
||||
// OpConstantFalse and spec constants defined by OpSpecConstant,
|
||||
// OpSpecConstantComposite, OpSpecConstantTrue, OpSpecConstantFalse or
|
||||
// OpSpecConstantOp.
|
||||
Optimizer::PassToken CreateEliminateDeadConstantPass();
|
||||
|
||||
// Creates a strength-reduction pass.
|
||||
// A strength-reduction pass will look for opportunities to replace an
|
||||
// instruction with an equivalent and less expensive one. For example,
|
||||
// multiplying by a power of 2 can be replaced by a bit shift.
|
||||
Optimizer::PassToken CreateStrengthReductionPass();
|
||||
|
||||
// Creates a block merge pass.
|
||||
// This pass searches for blocks with a single Branch to a block with no
|
||||
// other predecessors and merges the blocks into a single block. Continue
|
||||
// blocks and Merge blocks are not candidates for the second block.
|
||||
//
|
||||
// The pass is most useful after Dead Branch Elimination, which can leave
|
||||
// such sequences of blocks. Merging them makes subsequent passes more
|
||||
// effective, such as single block local store-load elimination.
|
||||
//
|
||||
// While this pass reduces the number of occurrences of this sequence, at
|
||||
// this time it does not guarantee all such sequences are eliminated.
|
||||
//
|
||||
// Presence of phi instructions can inhibit this optimization. Handling
|
||||
// these is left for future improvements.
|
||||
Optimizer::PassToken CreateBlockMergePass();
|
||||
|
||||
// Creates an exhaustive inline pass.
|
||||
// An exhaustive inline pass attempts to exhaustively inline all function
|
||||
// calls in all functions in an entry point call tree. The intent is to enable,
|
||||
// albeit through brute force, analysis and optimization across function
|
||||
// calls by subsequent optimization passes. As the inlining is exhaustive,
|
||||
// there is no attempt to optimize for size or runtime performance. Functions
|
||||
// that are not in the call tree of an entry point are not changed.
|
||||
Optimizer::PassToken CreateInlineExhaustivePass();
|
||||
|
||||
// Creates an opaque inline pass.
|
||||
// An opaque inline pass inlines all function calls in all functions in all
|
||||
// entry point call trees where the called function contains an opaque type
|
||||
// in either its parameter types or return type. An opaque type is currently
|
||||
// defined as Image, Sampler or SampledImage. The intent is to enable, albeit
|
||||
// through brute force, analysis and optimization across these function calls
|
||||
// by subsequent passes in order to remove the storing of opaque types which is
|
||||
// not legal in Vulkan. Functions that are not in the call tree of an entry
|
||||
// point are not changed.
|
||||
Optimizer::PassToken CreateInlineOpaquePass();
|
||||
|
||||
// Creates a single-block local variable load/store elimination pass.
|
||||
// For every entry point function, do single block memory optimization of
|
||||
// function variables referenced only with non-access-chain loads and stores.
|
||||
// For each targeted variable load, if previous store to that variable in the
|
||||
// block, replace the load's result id with the value id of the store.
|
||||
// If previous load within the block, replace the current load's result id
|
||||
// with the previous load's result id. In either case, delete the current
|
||||
// load. Finally, check if any remaining stores are useless, and delete store
|
||||
// and variable if possible.
|
||||
//
|
||||
// The presence of access chain references and function calls can inhibit
|
||||
// the above optimization.
|
||||
//
|
||||
// Only modules with relaxed logical addressing (see opt/instruction.h) are
|
||||
// currently processed.
|
||||
//
|
||||
// This pass is most effective if preceeded by Inlining and
|
||||
// LocalAccessChainConvert. This pass will reduce the work needed to be done
|
||||
// by LocalSingleStoreElim and LocalMultiStoreElim.
|
||||
//
|
||||
// Only functions in the call tree of an entry point are processed.
|
||||
Optimizer::PassToken CreateLocalSingleBlockLoadStoreElimPass();
|
||||
|
||||
// Create dead branch elimination pass.
|
||||
// For each entry point function, this pass will look for SelectionMerge
|
||||
// BranchConditionals with constant condition and convert to a Branch to
|
||||
// the indicated label. It will delete resulting dead blocks.
|
||||
//
|
||||
// For all phi functions in merge block, replace all uses with the id
|
||||
// corresponding to the living predecessor.
|
||||
//
|
||||
// Note that some branches and blocks may be left to avoid creating invalid
|
||||
// control flow. Improving this is left to future work.
|
||||
//
|
||||
// This pass is most effective when preceeded by passes which eliminate
|
||||
// local loads and stores, effectively propagating constant values where
|
||||
// possible.
|
||||
Optimizer::PassToken CreateDeadBranchElimPass();
|
||||
|
||||
// Creates an SSA local variable load/store elimination pass.
|
||||
// For every entry point function, eliminate all loads and stores of function
|
||||
// scope variables only referenced with non-access-chain loads and stores.
|
||||
// Eliminate the variables as well.
|
||||
//
|
||||
// The presence of access chain references and function calls can inhibit
|
||||
// the above optimization.
|
||||
//
|
||||
// Only shader modules with relaxed logical addressing (see opt/instruction.h)
|
||||
// are currently processed. Currently modules with any extensions enabled are
|
||||
// not processed. This is left for future work.
|
||||
//
|
||||
// This pass is most effective if preceeded by Inlining and
|
||||
// LocalAccessChainConvert. LocalSingleStoreElim and LocalSingleBlockElim
|
||||
// will reduce the work that this pass has to do.
|
||||
Optimizer::PassToken CreateLocalMultiStoreElimPass();
|
||||
|
||||
// Creates a local access chain conversion pass.
|
||||
// A local access chain conversion pass identifies all function scope
|
||||
// variables which are accessed only with loads, stores and access chains
|
||||
// with constant indices. It then converts all loads and stores of such
|
||||
// variables into equivalent sequences of loads, stores, extracts and inserts.
|
||||
//
|
||||
// This pass only processes entry point functions. It currently only converts
|
||||
// non-nested, non-ptr access chains. It does not process modules with
|
||||
// non-32-bit integer types present. Optional memory access options on loads
|
||||
// and stores are ignored as we are only processing function scope variables.
|
||||
//
|
||||
// This pass unifies access to these variables to a single mode and simplifies
|
||||
// subsequent analysis and elimination of these variables along with their
|
||||
// loads and stores allowing values to propagate to their points of use where
|
||||
// possible.
|
||||
Optimizer::PassToken CreateLocalAccessChainConvertPass();
|
||||
|
||||
// Creates a local single store elimination pass.
|
||||
// For each entry point function, this pass eliminates loads and stores for
|
||||
// function scope variable that are stored to only once, where possible. Only
|
||||
// whole variable loads and stores are eliminated; access-chain references are
|
||||
// not optimized. Replace all loads of such variables with the value that is
|
||||
// stored and eliminate any resulting dead code.
|
||||
//
|
||||
// Currently, the presence of access chains and function calls can inhibit this
|
||||
// pass, however the Inlining and LocalAccessChainConvert passes can make it
|
||||
// more effective. In additional, many non-load/store memory operations are
|
||||
// not supported and will prohibit optimization of a function. Support of
|
||||
// these operations are future work.
|
||||
//
|
||||
// Only shader modules with relaxed logical addressing (see opt/instruction.h)
|
||||
// are currently processed.
|
||||
//
|
||||
// This pass will reduce the work needed to be done by LocalSingleBlockElim
|
||||
// and LocalMultiStoreElim and can improve the effectiveness of other passes
|
||||
// such as DeadBranchElimination which depend on values for their analysis.
|
||||
Optimizer::PassToken CreateLocalSingleStoreElimPass();
|
||||
|
||||
// Creates an insert/extract elimination pass.
|
||||
// This pass processes each entry point function in the module, searching for
|
||||
// extracts on a sequence of inserts. It further searches the sequence for an
|
||||
// insert with indices identical to the extract. If such an insert can be
|
||||
// found before hitting a conflicting insert, the extract's result id is
|
||||
// replaced with the id of the values from the insert.
|
||||
//
|
||||
// Besides removing extracts this pass enables subsequent dead code elimination
|
||||
// passes to delete the inserts. This pass performs best after access chains are
|
||||
// converted to inserts and extracts and local loads and stores are eliminated.
|
||||
Optimizer::PassToken CreateInsertExtractElimPass();
|
||||
|
||||
// Creates a dead insert elimination pass.
|
||||
// This pass processes each entry point function in the module, searching for
|
||||
// unreferenced inserts into composite types. These are most often unused
|
||||
// stores to vector components. They are unused because they are never
|
||||
// referenced, or because there is another insert to the same component between
|
||||
// the insert and the reference. After removing the inserts, dead code
|
||||
// elimination is attempted on the inserted values.
|
||||
//
|
||||
// This pass performs best after access chains are converted to inserts and
|
||||
// extracts and local loads and stores are eliminated. While executing this
|
||||
// pass can be advantageous on its own, it is also advantageous to execute
|
||||
// this pass after CreateInsertExtractPass() as it will remove any unused
|
||||
// inserts created by that pass.
|
||||
Optimizer::PassToken CreateDeadInsertElimPass();
|
||||
|
||||
// Creates a pass to consolidate uniform references.
|
||||
// For each entry point function in the module, first change all constant index
|
||||
// access chain loads into equivalent composite extracts. Then consolidate
|
||||
// identical uniform loads into one uniform load. Finally, consolidate
|
||||
// identical uniform extracts into one uniform extract. This may require
|
||||
// moving a load or extract to a point which dominates all uses.
|
||||
//
|
||||
// This pass requires a module to have structured control flow ie shader
|
||||
// capability. It also requires logical addressing ie Addresses capability
|
||||
// is not enabled. It also currently does not support any extensions.
|
||||
//
|
||||
// This pass currently only optimizes loads with a single index.
|
||||
Optimizer::PassToken CreateCommonUniformElimPass();
|
||||
|
||||
// Create aggressive dead code elimination pass
|
||||
// This pass eliminates unused code from the module. In addition,
|
||||
// it detects and eliminates code which may have spurious uses but which do
|
||||
// not contribute to the output of the function. The most common cause of
|
||||
// such code sequences is summations in loops whose result is no longer used
|
||||
// due to dead code elimination. This optimization has additional compile
|
||||
// time cost over standard dead code elimination.
|
||||
//
|
||||
// This pass only processes entry point functions. It also only processes
|
||||
// shaders with relaxed logical addressing (see opt/instruction.h). It
|
||||
// currently will not process functions with function calls. Unreachable
|
||||
// functions are deleted.
|
||||
//
|
||||
// This pass will be made more effective by first running passes that remove
|
||||
// dead control flow and inlines function calls.
|
||||
//
|
||||
// This pass can be especially useful after running Local Access Chain
|
||||
// Conversion, which tends to cause cycles of dead code to be left after
|
||||
// Store/Load elimination passes are completed. These cycles cannot be
|
||||
// eliminated with standard dead code elimination.
|
||||
Optimizer::PassToken CreateAggressiveDCEPass();
|
||||
|
||||
// Creates a compact ids pass.
|
||||
// The pass remaps result ids to a compact and gapless range starting from %1.
|
||||
Optimizer::PassToken CreateCompactIdsPass();
|
||||
|
||||
// Creates a remove duplicate pass.
|
||||
// This pass removes various duplicates:
|
||||
// * duplicate capabilities;
|
||||
// * duplicate extended instruction imports;
|
||||
// * duplicate types;
|
||||
// * duplicate decorations.
|
||||
Optimizer::PassToken CreateRemoveDuplicatesPass();
|
||||
|
||||
// Creates a CFG cleanup pass.
|
||||
// This pass removes cruft from the control flow graph of functions that are
|
||||
// reachable from entry points and exported functions. It currently includes the
|
||||
// following functionality:
|
||||
//
|
||||
// - Removal of unreachable basic blocks.
|
||||
Optimizer::PassToken CreateCFGCleanupPass();
|
||||
|
||||
// Create dead variable elimination pass.
|
||||
// This pass will delete module scope variables, along with their decorations,
|
||||
// that are not referenced.
|
||||
Optimizer::PassToken CreateDeadVariableEliminationPass();
|
||||
|
||||
// create merge return pass.
|
||||
// changes functions that have multiple return statements so they have a single
|
||||
// return statement.
|
||||
//
|
||||
// for structured control flow it is assumed that the only unreachable blocks in
|
||||
// the function are trivial merge and continue blocks.
|
||||
//
|
||||
// a trivial merge block contains the label and an opunreachable instructions,
|
||||
// nothing else. a trivial continue block contain a label and an opbranch to
|
||||
// the header, nothing else.
|
||||
//
|
||||
// these conditions are guaranteed to be met after running dead-branch
|
||||
// elimination.
|
||||
Optimizer::PassToken CreateMergeReturnPass();
|
||||
|
||||
// Create value numbering pass.
|
||||
// This pass will look for instructions in the same basic block that compute the
|
||||
// same value, and remove the redundant ones.
|
||||
Optimizer::PassToken CreateLocalRedundancyEliminationPass();
|
||||
|
||||
// Create LICM pass.
|
||||
// This pass will look for invariant instructions inside loops and hoist them to
|
||||
// the loops preheader.
|
||||
Optimizer::PassToken CreateLoopInvariantCodeMotionPass();
|
||||
|
||||
// Creates a loop unswitch pass.
|
||||
// This pass will look for loop independent branch conditions and move the
|
||||
// condition out of the loop and version the loop based on the taken branch.
|
||||
// Works best after LICM and local multi store elimination pass.
|
||||
Optimizer::PassToken CreateLoopUnswitchPass();
|
||||
|
||||
// Create global value numbering pass.
|
||||
// This pass will look for instructions where the same value is computed on all
|
||||
// paths leading to the instruction. Those instructions are deleted.
|
||||
Optimizer::PassToken CreateRedundancyEliminationPass();
|
||||
|
||||
// Create scalar replacement pass.
|
||||
// This pass replaces composite function scope variables with variables for each
|
||||
// element if those elements are accessed individually.
|
||||
Optimizer::PassToken CreateScalarReplacementPass();
|
||||
|
||||
// Create a private to local pass.
|
||||
// This pass looks for variables delcared in the private storage class that are
|
||||
// used in only one function. Those variables are moved to the function storage
|
||||
// class in the function that they are used.
|
||||
Optimizer::PassToken CreatePrivateToLocalPass();
|
||||
|
||||
// Creates a conditional constant propagation (CCP) pass.
|
||||
// This pass implements the SSA-CCP algorithm in
|
||||
//
|
||||
// Constant propagation with conditional branches,
|
||||
// Wegman and Zadeck, ACM TOPLAS 13(2):181-210.
|
||||
//
|
||||
// Constant values in expressions and conditional jumps are folded and
|
||||
// simplified. This may reduce code size by removing never executed jump targets
|
||||
// and computations with constant operands.
|
||||
Optimizer::PassToken CreateCCPPass();
|
||||
|
||||
// Creates a workaround driver bugs pass. This pass attempts to work around
|
||||
// a known driver bug (issue #1209) by identifying the bad code sequences and
|
||||
// rewriting them.
|
||||
//
|
||||
// Current workaround: Avoid OpUnreachable instructions in loops.
|
||||
Optimizer::PassToken CreateWorkaround1209Pass();
|
||||
|
||||
// Creates a pass that converts if-then-else like assignments into OpSelect.
|
||||
Optimizer::PassToken CreateIfConversionPass();
|
||||
|
||||
// Creates a pass that will replace instructions that are not valid for the
|
||||
// current shader stage by constants. Has no effect on non-shader modules.
|
||||
Optimizer::PassToken CreateReplaceInvalidOpcodePass();
|
||||
|
||||
// Creates a pass that simplifies instructions using the instruction folder.
|
||||
Optimizer::PassToken CreateSimplificationPass();
|
||||
|
||||
// Create loop unroller pass.
|
||||
// Creates a pass to unroll loops which have the "Unroll" loop control
|
||||
// mask set. The loops must meet a specific criteria in order to be unrolled
|
||||
// safely this criteria is checked before doing the unroll by the
|
||||
// LoopUtils::CanPerformUnroll method. Any loop that does not meet the criteria
|
||||
// won't be unrolled. See CanPerformUnroll LoopUtils.h for more information.
|
||||
Optimizer::PassToken CreateLoopUnrollPass(bool fully_unroll, int factor = 0);
|
||||
|
||||
// Create the SSA rewrite pass.
|
||||
// This pass converts load/store operations on function local variables into
|
||||
// operations on SSA IDs. This allows SSA optimizers to act on these variables.
|
||||
// Only variables that are local to the function and of supported types are
|
||||
// processed (see IsSSATargetVar for details).
|
||||
Optimizer::PassToken CreateSSARewritePass();
|
||||
|
||||
// Create copy propagate arrays pass.
|
||||
// This pass looks to copy propagate memory references for arrays. It looks
|
||||
// for specific code patterns to recognize array copies.
|
||||
Optimizer::PassToken CreateCopyPropagateArraysPass();
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SPIRV_TOOLS_OPTIMIZER_HPP_
|
82
3rdparty/spirv-tools/projects.md
vendored
Normal file
82
3rdparty/spirv-tools/projects.md
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
# Tracking SPIRV-Tools work with GitHub projects
|
||||
|
||||
We are experimenting with using the [GitHub Project
|
||||
feature](https://help.github.com/articles/tracking-the-progress-of-your-work-with-projects/)
|
||||
to track progress toward large goals.
|
||||
|
||||
For more on GitHub Projects in general, see:
|
||||
* [Introductory blog post](https://github.com/blog/2256-a-whole-new-github-universe-announcing-new-tools-forums-and-features)
|
||||
* [Introductory video](https://www.youtube.com/watch?v=C6MGKHkNtxU)
|
||||
|
||||
The current SPIRV-Tools project list can be found at
|
||||
[https://github.com/KhronosGroup/SPIRV-Tools/projects](https://github.com/KhronosGroup/SPIRV-Tools/projects)
|
||||
|
||||
## How we use a Project
|
||||
|
||||
A GitHub Project is a set of work with an overall purpose, and
|
||||
consists of a collection of *Cards*.
|
||||
Each card is either a *Note* or a regular GitHub *Issue.*
|
||||
A Note can be converted to an Issue.
|
||||
|
||||
In our projects, a card represents work, i.e. a change that can
|
||||
be applied to the repository.
|
||||
The work could be a feature, a bug to be fixed, documentation to be
|
||||
updated, etc.
|
||||
|
||||
A project and its cards are used as a [Kanban
|
||||
board](https://en.wikipedia.org/wiki/Kanban_board), where cards progress
|
||||
through a workflow starting with ideas through to implementation and completion.
|
||||
|
||||
In our usage, a *project manager* is someone who organizes the work.
|
||||
They manage the creation and movement of cards
|
||||
through the project workflow:
|
||||
* They create cards to capture ideas, or to decompose large ideas into smaller
|
||||
ones.
|
||||
* They determine if the work for a card has been completed.
|
||||
* Normally they are the person (or persons) who can approve and merge a pull
|
||||
request into the `master` branch.
|
||||
|
||||
Our projects organize cards into the following columns:
|
||||
* `Ideas`: Work which could be done, captured either as Cards or Notes.
|
||||
* A card in this column could be marked as a [PLACEHOLDER](#placeholders).
|
||||
* `Ready to start`: Issues which represent work we'd like to do, and which
|
||||
are not blocked by other work.
|
||||
* The issue should be narrow enough that it can usually be addressed by a
|
||||
single pull request.
|
||||
* We want these to be Issues (not Notes) so that someone can claim the work
|
||||
by updating the Issue with their intent to do the work.
|
||||
Once an Issue is claimed, the project manager moves the corresponding card
|
||||
from `Ready to start` to `In progress`.
|
||||
* `In progress`: Issues which were in `Ready to start` but which have been
|
||||
claimed by someone.
|
||||
* `Done`: Issues which have been resolved, by completing their work.
|
||||
* The changes have been applied to the repository, typically by being pushed
|
||||
into the `master` branch.
|
||||
* Other kinds of work could update repository settings, for example.
|
||||
* `Rejected ideas`: Work which has been considered, but which we don't want
|
||||
implemented.
|
||||
* We keep rejected ideas so they are not proposed again. This serves
|
||||
as a form of institutional memory.
|
||||
* We should record why an idea is rejected. For this reason, a rejected
|
||||
idea is likely to be an Issue which has been closed.
|
||||
|
||||
## Prioritization
|
||||
|
||||
We are considering prioritizing cards in the `Ideas` and `Ready to start`
|
||||
columns so that things that should be considered first float up to the top.
|
||||
|
||||
Experience will tell us if we stick to that rule, and if it proves helpful.
|
||||
|
||||
## Placeholders
|
||||
|
||||
A *placeholder* is a Note or Issue that represents a possibly large amount
|
||||
of work that can be broadly defined but which may not have been broken down
|
||||
into small implementable pieces of work.
|
||||
|
||||
Use a placeholder to capture a big idea, but without doing the upfront work
|
||||
to consider all the details of how it should be implemented.
|
||||
Over time, break off pieces of the placeholder into implementable Issues.
|
||||
Move those Issues into the `Ready to start` column when they become unblocked.
|
||||
|
||||
We delete the placeholder when all its work has been decomposed into
|
||||
implementable cards.
|
362
3rdparty/spirv-tools/source/CMakeLists.txt
vendored
Normal file
362
3rdparty/spirv-tools/source/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,362 @@
|
||||
# Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(GRAMMAR_PROCESSING_SCRIPT "${spirv-tools_SOURCE_DIR}/utils/generate_grammar_tables.py")
|
||||
set(VIMSYNTAX_PROCESSING_SCRIPT "${spirv-tools_SOURCE_DIR}/utils/generate_vim_syntax.py")
|
||||
set(XML_REGISTRY_PROCESSING_SCRIPT "${spirv-tools_SOURCE_DIR}/utils/generate_registry_tables.py")
|
||||
set(LANG_HEADER_PROCESSING_SCRIPT "${spirv-tools_SOURCE_DIR}/utils/generate_language_headers.py")
|
||||
|
||||
# For now, assume the DebugInfo grammar file is in the current directory.
|
||||
# It might migrate to SPIRV-Headers.
|
||||
set(DEBUGINFO_GRAMMAR_JSON_FILE "${CMAKE_CURRENT_SOURCE_DIR}/extinst.debuginfo.grammar.json")
|
||||
|
||||
# macro() definitions are used in the following because we need to append .inc
|
||||
# file paths into some global lists (*_CPP_DEPENDS). And those global lists are
|
||||
# later used by set_source_files_properties() calls.
|
||||
# function() definitions are not suitable because they create new scopes.
|
||||
macro(spvtools_core_tables VERSION)
|
||||
set(GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${VERSION}/spirv.core.grammar.json")
|
||||
set(GRAMMAR_INSTS_INC_FILE "${spirv-tools_BINARY_DIR}/core.insts-${VERSION}.inc")
|
||||
set(GRAMMAR_KINDS_INC_FILE "${spirv-tools_BINARY_DIR}/operand.kinds-${VERSION}.inc")
|
||||
add_custom_command(OUTPUT ${GRAMMAR_INSTS_INC_FILE} ${GRAMMAR_KINDS_INC_FILE}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
|
||||
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
|
||||
--extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
|
||||
--core-insts-output=${GRAMMAR_INSTS_INC_FILE}
|
||||
--operand-kinds-output=${GRAMMAR_KINDS_INC_FILE}
|
||||
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${GRAMMAR_JSON_FILE} ${DEBUGINFO_GRAMMAR_JSON_FILE}
|
||||
COMMENT "Generate info tables for SPIR-V v${VERSION} core instructions and operands.")
|
||||
list(APPEND OPCODE_CPP_DEPENDS ${GRAMMAR_INSTS_INC_FILE})
|
||||
list(APPEND OPERAND_CPP_DEPENDS ${GRAMMAR_KINDS_INC_FILE})
|
||||
endmacro(spvtools_core_tables)
|
||||
|
||||
macro(spvtools_enum_string_mapping VERSION)
|
||||
set(GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${VERSION}/spirv.core.grammar.json")
|
||||
set(GRAMMAR_EXTENSION_ENUM_INC_FILE "${spirv-tools_BINARY_DIR}/extension_enum.inc")
|
||||
set(GRAMMAR_ENUM_STRING_MAPPING_INC_FILE "${spirv-tools_BINARY_DIR}/enum_string_mapping.inc")
|
||||
add_custom_command(OUTPUT ${GRAMMAR_EXTENSION_ENUM_INC_FILE}
|
||||
${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
|
||||
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
|
||||
--extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
|
||||
--extension-enum-output=${GRAMMAR_EXTENSION_ENUM_INC_FILE}
|
||||
--enum-string-mapping-output=${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}
|
||||
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${GRAMMAR_JSON_FILE} ${DEBUGINFO_GRAMMAR_JSON_FILE}
|
||||
COMMENT "Generate enum-string mapping for SPIR-V v${VERSION}.")
|
||||
list(APPEND EXTENSION_H_DEPENDS ${GRAMMAR_EXTENSION_ENUM_INC_FILE})
|
||||
list(APPEND ENUM_STRING_MAPPING_CPP_DEPENDS ${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE})
|
||||
endmacro(spvtools_enum_string_mapping)
|
||||
|
||||
macro(spvtools_vimsyntax VERSION CLVERSION)
|
||||
set(GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${VERSION}/spirv.core.grammar.json")
|
||||
set(GLSL_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${VERSION}/extinst.glsl.std.450.grammar.json")
|
||||
set(OPENCL_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${VERSION}/extinst.opencl.std.100.grammar.json")
|
||||
set(VIMSYNTAX_FILE "${spirv-tools_BINARY_DIR}/spvasm.vim")
|
||||
add_custom_command(OUTPUT ${VIMSYNTAX_FILE}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${VIMSYNTAX_PROCESSING_SCRIPT}
|
||||
--spirv-core-grammar=${GRAMMAR_JSON_FILE}
|
||||
--extinst-debuginfo-grammar=${DEBUGINFO_GRAMMAR_JSON_FILE}
|
||||
--extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
|
||||
--extinst-opencl-grammar=${OPENCL_GRAMMAR_JSON_FILE}
|
||||
>${VIMSYNTAX_FILE}
|
||||
DEPENDS ${VIMSYNTAX_PROCESSING_SCRIPT} ${GRAMMAR_JSON_FILE}
|
||||
${GLSL_GRAMMAR_JSON_FILE} ${OPENCL_GRAMMAR_JSON_FILE} ${DEBUGINFO_GRAMMAR_JSON_FILE}
|
||||
COMMENT "Generate spvasm.vim: Vim syntax file for SPIR-V assembly.")
|
||||
endmacro(spvtools_vimsyntax)
|
||||
|
||||
macro(spvtools_glsl_tables VERSION)
|
||||
set(CORE_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${VERSION}/spirv.core.grammar.json")
|
||||
set(GLSL_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${VERSION}/extinst.glsl.std.450.grammar.json")
|
||||
set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/glsl.std.450.insts.inc")
|
||||
add_custom_command(OUTPUT ${GRAMMAR_INC_FILE}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
|
||||
--extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
|
||||
--glsl-insts-output=${GRAMMAR_INC_FILE}
|
||||
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${GLSL_GRAMMAR_JSON_FILE}
|
||||
COMMENT "Generate info tables for GLSL extended instructions and operands v${VERSION}.")
|
||||
list(APPEND EXTINST_CPP_DEPENDS ${GRAMMAR_INC_FILE})
|
||||
endmacro(spvtools_glsl_tables)
|
||||
|
||||
macro(spvtools_opencl_tables VERSION)
|
||||
set(CORE_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${VERSION}/spirv.core.grammar.json")
|
||||
set(OPENCL_GRAMMAR_JSON_FILE "${SPIRV_HEADER_INCLUDE_DIR}/spirv/${VERSION}/extinst.opencl.std.100.grammar.json")
|
||||
set(GRAMMAR_INC_FILE "${spirv-tools_BINARY_DIR}/opencl.std.insts.inc")
|
||||
add_custom_command(OUTPUT ${GRAMMAR_INC_FILE}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
|
||||
--extinst-opencl-grammar=${OPENCL_GRAMMAR_JSON_FILE}
|
||||
--opencl-insts-output=${GRAMMAR_INC_FILE}
|
||||
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${CORE_GRAMMAR_JSON_FILE} ${OPENCL_GRAMMAR_JSON_FILE}
|
||||
COMMENT "Generate info tables for OpenCL extended instructions and operands v${VERSION}.")
|
||||
list(APPEND EXTINST_CPP_DEPENDS ${GRAMMAR_INC_FILE})
|
||||
endmacro(spvtools_opencl_tables)
|
||||
|
||||
macro(spvtools_vendor_tables VENDOR_TABLE)
|
||||
set(INSTS_FILE "${spirv-tools_BINARY_DIR}/${VENDOR_TABLE}.insts.inc")
|
||||
set(GRAMMAR_FILE "${spirv-tools_SOURCE_DIR}/source/extinst.${VENDOR_TABLE}.grammar.json")
|
||||
add_custom_command(OUTPUT ${INSTS_FILE}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
|
||||
--extinst-vendor-grammar=${GRAMMAR_FILE}
|
||||
--vendor-insts-output=${INSTS_FILE}
|
||||
DEPENDS ${GRAMMAR_PROCESSING_SCRIPT} ${GRAMMAR_FILE}
|
||||
COMMENT "Generate extended instruction tables for ${VENDOR_TABLE}.")
|
||||
list(APPEND EXTINST_CPP_DEPENDS ${INSTS_FILE})
|
||||
add_custom_target(spirv-tools-${VENDOR_TABLE} DEPENDS ${INSTS_FILE})
|
||||
set_property(TARGET spirv-tools-${VENDOR_TABLE} PROPERTY FOLDER "SPIRV-Tools build")
|
||||
endmacro(spvtools_vendor_tables)
|
||||
|
||||
macro(spvtools_extinst_lang_headers NAME GRAMMAR_FILE)
|
||||
set(OUTBASE ${spirv-tools_BINARY_DIR}/${NAME})
|
||||
set(OUT_H ${OUTBASE}.h)
|
||||
add_custom_command(OUTPUT ${OUT_H}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${LANG_HEADER_PROCESSING_SCRIPT}
|
||||
--extinst-name=${NAME}
|
||||
--extinst-grammar=${GRAMMAR_FILE}
|
||||
--extinst-output-base=${OUTBASE}
|
||||
DEPENDS ${LANG_HEADER_PROCESSING_SCRIPT} ${GRAMMAR_FILE}
|
||||
COMMENT "Generate language specific header for ${NAME}.")
|
||||
list(APPEND EXTINST_CPP_DEPENDS ${OUT_H})
|
||||
add_custom_target(spirv-tools-header-${NAME} DEPENDS ${OUT_H})
|
||||
set_property(TARGET spirv-tools-header-${NAME} PROPERTY FOLDER "SPIRV-Tools build")
|
||||
endmacro(spvtools_extinst_lang_headers)
|
||||
|
||||
spvtools_core_tables("unified1")
|
||||
spvtools_enum_string_mapping("unified1")
|
||||
spvtools_opencl_tables("unified1")
|
||||
spvtools_glsl_tables("unified1")
|
||||
spvtools_vendor_tables("spv-amd-shader-explicit-vertex-parameter")
|
||||
spvtools_vendor_tables("spv-amd-shader-trinary-minmax")
|
||||
spvtools_vendor_tables("spv-amd-gcn-shader")
|
||||
spvtools_vendor_tables("spv-amd-shader-ballot")
|
||||
spvtools_vendor_tables("debuginfo")
|
||||
spvtools_extinst_lang_headers("DebugInfo" ${DEBUGINFO_GRAMMAR_JSON_FILE})
|
||||
|
||||
spvtools_vimsyntax("unified1" "1.0")
|
||||
add_custom_target(spirv-tools-vimsyntax DEPENDS ${VIMSYNTAX_FILE})
|
||||
set_property(TARGET spirv-tools-vimsyntax PROPERTY FOLDER "SPIRV-Tools utilities")
|
||||
|
||||
# Extract the list of known generators from the SPIR-V XML registry file.
|
||||
set(GENERATOR_INC_FILE ${spirv-tools_BINARY_DIR}/generators.inc)
|
||||
set(SPIRV_XML_REGISTRY_FILE ${SPIRV_HEADER_INCLUDE_DIR}/spirv/spir-v.xml)
|
||||
add_custom_command(OUTPUT ${GENERATOR_INC_FILE}
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${XML_REGISTRY_PROCESSING_SCRIPT}
|
||||
--xml=${SPIRV_XML_REGISTRY_FILE}
|
||||
--generator-output=${GENERATOR_INC_FILE}
|
||||
DEPENDS ${XML_REGISTRY_PROCESSING_SCRIPT} ${SPIRV_XML_REGISTRY_FILE}
|
||||
COMMENT "Generate tables based on the SPIR-V XML registry.")
|
||||
list(APPEND OPCODE_CPP_DEPENDS ${GENERATOR_INC_FILE})
|
||||
|
||||
# The following .cpp files include the above generated .inc files.
|
||||
# Add those .inc files as their dependencies.
|
||||
#
|
||||
# Why using such an awkward way?
|
||||
# * If we use add_custom_target() to define a target to generate all .inc files
|
||||
# and let ${SPIRV_TOOLS} depend on it, then we need to run ninja twice every
|
||||
# time the grammar is updated: the first time is for generating those .inc
|
||||
# files, and the second time is for rebuilding .cpp files, when ninja finds
|
||||
# out that .inc files are updated.
|
||||
# * If we use add_custom_command() with PRE_BUILD, then the grammar processing
|
||||
# script will always run no matter whether the grammar is updated.
|
||||
# * add_dependencies() is used to add *target* dependencies to a target.
|
||||
# * The following solution only generates .inc files when the script or the
|
||||
# grammar files is updated, and in a single ninja run.
|
||||
set_source_files_properties(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/opcode.cpp
|
||||
PROPERTIES OBJECT_DEPENDS "${OPCODE_CPP_DEPENDS}")
|
||||
set_source_files_properties(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/operand.cpp
|
||||
PROPERTIES OBJECT_DEPENDS "${OPERAND_CPP_DEPENDS}")
|
||||
set_source_files_properties(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ext_inst.cpp
|
||||
PROPERTIES OBJECT_DEPENDS "${EXTINST_CPP_DEPENDS}")
|
||||
set_source_files_properties(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/enum_string_mapping.cpp
|
||||
PROPERTIES OBJECT_DEPENDS "${ENUM_STRING_MAPPING_CPP_DEPENDS}")
|
||||
|
||||
set_source_files_properties(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/extension.h
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
set_source_files_properties(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/extension.h
|
||||
PROPERTIES OBJECT_DEPENDS "${EXTENSION_H_DEPENDS}")
|
||||
|
||||
set(SPIRV_TOOLS_BUILD_VERSION_INC
|
||||
${spirv-tools_BINARY_DIR}/build-version.inc)
|
||||
set(SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR
|
||||
${spirv-tools_SOURCE_DIR}/utils/update_build_version.py)
|
||||
set(SPIRV_TOOLS_CHANGES_FILE
|
||||
${spirv-tools_SOURCE_DIR}/CHANGES)
|
||||
add_custom_command(OUTPUT ${SPIRV_TOOLS_BUILD_VERSION_INC}
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
${SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR}
|
||||
${spirv-tools_SOURCE_DIR} ${SPIRV_TOOLS_BUILD_VERSION_INC}
|
||||
DEPENDS ${SPIRV_TOOLS_BUILD_VERSION_INC_GENERATOR}
|
||||
${SPIRV_TOOLS_CHANGES_FILE}
|
||||
COMMENT "Update build-version.inc in the SPIRV-Tools build directory (if necessary).")
|
||||
# Convenience target for standalone generation of the build-version.inc file.
|
||||
# This is not required for any dependence chain.
|
||||
add_custom_target(spirv-tools-build-version
|
||||
DEPENDS ${SPIRV_TOOLS_BUILD_VERSION_INC})
|
||||
set_property(TARGET spirv-tools-build-version PROPERTY FOLDER "SPIRV-Tools build")
|
||||
|
||||
add_subdirectory(comp)
|
||||
add_subdirectory(opt)
|
||||
add_subdirectory(link)
|
||||
|
||||
set(SPIRV_SOURCES
|
||||
${spirv-tools_SOURCE_DIR}/include/spirv-tools/libspirv.h
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/bitutils.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/bit_stream.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/hex_float.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/parse_number.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/string_utils.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/timer.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/assembly_grammar.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/binary.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cfa.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/diagnostic.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/disassemble.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/enum_set.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/enum_string_mapping.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ext_inst.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/extensions.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/id_descriptor.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/instruction.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/latest_version_glsl_std_450_header.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/latest_version_opencl_std_header.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/latest_version_spirv_header.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/macro.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/name_mapper.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/opcode.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/operand.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/parsed_operand.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/print.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_constant.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_definition.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_endian.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_target_env.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_validator_options.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/table.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/text.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/text_handler.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate.h
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/bit_stream.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/parse_number.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/string_utils.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/assembly_grammar.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/diagnostic.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/disassemble.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/enum_string_mapping.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ext_inst.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/extensions.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/id_descriptor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libspirv.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/message.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/name_mapper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/opcode.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/operand.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/parsed_operand.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/print.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/software_version.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_endian.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_stats.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_target_env.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_validator_options.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/table.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/text.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/text_handler.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_adjacency.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_arithmetics.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_atomics.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_barriers.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_bitwise.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_builtins.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_capability.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_cfg.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_composites.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_conversion.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_datarules.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_decorations.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_derivatives.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_ext_inst.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_id.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_image.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_instruction.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_layout.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_literals.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_logicals.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_primitives.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate_type_unique.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/val/decoration.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/val/basic_block.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/val/construct.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/val/function.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/val/instruction.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/val/validation_state.cpp)
|
||||
|
||||
if (${SPIRV_TIMER_ENABLED})
|
||||
set(SPIRV_SOURCES
|
||||
${SPIRV_SOURCES}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/timer.cpp)
|
||||
endif()
|
||||
|
||||
# The software_version.cpp file includes build-version.inc.
|
||||
# Rebuild the software_version.cpp object file if it is older than
|
||||
# build-version.inc or whenever build-version.inc itself is out of
|
||||
# date. In the latter case, rebuild build-version.inc first.
|
||||
# CMake is not smart enough to detect this dependency automatically.
|
||||
# Without this, the dependency detection system for #included files
|
||||
# does not kick in on a clean build for the following reason: The
|
||||
# build will fail early because it doesn't know how to build the
|
||||
# missing source file build-version.inc. That occurs before the
|
||||
# preprocessor is run on software_version.cpp to detect the
|
||||
# #include dependency.
|
||||
set_source_files_properties(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/software_version.cpp
|
||||
PROPERTIES OBJECT_DEPENDS "${SPIRV_TOOLS_BUILD_VERSION_INC}")
|
||||
|
||||
add_library(${SPIRV_TOOLS} ${SPIRV_SOURCES})
|
||||
spvtools_default_compile_options(${SPIRV_TOOLS})
|
||||
target_include_directories(${SPIRV_TOOLS}
|
||||
PUBLIC ${spirv-tools_SOURCE_DIR}/include
|
||||
PRIVATE ${spirv-tools_BINARY_DIR}
|
||||
PRIVATE ${SPIRV_HEADER_INCLUDE_DIR}
|
||||
)
|
||||
set_property(TARGET ${SPIRV_TOOLS} PROPERTY FOLDER "SPIRV-Tools libraries")
|
||||
spvtools_check_symbol_exports(${SPIRV_TOOLS})
|
||||
|
||||
add_library(${SPIRV_TOOLS}-shared SHARED ${SPIRV_SOURCES})
|
||||
spvtools_default_compile_options(${SPIRV_TOOLS}-shared)
|
||||
target_include_directories(${SPIRV_TOOLS}-shared
|
||||
PUBLIC ${spirv-tools_SOURCE_DIR}/include
|
||||
PRIVATE ${spirv-tools_BINARY_DIR}
|
||||
PRIVATE ${SPIRV_HEADER_INCLUDE_DIR}
|
||||
)
|
||||
set_target_properties(${SPIRV_TOOLS}-shared PROPERTIES CXX_VISIBILITY_PRESET hidden)
|
||||
set_property(TARGET ${SPIRV_TOOLS}-shared PROPERTY FOLDER "SPIRV-Tools libraries")
|
||||
spvtools_check_symbol_exports(${SPIRV_TOOLS}-shared)
|
||||
target_compile_definitions(${SPIRV_TOOLS}-shared
|
||||
PRIVATE SPIRV_TOOLS_IMPLEMENTATION
|
||||
PUBLIC SPIRV_TOOLS_SHAREDLIB
|
||||
)
|
||||
|
||||
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||
install(TARGETS ${SPIRV_TOOLS} ${SPIRV_TOOLS}-shared
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif(ENABLE_SPIRV_TOOLS_INSTALL)
|
263
3rdparty/spirv-tools/source/assembly_grammar.cpp
vendored
Normal file
263
3rdparty/spirv-tools/source/assembly_grammar.cpp
vendored
Normal file
@ -0,0 +1,263 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "assembly_grammar.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "ext_inst.h"
|
||||
#include "opcode.h"
|
||||
#include "operand.h"
|
||||
#include "table.h"
|
||||
|
||||
namespace {
|
||||
|
||||
/// @brief Parses a mask expression string for the given operand type.
|
||||
///
|
||||
/// A mask expression is a sequence of one or more terms separated by '|',
|
||||
/// where each term a named enum value for the given type. No whitespace
|
||||
/// is permitted.
|
||||
///
|
||||
/// On success, the value is written to pValue.
|
||||
///
|
||||
/// @param[in] operandTable operand lookup table
|
||||
/// @param[in] type of the operand
|
||||
/// @param[in] textValue word of text to be parsed
|
||||
/// @param[out] pValue where the resulting value is written
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t spvTextParseMaskOperand(spv_target_env env,
|
||||
const spv_operand_table operandTable,
|
||||
const spv_operand_type_t type,
|
||||
const char* textValue, uint32_t* pValue) {
|
||||
if (textValue == nullptr) return SPV_ERROR_INVALID_TEXT;
|
||||
size_t text_length = strlen(textValue);
|
||||
if (text_length == 0) return SPV_ERROR_INVALID_TEXT;
|
||||
const char* text_end = textValue + text_length;
|
||||
|
||||
// We only support mask expressions in ASCII, so the separator value is a
|
||||
// char.
|
||||
const char separator = '|';
|
||||
|
||||
// Accumulate the result by interpreting one word at a time, scanning
|
||||
// from left to right.
|
||||
uint32_t value = 0;
|
||||
const char* begin = textValue; // The left end of the current word.
|
||||
const char* end = nullptr; // One character past the end of the current word.
|
||||
do {
|
||||
end = std::find(begin, text_end, separator);
|
||||
|
||||
spv_operand_desc entry = nullptr;
|
||||
if (spvOperandTableNameLookup(env, operandTable, type, begin, end - begin,
|
||||
&entry)) {
|
||||
return SPV_ERROR_INVALID_TEXT;
|
||||
}
|
||||
value |= entry->value;
|
||||
|
||||
// Advance to the next word by skipping over the separator.
|
||||
begin = end + 1;
|
||||
} while (end != text_end);
|
||||
|
||||
*pValue = value;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// Associates an opcode with its name.
|
||||
struct SpecConstantOpcodeEntry {
|
||||
SpvOp opcode;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
// All the opcodes allowed as the operation for OpSpecConstantOp.
|
||||
// The name does not have the usual "Op" prefix. For example opcode SpvOpIAdd
|
||||
// is associated with the name "IAdd".
|
||||
//
|
||||
// clang-format off
|
||||
#define CASE(NAME) { SpvOp##NAME, #NAME }
|
||||
const SpecConstantOpcodeEntry kOpSpecConstantOpcodes[] = {
|
||||
// Conversion
|
||||
CASE(SConvert),
|
||||
CASE(FConvert),
|
||||
CASE(ConvertFToS),
|
||||
CASE(ConvertSToF),
|
||||
CASE(ConvertFToU),
|
||||
CASE(ConvertUToF),
|
||||
CASE(UConvert),
|
||||
CASE(ConvertPtrToU),
|
||||
CASE(ConvertUToPtr),
|
||||
CASE(GenericCastToPtr),
|
||||
CASE(PtrCastToGeneric),
|
||||
CASE(Bitcast),
|
||||
CASE(QuantizeToF16),
|
||||
// Arithmetic
|
||||
CASE(SNegate),
|
||||
CASE(Not),
|
||||
CASE(IAdd),
|
||||
CASE(ISub),
|
||||
CASE(IMul),
|
||||
CASE(UDiv),
|
||||
CASE(SDiv),
|
||||
CASE(UMod),
|
||||
CASE(SRem),
|
||||
CASE(SMod),
|
||||
CASE(ShiftRightLogical),
|
||||
CASE(ShiftRightArithmetic),
|
||||
CASE(ShiftLeftLogical),
|
||||
CASE(BitwiseOr),
|
||||
CASE(BitwiseAnd),
|
||||
CASE(BitwiseXor),
|
||||
CASE(FNegate),
|
||||
CASE(FAdd),
|
||||
CASE(FSub),
|
||||
CASE(FMul),
|
||||
CASE(FDiv),
|
||||
CASE(FRem),
|
||||
CASE(FMod),
|
||||
// Composite
|
||||
CASE(VectorShuffle),
|
||||
CASE(CompositeExtract),
|
||||
CASE(CompositeInsert),
|
||||
// Logical
|
||||
CASE(LogicalOr),
|
||||
CASE(LogicalAnd),
|
||||
CASE(LogicalNot),
|
||||
CASE(LogicalEqual),
|
||||
CASE(LogicalNotEqual),
|
||||
CASE(Select),
|
||||
// Comparison
|
||||
CASE(IEqual),
|
||||
CASE(INotEqual),
|
||||
CASE(ULessThan),
|
||||
CASE(SLessThan),
|
||||
CASE(UGreaterThan),
|
||||
CASE(SGreaterThan),
|
||||
CASE(ULessThanEqual),
|
||||
CASE(SLessThanEqual),
|
||||
CASE(UGreaterThanEqual),
|
||||
CASE(SGreaterThanEqual),
|
||||
// Memory
|
||||
CASE(AccessChain),
|
||||
CASE(InBoundsAccessChain),
|
||||
CASE(PtrAccessChain),
|
||||
CASE(InBoundsPtrAccessChain),
|
||||
};
|
||||
|
||||
// The 59 is determined by counting the opcodes listed in the spec.
|
||||
static_assert(59 == sizeof(kOpSpecConstantOpcodes)/sizeof(kOpSpecConstantOpcodes[0]),
|
||||
"OpSpecConstantOp opcode table is incomplete");
|
||||
#undef CASE
|
||||
// clang-format on
|
||||
|
||||
const size_t kNumOpSpecConstantOpcodes =
|
||||
sizeof(kOpSpecConstantOpcodes) / sizeof(kOpSpecConstantOpcodes[0]);
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
bool AssemblyGrammar::isValid() const {
|
||||
return operandTable_ && opcodeTable_ && extInstTable_;
|
||||
}
|
||||
|
||||
CapabilitySet AssemblyGrammar::filterCapsAgainstTargetEnv(
|
||||
const SpvCapability* cap_array, uint32_t count) const {
|
||||
CapabilitySet cap_set;
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
spv_operand_desc cap_desc = {};
|
||||
if (SPV_SUCCESS == lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
|
||||
static_cast<uint32_t>(cap_array[i]),
|
||||
&cap_desc)) {
|
||||
// spvOperandTableValueLookup() filters capabilities internally
|
||||
// according to the current target environment by itself. So we
|
||||
// should be safe to add this capability if the lookup succeeds.
|
||||
cap_set.Add(cap_array[i]);
|
||||
}
|
||||
}
|
||||
return cap_set;
|
||||
}
|
||||
|
||||
spv_result_t AssemblyGrammar::lookupOpcode(const char* name,
|
||||
spv_opcode_desc* desc) const {
|
||||
return spvOpcodeTableNameLookup(target_env_, opcodeTable_, name, desc);
|
||||
}
|
||||
|
||||
spv_result_t AssemblyGrammar::lookupOpcode(SpvOp opcode,
|
||||
spv_opcode_desc* desc) const {
|
||||
return spvOpcodeTableValueLookup(target_env_, opcodeTable_, opcode, desc);
|
||||
}
|
||||
|
||||
spv_result_t AssemblyGrammar::lookupOperand(spv_operand_type_t type,
|
||||
const char* name, size_t name_len,
|
||||
spv_operand_desc* desc) const {
|
||||
return spvOperandTableNameLookup(target_env_, operandTable_, type, name,
|
||||
name_len, desc);
|
||||
}
|
||||
|
||||
spv_result_t AssemblyGrammar::lookupOperand(spv_operand_type_t type,
|
||||
uint32_t operand,
|
||||
spv_operand_desc* desc) const {
|
||||
return spvOperandTableValueLookup(target_env_, operandTable_, type, operand,
|
||||
desc);
|
||||
}
|
||||
|
||||
spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(const char* name,
|
||||
SpvOp* opcode) const {
|
||||
const auto* last = kOpSpecConstantOpcodes + kNumOpSpecConstantOpcodes;
|
||||
const auto* found =
|
||||
std::find_if(kOpSpecConstantOpcodes, last,
|
||||
[name](const SpecConstantOpcodeEntry& entry) {
|
||||
return 0 == strcmp(name, entry.name);
|
||||
});
|
||||
if (found == last) return SPV_ERROR_INVALID_LOOKUP;
|
||||
*opcode = found->opcode;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(SpvOp opcode) const {
|
||||
const auto* last = kOpSpecConstantOpcodes + kNumOpSpecConstantOpcodes;
|
||||
const auto* found =
|
||||
std::find_if(kOpSpecConstantOpcodes, last,
|
||||
[opcode](const SpecConstantOpcodeEntry& entry) {
|
||||
return opcode == entry.opcode;
|
||||
});
|
||||
if (found == last) return SPV_ERROR_INVALID_LOOKUP;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t AssemblyGrammar::parseMaskOperand(const spv_operand_type_t type,
|
||||
const char* textValue,
|
||||
uint32_t* pValue) const {
|
||||
return spvTextParseMaskOperand(target_env_, operandTable_, type, textValue,
|
||||
pValue);
|
||||
}
|
||||
spv_result_t AssemblyGrammar::lookupExtInst(spv_ext_inst_type_t type,
|
||||
const char* textValue,
|
||||
spv_ext_inst_desc* extInst) const {
|
||||
return spvExtInstTableNameLookup(extInstTable_, type, textValue, extInst);
|
||||
}
|
||||
|
||||
spv_result_t AssemblyGrammar::lookupExtInst(spv_ext_inst_type_t type,
|
||||
uint32_t firstWord,
|
||||
spv_ext_inst_desc* extInst) const {
|
||||
return spvExtInstTableValueLookup(extInstTable_, type, firstWord, extInst);
|
||||
}
|
||||
|
||||
void AssemblyGrammar::pushOperandTypesForMask(
|
||||
const spv_operand_type_t type, const uint32_t mask,
|
||||
spv_operand_pattern_t* pattern) const {
|
||||
spvPushOperandTypesForMask(target_env_, operandTable_, type, mask, pattern);
|
||||
}
|
||||
} // namespace libspirv
|
137
3rdparty/spirv-tools/source/assembly_grammar.h
vendored
Normal file
137
3rdparty/spirv-tools/source/assembly_grammar.h
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_ASSEMBLY_GRAMMAR_H_
|
||||
#define LIBSPIRV_ASSEMBLY_GRAMMAR_H_
|
||||
|
||||
#include "enum_set.h"
|
||||
#include "latest_version_spirv_header.h"
|
||||
#include "operand.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "table.h"
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
// Encapsulates the grammar to use for SPIR-V assembly.
|
||||
// Contains methods to query for valid instructions and operands.
|
||||
class AssemblyGrammar {
|
||||
public:
|
||||
explicit AssemblyGrammar(const spv_const_context context)
|
||||
: target_env_(context->target_env),
|
||||
operandTable_(context->operand_table),
|
||||
opcodeTable_(context->opcode_table),
|
||||
extInstTable_(context->ext_inst_table) {}
|
||||
|
||||
// Returns true if the internal tables have been initialized with valid data.
|
||||
bool isValid() const;
|
||||
|
||||
// Returns the SPIR-V target environment.
|
||||
spv_target_env target_env() const { return target_env_; }
|
||||
|
||||
// Removes capabilities not available in the current target environment and
|
||||
// returns the rest.
|
||||
CapabilitySet filterCapsAgainstTargetEnv(const SpvCapability* cap_array,
|
||||
uint32_t count) const;
|
||||
|
||||
// Fills in the desc parameter with the information about the opcode
|
||||
// of the given name. Returns SPV_SUCCESS if the opcode was found, and
|
||||
// SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
|
||||
spv_result_t lookupOpcode(const char* name, spv_opcode_desc* desc) const;
|
||||
|
||||
// Fills in the desc parameter with the information about the opcode
|
||||
// of the valid. Returns SPV_SUCCESS if the opcode was found, and
|
||||
// SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
|
||||
spv_result_t lookupOpcode(SpvOp opcode, spv_opcode_desc* desc) const;
|
||||
|
||||
// Fills in the desc parameter with the information about the given
|
||||
// operand. Returns SPV_SUCCESS if the operand was found, and
|
||||
// SPV_ERROR_INVALID_LOOKUP otherwise.
|
||||
spv_result_t lookupOperand(spv_operand_type_t type, const char* name,
|
||||
size_t name_len, spv_operand_desc* desc) const;
|
||||
|
||||
// Fills in the desc parameter with the information about the given
|
||||
// operand. Returns SPV_SUCCESS if the operand was found, and
|
||||
// SPV_ERROR_INVALID_LOOKUP otherwise.
|
||||
spv_result_t lookupOperand(spv_operand_type_t type, uint32_t operand,
|
||||
spv_operand_desc* desc) const;
|
||||
|
||||
// Finds operand entry in the grammar table and returns its name.
|
||||
// Returns "Unknown" if not found.
|
||||
const char* lookupOperandName(spv_operand_type_t type,
|
||||
uint32_t operand) const {
|
||||
spv_operand_desc desc = nullptr;
|
||||
if (lookupOperand(type, operand, &desc) != SPV_SUCCESS || !desc) {
|
||||
return "Unknown";
|
||||
}
|
||||
return desc->name;
|
||||
}
|
||||
|
||||
// Finds the opcode for the given OpSpecConstantOp opcode name. The name
|
||||
// should not have the "Op" prefix. For example, "IAdd" corresponds to
|
||||
// the integer add opcode for OpSpecConstantOp. On success, returns
|
||||
// SPV_SUCCESS and sends the discovered operation code through the opcode
|
||||
// parameter. On failure, returns SPV_ERROR_INVALID_LOOKUP.
|
||||
spv_result_t lookupSpecConstantOpcode(const char* name, SpvOp* opcode) const;
|
||||
|
||||
// Returns SPV_SUCCESS if the given opcode is valid as the opcode operand
|
||||
// to OpSpecConstantOp.
|
||||
spv_result_t lookupSpecConstantOpcode(SpvOp opcode) const;
|
||||
|
||||
// Parses a mask expression string for the given operand type.
|
||||
//
|
||||
// A mask expression is a sequence of one or more terms separated by '|',
|
||||
// where each term is a named enum value for a given type. No whitespace
|
||||
// is permitted.
|
||||
//
|
||||
// On success, the value is written to pValue, and SPV_SUCCESS is returned.
|
||||
// The operand type is defined by the type parameter, and the text to be
|
||||
// parsed is defined by the textValue parameter.
|
||||
spv_result_t parseMaskOperand(const spv_operand_type_t type,
|
||||
const char* textValue, uint32_t* pValue) const;
|
||||
|
||||
// Writes the extended operand with the given type and text to the *extInst
|
||||
// parameter.
|
||||
// Returns SPV_SUCCESS if the value could be found.
|
||||
spv_result_t lookupExtInst(spv_ext_inst_type_t type, const char* textValue,
|
||||
spv_ext_inst_desc* extInst) const;
|
||||
|
||||
// Writes the extended operand with the given type and first encoded word
|
||||
// to the *extInst parameter.
|
||||
// Returns SPV_SUCCESS if the value could be found.
|
||||
spv_result_t lookupExtInst(spv_ext_inst_type_t type, uint32_t firstWord,
|
||||
spv_ext_inst_desc* extInst) const;
|
||||
|
||||
// Inserts the operands expected after the given typed mask onto the end
|
||||
// of the given pattern.
|
||||
//
|
||||
// Each set bit in the mask represents zero or more operand types that
|
||||
// should be appended onto the pattern. Operands for a less significant
|
||||
// bit must always match before operands for a more significant bit, so
|
||||
// the operands for a less significant bit must appear closer to the end
|
||||
// of the pattern stack.
|
||||
//
|
||||
// If a set bit is unknown, then we assume it has no operands.
|
||||
void pushOperandTypesForMask(const spv_operand_type_t type,
|
||||
const uint32_t mask,
|
||||
spv_operand_pattern_t* pattern) const;
|
||||
|
||||
private:
|
||||
const spv_target_env target_env_;
|
||||
const spv_operand_table operandTable_;
|
||||
const spv_opcode_table opcodeTable_;
|
||||
const spv_ext_inst_table extInstTable_;
|
||||
};
|
||||
} // namespace libspirv
|
||||
|
||||
#endif // LIBSPIRV_ASSEMBLY_GRAMMAR_H_
|
789
3rdparty/spirv-tools/source/binary.cpp
vendored
Normal file
789
3rdparty/spirv-tools/source/binary.cpp
vendored
Normal file
@ -0,0 +1,789 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "binary.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "assembly_grammar.h"
|
||||
#include "diagnostic.h"
|
||||
#include "ext_inst.h"
|
||||
#include "latest_version_spirv_header.h"
|
||||
#include "opcode.h"
|
||||
#include "operand.h"
|
||||
#include "spirv_constant.h"
|
||||
#include "spirv_endian.h"
|
||||
|
||||
spv_result_t spvBinaryHeaderGet(const spv_const_binary binary,
|
||||
const spv_endianness_t endian,
|
||||
spv_header_t* pHeader) {
|
||||
if (!binary->code) return SPV_ERROR_INVALID_BINARY;
|
||||
if (binary->wordCount < SPV_INDEX_INSTRUCTION)
|
||||
return SPV_ERROR_INVALID_BINARY;
|
||||
if (!pHeader) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
// TODO: Validation checking?
|
||||
pHeader->magic = spvFixWord(binary->code[SPV_INDEX_MAGIC_NUMBER], endian);
|
||||
pHeader->version = spvFixWord(binary->code[SPV_INDEX_VERSION_NUMBER], endian);
|
||||
pHeader->generator =
|
||||
spvFixWord(binary->code[SPV_INDEX_GENERATOR_NUMBER], endian);
|
||||
pHeader->bound = spvFixWord(binary->code[SPV_INDEX_BOUND], endian);
|
||||
pHeader->schema = spvFixWord(binary->code[SPV_INDEX_SCHEMA], endian);
|
||||
pHeader->instructions = &binary->code[SPV_INDEX_INSTRUCTION];
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// A SPIR-V binary parser. A parser instance communicates detailed parse
|
||||
// results via callbacks.
|
||||
class Parser {
|
||||
public:
|
||||
// The user_data value is provided to the callbacks as context.
|
||||
Parser(const spv_const_context context, void* user_data,
|
||||
spv_parsed_header_fn_t parsed_header_fn,
|
||||
spv_parsed_instruction_fn_t parsed_instruction_fn)
|
||||
: grammar_(context),
|
||||
consumer_(context->consumer),
|
||||
user_data_(user_data),
|
||||
parsed_header_fn_(parsed_header_fn),
|
||||
parsed_instruction_fn_(parsed_instruction_fn) {}
|
||||
|
||||
// Parses the specified binary SPIR-V module, issuing callbacks on a parsed
|
||||
// header and for each parsed instruction. Returns SPV_SUCCESS on success.
|
||||
// Otherwise returns an error code and issues a diagnostic.
|
||||
spv_result_t parse(const uint32_t* words, size_t num_words,
|
||||
spv_diagnostic* diagnostic);
|
||||
|
||||
private:
|
||||
// All remaining methods work on the current module parse state.
|
||||
|
||||
// Like the parse method, but works on the current module parse state.
|
||||
spv_result_t parseModule();
|
||||
|
||||
// Parses an instruction at the current position of the binary. Assumes
|
||||
// the header has been parsed, the endian has been set, and the word index is
|
||||
// still in range. Advances the parsing position past the instruction, and
|
||||
// updates other parsing state for the current module.
|
||||
// On success, returns SPV_SUCCESS and issues the parsed-instruction callback.
|
||||
// On failure, returns an error code and issues a diagnostic.
|
||||
spv_result_t parseInstruction();
|
||||
|
||||
// Parses an instruction operand with the given type, for an instruction
|
||||
// starting at inst_offset words into the SPIR-V binary.
|
||||
// If the SPIR-V binary is the same endianness as the host, then the
|
||||
// endian_converted_inst_words parameter is ignored. Otherwise, this method
|
||||
// appends the words for this operand, converted to host native endianness,
|
||||
// to the end of endian_converted_inst_words. This method also updates the
|
||||
// expected_operands parameter, and the scalar members of the inst parameter.
|
||||
// On success, returns SPV_SUCCESS, advances past the operand, and pushes a
|
||||
// new entry on to the operands vector. Otherwise returns an error code and
|
||||
// issues a diagnostic.
|
||||
spv_result_t parseOperand(size_t inst_offset, spv_parsed_instruction_t* inst,
|
||||
const spv_operand_type_t type,
|
||||
std::vector<uint32_t>* endian_converted_inst_words,
|
||||
std::vector<spv_parsed_operand_t>* operands,
|
||||
spv_operand_pattern_t* expected_operands);
|
||||
|
||||
// Records the numeric type for an operand according to the type information
|
||||
// associated with the given non-zero type Id. This can fail if the type Id
|
||||
// is not a type Id, or if the type Id does not reference a scalar numeric
|
||||
// type. On success, return SPV_SUCCESS and populates the num_words,
|
||||
// number_kind, and number_bit_width fields of parsed_operand.
|
||||
spv_result_t setNumericTypeInfoForType(spv_parsed_operand_t* parsed_operand,
|
||||
uint32_t type_id);
|
||||
|
||||
// Records the number type for an instruction at the given offset, if that
|
||||
// instruction generates a type. For types that aren't scalar numbers,
|
||||
// record something with number kind SPV_NUMBER_NONE.
|
||||
void recordNumberType(size_t inst_offset,
|
||||
const spv_parsed_instruction_t* inst);
|
||||
|
||||
// Returns a diagnostic stream object initialized with current position in
|
||||
// the input stream, and for the given error code. Any data written to the
|
||||
// returned object will be propagated to the current parse's diagnostic
|
||||
// object.
|
||||
libspirv::DiagnosticStream diagnostic(spv_result_t error) {
|
||||
return libspirv::DiagnosticStream({0, 0, _.word_index}, consumer_, error);
|
||||
}
|
||||
|
||||
// Returns a diagnostic stream object with the default parse error code.
|
||||
libspirv::DiagnosticStream diagnostic() {
|
||||
// The default failure for parsing is invalid binary.
|
||||
return diagnostic(SPV_ERROR_INVALID_BINARY);
|
||||
}
|
||||
|
||||
// Issues a diagnostic describing an exhaustion of input condition when
|
||||
// trying to decode an instruction operand, and returns
|
||||
// SPV_ERROR_INVALID_BINARY.
|
||||
spv_result_t exhaustedInputDiagnostic(size_t inst_offset, SpvOp opcode,
|
||||
spv_operand_type_t type) {
|
||||
return diagnostic() << "End of input reached while decoding Op"
|
||||
<< spvOpcodeString(opcode) << " starting at word "
|
||||
<< inst_offset
|
||||
<< ((_.word_index < _.num_words) ? ": truncated "
|
||||
: ": missing ")
|
||||
<< spvOperandTypeStr(type) << " operand at word offset "
|
||||
<< _.word_index - inst_offset << ".";
|
||||
}
|
||||
|
||||
// Returns the endian-corrected word at the current position.
|
||||
uint32_t peek() const { return peekAt(_.word_index); }
|
||||
|
||||
// Returns the endian-corrected word at the given position.
|
||||
uint32_t peekAt(size_t index) const {
|
||||
assert(index < _.num_words);
|
||||
return spvFixWord(_.words[index], _.endian);
|
||||
}
|
||||
|
||||
// Data members
|
||||
|
||||
const libspirv::AssemblyGrammar grammar_; // SPIR-V syntax utility.
|
||||
const spvtools::MessageConsumer& consumer_; // Message consumer callback.
|
||||
void* const user_data_; // Context for the callbacks
|
||||
const spv_parsed_header_fn_t parsed_header_fn_; // Parsed header callback
|
||||
const spv_parsed_instruction_fn_t
|
||||
parsed_instruction_fn_; // Parsed instruction callback
|
||||
|
||||
// Describes the format of a typed literal number.
|
||||
struct NumberType {
|
||||
spv_number_kind_t type;
|
||||
uint32_t bit_width;
|
||||
};
|
||||
|
||||
// The state used to parse a single SPIR-V binary module.
|
||||
struct State {
|
||||
State(const uint32_t* words_arg, size_t num_words_arg,
|
||||
spv_diagnostic* diagnostic_arg)
|
||||
: words(words_arg),
|
||||
num_words(num_words_arg),
|
||||
diagnostic(diagnostic_arg),
|
||||
word_index(0),
|
||||
endian(),
|
||||
requires_endian_conversion(false) {
|
||||
// Temporary storage for parser state within a single instruction.
|
||||
// Most instructions require fewer than 25 words or operands.
|
||||
operands.reserve(25);
|
||||
endian_converted_words.reserve(25);
|
||||
expected_operands.reserve(25);
|
||||
}
|
||||
State() : State(0, 0, nullptr) {}
|
||||
const uint32_t* words; // Words in the binary SPIR-V module.
|
||||
size_t num_words; // Number of words in the module.
|
||||
spv_diagnostic* diagnostic; // Where diagnostics go.
|
||||
size_t word_index; // The current position in words.
|
||||
spv_endianness_t endian; // The endianness of the binary.
|
||||
// Is the SPIR-V binary in a different endiannes from the host native
|
||||
// endianness?
|
||||
bool requires_endian_conversion;
|
||||
|
||||
// Maps a result ID to its type ID. By convention:
|
||||
// - a result ID that is a type definition maps to itself.
|
||||
// - a result ID without a type maps to 0. (E.g. for OpLabel)
|
||||
std::unordered_map<uint32_t, uint32_t> id_to_type_id;
|
||||
// Maps a type ID to its number type description.
|
||||
std::unordered_map<uint32_t, NumberType> type_id_to_number_type_info;
|
||||
// Maps an ExtInstImport id to the extended instruction type.
|
||||
std::unordered_map<uint32_t, spv_ext_inst_type_t>
|
||||
import_id_to_ext_inst_type;
|
||||
|
||||
// Used by parseOperand
|
||||
std::vector<spv_parsed_operand_t> operands;
|
||||
std::vector<uint32_t> endian_converted_words;
|
||||
spv_operand_pattern_t expected_operands;
|
||||
} _;
|
||||
};
|
||||
|
||||
spv_result_t Parser::parse(const uint32_t* words, size_t num_words,
|
||||
spv_diagnostic* diagnostic_arg) {
|
||||
_ = State(words, num_words, diagnostic_arg);
|
||||
|
||||
const spv_result_t result = parseModule();
|
||||
|
||||
// Clear the module state. The tables might be big.
|
||||
_ = State();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
spv_result_t Parser::parseModule() {
|
||||
if (!_.words) return diagnostic() << "Missing module.";
|
||||
|
||||
if (_.num_words < SPV_INDEX_INSTRUCTION)
|
||||
return diagnostic() << "Module has incomplete header: only " << _.num_words
|
||||
<< " words instead of " << SPV_INDEX_INSTRUCTION;
|
||||
|
||||
// Check the magic number and detect the module's endianness.
|
||||
spv_const_binary_t binary{_.words, _.num_words};
|
||||
if (spvBinaryEndianness(&binary, &_.endian)) {
|
||||
return diagnostic() << "Invalid SPIR-V magic number '" << std::hex
|
||||
<< _.words[0] << "'.";
|
||||
}
|
||||
_.requires_endian_conversion = !spvIsHostEndian(_.endian);
|
||||
|
||||
// Process the header.
|
||||
spv_header_t header;
|
||||
if (spvBinaryHeaderGet(&binary, _.endian, &header)) {
|
||||
// It turns out there is no way to trigger this error since the only
|
||||
// failure cases are already handled above, with better messages.
|
||||
return diagnostic(SPV_ERROR_INTERNAL)
|
||||
<< "Internal error: unhandled header parse failure";
|
||||
}
|
||||
if (parsed_header_fn_) {
|
||||
if (auto error = parsed_header_fn_(user_data_, _.endian, header.magic,
|
||||
header.version, header.generator,
|
||||
header.bound, header.schema)) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
// Process the instructions.
|
||||
_.word_index = SPV_INDEX_INSTRUCTION;
|
||||
while (_.word_index < _.num_words)
|
||||
if (auto error = parseInstruction()) return error;
|
||||
|
||||
// Running off the end should already have been reported earlier.
|
||||
assert(_.word_index == _.num_words);
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t Parser::parseInstruction() {
|
||||
// The zero values for all members except for opcode are the
|
||||
// correct initial values.
|
||||
spv_parsed_instruction_t inst = {};
|
||||
|
||||
const uint32_t first_word = peek();
|
||||
|
||||
// If the module's endianness is different from the host native endianness,
|
||||
// then converted_words contains the the endian-translated words in the
|
||||
// instruction.
|
||||
_.endian_converted_words.clear();
|
||||
_.endian_converted_words.push_back(first_word);
|
||||
|
||||
// After a successful parse of the instruction, the inst.operands member
|
||||
// will point to this vector's storage.
|
||||
_.operands.clear();
|
||||
|
||||
assert(_.word_index < _.num_words);
|
||||
// Decompose and check the first word.
|
||||
uint16_t inst_word_count = 0;
|
||||
spvOpcodeSplit(first_word, &inst_word_count, &inst.opcode);
|
||||
if (inst_word_count < 1) {
|
||||
return diagnostic() << "Invalid instruction word count: "
|
||||
<< inst_word_count;
|
||||
}
|
||||
spv_opcode_desc opcode_desc;
|
||||
if (grammar_.lookupOpcode(static_cast<SpvOp>(inst.opcode), &opcode_desc))
|
||||
return diagnostic() << "Invalid opcode: " << inst.opcode;
|
||||
|
||||
// Advance past the opcode word. But remember the of the start
|
||||
// of the instruction.
|
||||
const size_t inst_offset = _.word_index;
|
||||
_.word_index++;
|
||||
|
||||
// Maintains the ordered list of expected operand types.
|
||||
// For many instructions we only need the {numTypes, operandTypes}
|
||||
// entries in opcode_desc. However, sometimes we need to modify
|
||||
// the list as we parse the operands. This occurs when an operand
|
||||
// has its own logical operands (such as the LocalSize operand for
|
||||
// ExecutionMode), or for extended instructions that may have their
|
||||
// own operands depending on the selected extended instruction.
|
||||
_.expected_operands.clear();
|
||||
for (auto i = 0; i < opcode_desc->numTypes; i++)
|
||||
_.expected_operands.push_back(
|
||||
opcode_desc->operandTypes[opcode_desc->numTypes - i - 1]);
|
||||
|
||||
while (_.word_index < inst_offset + inst_word_count) {
|
||||
const uint16_t inst_word_index = uint16_t(_.word_index - inst_offset);
|
||||
if (_.expected_operands.empty()) {
|
||||
return diagnostic() << "Invalid instruction Op" << opcode_desc->name
|
||||
<< " starting at word " << inst_offset
|
||||
<< ": expected no more operands after "
|
||||
<< inst_word_index
|
||||
<< " words, but stated word count is "
|
||||
<< inst_word_count << ".";
|
||||
}
|
||||
|
||||
spv_operand_type_t type =
|
||||
spvTakeFirstMatchableOperand(&_.expected_operands);
|
||||
|
||||
if (auto error =
|
||||
parseOperand(inst_offset, &inst, type, &_.endian_converted_words,
|
||||
&_.operands, &_.expected_operands)) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_.expected_operands.empty() &&
|
||||
!spvOperandIsOptional(_.expected_operands.back())) {
|
||||
return diagnostic() << "End of input reached while decoding Op"
|
||||
<< opcode_desc->name << " starting at word "
|
||||
<< inst_offset << ": expected more operands after "
|
||||
<< inst_word_count << " words.";
|
||||
}
|
||||
|
||||
if ((inst_offset + inst_word_count) != _.word_index) {
|
||||
return diagnostic() << "Invalid word count: Op" << opcode_desc->name
|
||||
<< " starting at word " << inst_offset
|
||||
<< " says it has " << inst_word_count
|
||||
<< " words, but found " << _.word_index - inst_offset
|
||||
<< " words instead.";
|
||||
}
|
||||
|
||||
// Check the computed length of the endian-converted words vector against
|
||||
// the declared number of words in the instruction. If endian conversion
|
||||
// is required, then they should match. If no endian conversion was
|
||||
// performed, then the vector only contains the initial opcode/word-count
|
||||
// word.
|
||||
assert(!_.requires_endian_conversion ||
|
||||
(inst_word_count == _.endian_converted_words.size()));
|
||||
assert(_.requires_endian_conversion ||
|
||||
(_.endian_converted_words.size() == 1));
|
||||
|
||||
recordNumberType(inst_offset, &inst);
|
||||
|
||||
if (_.requires_endian_conversion) {
|
||||
// We must wait until here to set this pointer, because the vector might
|
||||
// have been be resized while we accumulated its elements.
|
||||
inst.words = _.endian_converted_words.data();
|
||||
} else {
|
||||
// If no conversion is required, then just point to the underlying binary.
|
||||
// This saves time and space.
|
||||
inst.words = _.words + inst_offset;
|
||||
}
|
||||
inst.num_words = inst_word_count;
|
||||
|
||||
// We must wait until here to set this pointer, because the vector might
|
||||
// have been be resized while we accumulated its elements.
|
||||
inst.operands = _.operands.data();
|
||||
inst.num_operands = uint16_t(_.operands.size());
|
||||
|
||||
// Issue the callback. The callee should know that all the storage in inst
|
||||
// is transient, and will disappear immediately afterward.
|
||||
if (parsed_instruction_fn_) {
|
||||
if (auto error = parsed_instruction_fn_(user_data_, &inst)) return error;
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
spv_parsed_instruction_t* inst,
|
||||
const spv_operand_type_t type,
|
||||
std::vector<uint32_t>* words,
|
||||
std::vector<spv_parsed_operand_t>* operands,
|
||||
spv_operand_pattern_t* expected_operands) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
// We'll fill in this result as we go along.
|
||||
spv_parsed_operand_t parsed_operand;
|
||||
parsed_operand.offset = uint16_t(_.word_index - inst_offset);
|
||||
// Most operands occupy one word. This might be be adjusted later.
|
||||
parsed_operand.num_words = 1;
|
||||
// The type argument is the one used by the grammar to parse the instruction.
|
||||
// But it can exposes internal parser details such as whether an operand is
|
||||
// optional or actually represents a variable-length sequence of operands.
|
||||
// The resulting type should be adjusted to avoid those internal details.
|
||||
// In most cases, the resulting operand type is the same as the grammar type.
|
||||
parsed_operand.type = type;
|
||||
|
||||
// Assume non-numeric values. This will be updated for literal numbers.
|
||||
parsed_operand.number_kind = SPV_NUMBER_NONE;
|
||||
parsed_operand.number_bit_width = 0;
|
||||
|
||||
if (_.word_index >= _.num_words)
|
||||
return exhaustedInputDiagnostic(inst_offset, opcode, type);
|
||||
|
||||
const uint32_t word = peek();
|
||||
|
||||
// Do the words in this operand have to be converted to native endianness?
|
||||
// True for all but literal strings.
|
||||
bool convert_operand_endianness = true;
|
||||
|
||||
switch (type) {
|
||||
case SPV_OPERAND_TYPE_TYPE_ID:
|
||||
if (!word)
|
||||
return diagnostic(SPV_ERROR_INVALID_ID) << "Error: Type Id is 0";
|
||||
inst->type_id = word;
|
||||
break;
|
||||
|
||||
case SPV_OPERAND_TYPE_RESULT_ID:
|
||||
if (!word)
|
||||
return diagnostic(SPV_ERROR_INVALID_ID) << "Error: Result Id is 0";
|
||||
inst->result_id = word;
|
||||
// Save the result ID to type ID mapping.
|
||||
// In the grammar, type ID always appears before result ID.
|
||||
if (_.id_to_type_id.find(inst->result_id) != _.id_to_type_id.end())
|
||||
return diagnostic(SPV_ERROR_INVALID_ID)
|
||||
<< "Id " << inst->result_id << " is defined more than once";
|
||||
// Record it.
|
||||
// A regular value maps to its type. Some instructions (e.g. OpLabel)
|
||||
// have no type Id, and will map to 0. The result Id for a
|
||||
// type-generating instruction (e.g. OpTypeInt) maps to itself.
|
||||
_.id_to_type_id[inst->result_id] =
|
||||
spvOpcodeGeneratesType(opcode) ? inst->result_id : inst->type_id;
|
||||
break;
|
||||
|
||||
case SPV_OPERAND_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_ID:
|
||||
if (!word) return diagnostic(SPV_ERROR_INVALID_ID) << "Id is 0";
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_ID;
|
||||
|
||||
if (opcode == SpvOpExtInst && parsed_operand.offset == 3) {
|
||||
// The current word is the extended instruction set Id.
|
||||
// Set the extended instruction set type for the current instruction.
|
||||
auto ext_inst_type_iter = _.import_id_to_ext_inst_type.find(word);
|
||||
if (ext_inst_type_iter == _.import_id_to_ext_inst_type.end()) {
|
||||
return diagnostic(SPV_ERROR_INVALID_ID)
|
||||
<< "OpExtInst set Id " << word
|
||||
<< " does not reference an OpExtInstImport result Id";
|
||||
}
|
||||
inst->ext_inst_type = ext_inst_type_iter->second;
|
||||
}
|
||||
break;
|
||||
|
||||
case SPV_OPERAND_TYPE_SCOPE_ID:
|
||||
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
|
||||
// Check for trivially invalid values. The operand descriptions already
|
||||
// have the word "ID" in them.
|
||||
if (!word) return diagnostic() << spvOperandTypeStr(type) << " is 0";
|
||||
break;
|
||||
|
||||
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
|
||||
assert(SpvOpExtInst == opcode);
|
||||
assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE);
|
||||
spv_ext_inst_desc ext_inst;
|
||||
if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst))
|
||||
return diagnostic() << "Invalid extended instruction number: " << word;
|
||||
spvPushOperandTypes(ext_inst->operandTypes, expected_operands);
|
||||
} break;
|
||||
|
||||
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
|
||||
assert(SpvOpSpecConstantOp == opcode);
|
||||
if (grammar_.lookupSpecConstantOpcode(SpvOp(word))) {
|
||||
return diagnostic()
|
||||
<< "Invalid " << spvOperandTypeStr(type) << ": " << word;
|
||||
}
|
||||
spv_opcode_desc opcode_entry = nullptr;
|
||||
if (grammar_.lookupOpcode(SpvOp(word), &opcode_entry)) {
|
||||
return diagnostic(SPV_ERROR_INTERNAL)
|
||||
<< "OpSpecConstant opcode table out of sync";
|
||||
}
|
||||
// OpSpecConstant opcodes must have a type and result. We've already
|
||||
// processed them, so skip them when preparing to parse the other
|
||||
// operants for the opcode.
|
||||
assert(opcode_entry->hasType);
|
||||
assert(opcode_entry->hasResult);
|
||||
assert(opcode_entry->numTypes >= 2);
|
||||
spvPushOperandTypes(opcode_entry->operandTypes + 2, expected_operands);
|
||||
} break;
|
||||
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
|
||||
// These are regular single-word literal integer operands.
|
||||
// Post-parsing validation should check the range of the parsed value.
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_LITERAL_INTEGER;
|
||||
// It turns out they are always unsigned integers!
|
||||
parsed_operand.number_kind = SPV_NUMBER_UNSIGNED_INT;
|
||||
parsed_operand.number_bit_width = 32;
|
||||
break;
|
||||
|
||||
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
|
||||
if (opcode == SpvOpSwitch) {
|
||||
// The literal operands have the same type as the value
|
||||
// referenced by the selector Id.
|
||||
const uint32_t selector_id = peekAt(inst_offset + 1);
|
||||
const auto type_id_iter = _.id_to_type_id.find(selector_id);
|
||||
if (type_id_iter == _.id_to_type_id.end() ||
|
||||
type_id_iter->second == 0) {
|
||||
return diagnostic() << "Invalid OpSwitch: selector id " << selector_id
|
||||
<< " has no type";
|
||||
}
|
||||
uint32_t type_id = type_id_iter->second;
|
||||
|
||||
if (selector_id == type_id) {
|
||||
// Recall that by convention, a result ID that is a type definition
|
||||
// maps to itself.
|
||||
return diagnostic() << "Invalid OpSwitch: selector id " << selector_id
|
||||
<< " is a type, not a value";
|
||||
}
|
||||
if (auto error = setNumericTypeInfoForType(&parsed_operand, type_id))
|
||||
return error;
|
||||
if (parsed_operand.number_kind != SPV_NUMBER_UNSIGNED_INT &&
|
||||
parsed_operand.number_kind != SPV_NUMBER_SIGNED_INT) {
|
||||
return diagnostic() << "Invalid OpSwitch: selector id " << selector_id
|
||||
<< " is not a scalar integer";
|
||||
}
|
||||
} else {
|
||||
assert(opcode == SpvOpConstant || opcode == SpvOpSpecConstant);
|
||||
// The literal number type is determined by the type Id for the
|
||||
// constant.
|
||||
assert(inst->type_id);
|
||||
if (auto error =
|
||||
setNumericTypeInfoForType(&parsed_operand, inst->type_id))
|
||||
return error;
|
||||
}
|
||||
break;
|
||||
|
||||
case SPV_OPERAND_TYPE_LITERAL_STRING:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING: {
|
||||
convert_operand_endianness = false;
|
||||
const char* string =
|
||||
reinterpret_cast<const char*>(_.words + _.word_index);
|
||||
// Compute the length of the string, but make sure we don't run off the
|
||||
// end of the input.
|
||||
const size_t remaining_input_bytes =
|
||||
sizeof(uint32_t) * (_.num_words - _.word_index);
|
||||
const size_t string_num_content_bytes =
|
||||
spv_strnlen_s(string, remaining_input_bytes);
|
||||
// If there was no terminating null byte, then that's an end-of-input
|
||||
// error.
|
||||
if (string_num_content_bytes == remaining_input_bytes)
|
||||
return exhaustedInputDiagnostic(inst_offset, opcode, type);
|
||||
// Account for null in the word length, so add 1 for null, then add 3 to
|
||||
// make sure we round up. The following is equivalent to:
|
||||
// (string_num_content_bytes + 1 + 3) / 4
|
||||
const size_t string_num_words = string_num_content_bytes / 4 + 1;
|
||||
// Make sure we can record the word count without overflow.
|
||||
//
|
||||
// This error can't currently be triggered because of validity
|
||||
// checks elsewhere.
|
||||
if (string_num_words > std::numeric_limits<uint16_t>::max()) {
|
||||
return diagnostic() << "Literal string is longer than "
|
||||
<< std::numeric_limits<uint16_t>::max()
|
||||
<< " words: " << string_num_words << " words long";
|
||||
}
|
||||
parsed_operand.num_words = uint16_t(string_num_words);
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_LITERAL_STRING;
|
||||
|
||||
if (SpvOpExtInstImport == opcode) {
|
||||
// Record the extended instruction type for the ID for this import.
|
||||
// There is only one string literal argument to OpExtInstImport,
|
||||
// so it's sufficient to guard this just on the opcode.
|
||||
const spv_ext_inst_type_t ext_inst_type =
|
||||
spvExtInstImportTypeGet(string);
|
||||
if (SPV_EXT_INST_TYPE_NONE == ext_inst_type) {
|
||||
return diagnostic()
|
||||
<< "Invalid extended instruction import '" << string << "'";
|
||||
}
|
||||
// We must have parsed a valid result ID. It's a condition
|
||||
// of the grammar, and we only accept non-zero result Ids.
|
||||
assert(inst->result_id);
|
||||
_.import_id_to_ext_inst_type[inst->result_id] = ext_inst_type;
|
||||
}
|
||||
} break;
|
||||
|
||||
case SPV_OPERAND_TYPE_CAPABILITY:
|
||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODEL:
|
||||
case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
|
||||
case SPV_OPERAND_TYPE_MEMORY_MODEL:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODE:
|
||||
case SPV_OPERAND_TYPE_STORAGE_CLASS:
|
||||
case SPV_OPERAND_TYPE_DIMENSIONALITY:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
|
||||
case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
|
||||
case SPV_OPERAND_TYPE_LINKAGE_TYPE:
|
||||
case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
|
||||
case SPV_OPERAND_TYPE_DECORATION:
|
||||
case SPV_OPERAND_TYPE_BUILT_IN:
|
||||
case SPV_OPERAND_TYPE_GROUP_OPERATION:
|
||||
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
|
||||
case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
|
||||
case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
|
||||
case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
|
||||
case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_DEBUG_OPERATION: {
|
||||
// A single word that is a plain enum value.
|
||||
|
||||
// Map an optional operand type to its corresponding concrete type.
|
||||
if (type == SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER)
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_ACCESS_QUALIFIER;
|
||||
|
||||
spv_operand_desc entry;
|
||||
if (grammar_.lookupOperand(type, word, &entry)) {
|
||||
return diagnostic()
|
||||
<< "Invalid " << spvOperandTypeStr(parsed_operand.type)
|
||||
<< " operand: " << word;
|
||||
}
|
||||
// Prepare to accept operands to this operand, if needed.
|
||||
spvPushOperandTypes(entry->operandTypes, expected_operands);
|
||||
} break;
|
||||
|
||||
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_LOOP_CONTROL:
|
||||
case SPV_OPERAND_TYPE_IMAGE:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
|
||||
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS: {
|
||||
// This operand is a mask.
|
||||
|
||||
// Map an optional operand type to its corresponding concrete type.
|
||||
if (type == SPV_OPERAND_TYPE_OPTIONAL_IMAGE)
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_IMAGE;
|
||||
else if (type == SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS)
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_MEMORY_ACCESS;
|
||||
|
||||
// Check validity of set mask bits. Also prepare for operands for those
|
||||
// masks if they have any. To get operand order correct, scan from
|
||||
// MSB to LSB since we can only prepend operands to a pattern.
|
||||
// The only case in the grammar where you have more than one mask bit
|
||||
// having an operand is for image operands. See SPIR-V 3.14 Image
|
||||
// Operands.
|
||||
uint32_t remaining_word = word;
|
||||
for (uint32_t mask = (1u << 31); remaining_word; mask >>= 1) {
|
||||
if (remaining_word & mask) {
|
||||
spv_operand_desc entry;
|
||||
if (grammar_.lookupOperand(type, mask, &entry)) {
|
||||
return diagnostic()
|
||||
<< "Invalid " << spvOperandTypeStr(parsed_operand.type)
|
||||
<< " operand: " << word << " has invalid mask component "
|
||||
<< mask;
|
||||
}
|
||||
remaining_word ^= mask;
|
||||
spvPushOperandTypes(entry->operandTypes, expected_operands);
|
||||
}
|
||||
}
|
||||
if (word == 0) {
|
||||
// An all-zeroes mask *might* also be valid.
|
||||
spv_operand_desc entry;
|
||||
if (SPV_SUCCESS == grammar_.lookupOperand(type, 0, &entry)) {
|
||||
// Prepare for its operands, if any.
|
||||
spvPushOperandTypes(entry->operandTypes, expected_operands);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
return diagnostic() << "Internal error: Unhandled operand type: " << type;
|
||||
}
|
||||
|
||||
assert(spvOperandIsConcrete(parsed_operand.type));
|
||||
|
||||
operands->push_back(parsed_operand);
|
||||
|
||||
const size_t index_after_operand = _.word_index + parsed_operand.num_words;
|
||||
|
||||
// Avoid buffer overrun for the cases where the operand has more than one
|
||||
// word, and where it isn't a string. (Those other cases have already been
|
||||
// handled earlier.) For example, this error can occur for a multi-word
|
||||
// argument to OpConstant, or a multi-word case literal operand for OpSwitch.
|
||||
if (_.num_words < index_after_operand)
|
||||
return exhaustedInputDiagnostic(inst_offset, opcode, type);
|
||||
|
||||
if (_.requires_endian_conversion) {
|
||||
// Copy instruction words. Translate to native endianness as needed.
|
||||
if (convert_operand_endianness) {
|
||||
const spv_endianness_t endianness = _.endian;
|
||||
std::transform(_.words + _.word_index, _.words + index_after_operand,
|
||||
std::back_inserter(*words),
|
||||
[endianness](const uint32_t raw_word) {
|
||||
return spvFixWord(raw_word, endianness);
|
||||
});
|
||||
} else {
|
||||
words->insert(words->end(), _.words + _.word_index,
|
||||
_.words + index_after_operand);
|
||||
}
|
||||
}
|
||||
|
||||
// Advance past the operand.
|
||||
_.word_index = index_after_operand;
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t Parser::setNumericTypeInfoForType(
|
||||
spv_parsed_operand_t* parsed_operand, uint32_t type_id) {
|
||||
assert(type_id != 0);
|
||||
auto type_info_iter = _.type_id_to_number_type_info.find(type_id);
|
||||
if (type_info_iter == _.type_id_to_number_type_info.end()) {
|
||||
return diagnostic() << "Type Id " << type_id << " is not a type";
|
||||
}
|
||||
const NumberType& info = type_info_iter->second;
|
||||
if (info.type == SPV_NUMBER_NONE) {
|
||||
// This is a valid type, but for something other than a scalar number.
|
||||
return diagnostic() << "Type Id " << type_id
|
||||
<< " is not a scalar numeric type";
|
||||
}
|
||||
|
||||
parsed_operand->number_kind = info.type;
|
||||
parsed_operand->number_bit_width = info.bit_width;
|
||||
// Round up the word count.
|
||||
parsed_operand->num_words = static_cast<uint16_t>((info.bit_width + 31) / 32);
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
void Parser::recordNumberType(size_t inst_offset,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
if (spvOpcodeGeneratesType(opcode)) {
|
||||
NumberType info = {SPV_NUMBER_NONE, 0};
|
||||
if (SpvOpTypeInt == opcode) {
|
||||
const bool is_signed = peekAt(inst_offset + 3) != 0;
|
||||
info.type = is_signed ? SPV_NUMBER_SIGNED_INT : SPV_NUMBER_UNSIGNED_INT;
|
||||
info.bit_width = peekAt(inst_offset + 2);
|
||||
} else if (SpvOpTypeFloat == opcode) {
|
||||
info.type = SPV_NUMBER_FLOATING;
|
||||
info.bit_width = peekAt(inst_offset + 2);
|
||||
}
|
||||
// The *result* Id of a type generating instruction is the type Id.
|
||||
_.type_id_to_number_type_info[inst->result_id] = info;
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
spv_result_t spvBinaryParse(const spv_const_context context, void* user_data,
|
||||
const uint32_t* code, const size_t num_words,
|
||||
spv_parsed_header_fn_t parsed_header,
|
||||
spv_parsed_instruction_fn_t parsed_instruction,
|
||||
spv_diagnostic* diagnostic) {
|
||||
spv_context_t hijack_context = *context;
|
||||
if (diagnostic) {
|
||||
*diagnostic = nullptr;
|
||||
libspirv::UseDiagnosticAsMessageConsumer(&hijack_context, diagnostic);
|
||||
}
|
||||
Parser parser(&hijack_context, user_data, parsed_header, parsed_instruction);
|
||||
return parser.parse(code, num_words, diagnostic);
|
||||
}
|
||||
|
||||
// TODO(dneto): This probably belongs in text.cpp since that's the only place
|
||||
// that a spv_binary_t value is created.
|
||||
void spvBinaryDestroy(spv_binary binary) {
|
||||
if (!binary) return;
|
||||
delete[] binary->code;
|
||||
delete binary;
|
||||
}
|
||||
|
||||
size_t spv_strnlen_s(const char* str, size_t strsz) {
|
||||
if (!str) return 0;
|
||||
for (size_t i = 0; i < strsz; i++) {
|
||||
if (!str[i]) return i;
|
||||
}
|
||||
return strsz;
|
||||
}
|
36
3rdparty/spirv-tools/source/binary.h
vendored
Normal file
36
3rdparty/spirv-tools/source/binary.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_BINARY_H_
|
||||
#define LIBSPIRV_BINARY_H_
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv_definition.h"
|
||||
|
||||
// Functions
|
||||
|
||||
// Grabs the header from the SPIR-V module given in the binary parameter. The
|
||||
// endian parameter specifies the endianness of the binary module. On success,
|
||||
// returns SPV_SUCCESS and writes the parsed header into *header.
|
||||
spv_result_t spvBinaryHeaderGet(const spv_const_binary binary,
|
||||
const spv_endianness_t endian,
|
||||
spv_header_t* header);
|
||||
|
||||
// Returns the number of non-null characters in str before the first null
|
||||
// character, or strsz if there is no null character. Examines at most the
|
||||
// first strsz characters in str. Returns 0 if str is nullptr. This is a
|
||||
// replacement for C11's strnlen_s which might not exist in all environments.
|
||||
size_t spv_strnlen_s(const char* str, size_t strsz);
|
||||
|
||||
#endif // LIBSPIRV_BINARY_H_
|
338
3rdparty/spirv-tools/source/cfa.h
vendored
Normal file
338
3rdparty/spirv-tools/source/cfa.h
vendored
Normal file
@ -0,0 +1,338 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SPVTOOLS_CFA_H_
|
||||
#define SPVTOOLS_CFA_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using std::find;
|
||||
using std::function;
|
||||
using std::get;
|
||||
using std::pair;
|
||||
using std::unordered_map;
|
||||
using std::unordered_set;
|
||||
using std::vector;
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
// Control Flow Analysis of control flow graphs of basic block nodes |BB|.
|
||||
template <class BB>
|
||||
class CFA {
|
||||
using bb_ptr = BB*;
|
||||
using cbb_ptr = const BB*;
|
||||
using bb_iter = typename std::vector<BB*>::const_iterator;
|
||||
using get_blocks_func = std::function<const std::vector<BB*>*(const BB*)>;
|
||||
|
||||
struct block_info {
|
||||
cbb_ptr block; ///< pointer to the block
|
||||
bb_iter iter; ///< Iterator to the current child node being processed
|
||||
};
|
||||
|
||||
/// Returns true if a block with @p id is found in the @p work_list vector
|
||||
///
|
||||
/// @param[in] work_list Set of blocks visited in the the depth first
|
||||
/// traversal
|
||||
/// of the CFG
|
||||
/// @param[in] id The ID of the block being checked
|
||||
///
|
||||
/// @return true if the edge work_list.back().block->id() => id is a back-edge
|
||||
static bool FindInWorkList(const std::vector<block_info>& work_list,
|
||||
uint32_t id);
|
||||
|
||||
public:
|
||||
/// @brief Depth first traversal starting from the \p entry BasicBlock
|
||||
///
|
||||
/// This function performs a depth first traversal from the \p entry
|
||||
/// BasicBlock and calls the pre/postorder functions when it needs to process
|
||||
/// the node in pre order, post order. It also calls the backedge function
|
||||
/// when a back edge is encountered.
|
||||
///
|
||||
/// @param[in] entry The root BasicBlock of a CFG
|
||||
/// @param[in] successor_func A function which will return a pointer to the
|
||||
/// successor nodes
|
||||
/// @param[in] preorder A function that will be called for every block in a
|
||||
/// CFG following preorder traversal semantics
|
||||
/// @param[in] postorder A function that will be called for every block in a
|
||||
/// CFG following postorder traversal semantics
|
||||
/// @param[in] backedge A function that will be called when a backedge is
|
||||
/// encountered during a traversal
|
||||
/// NOTE: The @p successor_func and predecessor_func each return a pointer to
|
||||
/// a
|
||||
/// collection such that iterators to that collection remain valid for the
|
||||
/// lifetime of the algorithm.
|
||||
static void DepthFirstTraversal(
|
||||
const BB* entry, get_blocks_func successor_func,
|
||||
std::function<void(cbb_ptr)> preorder,
|
||||
std::function<void(cbb_ptr)> postorder,
|
||||
std::function<void(cbb_ptr, cbb_ptr)> backedge);
|
||||
|
||||
/// @brief Calculates dominator edges for a set of blocks
|
||||
///
|
||||
/// Computes dominators using the algorithm of Cooper, Harvey, and Kennedy
|
||||
/// "A Simple, Fast Dominance Algorithm", 2001.
|
||||
///
|
||||
/// The algorithm assumes there is a unique root node (a node without
|
||||
/// predecessors), and it is therefore at the end of the postorder vector.
|
||||
///
|
||||
/// This function calculates the dominator edges for a set of blocks in the
|
||||
/// CFG.
|
||||
/// Uses the dominator algorithm by Cooper et al.
|
||||
///
|
||||
/// @param[in] postorder A vector of blocks in post order traversal
|
||||
/// order
|
||||
/// in a CFG
|
||||
/// @param[in] predecessor_func Function used to get the predecessor nodes of
|
||||
/// a
|
||||
/// block
|
||||
///
|
||||
/// @return the dominator tree of the graph, as a vector of pairs of nodes.
|
||||
/// The first node in the pair is a node in the graph. The second node in the
|
||||
/// pair is its immediate dominator in the sense of Cooper et.al., where a
|
||||
/// block
|
||||
/// without predecessors (such as the root node) is its own immediate
|
||||
/// dominator.
|
||||
static vector<pair<BB*, BB*>> CalculateDominators(
|
||||
const vector<cbb_ptr>& postorder, get_blocks_func predecessor_func);
|
||||
|
||||
// Computes a minimal set of root nodes required to traverse, in the forward
|
||||
// direction, the CFG represented by the given vector of blocks, and successor
|
||||
// and predecessor functions. When considering adding two nodes, each having
|
||||
// predecessors, favour using the one that appears earlier on the input blocks
|
||||
// list.
|
||||
static std::vector<BB*> TraversalRoots(const std::vector<BB*>& blocks,
|
||||
get_blocks_func succ_func,
|
||||
get_blocks_func pred_func);
|
||||
|
||||
static void ComputeAugmentedCFG(
|
||||
std::vector<BB*>& ordered_blocks, BB* pseudo_entry_block,
|
||||
BB* pseudo_exit_block,
|
||||
std::unordered_map<const BB*, std::vector<BB*>>* augmented_successors_map,
|
||||
std::unordered_map<const BB*, std::vector<BB*>>*
|
||||
augmented_predecessors_map,
|
||||
get_blocks_func succ_func, get_blocks_func pred_func);
|
||||
};
|
||||
|
||||
template <class BB>
|
||||
bool CFA<BB>::FindInWorkList(const vector<block_info>& work_list, uint32_t id) {
|
||||
for (const auto b : work_list) {
|
||||
if (b.block->id() == id) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class BB>
|
||||
void CFA<BB>::DepthFirstTraversal(const BB* entry,
|
||||
get_blocks_func successor_func,
|
||||
function<void(cbb_ptr)> preorder,
|
||||
function<void(cbb_ptr)> postorder,
|
||||
function<void(cbb_ptr, cbb_ptr)> backedge) {
|
||||
unordered_set<uint32_t> processed;
|
||||
|
||||
/// NOTE: work_list is the sequence of nodes from the root node to the node
|
||||
/// being processed in the traversal
|
||||
vector<block_info> work_list;
|
||||
work_list.reserve(10);
|
||||
|
||||
work_list.push_back({entry, begin(*successor_func(entry))});
|
||||
preorder(entry);
|
||||
processed.insert(entry->id());
|
||||
|
||||
while (!work_list.empty()) {
|
||||
block_info& top = work_list.back();
|
||||
if (top.iter == end(*successor_func(top.block))) {
|
||||
postorder(top.block);
|
||||
work_list.pop_back();
|
||||
} else {
|
||||
BB* child = *top.iter;
|
||||
top.iter++;
|
||||
if (FindInWorkList(work_list, child->id())) {
|
||||
backedge(top.block, child);
|
||||
}
|
||||
if (processed.count(child->id()) == 0) {
|
||||
preorder(child);
|
||||
work_list.emplace_back(
|
||||
block_info{child, begin(*successor_func(child))});
|
||||
processed.insert(child->id());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class BB>
|
||||
vector<pair<BB*, BB*>> CFA<BB>::CalculateDominators(
|
||||
const vector<cbb_ptr>& postorder, get_blocks_func predecessor_func) {
|
||||
struct block_detail {
|
||||
size_t dominator; ///< The index of blocks's dominator in post order array
|
||||
size_t postorder_index; ///< The index of the block in the post order array
|
||||
};
|
||||
const size_t undefined_dom = postorder.size();
|
||||
|
||||
unordered_map<cbb_ptr, block_detail> idoms;
|
||||
for (size_t i = 0; i < postorder.size(); i++) {
|
||||
idoms[postorder[i]] = {undefined_dom, i};
|
||||
}
|
||||
idoms[postorder.back()].dominator = idoms[postorder.back()].postorder_index;
|
||||
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
for (auto b = postorder.rbegin() + 1; b != postorder.rend(); ++b) {
|
||||
const vector<BB*>& predecessors = *predecessor_func(*b);
|
||||
// Find the first processed/reachable predecessor that is reachable
|
||||
// in the forward traversal.
|
||||
auto res = find_if(begin(predecessors), end(predecessors),
|
||||
[&idoms, undefined_dom](BB* pred) {
|
||||
return idoms.count(pred) &&
|
||||
idoms[pred].dominator != undefined_dom;
|
||||
});
|
||||
if (res == end(predecessors)) continue;
|
||||
const BB* idom = *res;
|
||||
size_t idom_idx = idoms[idom].postorder_index;
|
||||
|
||||
// all other predecessors
|
||||
for (const auto* p : predecessors) {
|
||||
if (idom == p) continue;
|
||||
// Only consider nodes reachable in the forward traversal.
|
||||
// Otherwise the intersection doesn't make sense and will never
|
||||
// terminate.
|
||||
if (!idoms.count(p)) continue;
|
||||
if (idoms[p].dominator != undefined_dom) {
|
||||
size_t finger1 = idoms[p].postorder_index;
|
||||
size_t finger2 = idom_idx;
|
||||
while (finger1 != finger2) {
|
||||
while (finger1 < finger2) {
|
||||
finger1 = idoms[postorder[finger1]].dominator;
|
||||
}
|
||||
while (finger2 < finger1) {
|
||||
finger2 = idoms[postorder[finger2]].dominator;
|
||||
}
|
||||
}
|
||||
idom_idx = finger1;
|
||||
}
|
||||
}
|
||||
if (idoms[*b].dominator != idom_idx) {
|
||||
idoms[*b].dominator = idom_idx;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<pair<bb_ptr, bb_ptr>> out;
|
||||
for (auto idom : idoms) {
|
||||
// NOTE: performing a const cast for convenient usage with
|
||||
// UpdateImmediateDominators
|
||||
out.push_back({const_cast<BB*>(get<0>(idom)),
|
||||
const_cast<BB*>(postorder[get<1>(idom).dominator])});
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class BB>
|
||||
std::vector<BB*> CFA<BB>::TraversalRoots(const std::vector<BB*>& blocks,
|
||||
get_blocks_func succ_func,
|
||||
get_blocks_func pred_func) {
|
||||
// The set of nodes which have been visited from any of the roots so far.
|
||||
std::unordered_set<const BB*> visited;
|
||||
|
||||
auto mark_visited = [&visited](const BB* b) { visited.insert(b); };
|
||||
auto ignore_block = [](const BB*) {};
|
||||
auto ignore_blocks = [](const BB*, const BB*) {};
|
||||
|
||||
auto traverse_from_root = [&mark_visited, &succ_func, &ignore_block,
|
||||
&ignore_blocks](const BB* entry) {
|
||||
DepthFirstTraversal(entry, succ_func, mark_visited, ignore_block,
|
||||
ignore_blocks);
|
||||
};
|
||||
|
||||
std::vector<BB*> result;
|
||||
|
||||
// First collect nodes without predecessors.
|
||||
for (auto block : blocks) {
|
||||
if (pred_func(block)->empty()) {
|
||||
assert(visited.count(block) == 0 && "Malformed graph!");
|
||||
result.push_back(block);
|
||||
traverse_from_root(block);
|
||||
}
|
||||
}
|
||||
|
||||
// Now collect other stranded nodes. These must be in unreachable cycles.
|
||||
for (auto block : blocks) {
|
||||
if (visited.count(block) == 0) {
|
||||
result.push_back(block);
|
||||
traverse_from_root(block);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class BB>
|
||||
void CFA<BB>::ComputeAugmentedCFG(
|
||||
std::vector<BB*>& ordered_blocks, BB* pseudo_entry_block,
|
||||
BB* pseudo_exit_block,
|
||||
std::unordered_map<const BB*, std::vector<BB*>>* augmented_successors_map,
|
||||
std::unordered_map<const BB*, std::vector<BB*>>* augmented_predecessors_map,
|
||||
get_blocks_func succ_func, get_blocks_func pred_func) {
|
||||
// Compute the successors of the pseudo-entry block, and
|
||||
// the predecessors of the pseudo exit block.
|
||||
auto sources = TraversalRoots(ordered_blocks, succ_func, pred_func);
|
||||
|
||||
// For the predecessor traversals, reverse the order of blocks. This
|
||||
// will affect the post-dominance calculation as follows:
|
||||
// - Suppose you have blocks A and B, with A appearing before B in
|
||||
// the list of blocks.
|
||||
// - Also, A branches only to B, and B branches only to A.
|
||||
// - We want to compute A as dominating B, and B as post-dominating B.
|
||||
// By using reversed blocks for predecessor traversal roots discovery,
|
||||
// we'll add an edge from B to the pseudo-exit node, rather than from A.
|
||||
// All this is needed to correctly process the dominance/post-dominance
|
||||
// constraint when A is a loop header that points to itself as its
|
||||
// own continue target, and B is the latch block for the loop.
|
||||
std::vector<BB*> reversed_blocks(ordered_blocks.rbegin(),
|
||||
ordered_blocks.rend());
|
||||
auto sinks = TraversalRoots(reversed_blocks, pred_func, succ_func);
|
||||
|
||||
// Wire up the pseudo entry block.
|
||||
(*augmented_successors_map)[pseudo_entry_block] = sources;
|
||||
for (auto block : sources) {
|
||||
auto& augmented_preds = (*augmented_predecessors_map)[block];
|
||||
const auto preds = pred_func(block);
|
||||
augmented_preds.reserve(1 + preds->size());
|
||||
augmented_preds.push_back(pseudo_entry_block);
|
||||
augmented_preds.insert(augmented_preds.end(), preds->begin(), preds->end());
|
||||
}
|
||||
|
||||
// Wire up the pseudo exit block.
|
||||
(*augmented_predecessors_map)[pseudo_exit_block] = sinks;
|
||||
for (auto block : sinks) {
|
||||
auto& augmented_succ = (*augmented_successors_map)[block];
|
||||
const auto succ = succ_func(block);
|
||||
augmented_succ.reserve(1 + succ->size());
|
||||
augmented_succ.push_back(pseudo_exit_block);
|
||||
augmented_succ.insert(augmented_succ.end(), succ->begin(), succ->end());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SPVTOOLS_CFA_H_
|
38
3rdparty/spirv-tools/source/comp/CMakeLists.txt
vendored
Normal file
38
3rdparty/spirv-tools/source/comp/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2017 Google Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
if(SPIRV_BUILD_COMPRESSION)
|
||||
add_library(SPIRV-Tools-comp markv_codec.cpp)
|
||||
|
||||
spvtools_default_compile_options(SPIRV-Tools-comp)
|
||||
target_include_directories(SPIRV-Tools-comp
|
||||
PUBLIC ${spirv-tools_SOURCE_DIR}/include
|
||||
PUBLIC ${SPIRV_HEADER_INCLUDE_DIR}
|
||||
PRIVATE ${spirv-tools_BINARY_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(SPIRV-Tools-comp
|
||||
PUBLIC ${SPIRV_TOOLS})
|
||||
|
||||
set_property(TARGET SPIRV-Tools-comp PROPERTY FOLDER "SPIRV-Tools libraries")
|
||||
spvtools_check_symbol_exports(SPIRV-Tools-comp)
|
||||
|
||||
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||
install(TARGETS SPIRV-Tools-comp
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||
|
||||
endif(SPIRV_BUILD_COMPRESSION)
|
74
3rdparty/spirv-tools/source/comp/markv.h
vendored
Normal file
74
3rdparty/spirv-tools/source/comp/markv.h
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// MARK-V is a compression format for SPIR-V binaries. It strips away
|
||||
// non-essential information (such as result ids which can be regenerated) and
|
||||
// uses various bit reduction techiniques to reduce the size of the binary and
|
||||
// make it more similar to other compressed SPIR-V files to further improve
|
||||
// compression of the dataset.
|
||||
|
||||
#ifndef SPIRV_TOOLS_MARKV_HPP_
|
||||
#define SPIRV_TOOLS_MARKV_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "markv_model.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
struct MarkvCodecOptions {
|
||||
bool validate_spirv_binary = false;
|
||||
};
|
||||
|
||||
// Debug callback. Called once per instruction.
|
||||
// |words| is instruction SPIR-V words.
|
||||
// |bits| is a textual representation of the MARK-V bit sequence used to encode
|
||||
// the instruction (char '0' for 0, char '1' for 1).
|
||||
// |comment| contains all logs generated while processing the instruction.
|
||||
using MarkvDebugConsumer =
|
||||
std::function<bool(const std::vector<uint32_t>& words,
|
||||
const std::string& bits, const std::string& comment)>;
|
||||
|
||||
// Logging callback. Called often (if decoder reads a single bit, the log
|
||||
// consumer will receive 1 character string with that bit).
|
||||
// This callback is more suitable for continous output than MarkvDebugConsumer,
|
||||
// for example if the codec crashes it would allow to pinpoint on which operand
|
||||
// or bit the crash happened.
|
||||
// |snippet| could be any atomic fragment of text logged by the codec. It can
|
||||
// contain a paragraph of text with newlines, or can be just one character.
|
||||
using MarkvLogConsumer = std::function<void(const std::string& snippet)>;
|
||||
|
||||
// Encodes the given SPIR-V binary to MARK-V binary.
|
||||
// |log_consumer| is optional (pass MarkvLogConsumer() to disable).
|
||||
// |debug_consumer| is optional (pass MarkvDebugConsumer() to disable).
|
||||
spv_result_t SpirvToMarkv(
|
||||
spv_const_context context, const std::vector<uint32_t>& spirv,
|
||||
const MarkvCodecOptions& options, const MarkvModel& markv_model,
|
||||
MessageConsumer message_consumer, MarkvLogConsumer log_consumer,
|
||||
MarkvDebugConsumer debug_consumer, std::vector<uint8_t>* markv);
|
||||
|
||||
// Decodes a SPIR-V binary from the given MARK-V binary.
|
||||
// |log_consumer| is optional (pass MarkvLogConsumer() to disable).
|
||||
// |debug_consumer| is optional (pass MarkvDebugConsumer() to disable).
|
||||
spv_result_t MarkvToSpirv(
|
||||
spv_const_context context, const std::vector<uint8_t>& markv,
|
||||
const MarkvCodecOptions& options, const MarkvModel& markv_model,
|
||||
MessageConsumer message_consumer, MarkvLogConsumer log_consumer,
|
||||
MarkvDebugConsumer debug_consumer, std::vector<uint32_t>* spirv);
|
||||
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SPIRV_TOOLS_MARKV_HPP_
|
2920
3rdparty/spirv-tools/source/comp/markv_codec.cpp
vendored
Normal file
2920
3rdparty/spirv-tools/source/comp/markv_codec.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
232
3rdparty/spirv-tools/source/comp/markv_model.h
vendored
Normal file
232
3rdparty/spirv-tools/source/comp/markv_model.h
vendored
Normal file
@ -0,0 +1,232 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_COMP_MARKV_MODEL_H_
|
||||
#define LIBSPIRV_COMP_MARKV_MODEL_H_
|
||||
|
||||
#include <map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "latest_version_spirv_header.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "util/huffman_codec.h"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
// Base class for MARK-V models.
|
||||
// The class contains encoding/decoding model with various constants and
|
||||
// codecs used by the compression algorithm.
|
||||
class MarkvModel {
|
||||
public:
|
||||
MarkvModel()
|
||||
: operand_chunk_lengths_(
|
||||
static_cast<size_t>(SPV_OPERAND_TYPE_NUM_OPERAND_TYPES), 0) {
|
||||
// Set default values.
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_TYPE_ID] = 4;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_RESULT_ID] = 8;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_ID] = 8;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_SCOPE_ID] = 8;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID] = 8;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_LITERAL_INTEGER] = 6;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER] = 6;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_CAPABILITY] = 6;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_SOURCE_LANGUAGE] = 3;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_EXECUTION_MODEL] = 3;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_ADDRESSING_MODEL] = 2;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_MEMORY_MODEL] = 2;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_EXECUTION_MODE] = 6;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_STORAGE_CLASS] = 4;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_DIMENSIONALITY] = 3;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE] = 3;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE] = 2;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT] = 6;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_FP_ROUNDING_MODE] = 2;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_LINKAGE_TYPE] = 2;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_ACCESS_QUALIFIER] = 2;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER] = 2;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE] = 3;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_DECORATION] = 6;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_BUILT_IN] = 6;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_GROUP_OPERATION] = 2;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS] = 2;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO] = 2;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_FP_FAST_MATH_MODE] = 4;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_FUNCTION_CONTROL] = 4;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_LOOP_CONTROL] = 4;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_IMAGE] = 4;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_OPTIONAL_IMAGE] = 4;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS] = 4;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_SELECTION_CONTROL] = 4;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER] = 6;
|
||||
operand_chunk_lengths_[SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER] = 6;
|
||||
}
|
||||
|
||||
uint32_t model_type() const { return model_type_; }
|
||||
uint32_t model_version() const { return model_version_; }
|
||||
|
||||
uint32_t opcode_chunk_length() const { return opcode_chunk_length_; }
|
||||
uint32_t num_operands_chunk_length() const {
|
||||
return num_operands_chunk_length_;
|
||||
}
|
||||
uint32_t mtf_rank_chunk_length() const { return mtf_rank_chunk_length_; }
|
||||
|
||||
uint32_t u64_chunk_length() const { return u64_chunk_length_; }
|
||||
uint32_t s64_chunk_length() const { return s64_chunk_length_; }
|
||||
uint32_t s64_block_exponent() const { return s64_block_exponent_; }
|
||||
|
||||
enum class IdFallbackStrategy {
|
||||
kRuleBased = 0,
|
||||
kShortDescriptor,
|
||||
};
|
||||
|
||||
IdFallbackStrategy id_fallback_strategy() const {
|
||||
return id_fallback_strategy_;
|
||||
}
|
||||
|
||||
// Returns a codec for common opcode_and_num_operands words for the given
|
||||
// previous opcode. May return nullptr if the codec doesn't exist.
|
||||
const spvutils::HuffmanCodec<uint64_t>*
|
||||
GetOpcodeAndNumOperandsMarkovHuffmanCodec(uint32_t prev_opcode) const {
|
||||
if (prev_opcode == SpvOpNop)
|
||||
return opcode_and_num_operands_huffman_codec_.get();
|
||||
|
||||
const auto it =
|
||||
opcode_and_num_operands_markov_huffman_codecs_.find(prev_opcode);
|
||||
if (it == opcode_and_num_operands_markov_huffman_codecs_.end())
|
||||
return nullptr;
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
// Returns a codec for common non-id words used for given operand slot.
|
||||
// Operand slot is defined by the opcode and the operand index.
|
||||
// May return nullptr if the codec doesn't exist.
|
||||
const spvutils::HuffmanCodec<uint64_t>* GetNonIdWordHuffmanCodec(
|
||||
uint32_t opcode, uint32_t operand_index) const {
|
||||
const auto it = non_id_word_huffman_codecs_.find(
|
||||
std::pair<uint32_t, uint32_t>(opcode, operand_index));
|
||||
if (it == non_id_word_huffman_codecs_.end()) return nullptr;
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
// Returns a codec for common id descriptos used for given operand slot.
|
||||
// Operand slot is defined by the opcode and the operand index.
|
||||
// May return nullptr if the codec doesn't exist.
|
||||
const spvutils::HuffmanCodec<uint64_t>* GetIdDescriptorHuffmanCodec(
|
||||
uint32_t opcode, uint32_t operand_index) const {
|
||||
const auto it = id_descriptor_huffman_codecs_.find(
|
||||
std::pair<uint32_t, uint32_t>(opcode, operand_index));
|
||||
if (it == id_descriptor_huffman_codecs_.end()) return nullptr;
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
// Returns a codec for common strings used by the given opcode.
|
||||
// Operand slot is defined by the opcode and the operand index.
|
||||
// May return nullptr if the codec doesn't exist.
|
||||
const spvutils::HuffmanCodec<std::string>* GetLiteralStringHuffmanCodec(
|
||||
uint32_t opcode) const {
|
||||
const auto it = literal_string_huffman_codecs_.find(opcode);
|
||||
if (it == literal_string_huffman_codecs_.end()) return nullptr;
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
// Checks if |descriptor| has a coding scheme in any of
|
||||
// id_descriptor_huffman_codecs_.
|
||||
bool DescriptorHasCodingScheme(uint32_t descriptor) const {
|
||||
return descriptors_with_coding_scheme_.count(descriptor);
|
||||
}
|
||||
|
||||
// Checks if any descriptor has a coding scheme.
|
||||
bool AnyDescriptorHasCodingScheme() const {
|
||||
return !descriptors_with_coding_scheme_.empty();
|
||||
}
|
||||
|
||||
// Returns chunk length used for variable length encoding of spirv operand
|
||||
// words.
|
||||
uint32_t GetOperandVariableWidthChunkLength(spv_operand_type_t type) const {
|
||||
return operand_chunk_lengths_.at(static_cast<size_t>(type));
|
||||
}
|
||||
|
||||
// Sets model type.
|
||||
void SetModelType(uint32_t in_model_type) { model_type_ = in_model_type; }
|
||||
|
||||
// Sets model version.
|
||||
void SetModelVersion(uint32_t in_model_version) {
|
||||
model_version_ = in_model_version;
|
||||
}
|
||||
|
||||
// Returns value used by Huffman codecs as a signal that a value is not in the
|
||||
// coding table.
|
||||
static uint64_t GetMarkvNoneOfTheAbove() {
|
||||
// Magic number.
|
||||
return 1111111111111111111;
|
||||
}
|
||||
|
||||
MarkvModel(const MarkvModel&) = delete;
|
||||
const MarkvModel& operator=(const MarkvModel&) = delete;
|
||||
|
||||
protected:
|
||||
// Huffman codec for base-rate of opcode_and_num_operands.
|
||||
std::unique_ptr<spvutils::HuffmanCodec<uint64_t>>
|
||||
opcode_and_num_operands_huffman_codec_;
|
||||
|
||||
// Huffman codecs for opcode_and_num_operands. The map key is previous opcode.
|
||||
std::map<uint32_t, std::unique_ptr<spvutils::HuffmanCodec<uint64_t>>>
|
||||
opcode_and_num_operands_markov_huffman_codecs_;
|
||||
|
||||
// Huffman codecs for non-id single-word operand values.
|
||||
// The map key is pair <opcode, operand_index>.
|
||||
std::map<std::pair<uint32_t, uint32_t>,
|
||||
std::unique_ptr<spvutils::HuffmanCodec<uint64_t>>>
|
||||
non_id_word_huffman_codecs_;
|
||||
|
||||
// Huffman codecs for id descriptors. The map key is pair
|
||||
// <opcode, operand_index>.
|
||||
std::map<std::pair<uint32_t, uint32_t>,
|
||||
std::unique_ptr<spvutils::HuffmanCodec<uint64_t>>>
|
||||
id_descriptor_huffman_codecs_;
|
||||
|
||||
// Set of all descriptors which have a coding scheme in any of
|
||||
// id_descriptor_huffman_codecs_.
|
||||
std::unordered_set<uint32_t> descriptors_with_coding_scheme_;
|
||||
|
||||
// Huffman codecs for literal strings. The map key is the opcode of the
|
||||
// current instruction. This assumes, that there is no more than one literal
|
||||
// string operand per instruction, but would still work even if this is not
|
||||
// the case. Names and debug information strings are not collected.
|
||||
std::map<uint32_t, std::unique_ptr<spvutils::HuffmanCodec<std::string>>>
|
||||
literal_string_huffman_codecs_;
|
||||
|
||||
// Chunk lengths used for variable width encoding of operands (index is
|
||||
// spv_operand_type of the operand).
|
||||
std::vector<uint32_t> operand_chunk_lengths_;
|
||||
|
||||
uint32_t opcode_chunk_length_ = 7;
|
||||
uint32_t num_operands_chunk_length_ = 3;
|
||||
uint32_t mtf_rank_chunk_length_ = 5;
|
||||
|
||||
uint32_t u64_chunk_length_ = 8;
|
||||
uint32_t s64_chunk_length_ = 8;
|
||||
uint32_t s64_block_exponent_ = 10;
|
||||
|
||||
IdFallbackStrategy id_fallback_strategy_ =
|
||||
IdFallbackStrategy::kShortDescriptor;
|
||||
|
||||
uint32_t model_type_ = 0;
|
||||
uint32_t model_version_ = 0;
|
||||
};
|
||||
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_COMP_MARKV_MODEL_H_
|
186
3rdparty/spirv-tools/source/diagnostic.cpp
vendored
Normal file
186
3rdparty/spirv-tools/source/diagnostic.cpp
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "diagnostic.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "table.h"
|
||||
|
||||
// Diagnostic API
|
||||
|
||||
spv_diagnostic spvDiagnosticCreate(const spv_position position,
|
||||
const char* message) {
|
||||
spv_diagnostic diagnostic = new spv_diagnostic_t;
|
||||
if (!diagnostic) return nullptr;
|
||||
size_t length = strlen(message) + 1;
|
||||
diagnostic->error = new char[length];
|
||||
if (!diagnostic->error) {
|
||||
delete diagnostic;
|
||||
return nullptr;
|
||||
}
|
||||
diagnostic->position = *position;
|
||||
diagnostic->isTextSource = false;
|
||||
memset(diagnostic->error, 0, length);
|
||||
strncpy(diagnostic->error, message, length);
|
||||
return diagnostic;
|
||||
}
|
||||
|
||||
void spvDiagnosticDestroy(spv_diagnostic diagnostic) {
|
||||
if (!diagnostic) return;
|
||||
delete[] diagnostic->error;
|
||||
delete diagnostic;
|
||||
}
|
||||
|
||||
spv_result_t spvDiagnosticPrint(const spv_diagnostic diagnostic) {
|
||||
if (!diagnostic) return SPV_ERROR_INVALID_DIAGNOSTIC;
|
||||
|
||||
if (diagnostic->isTextSource) {
|
||||
// NOTE: This is a text position
|
||||
// NOTE: add 1 to the line as editors start at line 1, we are counting new
|
||||
// line characters to start at line 0
|
||||
std::cerr << "error: " << diagnostic->position.line + 1 << ": "
|
||||
<< diagnostic->position.column + 1 << ": " << diagnostic->error
|
||||
<< "\n";
|
||||
return SPV_SUCCESS;
|
||||
} else {
|
||||
// NOTE: Assume this is a binary position
|
||||
std::cerr << "error: " << diagnostic->position.index << ": "
|
||||
<< diagnostic->error << "\n";
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
DiagnosticStream::DiagnosticStream(DiagnosticStream&& other)
|
||||
: stream_(),
|
||||
position_(other.position_),
|
||||
consumer_(other.consumer_),
|
||||
error_(other.error_) {
|
||||
// Prevent the other object from emitting output during destruction.
|
||||
other.error_ = SPV_FAILED_MATCH;
|
||||
// Some platforms are missing support for std::ostringstream functionality,
|
||||
// including: move constructor, swap method. Either would have been a
|
||||
// better choice than copying the string.
|
||||
stream_ << other.stream_.str();
|
||||
}
|
||||
|
||||
DiagnosticStream::~DiagnosticStream() {
|
||||
if (error_ != SPV_FAILED_MATCH && consumer_ != nullptr) {
|
||||
auto level = SPV_MSG_ERROR;
|
||||
switch (error_) {
|
||||
case SPV_SUCCESS:
|
||||
case SPV_REQUESTED_TERMINATION: // Essentially success.
|
||||
level = SPV_MSG_INFO;
|
||||
break;
|
||||
case SPV_WARNING:
|
||||
level = SPV_MSG_WARNING;
|
||||
break;
|
||||
case SPV_UNSUPPORTED:
|
||||
case SPV_ERROR_INTERNAL:
|
||||
case SPV_ERROR_INVALID_TABLE:
|
||||
level = SPV_MSG_INTERNAL_ERROR;
|
||||
break;
|
||||
case SPV_ERROR_OUT_OF_MEMORY:
|
||||
level = SPV_MSG_FATAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
consumer_(level, "input", position_, stream_.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void UseDiagnosticAsMessageConsumer(spv_context context,
|
||||
spv_diagnostic* diagnostic) {
|
||||
assert(diagnostic && *diagnostic == nullptr);
|
||||
|
||||
auto create_diagnostic = [diagnostic](spv_message_level_t, const char*,
|
||||
const spv_position_t& position,
|
||||
const char* message) {
|
||||
auto p = position;
|
||||
spvDiagnosticDestroy(*diagnostic); // Avoid memory leak.
|
||||
*diagnostic = spvDiagnosticCreate(&p, message);
|
||||
};
|
||||
libspirv::SetContextMessageConsumer(context, std::move(create_diagnostic));
|
||||
}
|
||||
|
||||
std::string spvResultToString(spv_result_t res) {
|
||||
std::string out;
|
||||
switch (res) {
|
||||
case SPV_SUCCESS:
|
||||
out = "SPV_SUCCESS";
|
||||
break;
|
||||
case SPV_UNSUPPORTED:
|
||||
out = "SPV_UNSUPPORTED";
|
||||
break;
|
||||
case SPV_END_OF_STREAM:
|
||||
out = "SPV_END_OF_STREAM";
|
||||
break;
|
||||
case SPV_WARNING:
|
||||
out = "SPV_WARNING";
|
||||
break;
|
||||
case SPV_FAILED_MATCH:
|
||||
out = "SPV_FAILED_MATCH";
|
||||
break;
|
||||
case SPV_REQUESTED_TERMINATION:
|
||||
out = "SPV_REQUESTED_TERMINATION";
|
||||
break;
|
||||
case SPV_ERROR_INTERNAL:
|
||||
out = "SPV_ERROR_INTERNAL";
|
||||
break;
|
||||
case SPV_ERROR_OUT_OF_MEMORY:
|
||||
out = "SPV_ERROR_OUT_OF_MEMORY";
|
||||
break;
|
||||
case SPV_ERROR_INVALID_POINTER:
|
||||
out = "SPV_ERROR_INVALID_POINTER";
|
||||
break;
|
||||
case SPV_ERROR_INVALID_BINARY:
|
||||
out = "SPV_ERROR_INVALID_BINARY";
|
||||
break;
|
||||
case SPV_ERROR_INVALID_TEXT:
|
||||
out = "SPV_ERROR_INVALID_TEXT";
|
||||
break;
|
||||
case SPV_ERROR_INVALID_TABLE:
|
||||
out = "SPV_ERROR_INVALID_TABLE";
|
||||
break;
|
||||
case SPV_ERROR_INVALID_VALUE:
|
||||
out = "SPV_ERROR_INVALID_VALUE";
|
||||
break;
|
||||
case SPV_ERROR_INVALID_DIAGNOSTIC:
|
||||
out = "SPV_ERROR_INVALID_DIAGNOSTIC";
|
||||
break;
|
||||
case SPV_ERROR_INVALID_LOOKUP:
|
||||
out = "SPV_ERROR_INVALID_LOOKUP";
|
||||
break;
|
||||
case SPV_ERROR_INVALID_ID:
|
||||
out = "SPV_ERROR_INVALID_ID";
|
||||
break;
|
||||
case SPV_ERROR_INVALID_CFG:
|
||||
out = "SPV_ERROR_INVALID_CFG";
|
||||
break;
|
||||
case SPV_ERROR_INVALID_LAYOUT:
|
||||
out = "SPV_ERROR_INVALID_LAYOUT";
|
||||
break;
|
||||
default:
|
||||
out = "Unknown Error";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace libspirv
|
75
3rdparty/spirv-tools/source/diagnostic.h
vendored
Normal file
75
3rdparty/spirv-tools/source/diagnostic.h
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_DIAGNOSTIC_H_
|
||||
#define LIBSPIRV_DIAGNOSTIC_H_
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
// A DiagnosticStream remembers the current position of the input and an error
|
||||
// code, and captures diagnostic messages via the left-shift operator.
|
||||
// If the error code is not SPV_FAILED_MATCH, then captured messages are
|
||||
// emitted during the destructor.
|
||||
class DiagnosticStream {
|
||||
public:
|
||||
DiagnosticStream(spv_position_t position,
|
||||
const spvtools::MessageConsumer& consumer,
|
||||
spv_result_t error)
|
||||
: position_(position), consumer_(consumer), error_(error) {}
|
||||
|
||||
// Creates a DiagnosticStream from an expiring DiagnosticStream.
|
||||
// The new object takes the contents of the other, and prevents the
|
||||
// other from emitting anything during destruction.
|
||||
DiagnosticStream(DiagnosticStream&& other);
|
||||
|
||||
// Destroys a DiagnosticStream.
|
||||
// If its status code is something other than SPV_FAILED_MATCH
|
||||
// then emit the accumulated message to the consumer.
|
||||
~DiagnosticStream();
|
||||
|
||||
// Adds the given value to the diagnostic message to be written.
|
||||
template <typename T>
|
||||
DiagnosticStream& operator<<(const T& val) {
|
||||
stream_ << val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Conversion operator to spv_result, returning the error code.
|
||||
operator spv_result_t() { return error_; }
|
||||
|
||||
private:
|
||||
std::ostringstream stream_;
|
||||
spv_position_t position_;
|
||||
spvtools::MessageConsumer consumer_; // Message consumer callback.
|
||||
spv_result_t error_;
|
||||
};
|
||||
|
||||
// Changes the MessageConsumer in |context| to one that updates |diagnostic|
|
||||
// with the last message received.
|
||||
//
|
||||
// This function expects that |diagnostic| is not nullptr and its content is a
|
||||
// nullptr.
|
||||
void UseDiagnosticAsMessageConsumer(spv_context context,
|
||||
spv_diagnostic* diagnostic);
|
||||
|
||||
std::string spvResultToString(spv_result_t res);
|
||||
|
||||
} // namespace libspirv
|
||||
|
||||
#endif // LIBSPIRV_DIAGNOSTIC_H_
|
476
3rdparty/spirv-tools/source/disassemble.cpp
vendored
Normal file
476
3rdparty/spirv-tools/source/disassemble.cpp
vendored
Normal file
@ -0,0 +1,476 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// This file contains a disassembler: It converts a SPIR-V binary
|
||||
// to text.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "assembly_grammar.h"
|
||||
#include "binary.h"
|
||||
#include "diagnostic.h"
|
||||
#include "disassemble.h"
|
||||
#include "ext_inst.h"
|
||||
#include "name_mapper.h"
|
||||
#include "opcode.h"
|
||||
#include "parsed_operand.h"
|
||||
#include "print.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv_constant.h"
|
||||
#include "spirv_endian.h"
|
||||
#include "util/hex_float.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// A Disassembler instance converts a SPIR-V binary to its assembly
|
||||
// representation.
|
||||
class Disassembler {
|
||||
public:
|
||||
Disassembler(const libspirv::AssemblyGrammar& grammar, uint32_t options,
|
||||
libspirv::NameMapper name_mapper)
|
||||
: grammar_(grammar),
|
||||
print_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options)),
|
||||
color_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COLOR, options)),
|
||||
indent_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_INDENT, options)
|
||||
? kStandardIndent
|
||||
: 0),
|
||||
text_(),
|
||||
out_(print_ ? out_stream() : out_stream(text_)),
|
||||
stream_(out_.get()),
|
||||
header_(!spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER, options)),
|
||||
show_byte_offset_(spvIsInBitfield(
|
||||
SPV_BINARY_TO_TEXT_OPTION_SHOW_BYTE_OFFSET, options)),
|
||||
byte_offset_(0),
|
||||
name_mapper_(std::move(name_mapper)) {}
|
||||
|
||||
// Emits the assembly header for the module, and sets up internal state
|
||||
// so subsequent callbacks can handle the cases where the entire module
|
||||
// is either big-endian or little-endian.
|
||||
spv_result_t HandleHeader(spv_endianness_t endian, uint32_t version,
|
||||
uint32_t generator, uint32_t id_bound,
|
||||
uint32_t schema);
|
||||
// Emits the assembly text for the given instruction.
|
||||
spv_result_t HandleInstruction(const spv_parsed_instruction_t& inst);
|
||||
|
||||
// If not printing, populates text_result with the accumulated text.
|
||||
// Returns SPV_SUCCESS on success.
|
||||
spv_result_t SaveTextResult(spv_text* text_result) const;
|
||||
|
||||
private:
|
||||
enum { kStandardIndent = 15 };
|
||||
|
||||
using out_stream = libspirv::out_stream;
|
||||
|
||||
// Emits an operand for the given instruction, where the instruction
|
||||
// is at offset words from the start of the binary.
|
||||
void EmitOperand(const spv_parsed_instruction_t& inst,
|
||||
const uint16_t operand_index);
|
||||
|
||||
// Emits a mask expression for the given mask word of the specified type.
|
||||
void EmitMaskOperand(const spv_operand_type_t type, const uint32_t word);
|
||||
|
||||
// Resets the output color, if color is turned on.
|
||||
void ResetColor() {
|
||||
if (color_) out_.get() << libspirv::clr::reset{print_};
|
||||
}
|
||||
// Sets the output to grey, if color is turned on.
|
||||
void SetGrey() {
|
||||
if (color_) out_.get() << libspirv::clr::grey{print_};
|
||||
}
|
||||
// Sets the output to blue, if color is turned on.
|
||||
void SetBlue() {
|
||||
if (color_) out_.get() << libspirv::clr::blue{print_};
|
||||
}
|
||||
// Sets the output to yellow, if color is turned on.
|
||||
void SetYellow() {
|
||||
if (color_) out_.get() << libspirv::clr::yellow{print_};
|
||||
}
|
||||
// Sets the output to red, if color is turned on.
|
||||
void SetRed() {
|
||||
if (color_) out_.get() << libspirv::clr::red{print_};
|
||||
}
|
||||
// Sets the output to green, if color is turned on.
|
||||
void SetGreen() {
|
||||
if (color_) out_.get() << libspirv::clr::green{print_};
|
||||
}
|
||||
|
||||
const libspirv::AssemblyGrammar& grammar_;
|
||||
const bool print_; // Should we also print to the standard output stream?
|
||||
const bool color_; // Should we print in colour?
|
||||
const int indent_; // How much to indent. 0 means don't indent
|
||||
spv_endianness_t endian_; // The detected endianness of the binary.
|
||||
std::stringstream text_; // Captures the text, if not printing.
|
||||
out_stream out_; // The Output stream. Either to text_ or standard output.
|
||||
std::ostream& stream_; // The output std::stream.
|
||||
const bool header_; // Should we output header as the leading comment?
|
||||
const bool show_byte_offset_; // Should we print byte offset, in hex?
|
||||
size_t byte_offset_; // The number of bytes processed so far.
|
||||
libspirv::NameMapper name_mapper_;
|
||||
};
|
||||
|
||||
spv_result_t Disassembler::HandleHeader(spv_endianness_t endian,
|
||||
uint32_t version, uint32_t generator,
|
||||
uint32_t id_bound, uint32_t schema) {
|
||||
endian_ = endian;
|
||||
|
||||
if (header_) {
|
||||
SetGrey();
|
||||
const char* generator_tool =
|
||||
spvGeneratorStr(SPV_GENERATOR_TOOL_PART(generator));
|
||||
stream_ << "; SPIR-V\n"
|
||||
<< "; Version: " << SPV_SPIRV_VERSION_MAJOR_PART(version) << "."
|
||||
<< SPV_SPIRV_VERSION_MINOR_PART(version) << "\n"
|
||||
<< "; Generator: " << generator_tool;
|
||||
// For unknown tools, print the numeric tool value.
|
||||
if (0 == strcmp("Unknown", generator_tool)) {
|
||||
stream_ << "(" << SPV_GENERATOR_TOOL_PART(generator) << ")";
|
||||
}
|
||||
// Print the miscellaneous part of the generator word on the same
|
||||
// line as the tool name.
|
||||
stream_ << "; " << SPV_GENERATOR_MISC_PART(generator) << "\n"
|
||||
<< "; Bound: " << id_bound << "\n"
|
||||
<< "; Schema: " << schema << "\n";
|
||||
ResetColor();
|
||||
}
|
||||
|
||||
byte_offset_ = SPV_INDEX_INSTRUCTION * sizeof(uint32_t);
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t Disassembler::HandleInstruction(
|
||||
const spv_parsed_instruction_t& inst) {
|
||||
if (inst.result_id) {
|
||||
SetBlue();
|
||||
const std::string id_name = name_mapper_(inst.result_id);
|
||||
if (indent_)
|
||||
stream_ << std::setw(std::max(0, indent_ - 3 - int(id_name.size())));
|
||||
stream_ << "%" << id_name;
|
||||
ResetColor();
|
||||
stream_ << " = ";
|
||||
} else {
|
||||
stream_ << std::string(indent_, ' ');
|
||||
}
|
||||
|
||||
stream_ << "Op" << spvOpcodeString(static_cast<SpvOp>(inst.opcode));
|
||||
|
||||
for (uint16_t i = 0; i < inst.num_operands; i++) {
|
||||
const spv_operand_type_t type = inst.operands[i].type;
|
||||
assert(type != SPV_OPERAND_TYPE_NONE);
|
||||
if (type == SPV_OPERAND_TYPE_RESULT_ID) continue;
|
||||
stream_ << " ";
|
||||
EmitOperand(inst, i);
|
||||
}
|
||||
|
||||
if (show_byte_offset_) {
|
||||
SetGrey();
|
||||
auto saved_flags = stream_.flags();
|
||||
auto saved_fill = stream_.fill();
|
||||
stream_ << " ; 0x" << std::setw(8) << std::hex << std::setfill('0')
|
||||
<< byte_offset_;
|
||||
stream_.flags(saved_flags);
|
||||
stream_.fill(saved_fill);
|
||||
ResetColor();
|
||||
}
|
||||
|
||||
byte_offset_ += inst.num_words * sizeof(uint32_t);
|
||||
|
||||
stream_ << "\n";
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
void Disassembler::EmitOperand(const spv_parsed_instruction_t& inst,
|
||||
const uint16_t operand_index) {
|
||||
assert(operand_index < inst.num_operands);
|
||||
const spv_parsed_operand_t& operand = inst.operands[operand_index];
|
||||
const uint32_t word = inst.words[operand.offset];
|
||||
switch (operand.type) {
|
||||
case SPV_OPERAND_TYPE_RESULT_ID:
|
||||
assert(false && "<result-id> is not supposed to be handled here");
|
||||
SetBlue();
|
||||
stream_ << "%" << name_mapper_(word);
|
||||
break;
|
||||
case SPV_OPERAND_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_SCOPE_ID:
|
||||
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
|
||||
SetYellow();
|
||||
stream_ << "%" << name_mapper_(word);
|
||||
break;
|
||||
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
|
||||
spv_ext_inst_desc ext_inst;
|
||||
if (grammar_.lookupExtInst(inst.ext_inst_type, word, &ext_inst))
|
||||
assert(false && "should have caught this earlier");
|
||||
SetRed();
|
||||
stream_ << ext_inst->name;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
|
||||
spv_opcode_desc opcode_desc;
|
||||
if (grammar_.lookupOpcode(SpvOp(word), &opcode_desc))
|
||||
assert(false && "should have caught this earlier");
|
||||
SetRed();
|
||||
stream_ << opcode_desc->name;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER:
|
||||
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER: {
|
||||
SetRed();
|
||||
libspirv::EmitNumericLiteral(&stream_, inst, operand);
|
||||
ResetColor();
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_STRING: {
|
||||
stream_ << "\"";
|
||||
SetGreen();
|
||||
// Strings are always little-endian, and null-terminated.
|
||||
// Write out the characters, escaping as needed, and without copying
|
||||
// the entire string.
|
||||
auto c_str = reinterpret_cast<const char*>(inst.words + operand.offset);
|
||||
for (auto p = c_str; *p; ++p) {
|
||||
if (*p == '"' || *p == '\\') stream_ << '\\';
|
||||
stream_ << *p;
|
||||
}
|
||||
ResetColor();
|
||||
stream_ << '"';
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_CAPABILITY:
|
||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODEL:
|
||||
case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
|
||||
case SPV_OPERAND_TYPE_MEMORY_MODEL:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODE:
|
||||
case SPV_OPERAND_TYPE_STORAGE_CLASS:
|
||||
case SPV_OPERAND_TYPE_DIMENSIONALITY:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
|
||||
case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
|
||||
case SPV_OPERAND_TYPE_LINKAGE_TYPE:
|
||||
case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
|
||||
case SPV_OPERAND_TYPE_DECORATION:
|
||||
case SPV_OPERAND_TYPE_BUILT_IN:
|
||||
case SPV_OPERAND_TYPE_GROUP_OPERATION:
|
||||
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
|
||||
case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
|
||||
case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
|
||||
case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
|
||||
case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_DEBUG_OPERATION: {
|
||||
spv_operand_desc entry;
|
||||
if (grammar_.lookupOperand(operand.type, word, &entry))
|
||||
assert(false && "should have caught this earlier");
|
||||
stream_ << entry->name;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_LOOP_CONTROL:
|
||||
case SPV_OPERAND_TYPE_IMAGE:
|
||||
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
|
||||
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
|
||||
EmitMaskOperand(operand.type, word);
|
||||
break;
|
||||
default:
|
||||
assert(false && "unhandled or invalid case");
|
||||
}
|
||||
ResetColor();
|
||||
}
|
||||
|
||||
void Disassembler::EmitMaskOperand(const spv_operand_type_t type,
|
||||
const uint32_t word) {
|
||||
// Scan the mask from least significant bit to most significant bit. For each
|
||||
// set bit, emit the name of that bit. Separate multiple names with '|'.
|
||||
uint32_t remaining_word = word;
|
||||
uint32_t mask;
|
||||
int num_emitted = 0;
|
||||
for (mask = 1; remaining_word; mask <<= 1) {
|
||||
if (remaining_word & mask) {
|
||||
remaining_word ^= mask;
|
||||
spv_operand_desc entry;
|
||||
if (grammar_.lookupOperand(type, mask, &entry))
|
||||
assert(false && "should have caught this earlier");
|
||||
if (num_emitted) stream_ << "|";
|
||||
stream_ << entry->name;
|
||||
num_emitted++;
|
||||
}
|
||||
}
|
||||
if (!num_emitted) {
|
||||
// An operand value of 0 was provided, so represent it by the name
|
||||
// of the 0 value. In many cases, that's "None".
|
||||
spv_operand_desc entry;
|
||||
if (SPV_SUCCESS == grammar_.lookupOperand(type, 0, &entry))
|
||||
stream_ << entry->name;
|
||||
}
|
||||
}
|
||||
|
||||
spv_result_t Disassembler::SaveTextResult(spv_text* text_result) const {
|
||||
if (!print_) {
|
||||
size_t length = text_.str().size();
|
||||
char* str = new char[length + 1];
|
||||
if (!str) return SPV_ERROR_OUT_OF_MEMORY;
|
||||
strncpy(str, text_.str().c_str(), length + 1);
|
||||
spv_text text = new spv_text_t();
|
||||
if (!text) {
|
||||
delete[] str;
|
||||
return SPV_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
text->str = str;
|
||||
text->length = length;
|
||||
*text_result = text;
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t DisassembleHeader(void* user_data, spv_endianness_t endian,
|
||||
uint32_t /* magic */, uint32_t version,
|
||||
uint32_t generator, uint32_t id_bound,
|
||||
uint32_t schema) {
|
||||
assert(user_data);
|
||||
auto disassembler = static_cast<Disassembler*>(user_data);
|
||||
return disassembler->HandleHeader(endian, version, generator, id_bound,
|
||||
schema);
|
||||
}
|
||||
|
||||
spv_result_t DisassembleInstruction(
|
||||
void* user_data, const spv_parsed_instruction_t* parsed_instruction) {
|
||||
assert(user_data);
|
||||
auto disassembler = static_cast<Disassembler*>(user_data);
|
||||
return disassembler->HandleInstruction(*parsed_instruction);
|
||||
}
|
||||
|
||||
// Simple wrapper class to provide extra data necessary for targeted
|
||||
// instruction disassembly.
|
||||
class WrappedDisassembler {
|
||||
public:
|
||||
WrappedDisassembler(Disassembler* dis, const uint32_t* binary, size_t wc)
|
||||
: disassembler_(dis), inst_binary_(binary), word_count_(wc) {}
|
||||
|
||||
Disassembler* disassembler() { return disassembler_; }
|
||||
const uint32_t* inst_binary() const { return inst_binary_; }
|
||||
size_t word_count() const { return word_count_; }
|
||||
|
||||
private:
|
||||
Disassembler* disassembler_;
|
||||
const uint32_t* inst_binary_;
|
||||
const size_t word_count_;
|
||||
};
|
||||
|
||||
spv_result_t DisassembleTargetHeader(void* user_data, spv_endianness_t endian,
|
||||
uint32_t /* magic */, uint32_t version,
|
||||
uint32_t generator, uint32_t id_bound,
|
||||
uint32_t schema) {
|
||||
assert(user_data);
|
||||
auto wrapped = static_cast<WrappedDisassembler*>(user_data);
|
||||
return wrapped->disassembler()->HandleHeader(endian, version, generator,
|
||||
id_bound, schema);
|
||||
}
|
||||
|
||||
spv_result_t DisassembleTargetInstruction(
|
||||
void* user_data, const spv_parsed_instruction_t* parsed_instruction) {
|
||||
assert(user_data);
|
||||
auto wrapped = static_cast<WrappedDisassembler*>(user_data);
|
||||
// Check if this is the instruction we want to disassemble.
|
||||
if (wrapped->word_count() == parsed_instruction->num_words &&
|
||||
std::equal(wrapped->inst_binary(),
|
||||
wrapped->inst_binary() + wrapped->word_count(),
|
||||
parsed_instruction->words)) {
|
||||
// Found the target instruction. Disassemble it and signal that we should
|
||||
// stop searching so we don't output the same instruction again.
|
||||
if (auto error =
|
||||
wrapped->disassembler()->HandleInstruction(*parsed_instruction))
|
||||
return error;
|
||||
return SPV_REQUESTED_TERMINATION;
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
spv_result_t spvBinaryToText(const spv_const_context context,
|
||||
const uint32_t* code, const size_t wordCount,
|
||||
const uint32_t options, spv_text* pText,
|
||||
spv_diagnostic* pDiagnostic) {
|
||||
spv_context_t hijack_context = *context;
|
||||
if (pDiagnostic) {
|
||||
*pDiagnostic = nullptr;
|
||||
libspirv::UseDiagnosticAsMessageConsumer(&hijack_context, pDiagnostic);
|
||||
}
|
||||
|
||||
const libspirv::AssemblyGrammar grammar(&hijack_context);
|
||||
if (!grammar.isValid()) return SPV_ERROR_INVALID_TABLE;
|
||||
|
||||
// Generate friendly names for Ids if requested.
|
||||
std::unique_ptr<libspirv::FriendlyNameMapper> friendly_mapper;
|
||||
libspirv::NameMapper name_mapper = libspirv::GetTrivialNameMapper();
|
||||
if (options & SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES) {
|
||||
friendly_mapper.reset(
|
||||
new libspirv::FriendlyNameMapper(&hijack_context, code, wordCount));
|
||||
name_mapper = friendly_mapper->GetNameMapper();
|
||||
}
|
||||
|
||||
// Now disassemble!
|
||||
Disassembler disassembler(grammar, options, name_mapper);
|
||||
if (auto error = spvBinaryParse(&hijack_context, &disassembler, code,
|
||||
wordCount, DisassembleHeader,
|
||||
DisassembleInstruction, pDiagnostic)) {
|
||||
return error;
|
||||
}
|
||||
|
||||
return disassembler.SaveTextResult(pText);
|
||||
}
|
||||
|
||||
std::string spvtools::spvInstructionBinaryToText(const spv_target_env env,
|
||||
const uint32_t* instCode,
|
||||
const size_t instWordCount,
|
||||
const uint32_t* code,
|
||||
const size_t wordCount,
|
||||
const uint32_t options) {
|
||||
spv_context context = spvContextCreate(env);
|
||||
const libspirv::AssemblyGrammar grammar(context);
|
||||
if (!grammar.isValid()) {
|
||||
spvContextDestroy(context);
|
||||
return "";
|
||||
}
|
||||
|
||||
// Generate friendly names for Ids if requested.
|
||||
std::unique_ptr<libspirv::FriendlyNameMapper> friendly_mapper;
|
||||
libspirv::NameMapper name_mapper = libspirv::GetTrivialNameMapper();
|
||||
if (options & SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES) {
|
||||
friendly_mapper.reset(
|
||||
new libspirv::FriendlyNameMapper(context, code, wordCount));
|
||||
name_mapper = friendly_mapper->GetNameMapper();
|
||||
}
|
||||
|
||||
// Now disassemble!
|
||||
Disassembler disassembler(grammar, options, name_mapper);
|
||||
WrappedDisassembler wrapped(&disassembler, instCode, instWordCount);
|
||||
spvBinaryParse(context, &wrapped, code, wordCount, DisassembleTargetHeader,
|
||||
DisassembleTargetInstruction, nullptr);
|
||||
|
||||
spv_text text = nullptr;
|
||||
std::string output;
|
||||
if (disassembler.SaveTextResult(&text) == SPV_SUCCESS) {
|
||||
output.assign(text->str, text->str + text->length);
|
||||
// Drop trailing newline characters.
|
||||
while (!output.empty() && output.back() == '\n') output.pop_back();
|
||||
}
|
||||
spvTextDestroy(text);
|
||||
spvContextDestroy(context);
|
||||
|
||||
return output;
|
||||
}
|
38
3rdparty/spirv-tools/source/disassemble.h
vendored
Normal file
38
3rdparty/spirv-tools/source/disassemble.h
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2018 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SPIRV_TOOLS_DISASSEMBLE_H_
|
||||
#define SPIRV_TOOLS_DISASSEMBLE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
// Decodes the given SPIR-V instruction binary representation to its assembly
|
||||
// text. The context is inferred from the provided module binary. The options
|
||||
// parameter is a bit field of spv_binary_to_text_options_t. Decoded text will
|
||||
// be stored into *text. Any error will be written into *diagnostic if
|
||||
// diagnostic is non-null.
|
||||
std::string spvInstructionBinaryToText(const spv_target_env env,
|
||||
const uint32_t* inst_binary,
|
||||
const size_t inst_word_count,
|
||||
const uint32_t* binary,
|
||||
const size_t word_count,
|
||||
const uint32_t options);
|
||||
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SPIRV_TOOLS_DISASSEMBLE_H_
|
172
3rdparty/spirv-tools/source/enum_set.h
vendored
Normal file
172
3rdparty/spirv-tools/source/enum_set.h
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_ENUM_SET_H
|
||||
#define LIBSPIRV_ENUM_SET_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
#include "latest_version_spirv_header.h"
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
// A set of values of a 32-bit enum type.
|
||||
// It is fast and compact for the common case, where enum values
|
||||
// are at most 63. But it can represent enums with larger values,
|
||||
// as may appear in extensions.
|
||||
template <typename EnumType>
|
||||
class EnumSet {
|
||||
private:
|
||||
// The ForEach method will call the functor on enum values in
|
||||
// enum value order (lowest to highest). To make that easier, use
|
||||
// an ordered set for the overflow values.
|
||||
using OverflowSetType = std::set<uint32_t>;
|
||||
|
||||
public:
|
||||
// Construct an empty set.
|
||||
EnumSet() {}
|
||||
// Construct an set with just the given enum value.
|
||||
explicit EnumSet(EnumType c) { Add(c); }
|
||||
// Construct an set from an initializer list of enum values.
|
||||
EnumSet(std::initializer_list<EnumType> cs) {
|
||||
for (auto c : cs) Add(c);
|
||||
}
|
||||
EnumSet(uint32_t count, const EnumType* ptr) {
|
||||
for (uint32_t i = 0; i < count; ++i) Add(ptr[i]);
|
||||
}
|
||||
// Copy constructor.
|
||||
EnumSet(const EnumSet& other) { *this = other; }
|
||||
// Move constructor. The moved-from set is emptied.
|
||||
EnumSet(EnumSet&& other) {
|
||||
mask_ = other.mask_;
|
||||
overflow_ = std::move(other.overflow_);
|
||||
other.mask_ = 0;
|
||||
other.overflow_.reset(nullptr);
|
||||
}
|
||||
// Assignment operator.
|
||||
EnumSet& operator=(const EnumSet& other) {
|
||||
if (&other != this) {
|
||||
mask_ = other.mask_;
|
||||
overflow_.reset(other.overflow_ ? new OverflowSetType(*other.overflow_)
|
||||
: nullptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Adds the given enum value to the set. This has no effect if the
|
||||
// enum value is already in the set.
|
||||
void Add(EnumType c) { AddWord(ToWord(c)); }
|
||||
|
||||
// Returns true if this enum value is in the set.
|
||||
bool Contains(EnumType c) const { return ContainsWord(ToWord(c)); }
|
||||
|
||||
// Applies f to each enum in the set, in order from smallest enum
|
||||
// value to largest.
|
||||
void ForEach(std::function<void(EnumType)> f) const {
|
||||
for (uint32_t i = 0; i < 64; ++i) {
|
||||
if (mask_ & AsMask(i)) f(static_cast<EnumType>(i));
|
||||
}
|
||||
if (overflow_) {
|
||||
for (uint32_t c : *overflow_) f(static_cast<EnumType>(c));
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the set is empty.
|
||||
bool IsEmpty() const {
|
||||
if (mask_) return false;
|
||||
if (overflow_ && !overflow_->empty()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns true if the set contains ANY of the elements of |in_set|,
|
||||
// or if |in_set| is empty.
|
||||
bool HasAnyOf(const EnumSet<EnumType>& in_set) const {
|
||||
if (in_set.IsEmpty()) return true;
|
||||
|
||||
if (mask_ & in_set.mask_) return true;
|
||||
|
||||
if (!overflow_ || !in_set.overflow_) return false;
|
||||
|
||||
for (uint32_t item : *in_set.overflow_) {
|
||||
if (overflow_->find(item) != overflow_->end()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
// Adds the given enum value (as a 32-bit word) to the set. This has no
|
||||
// effect if the enum value is already in the set.
|
||||
void AddWord(uint32_t word) {
|
||||
if (auto new_bits = AsMask(word)) {
|
||||
mask_ |= new_bits;
|
||||
} else {
|
||||
Overflow().insert(word);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the enum represented as a 32-bit word is in the set.
|
||||
bool ContainsWord(uint32_t word) const {
|
||||
// We shouldn't call Overflow() since this is a const method.
|
||||
if (auto bits = AsMask(word)) {
|
||||
return (mask_ & bits) != 0;
|
||||
} else if (auto overflow = overflow_.get()) {
|
||||
return overflow->find(word) != overflow->end();
|
||||
}
|
||||
// The word is large, but the set doesn't have large members, so
|
||||
// it doesn't have an overflow set.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the enum value as a uint32_t.
|
||||
uint32_t ToWord(EnumType value) const {
|
||||
static_assert(sizeof(EnumType) <= sizeof(uint32_t),
|
||||
"EnumType must statically castable to uint32_t");
|
||||
return static_cast<uint32_t>(value);
|
||||
}
|
||||
|
||||
// Determines whether the given enum value can be represented
|
||||
// as a bit in a uint64_t mask. If so, then returns that mask bit.
|
||||
// Otherwise, returns 0.
|
||||
uint64_t AsMask(uint32_t word) const {
|
||||
if (word > 63) return 0;
|
||||
return uint64_t(1) << word;
|
||||
}
|
||||
|
||||
// Ensures that overflow_set_ references a set. A new empty set is
|
||||
// allocated if one doesn't exist yet. Returns overflow_set_.
|
||||
OverflowSetType& Overflow() {
|
||||
if (overflow_.get() == nullptr) {
|
||||
overflow_.reset(new OverflowSetType);
|
||||
}
|
||||
return *overflow_;
|
||||
}
|
||||
|
||||
// Enums with values up to 63 are stored as bits in this mask.
|
||||
uint64_t mask_ = 0;
|
||||
// Enums with values larger than 63 are stored in this set.
|
||||
// This set should normally be empty or very small.
|
||||
std::unique_ptr<OverflowSetType> overflow_ = {};
|
||||
};
|
||||
|
||||
// A set of SpvCapability, optimized for small capability values.
|
||||
using CapabilitySet = EnumSet<SpvCapability>;
|
||||
|
||||
} // namespace libspirv
|
||||
|
||||
#endif // LIBSPIRV_ENUM_SET_H
|
29
3rdparty/spirv-tools/source/enum_string_mapping.cpp
vendored
Normal file
29
3rdparty/spirv-tools/source/enum_string_mapping.cpp
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "enum_string_mapping.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "extensions.h"
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
#include "enum_string_mapping.inc"
|
||||
|
||||
} // namespace libspirv
|
36
3rdparty/spirv-tools/source/enum_string_mapping.h
vendored
Normal file
36
3rdparty/spirv-tools/source/enum_string_mapping.h
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_ENUM_STRING_MAPPING_H_
|
||||
#define LIBSPIRV_ENUM_STRING_MAPPING_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "extensions.h"
|
||||
#include "latest_version_spirv_header.h"
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
// Finds Extension enum corresponding to |str|. Returns false if not found.
|
||||
bool GetExtensionFromString(const char* str, Extension* extension);
|
||||
|
||||
// Returns text string corresponding to |extension|.
|
||||
const char* ExtensionToString(Extension extension);
|
||||
|
||||
// Returns text string corresponding to |capability|.
|
||||
const char* CapabilityToString(SpvCapability capability);
|
||||
|
||||
} // namespace libspirv
|
||||
|
||||
#endif // LIBSPIRV_ENUM_STRING_MAPPING_H_
|
161
3rdparty/spirv-tools/source/ext_inst.cpp
vendored
Normal file
161
3rdparty/spirv-tools/source/ext_inst.cpp
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ext_inst.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
// DebugInfo extended instruction set.
|
||||
// See https://www.khronos.org/registry/spir-v/specs/1.0/DebugInfo.html
|
||||
// TODO(dneto): DebugInfo.h should probably move to SPIRV-Headers.
|
||||
#include "DebugInfo.h"
|
||||
|
||||
#include "latest_version_glsl_std_450_header.h"
|
||||
#include "latest_version_opencl_std_header.h"
|
||||
#include "macro.h"
|
||||
#include "spirv_definition.h"
|
||||
|
||||
#include "debuginfo.insts.inc" // defines opencl_entries
|
||||
#include "glsl.std.450.insts.inc" // defines glsl_entries
|
||||
#include "opencl.std.insts.inc" // defines opencl_entries
|
||||
|
||||
#include "spv-amd-gcn-shader.insts.inc"
|
||||
#include "spv-amd-shader-ballot.insts.inc"
|
||||
#include "spv-amd-shader-explicit-vertex-parameter.insts.inc"
|
||||
#include "spv-amd-shader-trinary-minmax.insts.inc"
|
||||
|
||||
static const spv_ext_inst_group_t kGroups_1_0[] = {
|
||||
{SPV_EXT_INST_TYPE_GLSL_STD_450, ARRAY_SIZE(glsl_entries), glsl_entries},
|
||||
{SPV_EXT_INST_TYPE_OPENCL_STD, ARRAY_SIZE(opencl_entries), opencl_entries},
|
||||
{SPV_EXT_INST_TYPE_SPV_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER,
|
||||
ARRAY_SIZE(spv_amd_shader_explicit_vertex_parameter_entries),
|
||||
spv_amd_shader_explicit_vertex_parameter_entries},
|
||||
{SPV_EXT_INST_TYPE_SPV_AMD_SHADER_TRINARY_MINMAX,
|
||||
ARRAY_SIZE(spv_amd_shader_trinary_minmax_entries),
|
||||
spv_amd_shader_trinary_minmax_entries},
|
||||
{SPV_EXT_INST_TYPE_SPV_AMD_GCN_SHADER,
|
||||
ARRAY_SIZE(spv_amd_gcn_shader_entries), spv_amd_gcn_shader_entries},
|
||||
{SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT,
|
||||
ARRAY_SIZE(spv_amd_shader_ballot_entries), spv_amd_shader_ballot_entries},
|
||||
{SPV_EXT_INST_TYPE_DEBUGINFO, ARRAY_SIZE(debuginfo_entries),
|
||||
debuginfo_entries},
|
||||
};
|
||||
|
||||
static const spv_ext_inst_table_t kTable_1_0 = {ARRAY_SIZE(kGroups_1_0),
|
||||
kGroups_1_0};
|
||||
|
||||
spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable,
|
||||
spv_target_env env) {
|
||||
if (!pExtInstTable) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
switch (env) {
|
||||
// The extended instruction sets are all version 1.0 so far.
|
||||
case SPV_ENV_UNIVERSAL_1_0:
|
||||
case SPV_ENV_VULKAN_1_0:
|
||||
case SPV_ENV_UNIVERSAL_1_1:
|
||||
case SPV_ENV_UNIVERSAL_1_2:
|
||||
case SPV_ENV_OPENCL_1_2:
|
||||
case SPV_ENV_OPENCL_EMBEDDED_1_2:
|
||||
case SPV_ENV_OPENCL_2_0:
|
||||
case SPV_ENV_OPENCL_EMBEDDED_2_0:
|
||||
case SPV_ENV_OPENCL_2_1:
|
||||
case SPV_ENV_OPENCL_EMBEDDED_2_1:
|
||||
case SPV_ENV_OPENCL_2_2:
|
||||
case SPV_ENV_OPENCL_EMBEDDED_2_2:
|
||||
case SPV_ENV_OPENGL_4_0:
|
||||
case SPV_ENV_OPENGL_4_1:
|
||||
case SPV_ENV_OPENGL_4_2:
|
||||
case SPV_ENV_OPENGL_4_3:
|
||||
case SPV_ENV_OPENGL_4_5:
|
||||
case SPV_ENV_UNIVERSAL_1_3:
|
||||
case SPV_ENV_VULKAN_1_1:
|
||||
*pExtInstTable = &kTable_1_0;
|
||||
return SPV_SUCCESS;
|
||||
default:
|
||||
assert(0 && "Unknown spv_target_env in spvExtInstTableGet()");
|
||||
return SPV_ERROR_INVALID_TABLE;
|
||||
}
|
||||
}
|
||||
|
||||
spv_ext_inst_type_t spvExtInstImportTypeGet(const char* name) {
|
||||
// The names are specified by the respective extension instruction
|
||||
// specifications.
|
||||
if (!strcmp("GLSL.std.450", name)) {
|
||||
return SPV_EXT_INST_TYPE_GLSL_STD_450;
|
||||
}
|
||||
if (!strcmp("OpenCL.std", name)) {
|
||||
return SPV_EXT_INST_TYPE_OPENCL_STD;
|
||||
}
|
||||
if (!strcmp("SPV_AMD_shader_explicit_vertex_parameter", name)) {
|
||||
return SPV_EXT_INST_TYPE_SPV_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER;
|
||||
}
|
||||
if (!strcmp("SPV_AMD_shader_trinary_minmax", name)) {
|
||||
return SPV_EXT_INST_TYPE_SPV_AMD_SHADER_TRINARY_MINMAX;
|
||||
}
|
||||
if (!strcmp("SPV_AMD_gcn_shader", name)) {
|
||||
return SPV_EXT_INST_TYPE_SPV_AMD_GCN_SHADER;
|
||||
}
|
||||
if (!strcmp("SPV_AMD_shader_ballot", name)) {
|
||||
return SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT;
|
||||
}
|
||||
if (!strcmp("DebugInfo", name)) {
|
||||
return SPV_EXT_INST_TYPE_DEBUGINFO;
|
||||
}
|
||||
return SPV_EXT_INST_TYPE_NONE;
|
||||
}
|
||||
|
||||
spv_result_t spvExtInstTableNameLookup(const spv_ext_inst_table table,
|
||||
const spv_ext_inst_type_t type,
|
||||
const char* name,
|
||||
spv_ext_inst_desc* pEntry) {
|
||||
if (!table) return SPV_ERROR_INVALID_TABLE;
|
||||
if (!pEntry) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
for (uint32_t groupIndex = 0; groupIndex < table->count; groupIndex++) {
|
||||
const auto& group = table->groups[groupIndex];
|
||||
if (type != group.type) continue;
|
||||
for (uint32_t index = 0; index < group.count; index++) {
|
||||
const auto& entry = group.entries[index];
|
||||
if (!strcmp(name, entry.name)) {
|
||||
*pEntry = &entry;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_LOOKUP;
|
||||
}
|
||||
|
||||
spv_result_t spvExtInstTableValueLookup(const spv_ext_inst_table table,
|
||||
const spv_ext_inst_type_t type,
|
||||
const uint32_t value,
|
||||
spv_ext_inst_desc* pEntry) {
|
||||
if (!table) return SPV_ERROR_INVALID_TABLE;
|
||||
if (!pEntry) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
for (uint32_t groupIndex = 0; groupIndex < table->count; groupIndex++) {
|
||||
const auto& group = table->groups[groupIndex];
|
||||
if (type != group.type) continue;
|
||||
for (uint32_t index = 0; index < group.count; index++) {
|
||||
const auto& entry = group.entries[index];
|
||||
if (value == entry.ext_inst) {
|
||||
*pEntry = &entry;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_LOOKUP;
|
||||
}
|
40
3rdparty/spirv-tools/source/ext_inst.h
vendored
Normal file
40
3rdparty/spirv-tools/source/ext_inst.h
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_EXT_INST_H_
|
||||
#define LIBSPIRV_EXT_INST_H_
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "table.h"
|
||||
|
||||
// Gets the type of the extended instruction set with the specified name.
|
||||
spv_ext_inst_type_t spvExtInstImportTypeGet(const char* name);
|
||||
|
||||
// Finds the named extented instruction of the given type in the given extended
|
||||
// instruction table. On success, returns SPV_SUCCESS and writes a handle of
|
||||
// the instruction entry into *entry.
|
||||
spv_result_t spvExtInstTableNameLookup(const spv_ext_inst_table table,
|
||||
const spv_ext_inst_type_t type,
|
||||
const char* name,
|
||||
spv_ext_inst_desc* entry);
|
||||
|
||||
// Finds the extented instruction of the given type in the given extended
|
||||
// instruction table by value. On success, returns SPV_SUCCESS and writes a
|
||||
// handle of the instruction entry into *entry.
|
||||
spv_result_t spvExtInstTableValueLookup(const spv_ext_inst_table table,
|
||||
const spv_ext_inst_type_t type,
|
||||
const uint32_t value,
|
||||
spv_ext_inst_desc* pEntry);
|
||||
|
||||
#endif // LIBSPIRV_EXT_INST_H_
|
44
3rdparty/spirv-tools/source/extensions.cpp
vendored
Normal file
44
3rdparty/spirv-tools/source/extensions.cpp
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "extensions.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "enum_string_mapping.h"
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
std::string GetExtensionString(const spv_parsed_instruction_t* inst) {
|
||||
if (inst->opcode != SpvOpExtension) return "ERROR_not_op_extension";
|
||||
|
||||
assert(inst->num_operands == 1);
|
||||
|
||||
const auto& operand = inst->operands[0];
|
||||
assert(operand.type == SPV_OPERAND_TYPE_LITERAL_STRING);
|
||||
assert(inst->num_words > operand.offset);
|
||||
|
||||
return reinterpret_cast<const char*>(inst->words + operand.offset);
|
||||
}
|
||||
|
||||
std::string ExtensionSetToString(const ExtensionSet& extensions) {
|
||||
std::stringstream ss;
|
||||
extensions.ForEach(
|
||||
[&ss](Extension ext) { ss << ExtensionToString(ext) << " "; });
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace libspirv
|
40
3rdparty/spirv-tools/source/extensions.h
vendored
Normal file
40
3rdparty/spirv-tools/source/extensions.h
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_EXTENSIONS_H_
|
||||
#define LIBSPIRV_EXTENSIONS_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "enum_set.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
// The known SPIR-V extensions.
|
||||
enum Extension {
|
||||
#include "extension_enum.inc"
|
||||
};
|
||||
|
||||
using ExtensionSet = EnumSet<Extension>;
|
||||
|
||||
// Returns literal string operand of OpExtension instruction.
|
||||
std::string GetExtensionString(const spv_parsed_instruction_t* inst);
|
||||
|
||||
// Returns text string listing |extensions| separated by whitespace.
|
||||
std::string ExtensionSetToString(const ExtensionSet& extensions);
|
||||
|
||||
} // namespace libspirv
|
||||
|
||||
#endif // LIBSPIRV_EXTENSIONS_H_
|
568
3rdparty/spirv-tools/source/extinst.debuginfo.grammar.json
vendored
Normal file
568
3rdparty/spirv-tools/source/extinst.debuginfo.grammar.json
vendored
Normal file
@ -0,0 +1,568 @@
|
||||
{
|
||||
"copyright" : [
|
||||
"Copyright (c) 2017 The Khronos Group Inc.",
|
||||
"",
|
||||
"Permission is hereby granted, free of charge, to any person obtaining a copy",
|
||||
"of this software and/or associated documentation files (the \"Materials\"),",
|
||||
"to deal in the Materials without restriction, including without limitation",
|
||||
"the rights to use, copy, modify, merge, publish, distribute, sublicense,",
|
||||
"and/or sell copies of the Materials, and to permit persons to whom the",
|
||||
"Materials are furnished to do so, subject to the following conditions:",
|
||||
"",
|
||||
"The above copyright notice and this permission notice shall be included in",
|
||||
"all copies or substantial portions of the Materials.",
|
||||
"",
|
||||
"MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS",
|
||||
"STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND",
|
||||
"HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ ",
|
||||
"",
|
||||
"THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS",
|
||||
"OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
|
||||
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL",
|
||||
"THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
|
||||
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING",
|
||||
"FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS",
|
||||
"IN THE MATERIALS."
|
||||
],
|
||||
"version" : 100,
|
||||
"revision" : 1,
|
||||
"instructions" : [
|
||||
{
|
||||
"opname" : "DebugInfoNone",
|
||||
"opcode" : 0
|
||||
},
|
||||
{
|
||||
"opname" : "DebugCompilationUnit",
|
||||
"opcode" : 1,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Version'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'DWARF Version'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeBasic",
|
||||
"opcode" : 2,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Size'" },
|
||||
{ "kind" : "DebugBaseTypeAttributeEncoding", "name" : "'Encoding'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypePointer",
|
||||
"opcode" : 3,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Base Type'" },
|
||||
{ "kind" : "StorageClass", "name" : "'Storage Class'" },
|
||||
{ "kind" : "DebugInfoFlags", "name" : "'Literal Flags'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeQualifier",
|
||||
"opcode" : 4,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Base Type'" },
|
||||
{ "kind" : "DebugTypeQualifier", "name" : "'Type Qualifier'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeArray",
|
||||
"opcode" : 5,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Base Type'" },
|
||||
{ "kind" : "IdRef", "name" : "'Component Counts'", "quantifier" : "*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeVector",
|
||||
"opcode" : 6,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Base Type'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Component Count'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypedef",
|
||||
"opcode" : 7,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Base Type'" },
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeFunction",
|
||||
"opcode" : 8,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Return Type'" },
|
||||
{ "kind" : "IdRef", "name" : "'Paramter Types'", "quantifier" : "*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeEnum",
|
||||
"opcode" : 9,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Underlying Type'" },
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" },
|
||||
{ "kind" : "IdRef", "name" : "'Size'" },
|
||||
{ "kind" : "DebugInfoFlags", "name" : "'Flags'" },
|
||||
{ "kind" : "PairIdRefIdRef", "name" : "'Value, Name, Value, Name, ...'", "quantifier" : "*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeComposite",
|
||||
"opcode" : 10,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "DebugCompositeType", "name" : "'Tag'" },
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" },
|
||||
{ "kind" : "IdRef", "name" : "'Size'" },
|
||||
{ "kind" : "DebugInfoFlags", "name" : "'Flags'" },
|
||||
{ "kind" : "IdRef", "name" : "'Members'", "quantifier" : "*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeMember",
|
||||
"opcode" : 11,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Type'" },
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" },
|
||||
{ "kind" : "IdRef", "name" : "'Offset'" },
|
||||
{ "kind" : "IdRef", "name" : "'Size'" },
|
||||
{ "kind" : "DebugInfoFlags", "name" : "'Flags'" },
|
||||
{ "kind" : "IdRef", "name" : "'Value'", "quantifier" : "?" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeInheritance",
|
||||
"opcode" : 12,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Child'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" },
|
||||
{ "kind" : "IdRef", "name" : "'Offset'" },
|
||||
{ "kind" : "IdRef", "name" : "'Size'" },
|
||||
{ "kind" : "DebugInfoFlags", "name" : "'Flags'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypePtrToMember",
|
||||
"opcode" : 13,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Member Type'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeTemplate",
|
||||
"opcode" : 14,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Target'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parameters'", "quantifier" : "*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeTemplateParameter",
|
||||
"opcode" : 15,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Actual Type'" },
|
||||
{ "kind" : "IdRef", "name" : "'Value'" },
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeTemplateTemplateParameter",
|
||||
"opcode" : 16,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Template Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugTypeTemplateParameterPack",
|
||||
"opcode" : 17,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" },
|
||||
{ "kind" : "IdRef", "name" : "'Template Parameters'", "quantifier" : "*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugGlobalVariable",
|
||||
"opcode" : 18,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Type'" },
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" },
|
||||
{ "kind" : "IdRef", "name" : "'Linkage Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Variable'" },
|
||||
{ "kind" : "DebugInfoFlags", "name" : "'Flags'" },
|
||||
{ "kind" : "IdRef", "name" : "'Static Member Declaration'", "quantifier" : "?" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugFunctionDeclaration",
|
||||
"opcode" : 19,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Type'" },
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" },
|
||||
{ "kind" : "IdRef", "name" : "'Linkage Name'" },
|
||||
{ "kind" : "DebugInfoFlags", "name" : "'Flags'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugFunction",
|
||||
"opcode" : 20,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Type'" },
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" },
|
||||
{ "kind" : "IdRef", "name" : "'Linkage Name'" },
|
||||
{ "kind" : "DebugInfoFlags", "name" : "'Flags'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Scope Line'" },
|
||||
{ "kind" : "IdRef", "name" : "'Function'" },
|
||||
{ "kind" : "IdRef", "name" : "'Declaration'", "quantifier" : "?" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugLexicalBlock",
|
||||
"opcode" : 21,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" },
|
||||
{ "kind" : "IdRef", "name" : "'Name'", "quantifier" : "?" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugLexicalBlockDiscriminator",
|
||||
"opcode" : 22,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Scope'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Discriminator'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugScope",
|
||||
"opcode" : 23,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Scope'" },
|
||||
{ "kind" : "IdRef", "name" : "'Inlined At'", "quantifier" : "?" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugNoScope",
|
||||
"opcode" : 24
|
||||
},
|
||||
{
|
||||
"opname" : "DebugInlinedAt",
|
||||
"opcode" : 25,
|
||||
"operands" : [
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "IdRef", "name" : "'Scope'" },
|
||||
{ "kind" : "IdRef", "name" : "'Inlined'", "quantifier" : "?" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugLocalVariable",
|
||||
"opcode" : 26,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Type'" },
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Column'" },
|
||||
{ "kind" : "IdRef", "name" : "'Parent'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Arg Number'", "quantifier" : "?" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugInlinedVariable",
|
||||
"opcode" : 27,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Variable'" },
|
||||
{ "kind" : "IdRef", "name" : "'Inlined'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugDeclare",
|
||||
"opcode" : 28,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Local Variable'" },
|
||||
{ "kind" : "IdRef", "name" : "'Variable'" },
|
||||
{ "kind" : "IdRef", "name" : "'Expression'" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugValue",
|
||||
"opcode" : 29,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Value'" },
|
||||
{ "kind" : "IdRef", "name" : "'Expression'" },
|
||||
{ "kind" : "IdRef", "name" : "'Indexes'", "quantifier" : "*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugOperation",
|
||||
"opcode" : 30,
|
||||
"operands" : [
|
||||
{ "kind" : "DebugOperation", "name" : "'OpCode'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Operands ...'", "quantifier" : "*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugExpression",
|
||||
"opcode" : 31,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Operands ...'", "quantifier" : "*" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugMacroDef",
|
||||
"opcode" : 32,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "IdRef", "name" : "'Name'" },
|
||||
{ "kind" : "IdRef", "name" : "'Value'", "quantifier" : "?" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"opname" : "DebugMacroUndef",
|
||||
"opcode" : 33,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'Source'" },
|
||||
{ "kind" : "LiteralInteger", "name" : "'Line'" },
|
||||
{ "kind" : "IdRef", "name" : "'Macro'" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"operand_kinds" : [
|
||||
{
|
||||
"category" : "BitEnum",
|
||||
"kind" : "DebugInfoFlags",
|
||||
"enumerants" : [
|
||||
{
|
||||
"enumerant" : "FlagIsProtected",
|
||||
"value" : "0x01"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagIsPrivate",
|
||||
"value" : "0x02"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagIsPublic",
|
||||
"value" : "0x03"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagIsLocal",
|
||||
"value" : "0x04"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagIsDefinition",
|
||||
"value" : "0x08"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagFwdDecl",
|
||||
"value" : "0x10"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagArtificial",
|
||||
"value" : "0x20"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagExplicit",
|
||||
"value" : "0x40"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagPrototyped",
|
||||
"value" : "0x80"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagObjectPointer",
|
||||
"value" : "0x100"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagStaticMember",
|
||||
"value" : "0x200"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagIndirectVariable",
|
||||
"value" : "0x400"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagLValueReference",
|
||||
"value" : "0x800"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagRValueReference",
|
||||
"value" : "0x1000"
|
||||
},
|
||||
{
|
||||
"enumerant" : "FlagIsOptimized",
|
||||
"value" : "0x2000"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category" : "ValueEnum",
|
||||
"kind" : "DebugBaseTypeAttributeEncoding",
|
||||
"enumerants" : [
|
||||
{
|
||||
"enumerant" : "Unspecified",
|
||||
"value" : "0"
|
||||
},
|
||||
{
|
||||
"enumerant" : "Address",
|
||||
"value" : "1"
|
||||
},
|
||||
{
|
||||
"enumerant" : "Boolean",
|
||||
"value" : "2"
|
||||
},
|
||||
{
|
||||
"enumerant" : "Float",
|
||||
"value" : "4"
|
||||
},
|
||||
{
|
||||
"enumerant" : "Signed",
|
||||
"value" : "5"
|
||||
},
|
||||
{
|
||||
"enumerant" : "SignedChar",
|
||||
"value" : "6"
|
||||
},
|
||||
{
|
||||
"enumerant" : "Unsigned",
|
||||
"value" : "7"
|
||||
},
|
||||
{
|
||||
"enumerant" : "UnsignedChar",
|
||||
"value" : "8"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category" : "ValueEnum",
|
||||
"kind" : "DebugCompositeType",
|
||||
"enumerants" : [
|
||||
{
|
||||
"enumerant" : "Class",
|
||||
"value" : "0"
|
||||
},
|
||||
{
|
||||
"enumerant" : "Structure",
|
||||
"value" : "1"
|
||||
},
|
||||
{
|
||||
"enumerant" : "Union",
|
||||
"value" : "2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category" : "ValueEnum",
|
||||
"kind" : "DebugTypeQualifier",
|
||||
"enumerants" : [
|
||||
{
|
||||
"enumerant" : "ConstType",
|
||||
"value" : "0"
|
||||
},
|
||||
{
|
||||
"enumerant" : "VolatileType",
|
||||
"value" : "1"
|
||||
},
|
||||
{
|
||||
"enumerant" : "RestrictType",
|
||||
"value" : "2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"category" : "ValueEnum",
|
||||
"kind" : "DebugOperation",
|
||||
"enumerants" : [
|
||||
{
|
||||
"enumerant" : "Deref",
|
||||
"value" : "0"
|
||||
},
|
||||
{
|
||||
"enumerant" : "Plus",
|
||||
"value" : "1"
|
||||
},
|
||||
{
|
||||
"enumerant" : "Minus",
|
||||
"value" : "2"
|
||||
},
|
||||
{
|
||||
"enumerant" : "PlusUconst",
|
||||
"value" : "3",
|
||||
"parameters" : [
|
||||
{ "kind" : "LiteralInteger" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"enumerant" : "BitPiece",
|
||||
"value" : "4",
|
||||
"parameters" : [
|
||||
{ "kind" : "LiteralInteger" },
|
||||
{ "kind" : "LiteralInteger" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"enumerant" : "Swap",
|
||||
"value" : "5"
|
||||
},
|
||||
{
|
||||
"enumerant" : "Xderef",
|
||||
"value" : "6"
|
||||
},
|
||||
{
|
||||
"enumerant" : "StackValue",
|
||||
"value" : "7"
|
||||
},
|
||||
{
|
||||
"enumerant" : "Constu",
|
||||
"value" : "8",
|
||||
"parameters" : [
|
||||
{ "kind" : "LiteralInteger" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
26
3rdparty/spirv-tools/source/extinst.spv-amd-gcn-shader.grammar.json
vendored
Normal file
26
3rdparty/spirv-tools/source/extinst.spv-amd-gcn-shader.grammar.json
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"revision" : 2,
|
||||
"instructions" : [
|
||||
{
|
||||
"opname" : "CubeFaceIndexAMD",
|
||||
"opcode" : 1,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'P'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_gcn_shader" ]
|
||||
},
|
||||
{
|
||||
"opname" : "CubeFaceCoordAMD",
|
||||
"opcode" : 2,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'P'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_gcn_shader" ]
|
||||
},
|
||||
{
|
||||
"opname" : "TimeAMD",
|
||||
"opcode" : 3,
|
||||
"extensions" : [ "SPV_AMD_gcn_shader" ]
|
||||
}
|
||||
]
|
||||
}
|
41
3rdparty/spirv-tools/source/extinst.spv-amd-shader-ballot.grammar.json
vendored
Normal file
41
3rdparty/spirv-tools/source/extinst.spv-amd-shader-ballot.grammar.json
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
{
|
||||
"revision" : 5,
|
||||
"instructions" : [
|
||||
{
|
||||
"opname" : "SwizzleInvocationsAMD",
|
||||
"opcode" : 1,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'data'" },
|
||||
{ "kind" : "IdRef", "name" : "'offset'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_ballot" ]
|
||||
},
|
||||
{
|
||||
"opname" : "SwizzleInvocationsMaskedAMD",
|
||||
"opcode" : 2,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'data'" },
|
||||
{ "kind" : "IdRef", "name" : "'mask'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_ballot" ]
|
||||
},
|
||||
{
|
||||
"opname" : "WriteInvocationAMD",
|
||||
"opcode" : 3,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'inputValue'" },
|
||||
{ "kind" : "IdRef", "name" : "'writeValue'" },
|
||||
{ "kind" : "IdRef", "name" : "'invocationIndex'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_ballot" ]
|
||||
},
|
||||
{
|
||||
"opname" : "MbcntAMD",
|
||||
"opcode" : 4,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'mask'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_ballot" ]
|
||||
}
|
||||
]
|
||||
}
|
14
3rdparty/spirv-tools/source/extinst.spv-amd-shader-explicit-vertex-parameter.grammar.json
vendored
Normal file
14
3rdparty/spirv-tools/source/extinst.spv-amd-shader-explicit-vertex-parameter.grammar.json
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"revision" : 4,
|
||||
"instructions" : [
|
||||
{
|
||||
"opname" : "InterpolateAtVertexAMD",
|
||||
"opcode" : 1,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'interpolant'" },
|
||||
{ "kind" : "IdRef", "name" : "'vertexIdx'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_explicit_vertex_parameter" ]
|
||||
}
|
||||
]
|
||||
}
|
95
3rdparty/spirv-tools/source/extinst.spv-amd-shader-trinary-minmax.grammar.json
vendored
Normal file
95
3rdparty/spirv-tools/source/extinst.spv-amd-shader-trinary-minmax.grammar.json
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
{
|
||||
"revision" : 4,
|
||||
"instructions" : [
|
||||
{
|
||||
"opname" : "FMin3AMD",
|
||||
"opcode" : 1,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'x'" },
|
||||
{ "kind" : "IdRef", "name" : "'y'" },
|
||||
{ "kind" : "IdRef", "name" : "'z'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_trinary_minmax" ]
|
||||
},
|
||||
{
|
||||
"opname" : "UMin3AMD",
|
||||
"opcode" : 2,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'x'" },
|
||||
{ "kind" : "IdRef", "name" : "'y'" },
|
||||
{ "kind" : "IdRef", "name" : "'z'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_trinary_minmax" ]
|
||||
},
|
||||
{
|
||||
"opname" : "SMin3AMD",
|
||||
"opcode" : 3,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'x'" },
|
||||
{ "kind" : "IdRef", "name" : "'y'" },
|
||||
{ "kind" : "IdRef", "name" : "'z'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_trinary_minmax" ]
|
||||
},
|
||||
{
|
||||
"opname" : "FMax3AMD",
|
||||
"opcode" : 4,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'x'" },
|
||||
{ "kind" : "IdRef", "name" : "'y'" },
|
||||
{ "kind" : "IdRef", "name" : "'z'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_trinary_minmax" ]
|
||||
},
|
||||
{
|
||||
"opname" : "UMax3AMD",
|
||||
"opcode" : 5,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'x'" },
|
||||
{ "kind" : "IdRef", "name" : "'y'" },
|
||||
{ "kind" : "IdRef", "name" : "'z'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_trinary_minmax" ]
|
||||
},
|
||||
{
|
||||
"opname" : "SMax3AMD",
|
||||
"opcode" : 6,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'x'" },
|
||||
{ "kind" : "IdRef", "name" : "'y'" },
|
||||
{ "kind" : "IdRef", "name" : "'z'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_trinary_minmax" ]
|
||||
},
|
||||
{
|
||||
"opname" : "FMid3AMD",
|
||||
"opcode" : 7,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'x'" },
|
||||
{ "kind" : "IdRef", "name" : "'y'" },
|
||||
{ "kind" : "IdRef", "name" : "'z'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_trinary_minmax" ]
|
||||
},
|
||||
{
|
||||
"opname" : "UMid3AMD",
|
||||
"opcode" : 8,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'x'" },
|
||||
{ "kind" : "IdRef", "name" : "'y'" },
|
||||
{ "kind" : "IdRef", "name" : "'z'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_trinary_minmax" ]
|
||||
},
|
||||
{
|
||||
"opname" : "SMid3AMD",
|
||||
"opcode" : 9,
|
||||
"operands" : [
|
||||
{ "kind" : "IdRef", "name" : "'x'" },
|
||||
{ "kind" : "IdRef", "name" : "'y'" },
|
||||
{ "kind" : "IdRef", "name" : "'z'" }
|
||||
],
|
||||
"extensions" : [ "SPV_AMD_shader_trinary_minmax" ]
|
||||
}
|
||||
]
|
||||
}
|
79
3rdparty/spirv-tools/source/id_descriptor.cpp
vendored
Normal file
79
3rdparty/spirv-tools/source/id_descriptor.cpp
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "id_descriptor.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
#include "opcode.h"
|
||||
#include "operand.h"
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
namespace {
|
||||
|
||||
// Hashes an array of words. Order of words is important.
|
||||
uint32_t HashU32Array(const std::vector<uint32_t>& words) {
|
||||
// The hash function is a sum of hashes of each word seeded by word index.
|
||||
// Knuth's multiplicative hash is used to hash the words.
|
||||
const uint32_t kKnuthMulHash = 2654435761;
|
||||
uint32_t val = 0;
|
||||
for (uint32_t i = 0; i < words.size(); ++i) {
|
||||
val += (words[i] + i + 123) * kKnuthMulHash;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
uint32_t IdDescriptorCollection::ProcessInstruction(
|
||||
const spv_parsed_instruction_t& inst) {
|
||||
if (!inst.result_id) return 0;
|
||||
|
||||
assert(words_.empty());
|
||||
words_.push_back(inst.words[0]);
|
||||
|
||||
for (size_t operand_index = 0; operand_index < inst.num_operands;
|
||||
++operand_index) {
|
||||
const auto& operand = inst.operands[operand_index];
|
||||
if (spvIsIdType(operand.type)) {
|
||||
const uint32_t id = inst.words[operand.offset];
|
||||
const auto it = id_to_descriptor_.find(id);
|
||||
// Forward declared ids are not hashed.
|
||||
if (it != id_to_descriptor_.end()) {
|
||||
words_.push_back(it->second);
|
||||
}
|
||||
} else {
|
||||
for (size_t operand_word_index = 0;
|
||||
operand_word_index < operand.num_words; ++operand_word_index) {
|
||||
words_.push_back(inst.words[operand.offset + operand_word_index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t descriptor =
|
||||
custom_hash_func_ ? custom_hash_func_(words_) : HashU32Array(words_);
|
||||
if (descriptor == 0) descriptor = 1;
|
||||
assert(descriptor);
|
||||
|
||||
words_.clear();
|
||||
|
||||
const auto result = id_to_descriptor_.emplace(inst.result_id, descriptor);
|
||||
assert(result.second);
|
||||
(void)result;
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
} // namespace libspirv
|
63
3rdparty/spirv-tools/source/id_descriptor.h
vendored
Normal file
63
3rdparty/spirv-tools/source/id_descriptor.h
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_ID_DESCRIPTOR_H_
|
||||
#define LIBSPIRV_ID_DESCRIPTOR_H_
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
using CustomHashFunc = std::function<uint32_t(const std::vector<uint32_t>&)>;
|
||||
|
||||
// Computes and stores id descriptors.
|
||||
//
|
||||
// Descriptors are computed as hash of all words in the instruction where ids
|
||||
// were substituted with previously computed descriptors.
|
||||
class IdDescriptorCollection {
|
||||
public:
|
||||
explicit IdDescriptorCollection(
|
||||
CustomHashFunc custom_hash_func = CustomHashFunc())
|
||||
: custom_hash_func_(custom_hash_func) {
|
||||
words_.reserve(16);
|
||||
}
|
||||
|
||||
// Computes descriptor for the result id of the given instruction and
|
||||
// registers it in id_to_descriptor_. Returns the computed descriptor.
|
||||
// This function needs to be sequentially called for every instruction in the
|
||||
// module.
|
||||
uint32_t ProcessInstruction(const spv_parsed_instruction_t& inst);
|
||||
|
||||
// Returns a previously computed descriptor id.
|
||||
uint32_t GetDescriptor(uint32_t id) const {
|
||||
const auto it = id_to_descriptor_.find(id);
|
||||
if (it == id_to_descriptor_.end()) return 0;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<uint32_t, uint32_t> id_to_descriptor_;
|
||||
|
||||
std::function<uint32_t(const std::vector<uint32_t>&)> custom_hash_func_;
|
||||
|
||||
// Scratch buffer used for hashing. Class member to optimize on allocation.
|
||||
std::vector<uint32_t> words_;
|
||||
};
|
||||
|
||||
} // namespace libspirv
|
||||
|
||||
#endif // LIBSPIRV_ID_DESCRIPTOR_H_
|
49
3rdparty/spirv-tools/source/instruction.h
vendored
Normal file
49
3rdparty/spirv-tools/source/instruction.h
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_INSTRUCTION_H_
|
||||
#define LIBSPIRV_INSTRUCTION_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "latest_version_spirv_header.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
// Describes an instruction.
|
||||
struct spv_instruction_t {
|
||||
// Normally, both opcode and extInstType contain valid data.
|
||||
// However, when the assembler parses !<number> as the first word in
|
||||
// an instruction and opcode and extInstType are invalid.
|
||||
SpvOp opcode;
|
||||
spv_ext_inst_type_t extInstType;
|
||||
|
||||
// The Id of the result type, if this instruction has one. Zero otherwise.
|
||||
uint32_t resultTypeId;
|
||||
|
||||
// The instruction, as a sequence of 32-bit words.
|
||||
// For a regular instruction the opcode and word count are combined
|
||||
// in words[0], as described in the SPIR-V spec.
|
||||
// Otherwise, the first token was !<number>, and that number appears
|
||||
// in words[0]. Subsequent elements are the result of parsing
|
||||
// tokens in the alternate parsing mode as described in syntax.md.
|
||||
std::vector<uint32_t> words;
|
||||
};
|
||||
|
||||
// Appends a word to an instruction, without checking for overflow.
|
||||
inline void spvInstructionAddWord(spv_instruction_t* inst, uint32_t value) {
|
||||
inst->words.push_back(value);
|
||||
}
|
||||
|
||||
#endif // LIBSPIRV_INSTRUCTION_H_
|
20
3rdparty/spirv-tools/source/latest_version_glsl_std_450_header.h
vendored
Normal file
20
3rdparty/spirv-tools/source/latest_version_glsl_std_450_header.h
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_LATEST_VERSION_GLSL_STD_450_HEADER_H_
|
||||
#define LIBSPIRV_LATEST_VERSION_GLSL_STD_450_HEADER_H_
|
||||
|
||||
#include "spirv/unified1/GLSL.std.450.h"
|
||||
|
||||
#endif // LIBSPIRV_LATEST_VERSION_GLSL_STD_450_HEADER_H_
|
20
3rdparty/spirv-tools/source/latest_version_opencl_std_header.h
vendored
Normal file
20
3rdparty/spirv-tools/source/latest_version_opencl_std_header.h
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_LATEST_VERSION_OPENCL_STD_HEADER_H_
|
||||
#define LIBSPIRV_LATEST_VERSION_OPENCL_STD_HEADER_H_
|
||||
|
||||
#include "spirv/unified1/OpenCL.std.h"
|
||||
|
||||
#endif // LIBSPIRV_LATEST_VERSION_OPENCL_STD_HEADER_H_
|
20
3rdparty/spirv-tools/source/latest_version_spirv_header.h
vendored
Normal file
20
3rdparty/spirv-tools/source/latest_version_spirv_header.h
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_LATEST_VERSION_SPIRV_HEADER_H_
|
||||
#define LIBSPIRV_LATEST_VERSION_SPIRV_HEADER_H_
|
||||
|
||||
#include "spirv/unified1/spirv.h"
|
||||
|
||||
#endif // LIBSPIRV_LATEST_VERSION_SPIRV_HEADER_H_
|
118
3rdparty/spirv-tools/source/libspirv.cpp
vendored
Normal file
118
3rdparty/spirv-tools/source/libspirv.cpp
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
|
||||
#include "table.h"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
Context::Context(spv_target_env env) : context_(spvContextCreate(env)) {}
|
||||
|
||||
Context::Context(Context&& other) : context_(other.context_) {
|
||||
other.context_ = nullptr;
|
||||
}
|
||||
|
||||
Context& Context::operator=(Context&& other) {
|
||||
spvContextDestroy(context_);
|
||||
context_ = other.context_;
|
||||
other.context_ = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Context::~Context() { spvContextDestroy(context_); }
|
||||
|
||||
void Context::SetMessageConsumer(MessageConsumer consumer) {
|
||||
libspirv::SetContextMessageConsumer(context_, std::move(consumer));
|
||||
}
|
||||
|
||||
spv_context& Context::CContext() { return context_; }
|
||||
|
||||
const spv_context& Context::CContext() const { return context_; }
|
||||
|
||||
// Structs for holding the data members for SpvTools.
|
||||
struct SpirvTools::Impl {
|
||||
explicit Impl(spv_target_env env) : context(spvContextCreate(env)) {
|
||||
// The default consumer in spv_context_t is a null consumer, which provides
|
||||
// equivalent functionality (from the user's perspective) as a real consumer
|
||||
// does nothing.
|
||||
}
|
||||
~Impl() { spvContextDestroy(context); }
|
||||
|
||||
spv_context context; // C interface context object.
|
||||
};
|
||||
|
||||
SpirvTools::SpirvTools(spv_target_env env) : impl_(new Impl(env)) {}
|
||||
|
||||
SpirvTools::~SpirvTools() {}
|
||||
|
||||
void SpirvTools::SetMessageConsumer(MessageConsumer consumer) {
|
||||
libspirv::SetContextMessageConsumer(impl_->context, std::move(consumer));
|
||||
}
|
||||
|
||||
bool SpirvTools::Assemble(const std::string& text,
|
||||
std::vector<uint32_t>* binary,
|
||||
uint32_t options) const {
|
||||
return Assemble(text.data(), text.size(), binary, options);
|
||||
}
|
||||
|
||||
bool SpirvTools::Assemble(const char* text, const size_t text_size,
|
||||
std::vector<uint32_t>* binary,
|
||||
uint32_t options) const {
|
||||
spv_binary spvbinary = nullptr;
|
||||
spv_result_t status = spvTextToBinaryWithOptions(
|
||||
impl_->context, text, text_size, options, &spvbinary, nullptr);
|
||||
if (status == SPV_SUCCESS) {
|
||||
binary->assign(spvbinary->code, spvbinary->code + spvbinary->wordCount);
|
||||
}
|
||||
spvBinaryDestroy(spvbinary);
|
||||
return status == SPV_SUCCESS;
|
||||
}
|
||||
|
||||
bool SpirvTools::Disassemble(const std::vector<uint32_t>& binary,
|
||||
std::string* text, uint32_t options) const {
|
||||
return Disassemble(binary.data(), binary.size(), text, options);
|
||||
}
|
||||
|
||||
bool SpirvTools::Disassemble(const uint32_t* binary, const size_t binary_size,
|
||||
std::string* text, uint32_t options) const {
|
||||
spv_text spvtext = nullptr;
|
||||
spv_result_t status = spvBinaryToText(impl_->context, binary, binary_size,
|
||||
options, &spvtext, nullptr);
|
||||
if (status == SPV_SUCCESS) {
|
||||
text->assign(spvtext->str, spvtext->str + spvtext->length);
|
||||
}
|
||||
spvTextDestroy(spvtext);
|
||||
return status == SPV_SUCCESS;
|
||||
}
|
||||
|
||||
bool SpirvTools::Validate(const std::vector<uint32_t>& binary) const {
|
||||
return Validate(binary.data(), binary.size());
|
||||
}
|
||||
|
||||
bool SpirvTools::Validate(const uint32_t* binary,
|
||||
const size_t binary_size) const {
|
||||
return spvValidateBinary(impl_->context, binary, binary_size, nullptr) ==
|
||||
SPV_SUCCESS;
|
||||
}
|
||||
|
||||
bool SpirvTools::Validate(const uint32_t* binary, const size_t binary_size,
|
||||
const spvtools::ValidatorOptions& options) const {
|
||||
spv_const_binary_t the_binary{binary, binary_size};
|
||||
return spvValidateWithOptions(impl_->context, options, &the_binary,
|
||||
nullptr) == SPV_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace spvtools
|
36
3rdparty/spirv-tools/source/link/CMakeLists.txt
vendored
Normal file
36
3rdparty/spirv-tools/source/link/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
# Copyright (c) 2017 Pierre Moreau
|
||||
|
||||
# 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.
|
||||
add_library(SPIRV-Tools-link
|
||||
linker.cpp
|
||||
)
|
||||
|
||||
spvtools_default_compile_options(SPIRV-Tools-link)
|
||||
target_include_directories(SPIRV-Tools-link
|
||||
PUBLIC ${spirv-tools_SOURCE_DIR}/include
|
||||
PUBLIC ${SPIRV_HEADER_INCLUDE_DIR}
|
||||
PRIVATE ${spirv-tools_BINARY_DIR}
|
||||
)
|
||||
# We need the IR functionnalities from the optimizer
|
||||
target_link_libraries(SPIRV-Tools-link
|
||||
PUBLIC SPIRV-Tools-opt)
|
||||
|
||||
set_property(TARGET SPIRV-Tools-link PROPERTY FOLDER "SPIRV-Tools libraries")
|
||||
spvtools_check_symbol_exports(SPIRV-Tools-link)
|
||||
|
||||
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||
install(TARGETS SPIRV-Tools-link
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif(ENABLE_SPIRV_TOOLS_INSTALL)
|
786
3rdparty/spirv-tools/source/link/linker.cpp
vendored
Normal file
786
3rdparty/spirv-tools/source/link/linker.cpp
vendored
Normal file
@ -0,0 +1,786 @@
|
||||
// Copyright (c) 2017 Pierre Moreau
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "spirv-tools/linker.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include "assembly_grammar.h"
|
||||
#include "diagnostic.h"
|
||||
#include "opt/build_module.h"
|
||||
#include "opt/compact_ids_pass.h"
|
||||
#include "opt/decoration_manager.h"
|
||||
#include "opt/ir_loader.h"
|
||||
#include "opt/make_unique.h"
|
||||
#include "opt/pass_manager.h"
|
||||
#include "opt/remove_duplicates_pass.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
#include "spirv_target_env.h"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
using ir::Instruction;
|
||||
using ir::IRContext;
|
||||
using ir::Module;
|
||||
using ir::Operand;
|
||||
using opt::PassManager;
|
||||
using opt::RemoveDuplicatesPass;
|
||||
using opt::analysis::DecorationManager;
|
||||
using opt::analysis::DefUseManager;
|
||||
|
||||
// Stores various information about an imported or exported symbol.
|
||||
struct LinkageSymbolInfo {
|
||||
SpvId id; // ID of the symbol
|
||||
SpvId type_id; // ID of the type of the symbol
|
||||
std::string name; // unique name defining the symbol and used for matching
|
||||
// imports and exports together
|
||||
std::vector<SpvId> parameter_ids; // ID of the parameters of the symbol, if
|
||||
// it is a function
|
||||
};
|
||||
struct LinkageEntry {
|
||||
LinkageSymbolInfo imported_symbol;
|
||||
LinkageSymbolInfo exported_symbol;
|
||||
|
||||
LinkageEntry(const LinkageSymbolInfo& import_info,
|
||||
const LinkageSymbolInfo& export_info)
|
||||
: imported_symbol(import_info), exported_symbol(export_info) {}
|
||||
};
|
||||
using LinkageTable = std::vector<LinkageEntry>;
|
||||
|
||||
// Shifts the IDs used in each binary of |modules| so that they occupy a
|
||||
// disjoint range from the other binaries, and compute the new ID bound which
|
||||
// is returned in |max_id_bound|.
|
||||
//
|
||||
// Both |modules| and |max_id_bound| should not be null, and |modules| should
|
||||
// not be empty either. Furthermore |modules| should not contain any null
|
||||
// pointers.
|
||||
static spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
|
||||
std::vector<ir::Module*>* modules,
|
||||
uint32_t* max_id_bound);
|
||||
|
||||
// Generates the header for the linked module and returns it in |header|.
|
||||
//
|
||||
// |header| should not be null, |modules| should not be empty and pointers
|
||||
// should be non-null. |max_id_bound| should be strictly greater than 0.
|
||||
//
|
||||
// TODO(pierremoreau): What to do when binaries use different versions of
|
||||
// SPIR-V? For now, use the max of all versions found in
|
||||
// the input modules.
|
||||
static spv_result_t GenerateHeader(const MessageConsumer& consumer,
|
||||
const std::vector<ir::Module*>& modules,
|
||||
uint32_t max_id_bound,
|
||||
ir::ModuleHeader* header);
|
||||
|
||||
// Merge all the modules from |in_modules| into a single module owned by
|
||||
// |linked_context|.
|
||||
//
|
||||
// |linked_context| should not be null.
|
||||
static spv_result_t MergeModules(const MessageConsumer& consumer,
|
||||
const std::vector<Module*>& in_modules,
|
||||
const libspirv::AssemblyGrammar& grammar,
|
||||
IRContext* linked_context);
|
||||
|
||||
// Compute all pairs of import and export and return it in |linkings_to_do|.
|
||||
//
|
||||
// |linkings_to_do should not be null. Built-in symbols will be ignored.
|
||||
//
|
||||
// TODO(pierremoreau): Linkage attributes applied by a group decoration are
|
||||
// currently not handled. (You could have a group being
|
||||
// applied to a single ID.)
|
||||
// TODO(pierremoreau): What should be the proper behaviour with built-in
|
||||
// symbols?
|
||||
static spv_result_t GetImportExportPairs(
|
||||
const MessageConsumer& consumer, const ir::IRContext& linked_context,
|
||||
const DefUseManager& def_use_manager,
|
||||
const DecorationManager& decoration_manager, bool allow_partial_linkage,
|
||||
LinkageTable* linkings_to_do);
|
||||
|
||||
// Checks that for each pair of import and export, the import and export have
|
||||
// the same type as well as the same decorations.
|
||||
//
|
||||
// TODO(pierremoreau): Decorations on functions parameters are currently not
|
||||
// checked.
|
||||
static spv_result_t CheckImportExportCompatibility(
|
||||
const MessageConsumer& consumer, const LinkageTable& linkings_to_do,
|
||||
ir::IRContext* context);
|
||||
|
||||
// Remove linkage specific instructions, such as prototypes of imported
|
||||
// functions, declarations of imported variables, import (and export if
|
||||
// necessary) linkage attribtes.
|
||||
//
|
||||
// |linked_context| and |decoration_manager| should not be null, and the
|
||||
// 'RemoveDuplicatePass' should be run first.
|
||||
//
|
||||
// TODO(pierremoreau): Linkage attributes applied by a group decoration are
|
||||
// currently not handled. (You could have a group being
|
||||
// applied to a single ID.)
|
||||
// TODO(pierremoreau): Run a pass for removing dead instructions, for example
|
||||
// OpName for prototypes of imported funcions.
|
||||
static spv_result_t RemoveLinkageSpecificInstructions(
|
||||
const MessageConsumer& consumer, const LinkerOptions& options,
|
||||
const LinkageTable& linkings_to_do, DecorationManager* decoration_manager,
|
||||
ir::IRContext* linked_context);
|
||||
|
||||
// Verify that the unique ids of each instruction in |linked_context| (i.e. the
|
||||
// merged module) are truly unique. Does not check the validity of other ids
|
||||
static spv_result_t VerifyIds(const MessageConsumer& consumer,
|
||||
ir::IRContext* linked_context);
|
||||
|
||||
spv_result_t Link(const Context& context,
|
||||
const std::vector<std::vector<uint32_t>>& binaries,
|
||||
std::vector<uint32_t>* linked_binary,
|
||||
const LinkerOptions& options) {
|
||||
std::vector<const uint32_t*> binary_ptrs;
|
||||
binary_ptrs.reserve(binaries.size());
|
||||
std::vector<size_t> binary_sizes;
|
||||
binary_sizes.reserve(binaries.size());
|
||||
|
||||
for (const auto& binary : binaries) {
|
||||
binary_ptrs.push_back(binary.data());
|
||||
binary_sizes.push_back(binary.size());
|
||||
}
|
||||
|
||||
return Link(context, binary_ptrs.data(), binary_sizes.data(), binaries.size(),
|
||||
linked_binary, options);
|
||||
}
|
||||
|
||||
spv_result_t Link(const Context& context, const uint32_t* const* binaries,
|
||||
const size_t* binary_sizes, size_t num_binaries,
|
||||
std::vector<uint32_t>* linked_binary,
|
||||
const LinkerOptions& options) {
|
||||
spv_position_t position = {};
|
||||
const spv_context& c_context = context.CContext();
|
||||
const MessageConsumer& consumer = c_context->consumer;
|
||||
|
||||
linked_binary->clear();
|
||||
if (num_binaries == 0u)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_BINARY)
|
||||
<< "No modules were given.";
|
||||
|
||||
std::vector<std::unique_ptr<IRContext>> ir_contexts;
|
||||
std::vector<Module*> modules;
|
||||
modules.reserve(num_binaries);
|
||||
for (size_t i = 0u; i < num_binaries; ++i) {
|
||||
const uint32_t schema = binaries[i][4u];
|
||||
if (schema != 0u) {
|
||||
position.index = 4u;
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_BINARY)
|
||||
<< "Schema is non-zero for module " << i << ".";
|
||||
}
|
||||
|
||||
std::unique_ptr<IRContext> ir_context = BuildModule(
|
||||
c_context->target_env, consumer, binaries[i], binary_sizes[i]);
|
||||
if (ir_context == nullptr)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_BINARY)
|
||||
<< "Failed to build a module out of " << ir_contexts.size() << ".";
|
||||
modules.push_back(ir_context->module());
|
||||
ir_contexts.push_back(std::move(ir_context));
|
||||
}
|
||||
|
||||
// Phase 1: Shift the IDs used in each binary so that they occupy a disjoint
|
||||
// range from the other binaries, and compute the new ID bound.
|
||||
uint32_t max_id_bound = 0u;
|
||||
spv_result_t res = ShiftIdsInModules(consumer, &modules, &max_id_bound);
|
||||
if (res != SPV_SUCCESS) return res;
|
||||
|
||||
// Phase 2: Generate the header
|
||||
ir::ModuleHeader header;
|
||||
res = GenerateHeader(consumer, modules, max_id_bound, &header);
|
||||
if (res != SPV_SUCCESS) return res;
|
||||
IRContext linked_context(c_context->target_env, consumer);
|
||||
linked_context.module()->SetHeader(header);
|
||||
|
||||
// Phase 3: Merge all the binaries into a single one.
|
||||
libspirv::AssemblyGrammar grammar(c_context);
|
||||
res = MergeModules(consumer, modules, grammar, &linked_context);
|
||||
if (res != SPV_SUCCESS) return res;
|
||||
|
||||
if (options.GetVerifyIds()) {
|
||||
res = VerifyIds(consumer, &linked_context);
|
||||
if (res != SPV_SUCCESS) return res;
|
||||
}
|
||||
|
||||
// Phase 4: Find the import/export pairs
|
||||
LinkageTable linkings_to_do;
|
||||
res = GetImportExportPairs(consumer, linked_context,
|
||||
*linked_context.get_def_use_mgr(),
|
||||
*linked_context.get_decoration_mgr(),
|
||||
options.GetAllowPartialLinkage(), &linkings_to_do);
|
||||
if (res != SPV_SUCCESS) return res;
|
||||
|
||||
// Phase 5: Ensure the import and export have the same types and decorations.
|
||||
res =
|
||||
CheckImportExportCompatibility(consumer, linkings_to_do, &linked_context);
|
||||
if (res != SPV_SUCCESS) return res;
|
||||
|
||||
// Phase 6: Remove duplicates
|
||||
PassManager manager;
|
||||
manager.SetMessageConsumer(consumer);
|
||||
manager.AddPass<RemoveDuplicatesPass>();
|
||||
opt::Pass::Status pass_res = manager.Run(&linked_context);
|
||||
if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
|
||||
|
||||
// Phase 7: Rematch import variables/functions to export variables/functions
|
||||
for (const auto& linking_entry : linkings_to_do)
|
||||
linked_context.ReplaceAllUsesWith(linking_entry.imported_symbol.id,
|
||||
linking_entry.exported_symbol.id);
|
||||
|
||||
// Phase 8: Remove linkage specific instructions, such as import/export
|
||||
// attributes, linkage capability, etc. if applicable
|
||||
res = RemoveLinkageSpecificInstructions(consumer, options, linkings_to_do,
|
||||
linked_context.get_decoration_mgr(),
|
||||
&linked_context);
|
||||
if (res != SPV_SUCCESS) return res;
|
||||
|
||||
// Phase 9: Compact the IDs used in the module
|
||||
manager.AddPass<opt::CompactIdsPass>();
|
||||
pass_res = manager.Run(&linked_context);
|
||||
if (pass_res == opt::Pass::Status::Failure) return SPV_ERROR_INVALID_DATA;
|
||||
|
||||
// Phase 10: Output the module
|
||||
linked_context.module()->ToBinary(linked_binary, true);
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
static spv_result_t ShiftIdsInModules(const MessageConsumer& consumer,
|
||||
std::vector<ir::Module*>* modules,
|
||||
uint32_t* max_id_bound) {
|
||||
spv_position_t position = {};
|
||||
|
||||
if (modules == nullptr)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_DATA)
|
||||
<< "|modules| of ShiftIdsInModules should not be null.";
|
||||
if (modules->empty())
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_DATA)
|
||||
<< "|modules| of ShiftIdsInModules should not be empty.";
|
||||
if (max_id_bound == nullptr)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_DATA)
|
||||
<< "|max_id_bound| of ShiftIdsInModules should not be null.";
|
||||
|
||||
uint32_t id_bound = modules->front()->IdBound() - 1u;
|
||||
for (auto module_iter = modules->begin() + 1; module_iter != modules->end();
|
||||
++module_iter) {
|
||||
Module* module = *module_iter;
|
||||
module->ForEachInst([&id_bound](Instruction* insn) {
|
||||
insn->ForEachId([&id_bound](uint32_t* id) { *id += id_bound; });
|
||||
});
|
||||
id_bound += module->IdBound() - 1u;
|
||||
if (id_bound > 0x3FFFFF)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_ID)
|
||||
<< "The limit of IDs, 4194303, was exceeded:"
|
||||
<< " " << id_bound << " is the current ID bound.";
|
||||
|
||||
// Invalidate the DefUseManager
|
||||
module->context()->InvalidateAnalyses(ir::IRContext::kAnalysisDefUse);
|
||||
}
|
||||
++id_bound;
|
||||
if (id_bound > 0x3FFFFF)
|
||||
return libspirv::DiagnosticStream(position, consumer, SPV_ERROR_INVALID_ID)
|
||||
<< "The limit of IDs, 4194303, was exceeded:"
|
||||
<< " " << id_bound << " is the current ID bound.";
|
||||
|
||||
*max_id_bound = id_bound;
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
static spv_result_t GenerateHeader(const MessageConsumer& consumer,
|
||||
const std::vector<ir::Module*>& modules,
|
||||
uint32_t max_id_bound,
|
||||
ir::ModuleHeader* header) {
|
||||
spv_position_t position = {};
|
||||
|
||||
if (modules.empty())
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_DATA)
|
||||
<< "|modules| of GenerateHeader should not be empty.";
|
||||
if (max_id_bound == 0u)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_DATA)
|
||||
<< "|max_id_bound| of GenerateHeader should not be null.";
|
||||
|
||||
uint32_t version = 0u;
|
||||
for (const auto& module : modules)
|
||||
version = std::max(version, module->version());
|
||||
|
||||
header->magic_number = SpvMagicNumber;
|
||||
header->version = version;
|
||||
header->generator = 17u;
|
||||
header->bound = max_id_bound;
|
||||
header->reserved = 0u;
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
static spv_result_t MergeModules(const MessageConsumer& consumer,
|
||||
const std::vector<Module*>& input_modules,
|
||||
const libspirv::AssemblyGrammar& grammar,
|
||||
IRContext* linked_context) {
|
||||
spv_position_t position = {};
|
||||
|
||||
if (linked_context == nullptr)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_DATA)
|
||||
<< "|linked_module| of MergeModules should not be null.";
|
||||
Module* linked_module = linked_context->module();
|
||||
|
||||
if (input_modules.empty()) return SPV_SUCCESS;
|
||||
|
||||
for (const auto& module : input_modules)
|
||||
for (const auto& inst : module->capabilities())
|
||||
linked_module->AddCapability(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
|
||||
for (const auto& module : input_modules)
|
||||
for (const auto& inst : module->extensions())
|
||||
linked_module->AddExtension(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
|
||||
for (const auto& module : input_modules)
|
||||
for (const auto& inst : module->ext_inst_imports())
|
||||
linked_module->AddExtInstImport(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
|
||||
do {
|
||||
const Instruction* memory_model_inst = input_modules[0]->GetMemoryModel();
|
||||
if (memory_model_inst == nullptr) break;
|
||||
|
||||
uint32_t addressing_model = memory_model_inst->GetSingleWordOperand(0u);
|
||||
uint32_t memory_model = memory_model_inst->GetSingleWordOperand(1u);
|
||||
for (const auto& module : input_modules) {
|
||||
memory_model_inst = module->GetMemoryModel();
|
||||
if (memory_model_inst == nullptr) continue;
|
||||
|
||||
if (addressing_model != memory_model_inst->GetSingleWordOperand(0u)) {
|
||||
spv_operand_desc initial_desc = nullptr, current_desc = nullptr;
|
||||
grammar.lookupOperand(SPV_OPERAND_TYPE_ADDRESSING_MODEL,
|
||||
addressing_model, &initial_desc);
|
||||
grammar.lookupOperand(SPV_OPERAND_TYPE_ADDRESSING_MODEL,
|
||||
memory_model_inst->GetSingleWordOperand(0u),
|
||||
¤t_desc);
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INTERNAL)
|
||||
<< "Conflicting addressing models: " << initial_desc->name
|
||||
<< " vs " << current_desc->name << ".";
|
||||
}
|
||||
if (memory_model != memory_model_inst->GetSingleWordOperand(1u)) {
|
||||
spv_operand_desc initial_desc = nullptr, current_desc = nullptr;
|
||||
grammar.lookupOperand(SPV_OPERAND_TYPE_MEMORY_MODEL, memory_model,
|
||||
&initial_desc);
|
||||
grammar.lookupOperand(SPV_OPERAND_TYPE_MEMORY_MODEL,
|
||||
memory_model_inst->GetSingleWordOperand(1u),
|
||||
¤t_desc);
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INTERNAL)
|
||||
<< "Conflicting memory models: " << initial_desc->name << " vs "
|
||||
<< current_desc->name << ".";
|
||||
}
|
||||
}
|
||||
|
||||
if (memory_model_inst != nullptr)
|
||||
linked_module->SetMemoryModel(std::unique_ptr<Instruction>(
|
||||
memory_model_inst->Clone(linked_context)));
|
||||
} while (false);
|
||||
|
||||
std::vector<std::pair<uint32_t, const char*>> entry_points;
|
||||
for (const auto& module : input_modules)
|
||||
for (const auto& inst : module->entry_points()) {
|
||||
const uint32_t model = inst.GetSingleWordInOperand(0);
|
||||
const char* const name =
|
||||
reinterpret_cast<const char*>(inst.GetInOperand(2).words.data());
|
||||
const auto i = std::find_if(
|
||||
entry_points.begin(), entry_points.end(),
|
||||
[model, name](const std::pair<uint32_t, const char*>& v) {
|
||||
return v.first == model && strcmp(name, v.second) == 0;
|
||||
});
|
||||
if (i != entry_points.end()) {
|
||||
spv_operand_desc desc = nullptr;
|
||||
grammar.lookupOperand(SPV_OPERAND_TYPE_EXECUTION_MODEL, model, &desc);
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INTERNAL)
|
||||
<< "The entry point \"" << name << "\", with execution model "
|
||||
<< desc->name << ", was already defined.";
|
||||
}
|
||||
linked_module->AddEntryPoint(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
entry_points.emplace_back(model, name);
|
||||
}
|
||||
|
||||
for (const auto& module : input_modules)
|
||||
for (const auto& inst : module->execution_modes())
|
||||
linked_module->AddExecutionMode(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
|
||||
for (const auto& module : input_modules)
|
||||
for (const auto& inst : module->debugs1())
|
||||
linked_module->AddDebug1Inst(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
|
||||
for (const auto& module : input_modules)
|
||||
for (const auto& inst : module->debugs2())
|
||||
linked_module->AddDebug2Inst(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
|
||||
for (const auto& module : input_modules)
|
||||
for (const auto& inst : module->debugs3())
|
||||
linked_module->AddDebug3Inst(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
|
||||
// If the generated module uses SPIR-V 1.1 or higher, add an
|
||||
// OpModuleProcessed instruction about the linking step.
|
||||
if (linked_module->version() >= 0x10100) {
|
||||
const std::string processed_string("Linked by SPIR-V Tools Linker");
|
||||
const size_t words_nb =
|
||||
processed_string.size() / 4u + (processed_string.size() % 4u != 0u);
|
||||
std::vector<uint32_t> processed_words(words_nb, 0u);
|
||||
std::memcpy(processed_words.data(), processed_string.data(), words_nb * 4u);
|
||||
linked_module->AddDebug3Inst(std::unique_ptr<Instruction>(
|
||||
new Instruction(linked_context, SpvOpModuleProcessed, 0u, 0u,
|
||||
{{SPV_OPERAND_TYPE_LITERAL_STRING, processed_words}})));
|
||||
}
|
||||
|
||||
for (const auto& module : input_modules)
|
||||
for (const auto& inst : module->annotations())
|
||||
linked_module->AddAnnotationInst(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
|
||||
// TODO(pierremoreau): Since the modules have not been validate, should we
|
||||
// expect SpvStorageClassFunction variables outside
|
||||
// functions?
|
||||
uint32_t num_global_values = 0u;
|
||||
for (const auto& module : input_modules) {
|
||||
for (const auto& inst : module->types_values()) {
|
||||
linked_module->AddType(
|
||||
std::unique_ptr<Instruction>(inst.Clone(linked_context)));
|
||||
num_global_values += inst.opcode() == SpvOpVariable;
|
||||
}
|
||||
}
|
||||
if (num_global_values > 0xFFFF)
|
||||
return libspirv::DiagnosticStream(position, consumer, SPV_ERROR_INTERNAL)
|
||||
<< "The limit of global values, 65535, was exceeded;"
|
||||
<< " " << num_global_values << " global values were found.";
|
||||
|
||||
// Process functions and their basic blocks
|
||||
for (const auto& module : input_modules) {
|
||||
for (const auto& func : *module) {
|
||||
std::unique_ptr<ir::Function> cloned_func(func.Clone(linked_context));
|
||||
cloned_func->SetParent(linked_module);
|
||||
linked_module->AddFunction(std::move(cloned_func));
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
static spv_result_t GetImportExportPairs(
|
||||
const MessageConsumer& consumer, const ir::IRContext& linked_context,
|
||||
const DefUseManager& def_use_manager,
|
||||
const DecorationManager& decoration_manager, bool allow_partial_linkage,
|
||||
LinkageTable* linkings_to_do) {
|
||||
spv_position_t position = {};
|
||||
|
||||
if (linkings_to_do == nullptr)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_DATA)
|
||||
<< "|linkings_to_do| of GetImportExportPairs should not be empty.";
|
||||
|
||||
std::vector<LinkageSymbolInfo> imports;
|
||||
std::unordered_map<std::string, std::vector<LinkageSymbolInfo>> exports;
|
||||
|
||||
// Figure out the imports and exports
|
||||
for (const auto& decoration : linked_context.annotations()) {
|
||||
if (decoration.opcode() != SpvOpDecorate ||
|
||||
decoration.GetSingleWordInOperand(1u) != SpvDecorationLinkageAttributes)
|
||||
continue;
|
||||
|
||||
const SpvId id = decoration.GetSingleWordInOperand(0u);
|
||||
// Ignore if the targeted symbol is a built-in
|
||||
bool is_built_in = false;
|
||||
for (const auto& id_decoration :
|
||||
decoration_manager.GetDecorationsFor(id, false)) {
|
||||
if (id_decoration->GetSingleWordInOperand(1u) == SpvDecorationBuiltIn) {
|
||||
is_built_in = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_built_in) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint32_t type = decoration.GetSingleWordInOperand(3u);
|
||||
|
||||
LinkageSymbolInfo symbol_info;
|
||||
symbol_info.name =
|
||||
reinterpret_cast<const char*>(decoration.GetInOperand(2u).words.data());
|
||||
symbol_info.id = id;
|
||||
symbol_info.type_id = 0u;
|
||||
|
||||
// Retrieve the type of the current symbol. This information will be used
|
||||
// when checking that the imported and exported symbols have the same
|
||||
// types.
|
||||
const Instruction* def_inst = def_use_manager.GetDef(id);
|
||||
if (def_inst == nullptr)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_BINARY)
|
||||
<< "ID " << id << " is never defined:\n";
|
||||
|
||||
if (def_inst->opcode() == SpvOpVariable) {
|
||||
symbol_info.type_id = def_inst->type_id();
|
||||
} else if (def_inst->opcode() == SpvOpFunction) {
|
||||
symbol_info.type_id = def_inst->GetSingleWordInOperand(1u);
|
||||
|
||||
// range-based for loop calls begin()/end(), but never cbegin()/cend(),
|
||||
// which will not work here.
|
||||
for (auto func_iter = linked_context.module()->cbegin();
|
||||
func_iter != linked_context.module()->cend(); ++func_iter) {
|
||||
if (func_iter->result_id() != id) continue;
|
||||
func_iter->ForEachParam([&symbol_info](const Instruction* inst) {
|
||||
symbol_info.parameter_ids.push_back(inst->result_id());
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_BINARY)
|
||||
<< "Only global variables and functions can be decorated using"
|
||||
<< " LinkageAttributes; " << id << " is neither of them.\n";
|
||||
}
|
||||
|
||||
if (type == SpvLinkageTypeImport)
|
||||
imports.push_back(symbol_info);
|
||||
else if (type == SpvLinkageTypeExport)
|
||||
exports[symbol_info.name].push_back(symbol_info);
|
||||
}
|
||||
|
||||
// Find the import/export pairs
|
||||
for (const auto& import : imports) {
|
||||
std::vector<LinkageSymbolInfo> possible_exports;
|
||||
const auto& exp = exports.find(import.name);
|
||||
if (exp != exports.end()) possible_exports = exp->second;
|
||||
if (possible_exports.empty() && !allow_partial_linkage)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_BINARY)
|
||||
<< "Unresolved external reference to \"" << import.name << "\".";
|
||||
else if (possible_exports.size() > 1u)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_BINARY)
|
||||
<< "Too many external references, " << possible_exports.size()
|
||||
<< ", were found for \"" << import.name << "\".";
|
||||
|
||||
if (!possible_exports.empty())
|
||||
linkings_to_do->emplace_back(import, possible_exports.front());
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
static spv_result_t CheckImportExportCompatibility(
|
||||
const MessageConsumer& consumer, const LinkageTable& linkings_to_do,
|
||||
ir::IRContext* context) {
|
||||
spv_position_t position = {};
|
||||
|
||||
// Ensure th import and export types are the same.
|
||||
const DefUseManager& def_use_manager = *context->get_def_use_mgr();
|
||||
const DecorationManager& decoration_manager = *context->get_decoration_mgr();
|
||||
for (const auto& linking_entry : linkings_to_do) {
|
||||
if (!RemoveDuplicatesPass::AreTypesEqual(
|
||||
*def_use_manager.GetDef(linking_entry.imported_symbol.type_id),
|
||||
*def_use_manager.GetDef(linking_entry.exported_symbol.type_id),
|
||||
context))
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_BINARY)
|
||||
<< "Type mismatch on symbol \""
|
||||
<< linking_entry.imported_symbol.name
|
||||
<< "\" between imported variable/function %"
|
||||
<< linking_entry.imported_symbol.id
|
||||
<< " and exported variable/function %"
|
||||
<< linking_entry.exported_symbol.id << ".";
|
||||
}
|
||||
|
||||
// Ensure the import and export decorations are similar
|
||||
for (const auto& linking_entry : linkings_to_do) {
|
||||
if (!decoration_manager.HaveTheSameDecorations(
|
||||
linking_entry.imported_symbol.id, linking_entry.exported_symbol.id))
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_BINARY)
|
||||
<< "Decorations mismatch on symbol \""
|
||||
<< linking_entry.imported_symbol.name
|
||||
<< "\" between imported variable/function %"
|
||||
<< linking_entry.imported_symbol.id
|
||||
<< " and exported variable/function %"
|
||||
<< linking_entry.exported_symbol.id << ".";
|
||||
// TODO(pierremoreau): Decorations on function parameters should probably
|
||||
// match, except for FuncParamAttr if I understand the
|
||||
// spec correctly.
|
||||
// TODO(pierremoreau): Decorations on the function return type should
|
||||
// match, except for FuncParamAttr.
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
static spv_result_t RemoveLinkageSpecificInstructions(
|
||||
const MessageConsumer& consumer, const LinkerOptions& options,
|
||||
const LinkageTable& linkings_to_do, DecorationManager* decoration_manager,
|
||||
ir::IRContext* linked_context) {
|
||||
spv_position_t position = {};
|
||||
|
||||
if (decoration_manager == nullptr)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_DATA)
|
||||
<< "|decoration_manager| of RemoveLinkageSpecificInstructions "
|
||||
"should not be empty.";
|
||||
if (linked_context == nullptr)
|
||||
return libspirv::DiagnosticStream(position, consumer,
|
||||
SPV_ERROR_INVALID_DATA)
|
||||
<< "|linked_module| of RemoveLinkageSpecificInstructions should not "
|
||||
"be empty.";
|
||||
|
||||
// TODO(pierremoreau): Remove FuncParamAttr decorations of imported
|
||||
// functions' return type.
|
||||
|
||||
// Remove FuncParamAttr decorations of imported functions' parameters.
|
||||
// From the SPIR-V specification, Sec. 2.13:
|
||||
// When resolving imported functions, the Function Control and all Function
|
||||
// Parameter Attributes are taken from the function definition, and not
|
||||
// from the function declaration.
|
||||
for (const auto& linking_entry : linkings_to_do) {
|
||||
for (const auto parameter_id :
|
||||
linking_entry.imported_symbol.parameter_ids) {
|
||||
decoration_manager->RemoveDecorationsFrom(
|
||||
parameter_id, [](const Instruction& inst) {
|
||||
return (inst.opcode() == SpvOpDecorate ||
|
||||
inst.opcode() == SpvOpMemberDecorate) &&
|
||||
inst.GetSingleWordInOperand(1u) ==
|
||||
SpvDecorationFuncParamAttr;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Remove prototypes of imported functions
|
||||
for (const auto& linking_entry : linkings_to_do) {
|
||||
for (auto func_iter = linked_context->module()->begin();
|
||||
func_iter != linked_context->module()->end();) {
|
||||
if (func_iter->result_id() == linking_entry.imported_symbol.id)
|
||||
func_iter = func_iter.Erase();
|
||||
else
|
||||
++func_iter;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove declarations of imported variables
|
||||
for (const auto& linking_entry : linkings_to_do) {
|
||||
auto next = linked_context->types_values_begin();
|
||||
for (auto inst = next; inst != linked_context->types_values_end();
|
||||
inst = next) {
|
||||
++next;
|
||||
if (inst->result_id() == linking_entry.imported_symbol.id) {
|
||||
linked_context->KillInst(&*inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If partial linkage is allowed, we need an efficient way to check whether
|
||||
// an imported ID had a corresponding export symbol. As uses of the imported
|
||||
// symbol have already been replaced by the exported symbol, use the exported
|
||||
// symbol ID.
|
||||
// TODO(pierremoreau): This will not work if the decoration is applied
|
||||
// through a group, but the linker does not support that
|
||||
// either.
|
||||
std::unordered_set<SpvId> imports;
|
||||
if (options.GetAllowPartialLinkage()) {
|
||||
imports.reserve(linkings_to_do.size());
|
||||
for (const auto& linking_entry : linkings_to_do)
|
||||
imports.emplace(linking_entry.exported_symbol.id);
|
||||
}
|
||||
|
||||
// Remove import linkage attributes
|
||||
auto next = linked_context->annotation_begin();
|
||||
for (auto inst = next; inst != linked_context->annotation_end();
|
||||
inst = next) {
|
||||
++next;
|
||||
// If this is an import annotation:
|
||||
// * if we do not allow partial linkage, remove all import annotations;
|
||||
// * otherwise, remove the annotation only if there was a corresponding
|
||||
// export.
|
||||
if (inst->opcode() == SpvOpDecorate &&
|
||||
inst->GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
|
||||
inst->GetSingleWordOperand(3u) == SpvLinkageTypeImport &&
|
||||
(!options.GetAllowPartialLinkage() ||
|
||||
imports.find(inst->GetSingleWordOperand(0u)) != imports.end())) {
|
||||
linked_context->KillInst(&*inst);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove export linkage attributes if making an executable
|
||||
if (!options.GetCreateLibrary()) {
|
||||
next = linked_context->annotation_begin();
|
||||
for (auto inst = next; inst != linked_context->annotation_end();
|
||||
inst = next) {
|
||||
++next;
|
||||
if (inst->opcode() == SpvOpDecorate &&
|
||||
inst->GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
|
||||
inst->GetSingleWordOperand(3u) == SpvLinkageTypeExport) {
|
||||
linked_context->KillInst(&*inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove Linkage capability if making an executable and partial linkage is
|
||||
// not allowed
|
||||
if (!options.GetCreateLibrary() && !options.GetAllowPartialLinkage()) {
|
||||
for (auto& inst : linked_context->capabilities())
|
||||
if (inst.GetSingleWordInOperand(0u) == SpvCapabilityLinkage) {
|
||||
linked_context->KillInst(&inst);
|
||||
// The RemoveDuplicatesPass did remove duplicated capabilities, so we
|
||||
// now there aren’t more SpvCapabilityLinkage further down.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t VerifyIds(const MessageConsumer& consumer,
|
||||
ir::IRContext* linked_context) {
|
||||
std::unordered_set<uint32_t> ids;
|
||||
bool ok = true;
|
||||
linked_context->module()->ForEachInst(
|
||||
[&ids, &ok](const ir::Instruction* inst) {
|
||||
ok &= ids.insert(inst->unique_id()).second;
|
||||
});
|
||||
|
||||
if (!ok) {
|
||||
consumer(SPV_MSG_INTERNAL_ERROR, "", {}, "Non-unique id in merged module");
|
||||
return SPV_ERROR_INVALID_ID;
|
||||
}
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace spvtools
|
25
3rdparty/spirv-tools/source/macro.h
vendored
Normal file
25
3rdparty/spirv-tools/source/macro.h
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_MACRO_H_
|
||||
#define LIBSPIRV_MACRO_H_
|
||||
|
||||
// Evaluates to the number of elements of array A.
|
||||
//
|
||||
// If we could use constexpr, then we could make this a template function.
|
||||
// If the source arrays were std::array, then we could have used
|
||||
// std::array::size.
|
||||
#define ARRAY_SIZE(A) (static_cast<uint32_t>(sizeof(A) / sizeof(A[0])))
|
||||
|
||||
#endif // LIBSPIRV_MACRO_H_
|
54
3rdparty/spirv-tools/source/message.cpp
vendored
Normal file
54
3rdparty/spirv-tools/source/message.cpp
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "message.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
std::string StringifyMessage(spv_message_level_t level, const char* source,
|
||||
const spv_position_t& position,
|
||||
const char* message) {
|
||||
const char* level_string = nullptr;
|
||||
switch (level) {
|
||||
case SPV_MSG_FATAL:
|
||||
level_string = "fatal";
|
||||
break;
|
||||
case SPV_MSG_INTERNAL_ERROR:
|
||||
level_string = "internal error";
|
||||
break;
|
||||
case SPV_MSG_ERROR:
|
||||
level_string = "error";
|
||||
break;
|
||||
case SPV_MSG_WARNING:
|
||||
level_string = "warning";
|
||||
break;
|
||||
case SPV_MSG_INFO:
|
||||
level_string = "info";
|
||||
break;
|
||||
case SPV_MSG_DEBUG:
|
||||
level_string = "debug";
|
||||
break;
|
||||
}
|
||||
std::ostringstream oss;
|
||||
oss << level_string << ": ";
|
||||
if (source) oss << source << ":";
|
||||
oss << position.line << ":" << position.column << ":";
|
||||
oss << position.index << ": ";
|
||||
if (message) oss << message;
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
} // namespace spvtools
|
33
3rdparty/spirv-tools/source/message.h
vendored
Normal file
33
3rdparty/spirv-tools/source/message.h
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SPIRV_TOOLS_MESSAGE_H_
|
||||
#define SPIRV_TOOLS_MESSAGE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
// A helper function to compose and return a string from the message in the
|
||||
// following format:
|
||||
// "<level>: <source>:<line>:<column>:<index>: <message>"
|
||||
std::string StringifyMessage(spv_message_level_t level, const char* source,
|
||||
const spv_position_t& position,
|
||||
const char* message);
|
||||
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SPIRV_TOOLS_MESSAGE_H_
|
332
3rdparty/spirv-tools/source/name_mapper.cpp
vendored
Normal file
332
3rdparty/spirv-tools/source/name_mapper.cpp
vendored
Normal file
@ -0,0 +1,332 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "name_mapper.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
#include "latest_version_spirv_header.h"
|
||||
#include "parsed_operand.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Converts a uint32_t to its string decimal representation.
|
||||
std::string to_string(uint32_t id) {
|
||||
// Use stringstream, since some versions of Android compilers lack
|
||||
// std::to_string.
|
||||
std::stringstream os;
|
||||
os << id;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
NameMapper GetTrivialNameMapper() { return to_string; }
|
||||
|
||||
FriendlyNameMapper::FriendlyNameMapper(const spv_const_context context,
|
||||
const uint32_t* code,
|
||||
const size_t wordCount)
|
||||
: grammar_(libspirv::AssemblyGrammar(context)) {
|
||||
spv_diagnostic diag = nullptr;
|
||||
// We don't care if the parse fails.
|
||||
spvBinaryParse(context, this, code, wordCount, nullptr,
|
||||
ParseInstructionForwarder, &diag);
|
||||
spvDiagnosticDestroy(diag);
|
||||
}
|
||||
|
||||
std::string FriendlyNameMapper::NameForId(uint32_t id) {
|
||||
auto iter = name_for_id_.find(id);
|
||||
if (iter == name_for_id_.end()) {
|
||||
// It must have been an invalid module, so just return a trivial mapping.
|
||||
// We don't care about uniqueness.
|
||||
return to_string(id);
|
||||
} else {
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
std::string FriendlyNameMapper::Sanitize(const std::string& suggested_name) {
|
||||
if (suggested_name.empty()) return "_";
|
||||
// Otherwise, replace invalid characters by '_'.
|
||||
std::string result;
|
||||
std::string valid =
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"_0123456789";
|
||||
std::transform(suggested_name.begin(), suggested_name.end(),
|
||||
std::back_inserter(result), [&valid](const char c) {
|
||||
return (std::string::npos == valid.find(c)) ? '_' : c;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void FriendlyNameMapper::SaveName(uint32_t id,
|
||||
const std::string& suggested_name) {
|
||||
if (name_for_id_.find(id) != name_for_id_.end()) return;
|
||||
|
||||
const std::string sanitized_suggested_name = Sanitize(suggested_name);
|
||||
std::string name = sanitized_suggested_name;
|
||||
auto inserted = used_names_.insert(name);
|
||||
if (!inserted.second) {
|
||||
const std::string base_name = sanitized_suggested_name + "_";
|
||||
for (uint32_t index = 0; !inserted.second; ++index) {
|
||||
name = base_name + to_string(index);
|
||||
inserted = used_names_.insert(name);
|
||||
}
|
||||
}
|
||||
name_for_id_[id] = name;
|
||||
}
|
||||
|
||||
void FriendlyNameMapper::SaveBuiltInName(uint32_t target_id,
|
||||
uint32_t built_in) {
|
||||
#define GLCASE(name) \
|
||||
case SpvBuiltIn##name: \
|
||||
SaveName(target_id, "gl_" #name); \
|
||||
return;
|
||||
#define GLCASE2(name, suggested) \
|
||||
case SpvBuiltIn##name: \
|
||||
SaveName(target_id, "gl_" #suggested); \
|
||||
return;
|
||||
#define CASE(name) \
|
||||
case SpvBuiltIn##name: \
|
||||
SaveName(target_id, #name); \
|
||||
return;
|
||||
switch (built_in) {
|
||||
GLCASE(Position)
|
||||
GLCASE(PointSize)
|
||||
GLCASE(ClipDistance)
|
||||
GLCASE(CullDistance)
|
||||
GLCASE2(VertexId, VertexID)
|
||||
GLCASE2(InstanceId, InstanceID)
|
||||
GLCASE2(PrimitiveId, PrimitiveID)
|
||||
GLCASE2(InvocationId, InvocationID)
|
||||
GLCASE(Layer)
|
||||
GLCASE(ViewportIndex)
|
||||
GLCASE(TessLevelOuter)
|
||||
GLCASE(TessLevelInner)
|
||||
GLCASE(TessCoord)
|
||||
GLCASE(PatchVertices)
|
||||
GLCASE(FragCoord)
|
||||
GLCASE(PointCoord)
|
||||
GLCASE(FrontFacing)
|
||||
GLCASE2(SampleId, SampleID)
|
||||
GLCASE(SamplePosition)
|
||||
GLCASE(SampleMask)
|
||||
GLCASE(FragDepth)
|
||||
GLCASE(HelperInvocation)
|
||||
GLCASE2(NumWorkgroups, NumWorkGroups)
|
||||
GLCASE2(WorkgroupSize, WorkGroupSize)
|
||||
GLCASE2(WorkgroupId, WorkGroupID)
|
||||
GLCASE2(LocalInvocationId, LocalInvocationID)
|
||||
GLCASE2(GlobalInvocationId, GlobalInvocationID)
|
||||
GLCASE(LocalInvocationIndex)
|
||||
CASE(WorkDim)
|
||||
CASE(GlobalSize)
|
||||
CASE(EnqueuedWorkgroupSize)
|
||||
CASE(GlobalOffset)
|
||||
CASE(GlobalLinearId)
|
||||
CASE(SubgroupSize)
|
||||
CASE(SubgroupMaxSize)
|
||||
CASE(NumSubgroups)
|
||||
CASE(NumEnqueuedSubgroups)
|
||||
CASE(SubgroupId)
|
||||
CASE(SubgroupLocalInvocationId)
|
||||
GLCASE(VertexIndex)
|
||||
GLCASE(InstanceIndex)
|
||||
CASE(SubgroupEqMaskKHR)
|
||||
CASE(SubgroupGeMaskKHR)
|
||||
CASE(SubgroupGtMaskKHR)
|
||||
CASE(SubgroupLeMaskKHR)
|
||||
CASE(SubgroupLtMaskKHR)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#undef GLCASE
|
||||
#undef GLCASE2
|
||||
#undef CASE
|
||||
}
|
||||
|
||||
spv_result_t FriendlyNameMapper::ParseInstruction(
|
||||
const spv_parsed_instruction_t& inst) {
|
||||
const auto result_id = inst.result_id;
|
||||
switch (inst.opcode) {
|
||||
case SpvOpName:
|
||||
SaveName(inst.words[1], reinterpret_cast<const char*>(inst.words + 2));
|
||||
break;
|
||||
case SpvOpDecorate:
|
||||
// Decorations come after OpName. So OpName will take precedence over
|
||||
// decorations.
|
||||
//
|
||||
// In theory, we should also handle OpGroupDecorate. But that's unlikely
|
||||
// to occur.
|
||||
if (inst.words[2] == SpvDecorationBuiltIn) {
|
||||
assert(inst.num_words > 3);
|
||||
SaveBuiltInName(inst.words[1], inst.words[3]);
|
||||
}
|
||||
break;
|
||||
case SpvOpTypeVoid:
|
||||
SaveName(result_id, "void");
|
||||
break;
|
||||
case SpvOpTypeBool:
|
||||
SaveName(result_id, "bool");
|
||||
break;
|
||||
case SpvOpTypeInt: {
|
||||
std::string signedness;
|
||||
std::string root;
|
||||
const auto bit_width = inst.words[2];
|
||||
switch (bit_width) {
|
||||
case 8:
|
||||
root = "char";
|
||||
break;
|
||||
case 16:
|
||||
root = "short";
|
||||
break;
|
||||
case 32:
|
||||
root = "int";
|
||||
break;
|
||||
case 64:
|
||||
root = "long";
|
||||
break;
|
||||
default:
|
||||
root = to_string(bit_width);
|
||||
signedness = "i";
|
||||
break;
|
||||
}
|
||||
if (0 == inst.words[3]) signedness = "u";
|
||||
SaveName(result_id, signedness + root);
|
||||
} break;
|
||||
case SpvOpTypeFloat: {
|
||||
const auto bit_width = inst.words[2];
|
||||
switch (bit_width) {
|
||||
case 16:
|
||||
SaveName(result_id, "half");
|
||||
break;
|
||||
case 32:
|
||||
SaveName(result_id, "float");
|
||||
break;
|
||||
case 64:
|
||||
SaveName(result_id, "double");
|
||||
break;
|
||||
default:
|
||||
SaveName(result_id, std::string("fp") + to_string(bit_width));
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case SpvOpTypeVector:
|
||||
SaveName(result_id, std::string("v") + to_string(inst.words[3]) +
|
||||
NameForId(inst.words[2]));
|
||||
break;
|
||||
case SpvOpTypeMatrix:
|
||||
SaveName(result_id, std::string("mat") + to_string(inst.words[3]) +
|
||||
NameForId(inst.words[2]));
|
||||
break;
|
||||
case SpvOpTypeArray:
|
||||
SaveName(result_id, std::string("_arr_") + NameForId(inst.words[2]) +
|
||||
"_" + NameForId(inst.words[3]));
|
||||
break;
|
||||
case SpvOpTypeRuntimeArray:
|
||||
SaveName(result_id,
|
||||
std::string("_runtimearr_") + NameForId(inst.words[2]));
|
||||
break;
|
||||
case SpvOpTypePointer:
|
||||
SaveName(result_id, std::string("_ptr_") +
|
||||
NameForEnumOperand(SPV_OPERAND_TYPE_STORAGE_CLASS,
|
||||
inst.words[2]) +
|
||||
"_" + NameForId(inst.words[3]));
|
||||
break;
|
||||
case SpvOpTypePipe:
|
||||
SaveName(result_id,
|
||||
std::string("Pipe") +
|
||||
NameForEnumOperand(SPV_OPERAND_TYPE_ACCESS_QUALIFIER,
|
||||
inst.words[2]));
|
||||
break;
|
||||
case SpvOpTypeEvent:
|
||||
SaveName(result_id, "Event");
|
||||
break;
|
||||
case SpvOpTypeDeviceEvent:
|
||||
SaveName(result_id, "DeviceEvent");
|
||||
break;
|
||||
case SpvOpTypeReserveId:
|
||||
SaveName(result_id, "ReserveId");
|
||||
break;
|
||||
case SpvOpTypeQueue:
|
||||
SaveName(result_id, "Queue");
|
||||
break;
|
||||
case SpvOpTypeOpaque:
|
||||
SaveName(result_id,
|
||||
std::string("Opaque_") +
|
||||
Sanitize(reinterpret_cast<const char*>(inst.words + 2)));
|
||||
break;
|
||||
case SpvOpTypePipeStorage:
|
||||
SaveName(result_id, "PipeStorage");
|
||||
break;
|
||||
case SpvOpTypeNamedBarrier:
|
||||
SaveName(result_id, "NamedBarrier");
|
||||
break;
|
||||
case SpvOpTypeStruct:
|
||||
// Structs are mapped rather simplisitically. Just indicate that they
|
||||
// are a struct and then give the raw Id number.
|
||||
SaveName(result_id, std::string("_struct_") + to_string(result_id));
|
||||
break;
|
||||
case SpvOpConstantTrue:
|
||||
SaveName(result_id, "true");
|
||||
break;
|
||||
case SpvOpConstantFalse:
|
||||
SaveName(result_id, "false");
|
||||
break;
|
||||
case SpvOpConstant: {
|
||||
std::ostringstream value;
|
||||
EmitNumericLiteral(&value, inst, inst.operands[2]);
|
||||
auto value_str = value.str();
|
||||
// Use 'n' to signify negative. Other invalid characters will be mapped
|
||||
// to underscore.
|
||||
for (auto& c : value_str)
|
||||
if (c == '-') c = 'n';
|
||||
SaveName(result_id, NameForId(inst.type_id) + "_" + value_str);
|
||||
} break;
|
||||
default:
|
||||
// If this instruction otherwise defines an Id, then save a mapping for
|
||||
// it. This is needed to ensure uniqueness in there is an OpName with
|
||||
// string something like "1" that might collide with this result_id.
|
||||
// We should only do this if a name hasn't already been registered by some
|
||||
// previous forward reference.
|
||||
if (result_id && name_for_id_.find(result_id) == name_for_id_.end())
|
||||
SaveName(result_id, to_string(result_id));
|
||||
break;
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
std::string FriendlyNameMapper::NameForEnumOperand(spv_operand_type_t type,
|
||||
uint32_t word) {
|
||||
spv_operand_desc desc = nullptr;
|
||||
if (SPV_SUCCESS == grammar_.lookupOperand(type, word, &desc)) {
|
||||
return desc->name;
|
||||
} else {
|
||||
// Invalid input. Just give something sane.
|
||||
return std::string("StorageClass") + to_string(word);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace libspirv
|
122
3rdparty/spirv-tools/source/name_mapper.h
vendored
Normal file
122
3rdparty/spirv-tools/source/name_mapper.h
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_NAME_MAPPER_H_
|
||||
#define LIBSPIRV_NAME_MAPPER_H_
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "assembly_grammar.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace libspirv {
|
||||
|
||||
// A NameMapper maps SPIR-V Id values to names. Each name is valid to use in
|
||||
// SPIR-V assembly. The mapping is one-to-one, i.e. no two Ids map to the same
|
||||
// name.
|
||||
using NameMapper = std::function<std::string(uint32_t)>;
|
||||
|
||||
// Returns a NameMapper which always maps an Id to its decimal representation.
|
||||
NameMapper GetTrivialNameMapper();
|
||||
|
||||
// A FriendlyNameMapper parses a module upon construction. If the parse is
|
||||
// successful, then the NameForId method maps an Id to a friendly name
|
||||
// while also satisfying the constraints on a NameMapper.
|
||||
//
|
||||
// The mapping is friendly in the following sense:
|
||||
// - If an Id has a debug name (via OpName), then that will be used when
|
||||
// possible.
|
||||
// - Well known scalar types map to friendly names. For example,
|
||||
// OpTypeVoid should be %void. Scalar types map to their names in OpenCL
|
||||
// when
|
||||
// there is a correspondence, and otherwise as follows:
|
||||
// - unsigned integer type of n bits map to "u" followed by n
|
||||
// - signed integer type of n bits map to "i" followed by n
|
||||
// - floating point type of n bits map to "fp" followed by n
|
||||
// - Vector type names map to "v" followed by the number of components,
|
||||
// followed by the friendly name for the base type.
|
||||
// - Matrix type names map to "mat" followed by the number of columns,
|
||||
// followed by the friendly name for the base vector type.
|
||||
// - Pointer types map to "_ptr_", then the name of the storage class, then the
|
||||
// name for the pointee type.
|
||||
// - Exotic types like event, pipe, opaque, queue, reserve-id map to their own
|
||||
// human readable names.
|
||||
// - A struct type maps to "_struct_" followed by the raw Id number. That's
|
||||
// pretty simplistic, but workable.
|
||||
// - A built-in variable maps to its GLSL variable name.
|
||||
// - Numeric literals in OpConstant map to a human-friendly name.
|
||||
class FriendlyNameMapper {
|
||||
public:
|
||||
// Construct a friendly name mapper, and determine friendly names for each
|
||||
// defined Id in the specified module. The module is specified by the code
|
||||
// wordCount, and should be parseable in the specified context.
|
||||
FriendlyNameMapper(const spv_const_context context, const uint32_t* code,
|
||||
const size_t wordCount);
|
||||
|
||||
// Returns a NameMapper which maps ids to the friendly names parsed from the
|
||||
// module provided to the constructor.
|
||||
NameMapper GetNameMapper() {
|
||||
return [this](uint32_t id) { return this->NameForId(id); };
|
||||
}
|
||||
|
||||
// Returns the friendly name for the given id. If the module parsed during
|
||||
// construction is valid, then the mapping satisfies the rules for a
|
||||
// NameMapper.
|
||||
std::string NameForId(uint32_t id);
|
||||
|
||||
private:
|
||||
// Transforms the given string so that it is acceptable as an Id name in
|
||||
// assembly language. Two distinct inputs can map to the same output.
|
||||
std::string Sanitize(const std::string& suggested_name);
|
||||
|
||||
// Records a name for the given id. If this id already has a name, then
|
||||
// this is a no-op. If the id doesn't have a name, use the given
|
||||
// suggested_name if it hasn't already been taken, and otherwise generate
|
||||
// a new (unused) name based on the suggested name.
|
||||
void SaveName(uint32_t id, const std::string& suggested_name);
|
||||
|
||||
// Records a built-in variable name for target_id. If target_id already
|
||||
// has a name then this is a no-op.
|
||||
void SaveBuiltInName(uint32_t target_id, uint32_t built_in);
|
||||
|
||||
// Collects information from the given parsed instruction to populate
|
||||
// name_for_id_. Returns SPV_SUCCESS;
|
||||
spv_result_t ParseInstruction(const spv_parsed_instruction_t& inst);
|
||||
|
||||
// Forwards a parsed-instruction callback from the binary parser into the
|
||||
// FriendlyNameMapper hidden inside the user_data parameter.
|
||||
static spv_result_t ParseInstructionForwarder(
|
||||
void* user_data, const spv_parsed_instruction_t* parsed_instruction) {
|
||||
return reinterpret_cast<FriendlyNameMapper*>(user_data)->ParseInstruction(
|
||||
*parsed_instruction);
|
||||
}
|
||||
|
||||
// Returns the friendly name for an enumerant.
|
||||
std::string NameForEnumOperand(spv_operand_type_t type, uint32_t word);
|
||||
|
||||
// Maps an id to its friendly name. This will have an entry for each Id
|
||||
// defined in the module.
|
||||
std::unordered_map<uint32_t, std::string> name_for_id_;
|
||||
// The set of names that have a mapping in name_for_id_;
|
||||
std::unordered_set<std::string> used_names_;
|
||||
// The assembly grammar for the current context.
|
||||
const libspirv::AssemblyGrammar grammar_;
|
||||
};
|
||||
|
||||
} // namespace libspirv
|
||||
|
||||
#endif // _LIBSPIRV_NAME_MAPPER_H_
|
456
3rdparty/spirv-tools/source/opcode.cpp
vendored
Normal file
456
3rdparty/spirv-tools/source/opcode.cpp
vendored
Normal file
@ -0,0 +1,456 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "opcode.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "instruction.h"
|
||||
#include "macro.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv_constant.h"
|
||||
#include "spirv_endian.h"
|
||||
#include "spirv_target_env.h"
|
||||
|
||||
namespace {
|
||||
struct OpcodeDescPtrLen {
|
||||
const spv_opcode_desc_t* ptr;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
#include "core.insts-unified1.inc" // defines kOpcodeTableEntries_1_3
|
||||
|
||||
static const spv_opcode_table_t kOpcodeTable = {ARRAY_SIZE(kOpcodeTableEntries),
|
||||
kOpcodeTableEntries};
|
||||
|
||||
// Represents a vendor tool entry in the SPIR-V XML Regsitry.
|
||||
struct VendorTool {
|
||||
uint32_t value;
|
||||
const char* vendor;
|
||||
const char* tool; // Might be empty string.
|
||||
const char* vendor_tool; // Combiantion of vendor and tool.
|
||||
};
|
||||
|
||||
const VendorTool vendor_tools[] = {
|
||||
#include "generators.inc"
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// TODO(dneto): Move this to another file. It doesn't belong with opcode
|
||||
// processing.
|
||||
const char* spvGeneratorStr(uint32_t generator) {
|
||||
auto where = std::find_if(
|
||||
std::begin(vendor_tools), std::end(vendor_tools),
|
||||
[generator](const VendorTool& vt) { return generator == vt.value; });
|
||||
if (where != std::end(vendor_tools)) return where->vendor_tool;
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
|
||||
return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
|
||||
}
|
||||
|
||||
void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount,
|
||||
uint16_t* pOpcode) {
|
||||
if (pWordCount) {
|
||||
*pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
|
||||
}
|
||||
if (pOpcode) {
|
||||
*pOpcode = 0x0000ffff & word;
|
||||
}
|
||||
}
|
||||
|
||||
spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable, spv_target_env) {
|
||||
if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
// Descriptions of each opcode. Each entry describes the format of the
|
||||
// instruction that follows a particular opcode.
|
||||
|
||||
*pInstTable = &kOpcodeTable;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvOpcodeTableNameLookup(spv_target_env env,
|
||||
const spv_opcode_table table,
|
||||
const char* name,
|
||||
spv_opcode_desc* pEntry) {
|
||||
if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
|
||||
if (!table) return SPV_ERROR_INVALID_TABLE;
|
||||
|
||||
// TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
|
||||
// preferable but the table requires sorting on the Opcode name, but it's
|
||||
// static const initialized and matches the order of the spec.
|
||||
const size_t nameLength = strlen(name);
|
||||
for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
|
||||
const spv_opcode_desc_t& entry = table->entries[opcodeIndex];
|
||||
// We considers the current opcode as available as long as
|
||||
// 1. The target environment satisfies the minimal requirement of the
|
||||
// opcode; or
|
||||
// 2. There is at least one extension enabling this opcode.
|
||||
//
|
||||
// Note that the second rule assumes the extension enabling this instruction
|
||||
// is indeed requested in the SPIR-V code; checking that should be
|
||||
// validator's work.
|
||||
if ((spvVersionForTargetEnv(env) >= entry.minVersion ||
|
||||
entry.numExtensions > 0u) &&
|
||||
nameLength == strlen(entry.name) &&
|
||||
!strncmp(name, entry.name, nameLength)) {
|
||||
// NOTE: Found out Opcode!
|
||||
*pEntry = &entry;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_LOOKUP;
|
||||
}
|
||||
|
||||
spv_result_t spvOpcodeTableValueLookup(spv_target_env env,
|
||||
const spv_opcode_table table,
|
||||
const SpvOp opcode,
|
||||
spv_opcode_desc* pEntry) {
|
||||
if (!table) return SPV_ERROR_INVALID_TABLE;
|
||||
if (!pEntry) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
const auto beg = table->entries;
|
||||
const auto end = table->entries + table->count;
|
||||
|
||||
spv_opcode_desc_t needle = {"", opcode, 0, nullptr, 0, {},
|
||||
false, false, 0, nullptr, ~0u};
|
||||
|
||||
auto comp = [](const spv_opcode_desc_t& lhs, const spv_opcode_desc_t& rhs) {
|
||||
return lhs.opcode < rhs.opcode;
|
||||
};
|
||||
|
||||
// We need to loop here because there can exist multiple symbols for the same
|
||||
// opcode value, and they can be introduced in different target environments,
|
||||
// which means they can have different minimal version requirements.
|
||||
// Assumes the underlying table is already sorted ascendingly according to
|
||||
// opcode value.
|
||||
for (auto it = std::lower_bound(beg, end, needle, comp);
|
||||
it != end && it->opcode == opcode; ++it) {
|
||||
// We considers the current opcode as available as long as
|
||||
// 1. The target environment satisfies the minimal requirement of the
|
||||
// opcode; or
|
||||
// 2. There is at least one extension enabling this opcode.
|
||||
//
|
||||
// Note that the second rule assumes the extension enabling this instruction
|
||||
// is indeed requested in the SPIR-V code; checking that should be
|
||||
// validator's work.
|
||||
if (spvVersionForTargetEnv(env) >= it->minVersion ||
|
||||
it->numExtensions > 0u) {
|
||||
*pEntry = it;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_LOOKUP;
|
||||
}
|
||||
|
||||
void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
|
||||
const uint16_t wordCount, const spv_endianness_t endian,
|
||||
spv_instruction_t* pInst) {
|
||||
pInst->opcode = opcode;
|
||||
pInst->words.resize(wordCount);
|
||||
for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
|
||||
pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
|
||||
if (!wordIndex) {
|
||||
uint16_t thisWordCount;
|
||||
uint16_t thisOpcode;
|
||||
spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
|
||||
assert(opcode == static_cast<SpvOp>(thisOpcode) &&
|
||||
wordCount == thisWordCount && "Endianness failed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* spvOpcodeString(const SpvOp opcode) {
|
||||
const auto beg = kOpcodeTableEntries;
|
||||
const auto end = kOpcodeTableEntries + ARRAY_SIZE(kOpcodeTableEntries);
|
||||
spv_opcode_desc_t needle = {"", opcode, 0, nullptr, 0, {},
|
||||
false, false, 0, nullptr, ~0u};
|
||||
auto comp = [](const spv_opcode_desc_t& lhs, const spv_opcode_desc_t& rhs) {
|
||||
return lhs.opcode < rhs.opcode;
|
||||
};
|
||||
auto it = std::lower_bound(beg, end, needle, comp);
|
||||
if (it != end && it->opcode == opcode) {
|
||||
return it->name;
|
||||
}
|
||||
|
||||
assert(0 && "Unreachable!");
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpTypeInt:
|
||||
case SpvOpTypeFloat:
|
||||
case SpvOpTypeBool:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeIsSpecConstant(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpSpecConstantTrue:
|
||||
case SpvOpSpecConstantFalse:
|
||||
case SpvOpSpecConstant:
|
||||
case SpvOpSpecConstantComposite:
|
||||
case SpvOpSpecConstantOp:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeIsConstant(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpConstantTrue:
|
||||
case SpvOpConstantFalse:
|
||||
case SpvOpConstant:
|
||||
case SpvOpConstantComposite:
|
||||
case SpvOpConstantSampler:
|
||||
case SpvOpConstantNull:
|
||||
case SpvOpSpecConstantTrue:
|
||||
case SpvOpSpecConstantFalse:
|
||||
case SpvOpSpecConstant:
|
||||
case SpvOpSpecConstantComposite:
|
||||
case SpvOpSpecConstantOp:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsConstantOrUndef(const SpvOp opcode) {
|
||||
return opcode == SpvOpUndef || spvOpcodeIsConstant(opcode);
|
||||
}
|
||||
|
||||
bool spvOpcodeIsScalarSpecConstant(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpSpecConstantTrue:
|
||||
case SpvOpSpecConstantFalse:
|
||||
case SpvOpSpecConstant:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeIsComposite(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeMatrix:
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeStruct:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeReturnsLogicalVariablePointer(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpVariable:
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpFunctionParameter:
|
||||
case SpvOpImageTexelPointer:
|
||||
case SpvOpCopyObject:
|
||||
case SpvOpSelect:
|
||||
case SpvOpPhi:
|
||||
case SpvOpFunctionCall:
|
||||
case SpvOpPtrAccessChain:
|
||||
case SpvOpLoad:
|
||||
case SpvOpConstantNull:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpVariable:
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpFunctionParameter:
|
||||
case SpvOpImageTexelPointer:
|
||||
case SpvOpCopyObject:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t spvOpcodeGeneratesType(SpvOp op) {
|
||||
switch (op) {
|
||||
case SpvOpTypeVoid:
|
||||
case SpvOpTypeBool:
|
||||
case SpvOpTypeInt:
|
||||
case SpvOpTypeFloat:
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeMatrix:
|
||||
case SpvOpTypeImage:
|
||||
case SpvOpTypeSampler:
|
||||
case SpvOpTypeSampledImage:
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
case SpvOpTypeStruct:
|
||||
case SpvOpTypeOpaque:
|
||||
case SpvOpTypePointer:
|
||||
case SpvOpTypeFunction:
|
||||
case SpvOpTypeEvent:
|
||||
case SpvOpTypeDeviceEvent:
|
||||
case SpvOpTypeReserveId:
|
||||
case SpvOpTypeQueue:
|
||||
case SpvOpTypePipe:
|
||||
case SpvOpTypePipeStorage:
|
||||
case SpvOpTypeNamedBarrier:
|
||||
return true;
|
||||
default:
|
||||
// In particular, OpTypeForwardPointer does not generate a type,
|
||||
// but declares a storage class for a pointer type generated
|
||||
// by a different instruction.
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool spvOpcodeIsDecoration(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpDecorate:
|
||||
case SpvOpDecorateId:
|
||||
case SpvOpMemberDecorate:
|
||||
case SpvOpGroupDecorate:
|
||||
case SpvOpGroupMemberDecorate:
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
case SpvOpMemberDecorateStringGOOGLE:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool spvOpcodeIsLoad(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpLoad:
|
||||
case SpvOpImageSampleExplicitLod:
|
||||
case SpvOpImageSampleImplicitLod:
|
||||
case SpvOpImageSampleDrefImplicitLod:
|
||||
case SpvOpImageSampleDrefExplicitLod:
|
||||
case SpvOpImageSampleProjImplicitLod:
|
||||
case SpvOpImageSampleProjExplicitLod:
|
||||
case SpvOpImageSampleProjDrefImplicitLod:
|
||||
case SpvOpImageSampleProjDrefExplicitLod:
|
||||
case SpvOpImageFetch:
|
||||
case SpvOpImageGather:
|
||||
case SpvOpImageDrefGather:
|
||||
case SpvOpImageRead:
|
||||
case SpvOpImageSparseSampleImplicitLod:
|
||||
case SpvOpImageSparseSampleExplicitLod:
|
||||
case SpvOpImageSparseSampleDrefExplicitLod:
|
||||
case SpvOpImageSparseSampleDrefImplicitLod:
|
||||
case SpvOpImageSparseFetch:
|
||||
case SpvOpImageSparseGather:
|
||||
case SpvOpImageSparseDrefGather:
|
||||
case SpvOpImageSparseRead:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsBranch(SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpBranch:
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsAtomicOp(const SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpAtomicLoad:
|
||||
case SpvOpAtomicStore:
|
||||
case SpvOpAtomicExchange:
|
||||
case SpvOpAtomicCompareExchange:
|
||||
case SpvOpAtomicCompareExchangeWeak:
|
||||
case SpvOpAtomicIIncrement:
|
||||
case SpvOpAtomicIDecrement:
|
||||
case SpvOpAtomicIAdd:
|
||||
case SpvOpAtomicISub:
|
||||
case SpvOpAtomicSMin:
|
||||
case SpvOpAtomicUMin:
|
||||
case SpvOpAtomicSMax:
|
||||
case SpvOpAtomicUMax:
|
||||
case SpvOpAtomicAnd:
|
||||
case SpvOpAtomicOr:
|
||||
case SpvOpAtomicXor:
|
||||
case SpvOpAtomicFlagTestAndSet:
|
||||
case SpvOpAtomicFlagClear:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsReturn(SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpReturn:
|
||||
case SpvOpReturnValue:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsReturnOrAbort(SpvOp opcode) {
|
||||
return spvOpcodeIsReturn(opcode) || opcode == SpvOpKill ||
|
||||
opcode == SpvOpUnreachable;
|
||||
}
|
||||
|
||||
bool spvOpcodeIsBlockTerminator(SpvOp opcode) {
|
||||
return spvOpcodeIsBranch(opcode) || spvOpcodeIsReturnOrAbort(opcode);
|
||||
}
|
||||
|
||||
bool spvOpcodeIsBaseOpaqueType(SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpTypeImage:
|
||||
case SpvOpTypeSampler:
|
||||
case SpvOpTypeSampledImage:
|
||||
case SpvOpTypeOpaque:
|
||||
case SpvOpTypeEvent:
|
||||
case SpvOpTypeDeviceEvent:
|
||||
case SpvOpTypeReserveId:
|
||||
case SpvOpTypeQueue:
|
||||
case SpvOpTypePipe:
|
||||
case SpvOpTypeForwardPointer:
|
||||
case SpvOpTypePipeStorage:
|
||||
case SpvOpTypeNamedBarrier:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
121
3rdparty/spirv-tools/source/opcode.h
vendored
Normal file
121
3rdparty/spirv-tools/source/opcode.h
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_OPCODE_H_
|
||||
#define LIBSPIRV_OPCODE_H_
|
||||
|
||||
#include "instruction.h"
|
||||
#include "latest_version_spirv_header.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "table.h"
|
||||
|
||||
// Returns the name of a registered SPIR-V generator as a null-terminated
|
||||
// string. If the generator is not known, then returns the string "Unknown".
|
||||
// The generator parameter should be most significant 16-bits of the generator
|
||||
// word in the SPIR-V module header.
|
||||
//
|
||||
// See the registry at https://www.khronos.org/registry/spir-v/api/spir-v.xml.
|
||||
const char* spvGeneratorStr(uint32_t generator);
|
||||
|
||||
// Combines word_count and opcode enumerant in single word.
|
||||
uint32_t spvOpcodeMake(uint16_t word_count, SpvOp opcode);
|
||||
|
||||
// Splits word into into two constituent parts: word_count and opcode.
|
||||
void spvOpcodeSplit(const uint32_t word, uint16_t* word_count,
|
||||
uint16_t* opcode);
|
||||
|
||||
// Finds the named opcode in the given opcode table. On success, returns
|
||||
// SPV_SUCCESS and writes a handle of the table entry into *entry.
|
||||
spv_result_t spvOpcodeTableNameLookup(spv_target_env,
|
||||
const spv_opcode_table table,
|
||||
const char* name, spv_opcode_desc* entry);
|
||||
|
||||
// Finds the opcode by enumerant in the given opcode table. On success, returns
|
||||
// SPV_SUCCESS and writes a handle of the table entry into *entry.
|
||||
spv_result_t spvOpcodeTableValueLookup(spv_target_env,
|
||||
const spv_opcode_table table,
|
||||
const SpvOp opcode,
|
||||
spv_opcode_desc* entry);
|
||||
|
||||
// Copies an instruction's word and fixes the endianness to host native. The
|
||||
// source instruction's stream/opcode/endianness is in the words/opcode/endian
|
||||
// parameter. The word_count parameter specifies the number of words to copy.
|
||||
// Writes copied instruction into *inst.
|
||||
void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
|
||||
const uint16_t word_count,
|
||||
const spv_endianness_t endian, spv_instruction_t* inst);
|
||||
|
||||
// Gets the name of an instruction, without the "Op" prefix.
|
||||
const char* spvOpcodeString(const SpvOp opcode);
|
||||
|
||||
// Determine if the given opcode is a scalar type. Returns zero if false,
|
||||
// non-zero otherwise.
|
||||
int32_t spvOpcodeIsScalarType(const SpvOp opcode);
|
||||
|
||||
// Determines if the given opcode is a specialization constant. Returns zero if
|
||||
// false, non-zero otherwise.
|
||||
int32_t spvOpcodeIsSpecConstant(const SpvOp opcode);
|
||||
|
||||
// Determines if the given opcode is a constant. Returns zero if false, non-zero
|
||||
// otherwise.
|
||||
int32_t spvOpcodeIsConstant(const SpvOp opcode);
|
||||
|
||||
// Returns true if the given opcode is a constant or undef.
|
||||
bool spvOpcodeIsConstantOrUndef(const SpvOp opcode);
|
||||
|
||||
// Returns true if the given opcode is a scalar specialization constant.
|
||||
bool spvOpcodeIsScalarSpecConstant(const SpvOp opcode);
|
||||
|
||||
// Determines if the given opcode is a composite type. Returns zero if false,
|
||||
// non-zero otherwise.
|
||||
int32_t spvOpcodeIsComposite(const SpvOp opcode);
|
||||
|
||||
// Determines if the given opcode results in a pointer when using the logical
|
||||
// addressing model. Returns zero if false, non-zero otherwise.
|
||||
int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode);
|
||||
|
||||
// Returns whether the given opcode could result in a pointer or a variable
|
||||
// pointer when using the logical addressing model.
|
||||
bool spvOpcodeReturnsLogicalVariablePointer(const SpvOp opcode);
|
||||
|
||||
// Determines if the given opcode generates a type. Returns zero if false,
|
||||
// non-zero otherwise.
|
||||
int32_t spvOpcodeGeneratesType(SpvOp opcode);
|
||||
|
||||
// Returns true if the opcode adds a decoration to an id.
|
||||
bool spvOpcodeIsDecoration(const SpvOp opcode);
|
||||
|
||||
// Returns true if the opcode is a load from memory into a result id. This
|
||||
// function only considers core instructions.
|
||||
bool spvOpcodeIsLoad(const SpvOp opcode);
|
||||
|
||||
// Returns true if the opcode is an atomic operation.
|
||||
bool spvOpcodeIsAtomicOp(const SpvOp opcode);
|
||||
|
||||
// Returns true if the given opcode is a branch instruction.
|
||||
bool spvOpcodeIsBranch(SpvOp opcode);
|
||||
|
||||
// Returns true if the given opcode is a return instruction.
|
||||
bool spvOpcodeIsReturn(SpvOp opcode);
|
||||
|
||||
// Returns true if the given opcode is a return instruction or it aborts
|
||||
// execution.
|
||||
bool spvOpcodeIsReturnOrAbort(SpvOp opcode);
|
||||
|
||||
// Returns true if the given opcode is a basic block terminator.
|
||||
bool spvOpcodeIsBlockTerminator(SpvOp opcode);
|
||||
|
||||
// Returns true if the given opcode always defines an opaque type.
|
||||
bool spvOpcodeIsBaseOpaqueType(SpvOp opcode);
|
||||
#endif // LIBSPIRV_OPCODE_H_
|
470
3rdparty/spirv-tools/source/operand.cpp
vendored
Normal file
470
3rdparty/spirv-tools/source/operand.cpp
vendored
Normal file
@ -0,0 +1,470 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "operand.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "macro.h"
|
||||
#include "spirv_constant.h"
|
||||
#include "spirv_target_env.h"
|
||||
|
||||
// For now, assume unified1 contains up to SPIR-V 1.3 and no later
|
||||
// SPIR-V version.
|
||||
// TODO(dneto): Make one set of tables, but with version tags on a
|
||||
// per-item basis. https://github.com/KhronosGroup/SPIRV-Tools/issues/1195
|
||||
|
||||
#include "operand.kinds-unified1.inc"
|
||||
|
||||
static const spv_operand_table_t kOperandTable = {
|
||||
ARRAY_SIZE(pygen_variable_OperandInfoTable),
|
||||
pygen_variable_OperandInfoTable};
|
||||
|
||||
spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable,
|
||||
spv_target_env) {
|
||||
if (!pOperandTable) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
*pOperandTable = &kOperandTable;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvOperandTableNameLookup(spv_target_env env,
|
||||
const spv_operand_table table,
|
||||
const spv_operand_type_t type,
|
||||
const char* name,
|
||||
const size_t nameLength,
|
||||
spv_operand_desc* pEntry) {
|
||||
if (!table) return SPV_ERROR_INVALID_TABLE;
|
||||
if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
|
||||
const auto& group = table->types[typeIndex];
|
||||
if (type != group.type) continue;
|
||||
for (uint64_t index = 0; index < group.count; ++index) {
|
||||
const auto& entry = group.entries[index];
|
||||
// We considers the current operand as available as long as
|
||||
// 1. The target environment satisfies the minimal requirement of the
|
||||
// operand; or
|
||||
// 2. There is at least one extension enabling this operand.
|
||||
//
|
||||
// Note that the second rule assumes the extension enabling this operand
|
||||
// is indeed requested in the SPIR-V code; checking that should be
|
||||
// validator's work.
|
||||
if ((spvVersionForTargetEnv(env) >= entry.minVersion ||
|
||||
entry.numExtensions > 0u) &&
|
||||
nameLength == strlen(entry.name) &&
|
||||
!strncmp(entry.name, name, nameLength)) {
|
||||
*pEntry = &entry;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_LOOKUP;
|
||||
}
|
||||
|
||||
spv_result_t spvOperandTableValueLookup(spv_target_env env,
|
||||
const spv_operand_table table,
|
||||
const spv_operand_type_t type,
|
||||
const uint32_t value,
|
||||
spv_operand_desc* pEntry) {
|
||||
if (!table) return SPV_ERROR_INVALID_TABLE;
|
||||
if (!pEntry) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
spv_operand_desc_t needle = {"", value, 0, nullptr, 0, nullptr, {}, ~0u};
|
||||
|
||||
auto comp = [](const spv_operand_desc_t& lhs, const spv_operand_desc_t& rhs) {
|
||||
return lhs.value < rhs.value;
|
||||
};
|
||||
|
||||
for (uint64_t typeIndex = 0; typeIndex < table->count; ++typeIndex) {
|
||||
const auto& group = table->types[typeIndex];
|
||||
if (type != group.type) continue;
|
||||
|
||||
const auto beg = group.entries;
|
||||
const auto end = group.entries + group.count;
|
||||
|
||||
// We need to loop here because there can exist multiple symbols for the
|
||||
// same operand value, and they can be introduced in different target
|
||||
// environments, which means they can have different minimal version
|
||||
// requirements. For example, SubgroupEqMaskKHR can exist in any SPIR-V
|
||||
// version as long as the SPV_KHR_shader_ballot extension is there; but
|
||||
// starting from SPIR-V 1.3, SubgroupEqMask, which has the same numeric
|
||||
// value as SubgroupEqMaskKHR, is available in core SPIR-V without extension
|
||||
// requirements.
|
||||
// Assumes the underlying table is already sorted ascendingly according to
|
||||
// opcode value.
|
||||
for (auto it = std::lower_bound(beg, end, needle, comp);
|
||||
it != end && it->value == value; ++it) {
|
||||
// We considers the current operand as available as long as
|
||||
// 1. The target environment satisfies the minimal requirement of the
|
||||
// operand; or
|
||||
// 2. There is at least one extension enabling this operand.
|
||||
//
|
||||
// Note that the second rule assumes the extension enabling this operand
|
||||
// is indeed requested in the SPIR-V code; checking that should be
|
||||
// validator's work.
|
||||
if (spvVersionForTargetEnv(env) >= it->minVersion ||
|
||||
it->numExtensions > 0u) {
|
||||
*pEntry = it;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_LOOKUP;
|
||||
}
|
||||
|
||||
const char* spvOperandTypeStr(spv_operand_type_t type) {
|
||||
switch (type) {
|
||||
case SPV_OPERAND_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_ID:
|
||||
return "ID";
|
||||
case SPV_OPERAND_TYPE_TYPE_ID:
|
||||
return "type ID";
|
||||
case SPV_OPERAND_TYPE_RESULT_ID:
|
||||
return "result ID";
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
|
||||
return "literal number";
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
|
||||
return "possibly multi-word literal integer";
|
||||
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
|
||||
return "possibly multi-word literal number";
|
||||
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
|
||||
return "extension instruction number";
|
||||
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER:
|
||||
return "OpSpecConstantOp opcode";
|
||||
case SPV_OPERAND_TYPE_LITERAL_STRING:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING:
|
||||
return "literal string";
|
||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||
return "source language";
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODEL:
|
||||
return "execution model";
|
||||
case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
|
||||
return "addressing model";
|
||||
case SPV_OPERAND_TYPE_MEMORY_MODEL:
|
||||
return "memory model";
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODE:
|
||||
return "execution mode";
|
||||
case SPV_OPERAND_TYPE_STORAGE_CLASS:
|
||||
return "storage class";
|
||||
case SPV_OPERAND_TYPE_DIMENSIONALITY:
|
||||
return "dimensionality";
|
||||
case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
|
||||
return "sampler addressing mode";
|
||||
case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
|
||||
return "sampler filter mode";
|
||||
case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
|
||||
return "image format";
|
||||
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
|
||||
return "floating-point fast math mode";
|
||||
case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
|
||||
return "floating-point rounding mode";
|
||||
case SPV_OPERAND_TYPE_LINKAGE_TYPE:
|
||||
return "linkage type";
|
||||
case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER:
|
||||
return "access qualifier";
|
||||
case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
|
||||
return "function parameter attribute";
|
||||
case SPV_OPERAND_TYPE_DECORATION:
|
||||
return "decoration";
|
||||
case SPV_OPERAND_TYPE_BUILT_IN:
|
||||
return "built-in";
|
||||
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
|
||||
return "selection control";
|
||||
case SPV_OPERAND_TYPE_LOOP_CONTROL:
|
||||
return "loop control";
|
||||
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
|
||||
return "function control";
|
||||
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
|
||||
return "memory semantics ID";
|
||||
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
|
||||
return "memory access";
|
||||
case SPV_OPERAND_TYPE_SCOPE_ID:
|
||||
return "scope ID";
|
||||
case SPV_OPERAND_TYPE_GROUP_OPERATION:
|
||||
return "group operation";
|
||||
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
|
||||
return "kernel enqeue flags";
|
||||
case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
|
||||
return "kernel profiling info";
|
||||
case SPV_OPERAND_TYPE_CAPABILITY:
|
||||
return "capability";
|
||||
case SPV_OPERAND_TYPE_IMAGE:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
|
||||
return "image";
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_CIV:
|
||||
return "context-insensitive value";
|
||||
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
|
||||
return "debug info flags";
|
||||
case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
|
||||
return "debug base type encoding";
|
||||
case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
|
||||
return "debug composite type";
|
||||
case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
|
||||
return "debug type qualifier";
|
||||
case SPV_OPERAND_TYPE_DEBUG_OPERATION:
|
||||
return "debug operation";
|
||||
|
||||
// The next values are for values returned from an instruction, not actually
|
||||
// an operand. So the specific strings don't matter. But let's add them
|
||||
// for completeness and ease of testing.
|
||||
case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
|
||||
return "image channel order";
|
||||
case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
|
||||
return "image channel data type";
|
||||
|
||||
case SPV_OPERAND_TYPE_NONE:
|
||||
return "NONE";
|
||||
default:
|
||||
assert(0 && "Unhandled operand type!");
|
||||
break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
void spvPushOperandTypes(const spv_operand_type_t* types,
|
||||
spv_operand_pattern_t* pattern) {
|
||||
const spv_operand_type_t* endTypes;
|
||||
for (endTypes = types; *endTypes != SPV_OPERAND_TYPE_NONE; ++endTypes)
|
||||
;
|
||||
while (endTypes-- != types) {
|
||||
pattern->push_back(*endTypes);
|
||||
}
|
||||
}
|
||||
|
||||
void spvPushOperandTypesForMask(spv_target_env env,
|
||||
const spv_operand_table operandTable,
|
||||
const spv_operand_type_t type,
|
||||
const uint32_t mask,
|
||||
spv_operand_pattern_t* pattern) {
|
||||
// Scan from highest bits to lowest bits because we will append in LIFO
|
||||
// fashion, and we need the operands for lower order bits to be consumed first
|
||||
for (uint32_t candidate_bit = (1u << 31u); candidate_bit;
|
||||
candidate_bit >>= 1) {
|
||||
if (candidate_bit & mask) {
|
||||
spv_operand_desc entry = nullptr;
|
||||
if (SPV_SUCCESS == spvOperandTableValueLookup(env, operandTable, type,
|
||||
candidate_bit, &entry)) {
|
||||
spvPushOperandTypes(entry->operandTypes, pattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOperandIsConcrete(spv_operand_type_t type) {
|
||||
if (spvIsIdType(type) || spvOperandIsConcreteMask(type)) {
|
||||
return true;
|
||||
}
|
||||
switch (type) {
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER:
|
||||
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
|
||||
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER:
|
||||
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_LITERAL_STRING:
|
||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODEL:
|
||||
case SPV_OPERAND_TYPE_ADDRESSING_MODEL:
|
||||
case SPV_OPERAND_TYPE_MEMORY_MODEL:
|
||||
case SPV_OPERAND_TYPE_EXECUTION_MODE:
|
||||
case SPV_OPERAND_TYPE_STORAGE_CLASS:
|
||||
case SPV_OPERAND_TYPE_DIMENSIONALITY:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE:
|
||||
case SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT:
|
||||
case SPV_OPERAND_TYPE_IMAGE_CHANNEL_ORDER:
|
||||
case SPV_OPERAND_TYPE_IMAGE_CHANNEL_DATA_TYPE:
|
||||
case SPV_OPERAND_TYPE_FP_ROUNDING_MODE:
|
||||
case SPV_OPERAND_TYPE_LINKAGE_TYPE:
|
||||
case SPV_OPERAND_TYPE_ACCESS_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE:
|
||||
case SPV_OPERAND_TYPE_DECORATION:
|
||||
case SPV_OPERAND_TYPE_BUILT_IN:
|
||||
case SPV_OPERAND_TYPE_GROUP_OPERATION:
|
||||
case SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS:
|
||||
case SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO:
|
||||
case SPV_OPERAND_TYPE_CAPABILITY:
|
||||
case SPV_OPERAND_TYPE_DEBUG_BASE_TYPE_ATTRIBUTE_ENCODING:
|
||||
case SPV_OPERAND_TYPE_DEBUG_COMPOSITE_TYPE:
|
||||
case SPV_OPERAND_TYPE_DEBUG_TYPE_QUALIFIER:
|
||||
case SPV_OPERAND_TYPE_DEBUG_OPERATION:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool spvOperandIsConcreteMask(spv_operand_type_t type) {
|
||||
switch (type) {
|
||||
case SPV_OPERAND_TYPE_IMAGE:
|
||||
case SPV_OPERAND_TYPE_FP_FAST_MATH_MODE:
|
||||
case SPV_OPERAND_TYPE_SELECTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_LOOP_CONTROL:
|
||||
case SPV_OPERAND_TYPE_FUNCTION_CONTROL:
|
||||
case SPV_OPERAND_TYPE_MEMORY_ACCESS:
|
||||
case SPV_OPERAND_TYPE_DEBUG_INFO_FLAGS:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool spvOperandIsOptional(spv_operand_type_t type) {
|
||||
return SPV_OPERAND_TYPE_FIRST_OPTIONAL_TYPE <= type &&
|
||||
type <= SPV_OPERAND_TYPE_LAST_OPTIONAL_TYPE;
|
||||
}
|
||||
|
||||
bool spvOperandIsVariable(spv_operand_type_t type) {
|
||||
return SPV_OPERAND_TYPE_FIRST_VARIABLE_TYPE <= type &&
|
||||
type <= SPV_OPERAND_TYPE_LAST_VARIABLE_TYPE;
|
||||
}
|
||||
|
||||
bool spvExpandOperandSequenceOnce(spv_operand_type_t type,
|
||||
spv_operand_pattern_t* pattern) {
|
||||
switch (type) {
|
||||
case SPV_OPERAND_TYPE_VARIABLE_ID:
|
||||
pattern->push_back(type);
|
||||
pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID);
|
||||
return true;
|
||||
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
|
||||
pattern->push_back(type);
|
||||
pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER);
|
||||
return true;
|
||||
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID:
|
||||
// Represents Zero or more (Literal number, Id) pairs,
|
||||
// where the literal number must be a scalar integer.
|
||||
pattern->push_back(type);
|
||||
pattern->push_back(SPV_OPERAND_TYPE_ID);
|
||||
pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER);
|
||||
return true;
|
||||
case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
|
||||
// Represents Zero or more (Id, Literal number) pairs.
|
||||
pattern->push_back(type);
|
||||
pattern->push_back(SPV_OPERAND_TYPE_LITERAL_INTEGER);
|
||||
pattern->push_back(SPV_OPERAND_TYPE_OPTIONAL_ID);
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
spv_operand_type_t spvTakeFirstMatchableOperand(
|
||||
spv_operand_pattern_t* pattern) {
|
||||
assert(!pattern->empty());
|
||||
spv_operand_type_t result;
|
||||
do {
|
||||
result = pattern->back();
|
||||
pattern->pop_back();
|
||||
} while (spvExpandOperandSequenceOnce(result, pattern));
|
||||
return result;
|
||||
}
|
||||
|
||||
spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
|
||||
const spv_operand_pattern_t& pattern) {
|
||||
auto it =
|
||||
std::find(pattern.crbegin(), pattern.crend(), SPV_OPERAND_TYPE_RESULT_ID);
|
||||
if (it != pattern.crend()) {
|
||||
spv_operand_pattern_t alternatePattern(it - pattern.crbegin() + 2,
|
||||
SPV_OPERAND_TYPE_OPTIONAL_CIV);
|
||||
alternatePattern[1] = SPV_OPERAND_TYPE_RESULT_ID;
|
||||
return alternatePattern;
|
||||
}
|
||||
|
||||
// No result-id found, so just expect CIVs.
|
||||
return {SPV_OPERAND_TYPE_OPTIONAL_CIV};
|
||||
}
|
||||
|
||||
bool spvIsIdType(spv_operand_type_t type) {
|
||||
switch (type) {
|
||||
case SPV_OPERAND_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_TYPE_ID:
|
||||
case SPV_OPERAND_TYPE_RESULT_ID:
|
||||
case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
|
||||
case SPV_OPERAND_TYPE_SCOPE_ID:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
|
||||
SpvOp opcode) {
|
||||
std::function<bool(unsigned index)> out;
|
||||
switch (opcode) {
|
||||
case SpvOpExecutionMode:
|
||||
case SpvOpEntryPoint:
|
||||
case SpvOpName:
|
||||
case SpvOpMemberName:
|
||||
case SpvOpSelectionMerge:
|
||||
case SpvOpDecorate:
|
||||
case SpvOpMemberDecorate:
|
||||
case SpvOpDecorateId:
|
||||
case SpvOpDecorateStringGOOGLE:
|
||||
case SpvOpMemberDecorateStringGOOGLE:
|
||||
case SpvOpTypeStruct:
|
||||
case SpvOpBranch:
|
||||
case SpvOpLoopMerge:
|
||||
out = [](unsigned) { return true; };
|
||||
break;
|
||||
case SpvOpGroupDecorate:
|
||||
case SpvOpGroupMemberDecorate:
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch:
|
||||
out = [](unsigned index) { return index != 0; };
|
||||
break;
|
||||
|
||||
case SpvOpFunctionCall:
|
||||
// The Function parameter.
|
||||
out = [](unsigned index) { return index == 2; };
|
||||
break;
|
||||
|
||||
case SpvOpPhi:
|
||||
out = [](unsigned index) { return index > 1; };
|
||||
break;
|
||||
|
||||
case SpvOpEnqueueKernel:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 8; };
|
||||
break;
|
||||
|
||||
case SpvOpGetKernelNDrangeSubGroupCount:
|
||||
case SpvOpGetKernelNDrangeMaxSubGroupSize:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 3; };
|
||||
break;
|
||||
|
||||
case SpvOpGetKernelWorkGroupSize:
|
||||
case SpvOpGetKernelPreferredWorkGroupSizeMultiple:
|
||||
// The Invoke parameter.
|
||||
out = [](unsigned index) { return index == 2; };
|
||||
break;
|
||||
case SpvOpTypeForwardPointer:
|
||||
out = [](unsigned index) { return index == 0; };
|
||||
break;
|
||||
default:
|
||||
out = [](unsigned) { return false; };
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
141
3rdparty/spirv-tools/source/operand.h
vendored
Normal file
141
3rdparty/spirv-tools/source/operand.h
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_OPERAND_H_
|
||||
#define LIBSPIRV_OPERAND_H_
|
||||
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "table.h"
|
||||
|
||||
// A sequence of operand types.
|
||||
//
|
||||
// A SPIR-V parser uses an operand pattern to describe what is expected
|
||||
// next on the input.
|
||||
//
|
||||
// As we parse an instruction in text or binary form from left to right,
|
||||
// we pop and push at the end of the pattern vector. Symbols later in the
|
||||
// pattern vector are matched against the input before symbols earlier in the
|
||||
// pattern vector are matched.
|
||||
|
||||
// Using a vector in this way reduces memory traffic, which is good for
|
||||
// performance.
|
||||
using spv_operand_pattern_t = std::vector<spv_operand_type_t>;
|
||||
|
||||
// Finds the named operand in the table. The type parameter specifies the
|
||||
// operand's group. A handle of the operand table entry for this operand will
|
||||
// be written into *entry.
|
||||
spv_result_t spvOperandTableNameLookup(spv_target_env,
|
||||
const spv_operand_table table,
|
||||
const spv_operand_type_t type,
|
||||
const char* name,
|
||||
const size_t name_length,
|
||||
spv_operand_desc* entry);
|
||||
|
||||
// Finds the operand with value in the table. The type parameter specifies the
|
||||
// operand's group. A handle of the operand table entry for this operand will
|
||||
// be written into *entry.
|
||||
spv_result_t spvOperandTableValueLookup(spv_target_env,
|
||||
const spv_operand_table table,
|
||||
const spv_operand_type_t type,
|
||||
const uint32_t value,
|
||||
spv_operand_desc* entry);
|
||||
|
||||
// Gets the name string of the non-variable operand type.
|
||||
const char* spvOperandTypeStr(spv_operand_type_t type);
|
||||
|
||||
// Returns true if the given type is concrete.
|
||||
bool spvOperandIsConcrete(spv_operand_type_t type);
|
||||
|
||||
// Returns true if the given type is concrete and also a mask.
|
||||
bool spvOperandIsConcreteMask(spv_operand_type_t type);
|
||||
|
||||
// Returns true if an operand of the given type is optional.
|
||||
bool spvOperandIsOptional(spv_operand_type_t type);
|
||||
|
||||
// Returns true if an operand type represents zero or more logical operands.
|
||||
//
|
||||
// Note that a single logical operand may still be a variable number of words.
|
||||
// For example, a literal string may be many words, but is just one logical
|
||||
// operand.
|
||||
bool spvOperandIsVariable(spv_operand_type_t type);
|
||||
|
||||
// Append a list of operand types to the end of the pattern vector.
|
||||
// The types parameter specifies the source array of types, ending with
|
||||
// SPV_OPERAND_TYPE_NONE.
|
||||
void spvPushOperandTypes(const spv_operand_type_t* types,
|
||||
spv_operand_pattern_t* pattern);
|
||||
|
||||
// Appends the operands expected after the given typed mask onto the
|
||||
// end of the given pattern.
|
||||
//
|
||||
// Each set bit in the mask represents zero or more operand types that should
|
||||
// be appended onto the pattern. Operands for a less significant bit always
|
||||
// appear after operands for a more significant bit.
|
||||
//
|
||||
// If a set bit is unknown, then we assume it has no operands.
|
||||
void spvPushOperandTypesForMask(spv_target_env,
|
||||
const spv_operand_table operand_table,
|
||||
const spv_operand_type_t mask_type,
|
||||
const uint32_t mask,
|
||||
spv_operand_pattern_t* pattern);
|
||||
|
||||
// Expands an operand type representing zero or more logical operands,
|
||||
// exactly once.
|
||||
//
|
||||
// If the given type represents potentially several logical operands,
|
||||
// then prepend the given pattern with the first expansion of the logical
|
||||
// operands, followed by original type. Otherwise, don't modify the pattern.
|
||||
//
|
||||
// For example, the SPV_OPERAND_TYPE_VARIABLE_ID represents zero or more
|
||||
// IDs. In that case we would prepend the pattern with SPV_OPERAND_TYPE_ID
|
||||
// followed by SPV_OPERAND_TYPE_VARIABLE_ID again.
|
||||
//
|
||||
// This also applies to zero or more tuples of logical operands. In that case
|
||||
// we prepend pattern with for the members of the tuple, followed by the
|
||||
// original type argument. The pattern must encode the fact that if any part
|
||||
// of the tuple is present, then all tuple members should be. So the first
|
||||
// member of the tuple must be optional, and the remaining members
|
||||
// non-optional.
|
||||
//
|
||||
// Returns true if we modified the pattern.
|
||||
bool spvExpandOperandSequenceOnce(spv_operand_type_t type,
|
||||
spv_operand_pattern_t* pattern);
|
||||
|
||||
// Expands the first element in the pattern until it is a matchable operand
|
||||
// type, then pops it off the front and returns it. The pattern must not be
|
||||
// empty.
|
||||
//
|
||||
// A matchable operand type is anything other than a zero-or-more-items
|
||||
// operand type.
|
||||
spv_operand_type_t spvTakeFirstMatchableOperand(spv_operand_pattern_t* pattern);
|
||||
|
||||
// Calculates the corresponding post-immediate alternate pattern, which allows
|
||||
// a limited set of operand types.
|
||||
spv_operand_pattern_t spvAlternatePatternFollowingImmediate(
|
||||
const spv_operand_pattern_t& pattern);
|
||||
|
||||
// Is the operand an ID?
|
||||
bool spvIsIdType(spv_operand_type_t type);
|
||||
|
||||
// Takes the opcode of an instruction and returns
|
||||
// a function object that will return true if the index
|
||||
// of the operand can be forward declared. This function will
|
||||
// used in the SSA validation stage of the pipeline
|
||||
std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
|
||||
SpvOp opcode);
|
||||
|
||||
#endif // LIBSPIRV_OPERAND_H_
|
191
3rdparty/spirv-tools/source/opt/CMakeLists.txt
vendored
Normal file
191
3rdparty/spirv-tools/source/opt/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
# Copyright (c) 2016 Google Inc.
|
||||
|
||||
# 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.
|
||||
add_library(SPIRV-Tools-opt
|
||||
aggressive_dead_code_elim_pass.h
|
||||
basic_block.h
|
||||
block_merge_pass.h
|
||||
build_module.h
|
||||
ccp_pass.h
|
||||
cfg_cleanup_pass.h
|
||||
cfg.h
|
||||
common_uniform_elim_pass.h
|
||||
compact_ids_pass.h
|
||||
composite.h
|
||||
const_folding_rules.h
|
||||
constants.h
|
||||
copy_prop_arrays.h
|
||||
dead_branch_elim_pass.h
|
||||
dead_insert_elim_pass.h
|
||||
dead_variable_elimination.h
|
||||
decoration_manager.h
|
||||
def_use_manager.h
|
||||
dominator_analysis.h
|
||||
dominator_tree.h
|
||||
eliminate_dead_constant_pass.h
|
||||
eliminate_dead_functions_pass.h
|
||||
feature_manager.h
|
||||
flatten_decoration_pass.h
|
||||
fold.h
|
||||
folding_rules.h
|
||||
fold_spec_constant_op_and_composite_pass.h
|
||||
freeze_spec_constant_value_pass.h
|
||||
function.h
|
||||
if_conversion.h
|
||||
inline_exhaustive_pass.h
|
||||
inline_opaque_pass.h
|
||||
inline_pass.h
|
||||
insert_extract_elim.h
|
||||
instruction.h
|
||||
instruction_list.h
|
||||
ir_builder.h
|
||||
ir_context.h
|
||||
ir_loader.h
|
||||
licm_pass.h
|
||||
local_access_chain_convert_pass.h
|
||||
local_redundancy_elimination.h
|
||||
local_single_block_elim_pass.h
|
||||
local_single_store_elim_pass.h
|
||||
local_ssa_elim_pass.h
|
||||
log.h
|
||||
loop_descriptor.h
|
||||
loop_peeling.h
|
||||
loop_unroller.h
|
||||
loop_utils.h
|
||||
loop_unswitch_pass.h
|
||||
make_unique.h
|
||||
mem_pass.h
|
||||
merge_return_pass.h
|
||||
module.h
|
||||
null_pass.h
|
||||
passes.h
|
||||
pass.h
|
||||
pass_manager.h
|
||||
private_to_local_pass.h
|
||||
propagator.h
|
||||
redundancy_elimination.h
|
||||
reflect.h
|
||||
remove_duplicates_pass.h
|
||||
replace_invalid_opc.h
|
||||
scalar_analysis.h
|
||||
scalar_analysis_nodes.h
|
||||
scalar_replacement_pass.h
|
||||
set_spec_constant_default_value_pass.h
|
||||
simplification_pass.h
|
||||
ssa_rewrite_pass.h
|
||||
strength_reduction_pass.h
|
||||
strip_debug_info_pass.h
|
||||
strip_reflect_info_pass.h
|
||||
tree_iterator.h
|
||||
type_manager.h
|
||||
types.h
|
||||
unify_const_pass.h
|
||||
value_number_table.h
|
||||
workaround1209.h
|
||||
|
||||
aggressive_dead_code_elim_pass.cpp
|
||||
basic_block.cpp
|
||||
block_merge_pass.cpp
|
||||
build_module.cpp
|
||||
ccp_pass.cpp
|
||||
cfg_cleanup_pass.cpp
|
||||
cfg.cpp
|
||||
common_uniform_elim_pass.cpp
|
||||
compact_ids_pass.cpp
|
||||
composite.cpp
|
||||
const_folding_rules.cpp
|
||||
constants.cpp
|
||||
copy_prop_arrays.cpp
|
||||
dead_branch_elim_pass.cpp
|
||||
dead_insert_elim_pass.cpp
|
||||
dead_variable_elimination.cpp
|
||||
decoration_manager.cpp
|
||||
def_use_manager.cpp
|
||||
dominator_analysis.cpp
|
||||
dominator_tree.cpp
|
||||
eliminate_dead_constant_pass.cpp
|
||||
eliminate_dead_functions_pass.cpp
|
||||
feature_manager.cpp
|
||||
flatten_decoration_pass.cpp
|
||||
fold.cpp
|
||||
folding_rules.cpp
|
||||
fold_spec_constant_op_and_composite_pass.cpp
|
||||
freeze_spec_constant_value_pass.cpp
|
||||
function.cpp
|
||||
if_conversion.cpp
|
||||
inline_exhaustive_pass.cpp
|
||||
inline_opaque_pass.cpp
|
||||
inline_pass.cpp
|
||||
insert_extract_elim.cpp
|
||||
instruction.cpp
|
||||
instruction_list.cpp
|
||||
ir_context.cpp
|
||||
ir_loader.cpp
|
||||
licm_pass.cpp
|
||||
local_access_chain_convert_pass.cpp
|
||||
local_redundancy_elimination.cpp
|
||||
local_single_block_elim_pass.cpp
|
||||
local_single_store_elim_pass.cpp
|
||||
local_ssa_elim_pass.cpp
|
||||
loop_descriptor.cpp
|
||||
loop_peeling.cpp
|
||||
loop_utils.cpp
|
||||
loop_unroller.cpp
|
||||
loop_unswitch_pass.cpp
|
||||
mem_pass.cpp
|
||||
merge_return_pass.cpp
|
||||
module.cpp
|
||||
optimizer.cpp
|
||||
pass.cpp
|
||||
pass_manager.cpp
|
||||
private_to_local_pass.cpp
|
||||
propagator.cpp
|
||||
redundancy_elimination.cpp
|
||||
remove_duplicates_pass.cpp
|
||||
replace_invalid_opc.cpp
|
||||
scalar_analysis.cpp
|
||||
scalar_analysis_simplification.cpp
|
||||
scalar_replacement_pass.cpp
|
||||
set_spec_constant_default_value_pass.cpp
|
||||
simplification_pass.cpp
|
||||
ssa_rewrite_pass.cpp
|
||||
strength_reduction_pass.cpp
|
||||
strip_debug_info_pass.cpp
|
||||
strip_reflect_info_pass.cpp
|
||||
type_manager.cpp
|
||||
types.cpp
|
||||
unify_const_pass.cpp
|
||||
value_number_table.cpp
|
||||
workaround1209.cpp
|
||||
)
|
||||
|
||||
spvtools_default_compile_options(SPIRV-Tools-opt)
|
||||
target_include_directories(SPIRV-Tools-opt
|
||||
PUBLIC ${spirv-tools_SOURCE_DIR}/include
|
||||
PUBLIC ${SPIRV_HEADER_INCLUDE_DIR}
|
||||
PRIVATE ${spirv-tools_BINARY_DIR}
|
||||
)
|
||||
# We need the assembling and disassembling functionalities in the main library.
|
||||
target_link_libraries(SPIRV-Tools-opt
|
||||
PUBLIC ${SPIRV_TOOLS})
|
||||
|
||||
set_property(TARGET SPIRV-Tools-opt PROPERTY FOLDER "SPIRV-Tools libraries")
|
||||
spvtools_check_symbol_exports(SPIRV-Tools-opt)
|
||||
|
||||
if(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||
install(TARGETS SPIRV-Tools-opt
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif(ENABLE_SPIRV_TOOLS_INSTALL)
|
||||
|
721
3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp
vendored
Normal file
721
3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp
vendored
Normal file
@ -0,0 +1,721 @@
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
// Copyright (c) 2017 Valve Corporation
|
||||
// Copyright (c) 2017 LunarG Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "aggressive_dead_code_elim_pass.h"
|
||||
|
||||
#include "cfa.h"
|
||||
#include "iterator.h"
|
||||
#include "latest_version_glsl_std_450_header.h"
|
||||
#include "reflect.h"
|
||||
|
||||
#include <stack>
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kTypePointerStorageClassInIdx = 0;
|
||||
const uint32_t kEntryPointFunctionIdInIdx = 1;
|
||||
const uint32_t kSelectionMergeMergeBlockIdInIdx = 0;
|
||||
const uint32_t kLoopMergeMergeBlockIdInIdx = 0;
|
||||
const uint32_t kLoopMergeContinueBlockIdInIdx = 1;
|
||||
|
||||
// Sorting functor to present annotation instructions in an easy-to-process
|
||||
// order. The functor orders by opcode first and falls back on unique id
|
||||
// ordering if both instructions have the same opcode.
|
||||
//
|
||||
// Desired priority:
|
||||
// SpvOpGroupDecorate
|
||||
// SpvOpGroupMemberDecorate
|
||||
// SpvOpDecorate
|
||||
// SpvOpMemberDecorate
|
||||
// SpvOpDecorateId
|
||||
// SpvOpDecorationGroup
|
||||
struct DecorationLess {
|
||||
bool operator()(const ir::Instruction* lhs,
|
||||
const ir::Instruction* rhs) const {
|
||||
assert(lhs && rhs);
|
||||
SpvOp lhsOp = lhs->opcode();
|
||||
SpvOp rhsOp = rhs->opcode();
|
||||
if (lhsOp != rhsOp) {
|
||||
// OpGroupDecorate and OpGroupMember decorate are highest priority to
|
||||
// eliminate dead targets early and simplify subsequent checks.
|
||||
if (lhsOp == SpvOpGroupDecorate && rhsOp != SpvOpGroupDecorate)
|
||||
return true;
|
||||
if (rhsOp == SpvOpGroupDecorate && lhsOp != SpvOpGroupDecorate)
|
||||
return false;
|
||||
if (lhsOp == SpvOpGroupMemberDecorate &&
|
||||
rhsOp != SpvOpGroupMemberDecorate)
|
||||
return true;
|
||||
if (rhsOp == SpvOpGroupMemberDecorate &&
|
||||
lhsOp != SpvOpGroupMemberDecorate)
|
||||
return false;
|
||||
if (lhsOp == SpvOpDecorate && rhsOp != SpvOpDecorate) return true;
|
||||
if (rhsOp == SpvOpDecorate && lhsOp != SpvOpDecorate) return false;
|
||||
if (lhsOp == SpvOpMemberDecorate && rhsOp != SpvOpMemberDecorate)
|
||||
return true;
|
||||
if (rhsOp == SpvOpMemberDecorate && lhsOp != SpvOpMemberDecorate)
|
||||
return false;
|
||||
if (lhsOp == SpvOpDecorateId && rhsOp != SpvOpDecorateId) return true;
|
||||
if (rhsOp == SpvOpDecorateId && lhsOp != SpvOpDecorateId) return false;
|
||||
// OpDecorationGroup is lowest priority to ensure use/def chains remain
|
||||
// usable for instructions that target this group.
|
||||
if (lhsOp == SpvOpDecorationGroup && rhsOp != SpvOpDecorationGroup)
|
||||
return true;
|
||||
if (rhsOp == SpvOpDecorationGroup && lhsOp != SpvOpDecorationGroup)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Fall back to maintain total ordering (compare unique ids).
|
||||
return *lhs < *rhs;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool AggressiveDCEPass::IsVarOfStorage(uint32_t varId, uint32_t storageClass) {
|
||||
if (varId == 0) return false;
|
||||
const ir::Instruction* varInst = get_def_use_mgr()->GetDef(varId);
|
||||
const SpvOp op = varInst->opcode();
|
||||
if (op != SpvOpVariable) return false;
|
||||
const uint32_t varTypeId = varInst->type_id();
|
||||
const ir::Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
|
||||
if (varTypeInst->opcode() != SpvOpTypePointer) return false;
|
||||
return varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) ==
|
||||
storageClass;
|
||||
}
|
||||
|
||||
bool AggressiveDCEPass::IsLocalVar(uint32_t varId) {
|
||||
return IsVarOfStorage(varId, SpvStorageClassFunction) ||
|
||||
(IsVarOfStorage(varId, SpvStorageClassPrivate) && private_like_local_);
|
||||
}
|
||||
|
||||
void AggressiveDCEPass::AddStores(uint32_t ptrId) {
|
||||
get_def_use_mgr()->ForEachUser(ptrId, [this](ir::Instruction* user) {
|
||||
switch (user->opcode()) {
|
||||
case SpvOpAccessChain:
|
||||
case SpvOpInBoundsAccessChain:
|
||||
case SpvOpCopyObject:
|
||||
this->AddStores(user->result_id());
|
||||
break;
|
||||
case SpvOpLoad:
|
||||
break;
|
||||
// If default, assume it stores e.g. frexp, modf, function call
|
||||
case SpvOpStore:
|
||||
default:
|
||||
AddToWorklist(user);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool AggressiveDCEPass::AllExtensionsSupported() const {
|
||||
// If any extension not in whitelist, return false
|
||||
for (auto& ei : get_module()->extensions()) {
|
||||
const char* extName =
|
||||
reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
|
||||
if (extensions_whitelist_.find(extName) == extensions_whitelist_.end())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AggressiveDCEPass::IsDead(ir::Instruction* inst) {
|
||||
if (IsLive(inst)) return false;
|
||||
if (inst->IsBranch() && !IsStructuredHeader(context()->get_instr_block(inst),
|
||||
nullptr, nullptr, nullptr))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AggressiveDCEPass::IsTargetDead(ir::Instruction* inst) {
|
||||
const uint32_t tId = inst->GetSingleWordInOperand(0);
|
||||
ir::Instruction* tInst = get_def_use_mgr()->GetDef(tId);
|
||||
if (ir::IsAnnotationInst(tInst->opcode())) {
|
||||
// This must be a decoration group. We go through annotations in a specific
|
||||
// order. So if this is not used by any group or group member decorates, it
|
||||
// is dead.
|
||||
assert(tInst->opcode() == SpvOpDecorationGroup);
|
||||
bool dead = true;
|
||||
get_def_use_mgr()->ForEachUser(tInst, [&dead](ir::Instruction* user) {
|
||||
if (user->opcode() == SpvOpGroupDecorate ||
|
||||
user->opcode() == SpvOpGroupMemberDecorate)
|
||||
dead = false;
|
||||
});
|
||||
return dead;
|
||||
}
|
||||
return IsDead(tInst);
|
||||
}
|
||||
|
||||
void AggressiveDCEPass::ProcessLoad(uint32_t varId) {
|
||||
// Only process locals
|
||||
if (!IsLocalVar(varId)) return;
|
||||
// Return if already processed
|
||||
if (live_local_vars_.find(varId) != live_local_vars_.end()) return;
|
||||
// Mark all stores to varId as live
|
||||
AddStores(varId);
|
||||
// Cache varId as processed
|
||||
live_local_vars_.insert(varId);
|
||||
}
|
||||
|
||||
bool AggressiveDCEPass::IsStructuredHeader(ir::BasicBlock* bp,
|
||||
ir::Instruction** mergeInst,
|
||||
ir::Instruction** branchInst,
|
||||
uint32_t* mergeBlockId) {
|
||||
if (!bp) return false;
|
||||
ir::Instruction* mi = bp->GetMergeInst();
|
||||
if (mi == nullptr) return false;
|
||||
ir::Instruction* bri = &*bp->tail();
|
||||
if (branchInst != nullptr) *branchInst = bri;
|
||||
if (mergeInst != nullptr) *mergeInst = mi;
|
||||
if (mergeBlockId != nullptr) *mergeBlockId = mi->GetSingleWordInOperand(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AggressiveDCEPass::ComputeBlock2HeaderMaps(
|
||||
std::list<ir::BasicBlock*>& structuredOrder) {
|
||||
block2headerBranch_.clear();
|
||||
branch2merge_.clear();
|
||||
structured_order_index_.clear();
|
||||
std::stack<ir::Instruction*> currentHeaderBranch;
|
||||
currentHeaderBranch.push(nullptr);
|
||||
uint32_t currentMergeBlockId = 0;
|
||||
uint32_t index = 0;
|
||||
for (auto bi = structuredOrder.begin(); bi != structuredOrder.end();
|
||||
++bi, ++index) {
|
||||
structured_order_index_[*bi] = index;
|
||||
// If this block is the merge block of the current control construct,
|
||||
// we are leaving the current construct so we must update state
|
||||
if ((*bi)->id() == currentMergeBlockId) {
|
||||
currentHeaderBranch.pop();
|
||||
ir::Instruction* chb = currentHeaderBranch.top();
|
||||
if (chb != nullptr)
|
||||
currentMergeBlockId = branch2merge_[chb]->GetSingleWordInOperand(0);
|
||||
}
|
||||
ir::Instruction* mergeInst;
|
||||
ir::Instruction* branchInst;
|
||||
uint32_t mergeBlockId;
|
||||
bool is_header =
|
||||
IsStructuredHeader(*bi, &mergeInst, &branchInst, &mergeBlockId);
|
||||
// If this is a loop header, update state first so the block will map to
|
||||
// the loop.
|
||||
if (is_header && mergeInst->opcode() == SpvOpLoopMerge) {
|
||||
currentHeaderBranch.push(branchInst);
|
||||
branch2merge_[branchInst] = mergeInst;
|
||||
currentMergeBlockId = mergeBlockId;
|
||||
}
|
||||
// Map the block to the current construct.
|
||||
block2headerBranch_[*bi] = currentHeaderBranch.top();
|
||||
// If this is an if header, update state so following blocks map to the if.
|
||||
if (is_header && mergeInst->opcode() == SpvOpSelectionMerge) {
|
||||
currentHeaderBranch.push(branchInst);
|
||||
branch2merge_[branchInst] = mergeInst;
|
||||
currentMergeBlockId = mergeBlockId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AggressiveDCEPass::AddBranch(uint32_t labelId, ir::BasicBlock* bp) {
|
||||
std::unique_ptr<ir::Instruction> newBranch(new ir::Instruction(
|
||||
context(), SpvOpBranch, 0, 0,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {labelId}}}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*newBranch);
|
||||
bp->AddInstruction(std::move(newBranch));
|
||||
}
|
||||
|
||||
void AggressiveDCEPass::AddBreaksAndContinuesToWorklist(
|
||||
ir::Instruction* loopMerge) {
|
||||
ir::BasicBlock* header = context()->get_instr_block(loopMerge);
|
||||
uint32_t headerIndex = structured_order_index_[header];
|
||||
const uint32_t mergeId =
|
||||
loopMerge->GetSingleWordInOperand(kLoopMergeMergeBlockIdInIdx);
|
||||
ir::BasicBlock* merge = context()->get_instr_block(mergeId);
|
||||
uint32_t mergeIndex = structured_order_index_[merge];
|
||||
get_def_use_mgr()->ForEachUser(
|
||||
mergeId, [headerIndex, mergeIndex, this](ir::Instruction* user) {
|
||||
if (!user->IsBranch()) return;
|
||||
ir::BasicBlock* block = context()->get_instr_block(user);
|
||||
uint32_t index = structured_order_index_[block];
|
||||
if (headerIndex < index && index < mergeIndex) {
|
||||
// This is a break from the loop.
|
||||
AddToWorklist(user);
|
||||
// Add branch's merge if there is one.
|
||||
ir::Instruction* userMerge = branch2merge_[user];
|
||||
if (userMerge != nullptr) AddToWorklist(userMerge);
|
||||
}
|
||||
});
|
||||
const uint32_t contId =
|
||||
loopMerge->GetSingleWordInOperand(kLoopMergeContinueBlockIdInIdx);
|
||||
get_def_use_mgr()->ForEachUser(contId, [&contId,
|
||||
this](ir::Instruction* user) {
|
||||
SpvOp op = user->opcode();
|
||||
if (op == SpvOpBranchConditional || op == SpvOpSwitch) {
|
||||
// A conditional branch or switch can only be a continue if it does not
|
||||
// have a merge instruction or its merge block is not the continue block.
|
||||
ir::Instruction* hdrMerge = branch2merge_[user];
|
||||
if (hdrMerge != nullptr && hdrMerge->opcode() == SpvOpSelectionMerge) {
|
||||
uint32_t hdrMergeId =
|
||||
hdrMerge->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
|
||||
if (hdrMergeId == contId) return;
|
||||
// Need to mark merge instruction too
|
||||
AddToWorklist(hdrMerge);
|
||||
}
|
||||
} else if (op == SpvOpBranch) {
|
||||
// An unconditional branch can only be a continue if it is not
|
||||
// branching to its own merge block.
|
||||
ir::BasicBlock* blk = context()->get_instr_block(user);
|
||||
ir::Instruction* hdrBranch = block2headerBranch_[blk];
|
||||
if (hdrBranch == nullptr) return;
|
||||
ir::Instruction* hdrMerge = branch2merge_[hdrBranch];
|
||||
if (hdrMerge->opcode() == SpvOpLoopMerge) return;
|
||||
uint32_t hdrMergeId =
|
||||
hdrMerge->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
|
||||
if (contId == hdrMergeId) return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
AddToWorklist(user);
|
||||
});
|
||||
}
|
||||
|
||||
bool AggressiveDCEPass::AggressiveDCE(ir::Function* func) {
|
||||
// Mark function parameters as live.
|
||||
AddToWorklist(&func->DefInst());
|
||||
func->ForEachParam(
|
||||
[this](const ir::Instruction* param) {
|
||||
AddToWorklist(const_cast<ir::Instruction*>(param));
|
||||
},
|
||||
false);
|
||||
|
||||
// Compute map from block to controlling conditional branch
|
||||
std::list<ir::BasicBlock*> structuredOrder;
|
||||
cfg()->ComputeStructuredOrder(func, &*func->begin(), &structuredOrder);
|
||||
ComputeBlock2HeaderMaps(structuredOrder);
|
||||
bool modified = false;
|
||||
// Add instructions with external side effects to worklist. Also add branches
|
||||
// EXCEPT those immediately contained in an "if" selection construct or a loop
|
||||
// or continue construct.
|
||||
// TODO(greg-lunarg): Handle Frexp, Modf more optimally
|
||||
call_in_func_ = false;
|
||||
func_is_entry_point_ = false;
|
||||
private_stores_.clear();
|
||||
// Stacks to keep track of when we are inside an if- or loop-construct.
|
||||
// When immediately inside an if- or loop-construct, we do not initially
|
||||
// mark branches live. All other branches must be marked live.
|
||||
std::stack<bool> assume_branches_live;
|
||||
std::stack<uint32_t> currentMergeBlockId;
|
||||
// Push sentinel values on stack for when outside of any control flow.
|
||||
assume_branches_live.push(true);
|
||||
currentMergeBlockId.push(0);
|
||||
for (auto bi = structuredOrder.begin(); bi != structuredOrder.end(); ++bi) {
|
||||
// If exiting if or loop, update stacks
|
||||
if ((*bi)->id() == currentMergeBlockId.top()) {
|
||||
assume_branches_live.pop();
|
||||
currentMergeBlockId.pop();
|
||||
}
|
||||
for (auto ii = (*bi)->begin(); ii != (*bi)->end(); ++ii) {
|
||||
SpvOp op = ii->opcode();
|
||||
switch (op) {
|
||||
case SpvOpStore: {
|
||||
uint32_t varId;
|
||||
(void)GetPtr(&*ii, &varId);
|
||||
// Mark stores as live if their variable is not function scope
|
||||
// and is not private scope. Remember private stores for possible
|
||||
// later inclusion
|
||||
if (IsVarOfStorage(varId, SpvStorageClassPrivate))
|
||||
private_stores_.push_back(&*ii);
|
||||
else if (!IsVarOfStorage(varId, SpvStorageClassFunction))
|
||||
AddToWorklist(&*ii);
|
||||
} break;
|
||||
case SpvOpLoopMerge: {
|
||||
assume_branches_live.push(false);
|
||||
currentMergeBlockId.push(
|
||||
ii->GetSingleWordInOperand(kLoopMergeMergeBlockIdInIdx));
|
||||
} break;
|
||||
case SpvOpSelectionMerge: {
|
||||
assume_branches_live.push(false);
|
||||
currentMergeBlockId.push(
|
||||
ii->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx));
|
||||
} break;
|
||||
case SpvOpSwitch:
|
||||
case SpvOpBranch:
|
||||
case SpvOpBranchConditional: {
|
||||
if (assume_branches_live.top()) AddToWorklist(&*ii);
|
||||
} break;
|
||||
default: {
|
||||
// Function calls, atomics, function params, function returns, etc.
|
||||
// TODO(greg-lunarg): function calls live only if write to non-local
|
||||
if (!context()->IsCombinatorInstruction(&*ii)) {
|
||||
AddToWorklist(&*ii);
|
||||
}
|
||||
// Remember function calls
|
||||
if (op == SpvOpFunctionCall) call_in_func_ = true;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// See if current function is an entry point
|
||||
for (auto& ei : get_module()->entry_points()) {
|
||||
if (ei.GetSingleWordInOperand(kEntryPointFunctionIdInIdx) ==
|
||||
func->result_id()) {
|
||||
func_is_entry_point_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If the current function is an entry point and has no function calls,
|
||||
// we can optimize private variables as locals
|
||||
private_like_local_ = func_is_entry_point_ && !call_in_func_;
|
||||
// If privates are not like local, add their stores to worklist
|
||||
if (!private_like_local_)
|
||||
for (auto& ps : private_stores_) AddToWorklist(ps);
|
||||
// Perform closure on live instruction set.
|
||||
while (!worklist_.empty()) {
|
||||
ir::Instruction* liveInst = worklist_.front();
|
||||
// Add all operand instructions if not already live
|
||||
liveInst->ForEachInId([&liveInst, this](const uint32_t* iid) {
|
||||
ir::Instruction* inInst = get_def_use_mgr()->GetDef(*iid);
|
||||
// Do not add label if an operand of a branch. This is not needed
|
||||
// as part of live code discovery and can create false live code,
|
||||
// for example, the branch to a header of a loop.
|
||||
if (inInst->opcode() == SpvOpLabel && liveInst->IsBranch()) return;
|
||||
AddToWorklist(inInst);
|
||||
});
|
||||
if (liveInst->type_id() != 0) {
|
||||
AddToWorklist(get_def_use_mgr()->GetDef(liveInst->type_id()));
|
||||
}
|
||||
// If in a structured if or loop construct, add the controlling
|
||||
// conditional branch and its merge. Any containing control construct
|
||||
// is marked live when the merge and branch are processed out of the
|
||||
// worklist.
|
||||
ir::BasicBlock* blk = context()->get_instr_block(liveInst);
|
||||
ir::Instruction* branchInst = block2headerBranch_[blk];
|
||||
if (branchInst != nullptr) {
|
||||
AddToWorklist(branchInst);
|
||||
ir::Instruction* mergeInst = branch2merge_[branchInst];
|
||||
AddToWorklist(mergeInst);
|
||||
// If in a loop, mark all its break and continue instructions live
|
||||
if (mergeInst->opcode() == SpvOpLoopMerge)
|
||||
AddBreaksAndContinuesToWorklist(mergeInst);
|
||||
}
|
||||
// If local load, add all variable's stores if variable not already live
|
||||
if (liveInst->opcode() == SpvOpLoad) {
|
||||
uint32_t varId;
|
||||
(void)GetPtr(liveInst, &varId);
|
||||
if (varId != 0) {
|
||||
ProcessLoad(varId);
|
||||
}
|
||||
}
|
||||
// If function call, treat as if it loads from all pointer arguments
|
||||
else if (liveInst->opcode() == SpvOpFunctionCall) {
|
||||
liveInst->ForEachInId([this](const uint32_t* iid) {
|
||||
// Skip non-ptr args
|
||||
if (!IsPtr(*iid)) return;
|
||||
uint32_t varId;
|
||||
(void)GetPtr(*iid, &varId);
|
||||
ProcessLoad(varId);
|
||||
});
|
||||
}
|
||||
// If function parameter, treat as if it's result id is loaded from
|
||||
else if (liveInst->opcode() == SpvOpFunctionParameter) {
|
||||
ProcessLoad(liveInst->result_id());
|
||||
}
|
||||
// We treat an OpImageTexelPointer as a load of the pointer, and
|
||||
// that value is manipulated to get the result.
|
||||
else if (liveInst->opcode() == SpvOpImageTexelPointer) {
|
||||
uint32_t varId;
|
||||
(void)GetPtr(liveInst, &varId);
|
||||
if (varId != 0) {
|
||||
ProcessLoad(varId);
|
||||
}
|
||||
}
|
||||
worklist_.pop();
|
||||
}
|
||||
|
||||
// Kill dead instructions and remember dead blocks
|
||||
for (auto bi = structuredOrder.begin(); bi != structuredOrder.end();) {
|
||||
uint32_t mergeBlockId = 0;
|
||||
(*bi)->ForEachInst([this, &modified, &mergeBlockId](ir::Instruction* inst) {
|
||||
if (!IsDead(inst)) return;
|
||||
if (inst->opcode() == SpvOpLabel) return;
|
||||
// If dead instruction is selection merge, remember merge block
|
||||
// for new branch at end of block
|
||||
if (inst->opcode() == SpvOpSelectionMerge ||
|
||||
inst->opcode() == SpvOpLoopMerge)
|
||||
mergeBlockId = inst->GetSingleWordInOperand(0);
|
||||
to_kill_.push_back(inst);
|
||||
modified = true;
|
||||
});
|
||||
// If a structured if or loop was deleted, add a branch to its merge
|
||||
// block, and traverse to the merge block and continue processing there.
|
||||
// We know the block still exists because the label is not deleted.
|
||||
if (mergeBlockId != 0) {
|
||||
AddBranch(mergeBlockId, *bi);
|
||||
for (++bi; (*bi)->id() != mergeBlockId; ++bi) {
|
||||
}
|
||||
} else {
|
||||
++bi;
|
||||
}
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
void AggressiveDCEPass::Initialize(ir::IRContext* c) {
|
||||
InitializeProcessing(c);
|
||||
|
||||
// Clear collections
|
||||
worklist_ = std::queue<ir::Instruction*>{};
|
||||
live_insts_.clear();
|
||||
live_local_vars_.clear();
|
||||
|
||||
// Initialize extensions whitelist
|
||||
InitExtensions();
|
||||
}
|
||||
|
||||
void AggressiveDCEPass::InitializeModuleScopeLiveInstructions() {
|
||||
// Keep all execution modes.
|
||||
for (auto& exec : get_module()->execution_modes()) {
|
||||
AddToWorklist(&exec);
|
||||
}
|
||||
// Keep all entry points.
|
||||
for (auto& entry : get_module()->entry_points()) {
|
||||
AddToWorklist(&entry);
|
||||
}
|
||||
// Keep workgroup size.
|
||||
for (auto& anno : get_module()->annotations()) {
|
||||
if (anno.opcode() == SpvOpDecorate) {
|
||||
if (anno.GetSingleWordInOperand(1u) == SpvDecorationBuiltIn &&
|
||||
anno.GetSingleWordInOperand(2u) == SpvBuiltInWorkgroupSize) {
|
||||
AddToWorklist(&anno);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pass::Status AggressiveDCEPass::ProcessImpl() {
|
||||
// Current functionality assumes shader capability
|
||||
// TODO(greg-lunarg): Handle additional capabilities
|
||||
if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
|
||||
return Status::SuccessWithoutChange;
|
||||
// Current functionality assumes relaxed logical addressing (see
|
||||
// instruction.h)
|
||||
// TODO(greg-lunarg): Handle non-logical addressing
|
||||
if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
|
||||
return Status::SuccessWithoutChange;
|
||||
// If any extensions in the module are not explicitly supported,
|
||||
// return unmodified.
|
||||
if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
|
||||
|
||||
// Eliminate Dead functions.
|
||||
bool modified = EliminateDeadFunctions();
|
||||
|
||||
InitializeModuleScopeLiveInstructions();
|
||||
|
||||
// Process all entry point functions.
|
||||
ProcessFunction pfn = [this](ir::Function* fp) { return AggressiveDCE(fp); };
|
||||
modified |= ProcessEntryPointCallTree(pfn, get_module());
|
||||
|
||||
// Process module-level instructions. Now that all live instructions have
|
||||
// been marked, it is safe to remove dead global values.
|
||||
modified |= ProcessGlobalValues();
|
||||
|
||||
// Kill all dead instructions.
|
||||
for (auto inst : to_kill_) {
|
||||
context()->KillInst(inst);
|
||||
}
|
||||
|
||||
// Cleanup all CFG including all unreachable blocks.
|
||||
ProcessFunction cleanup = [this](ir::Function* f) { return CFGCleanup(f); };
|
||||
modified |= ProcessEntryPointCallTree(cleanup, get_module());
|
||||
|
||||
return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
bool AggressiveDCEPass::EliminateDeadFunctions() {
|
||||
// Identify live functions first. Those that are not live
|
||||
// are dead. ADCE is disabled for non-shaders so we do not check for exported
|
||||
// functions here.
|
||||
std::unordered_set<const ir::Function*> live_function_set;
|
||||
ProcessFunction mark_live = [&live_function_set](ir::Function* fp) {
|
||||
live_function_set.insert(fp);
|
||||
return false;
|
||||
};
|
||||
ProcessEntryPointCallTree(mark_live, get_module());
|
||||
|
||||
bool modified = false;
|
||||
for (auto funcIter = get_module()->begin();
|
||||
funcIter != get_module()->end();) {
|
||||
if (live_function_set.count(&*funcIter) == 0) {
|
||||
modified = true;
|
||||
EliminateFunction(&*funcIter);
|
||||
funcIter = funcIter.Erase();
|
||||
} else {
|
||||
++funcIter;
|
||||
}
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
void AggressiveDCEPass::EliminateFunction(ir::Function* func) {
|
||||
// Remove all of the instruction in the function body
|
||||
func->ForEachInst(
|
||||
[this](ir::Instruction* inst) { context()->KillInst(inst); }, true);
|
||||
}
|
||||
|
||||
bool AggressiveDCEPass::ProcessGlobalValues() {
|
||||
// Remove debug and annotation statements referencing dead instructions.
|
||||
// This must be done before killing the instructions, otherwise there are
|
||||
// dead objects in the def/use database.
|
||||
bool modified = false;
|
||||
ir::Instruction* instruction = &*get_module()->debug2_begin();
|
||||
while (instruction) {
|
||||
if (instruction->opcode() != SpvOpName) {
|
||||
instruction = instruction->NextNode();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IsTargetDead(instruction)) {
|
||||
instruction = context()->KillInst(instruction);
|
||||
modified = true;
|
||||
} else {
|
||||
instruction = instruction->NextNode();
|
||||
}
|
||||
}
|
||||
|
||||
// This code removes all unnecessary decorations safely (see #1174). It also
|
||||
// does so in a more efficient manner than deleting them only as the targets
|
||||
// are deleted.
|
||||
std::vector<ir::Instruction*> annotations;
|
||||
for (auto& inst : get_module()->annotations()) annotations.push_back(&inst);
|
||||
std::sort(annotations.begin(), annotations.end(), DecorationLess());
|
||||
for (auto annotation : annotations) {
|
||||
switch (annotation->opcode()) {
|
||||
case SpvOpDecorate:
|
||||
case SpvOpMemberDecorate:
|
||||
case SpvOpDecorateId:
|
||||
if (IsTargetDead(annotation)) context()->KillInst(annotation);
|
||||
break;
|
||||
case SpvOpGroupDecorate: {
|
||||
// Go through the targets of this group decorate. Remove each dead
|
||||
// target. If all targets are dead, remove this decoration.
|
||||
bool dead = true;
|
||||
for (uint32_t i = 1; i < annotation->NumOperands();) {
|
||||
ir::Instruction* opInst =
|
||||
get_def_use_mgr()->GetDef(annotation->GetSingleWordOperand(i));
|
||||
if (IsDead(opInst)) {
|
||||
// Don't increment |i|.
|
||||
annotation->RemoveOperand(i);
|
||||
} else {
|
||||
i++;
|
||||
dead = false;
|
||||
}
|
||||
}
|
||||
if (dead) context()->KillInst(annotation);
|
||||
break;
|
||||
}
|
||||
case SpvOpGroupMemberDecorate: {
|
||||
// Go through the targets of this group member decorate. Remove each
|
||||
// dead target (and member index). If all targets are dead, remove this
|
||||
// decoration.
|
||||
bool dead = true;
|
||||
for (uint32_t i = 1; i < annotation->NumOperands();) {
|
||||
ir::Instruction* opInst =
|
||||
get_def_use_mgr()->GetDef(annotation->GetSingleWordOperand(i));
|
||||
if (IsDead(opInst)) {
|
||||
// Don't increment |i|.
|
||||
annotation->RemoveOperand(i + 1);
|
||||
annotation->RemoveOperand(i);
|
||||
} else {
|
||||
i += 2;
|
||||
dead = false;
|
||||
}
|
||||
}
|
||||
if (dead) context()->KillInst(annotation);
|
||||
break;
|
||||
}
|
||||
case SpvOpDecorationGroup:
|
||||
// By the time we hit decoration groups we've checked everything that
|
||||
// can target them. So if they have no uses they must be dead.
|
||||
if (get_def_use_mgr()->NumUsers(annotation) == 0)
|
||||
context()->KillInst(annotation);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Since ADCE is disabled for non-shaders, we don't check for export linkage
|
||||
// attributes here.
|
||||
for (auto& val : get_module()->types_values()) {
|
||||
if (IsDead(&val)) {
|
||||
to_kill_.push_back(&val);
|
||||
}
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
AggressiveDCEPass::AggressiveDCEPass() {}
|
||||
|
||||
Pass::Status AggressiveDCEPass::Process(ir::IRContext* c) {
|
||||
Initialize(c);
|
||||
return ProcessImpl();
|
||||
}
|
||||
|
||||
void AggressiveDCEPass::InitExtensions() {
|
||||
extensions_whitelist_.clear();
|
||||
extensions_whitelist_.insert({
|
||||
"SPV_AMD_shader_explicit_vertex_parameter",
|
||||
"SPV_AMD_shader_trinary_minmax",
|
||||
"SPV_AMD_gcn_shader",
|
||||
"SPV_KHR_shader_ballot",
|
||||
"SPV_AMD_shader_ballot",
|
||||
"SPV_AMD_gpu_shader_half_float",
|
||||
"SPV_KHR_shader_draw_parameters",
|
||||
"SPV_KHR_subgroup_vote",
|
||||
"SPV_KHR_16bit_storage",
|
||||
"SPV_KHR_device_group",
|
||||
"SPV_KHR_multiview",
|
||||
"SPV_NVX_multiview_per_view_attributes",
|
||||
"SPV_NV_viewport_array2",
|
||||
"SPV_NV_stereo_view_rendering",
|
||||
"SPV_NV_sample_mask_override_coverage",
|
||||
"SPV_NV_geometry_shader_passthrough",
|
||||
"SPV_AMD_texture_gather_bias_lod",
|
||||
"SPV_KHR_storage_buffer_storage_class",
|
||||
// SPV_KHR_variable_pointers
|
||||
// Currently do not support extended pointer expressions
|
||||
"SPV_AMD_gpu_shader_int16",
|
||||
"SPV_KHR_post_depth_coverage",
|
||||
"SPV_KHR_shader_atomic_counter_ops",
|
||||
"SPV_EXT_shader_stencil_export",
|
||||
"SPV_EXT_shader_viewport_index_layer",
|
||||
"SPV_AMD_shader_image_load_store_lod",
|
||||
"SPV_AMD_shader_fragment_mask",
|
||||
"SPV_EXT_fragment_fully_covered",
|
||||
"SPV_AMD_gpu_shader_half_float_fetch",
|
||||
"SPV_GOOGLE_decorate_string",
|
||||
"SPV_GOOGLE_hlsl_functionality1",
|
||||
"SPV_NV_shader_subgroup_partitioned",
|
||||
"SPV_EXT_descriptor_indexing",
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
187
3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.h
vendored
Normal file
187
3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.h
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
// Copyright (c) 2017 Valve Corporation
|
||||
// Copyright (c) 2017 LunarG Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_AGGRESSIVE_DCE_PASS_H_
|
||||
#define LIBSPIRV_OPT_AGGRESSIVE_DCE_PASS_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
#include "basic_block.h"
|
||||
#include "def_use_manager.h"
|
||||
#include "mem_pass.h"
|
||||
#include "module.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
// See optimizer.hpp for documentation.
|
||||
class AggressiveDCEPass : public MemPass {
|
||||
using cbb_ptr = const ir::BasicBlock*;
|
||||
|
||||
public:
|
||||
using GetBlocksFunction =
|
||||
std::function<std::vector<ir::BasicBlock*>*(const ir::BasicBlock*)>;
|
||||
|
||||
AggressiveDCEPass();
|
||||
const char* name() const override { return "eliminate-dead-code-aggressive"; }
|
||||
Status Process(ir::IRContext* c) override;
|
||||
|
||||
ir::IRContext::Analysis GetPreservedAnalyses() override {
|
||||
return ir::IRContext::kAnalysisDefUse;
|
||||
}
|
||||
|
||||
private:
|
||||
// Return true if |varId| is a variable of |storageClass|. |varId| must either
|
||||
// be 0 or the result of an instruction.
|
||||
bool IsVarOfStorage(uint32_t varId, uint32_t storageClass);
|
||||
|
||||
// Return true if |varId| is variable of function storage class or is
|
||||
// private variable and privates can be optimized like locals (see
|
||||
// privates_like_local_).
|
||||
bool IsLocalVar(uint32_t varId);
|
||||
|
||||
// Return true if |inst| is marked live.
|
||||
bool IsLive(const ir::Instruction* inst) const {
|
||||
return live_insts_.find(inst) != live_insts_.end();
|
||||
}
|
||||
|
||||
// Returns true if |inst| is dead.
|
||||
bool IsDead(ir::Instruction* inst);
|
||||
|
||||
// Adds entry points, execution modes and workgroup size decorations to the
|
||||
// worklist for processing with the first function.
|
||||
void InitializeModuleScopeLiveInstructions();
|
||||
|
||||
// Add |inst| to worklist_ and live_insts_.
|
||||
void AddToWorklist(ir::Instruction* inst) {
|
||||
if (live_insts_.insert(inst).second) worklist_.push(inst);
|
||||
}
|
||||
|
||||
// Add all store instruction which use |ptrId|, directly or indirectly,
|
||||
// to the live instruction worklist.
|
||||
void AddStores(uint32_t ptrId);
|
||||
|
||||
// Initialize extensions whitelist
|
||||
void InitExtensions();
|
||||
|
||||
// Return true if all extensions in this module are supported by this pass.
|
||||
bool AllExtensionsSupported() const;
|
||||
|
||||
// Returns true if the target of |inst| is dead. An instruction is dead if
|
||||
// its result id is used in decoration or debug instructions only. |inst| is
|
||||
// assumed to be OpName, OpMemberName or an annotation instruction.
|
||||
bool IsTargetDead(ir::Instruction* inst);
|
||||
|
||||
// If |varId| is local, mark all stores of varId as live.
|
||||
void ProcessLoad(uint32_t varId);
|
||||
|
||||
// If |bp| is structured header block, returns true and sets |mergeInst| to
|
||||
// the merge instruction, |branchInst| to the branch and |mergeBlockId| to the
|
||||
// merge block if they are not nullptr. Any of |mergeInst|, |branchInst| or
|
||||
// |mergeBlockId| may be a null pointer. Returns false if |bp| is a null
|
||||
// pointer.
|
||||
bool IsStructuredHeader(ir::BasicBlock* bp, ir::Instruction** mergeInst,
|
||||
ir::Instruction** branchInst, uint32_t* mergeBlockId);
|
||||
|
||||
// Initialize block2headerBranch_ and branch2merge_ using |structuredOrder|
|
||||
// to order blocks.
|
||||
void ComputeBlock2HeaderMaps(std::list<ir::BasicBlock*>& structuredOrder);
|
||||
|
||||
// Add branch to |labelId| to end of block |bp|.
|
||||
void AddBranch(uint32_t labelId, ir::BasicBlock* bp);
|
||||
|
||||
// Add all break and continue branches in the loop associated with
|
||||
// |mergeInst| to worklist if not already live
|
||||
void AddBreaksAndContinuesToWorklist(ir::Instruction* mergeInst);
|
||||
|
||||
// Eliminates dead debug2 and annotation instructions. Marks dead globals for
|
||||
// removal (e.g. types, constants and variables).
|
||||
bool ProcessGlobalValues();
|
||||
|
||||
// Erases functions that are unreachable from the entry points of the module.
|
||||
bool EliminateDeadFunctions();
|
||||
|
||||
// Removes |func| from the module and deletes all its instructions.
|
||||
void EliminateFunction(ir::Function* func);
|
||||
|
||||
// For function |func|, mark all Stores to non-function-scope variables
|
||||
// and block terminating instructions as live. Recursively mark the values
|
||||
// they use. When complete, mark any non-live instructions to be deleted.
|
||||
// Returns true if the function has been modified.
|
||||
//
|
||||
// Note: This function does not delete useless control structures. All
|
||||
// existing control structures will remain. This can leave not-insignificant
|
||||
// sequences of ultimately useless code.
|
||||
// TODO(): Remove useless control constructs.
|
||||
bool AggressiveDCE(ir::Function* func);
|
||||
|
||||
void Initialize(ir::IRContext* c);
|
||||
Pass::Status ProcessImpl();
|
||||
|
||||
// True if current function has a call instruction contained in it
|
||||
bool call_in_func_;
|
||||
|
||||
// True if current function is an entry point
|
||||
bool func_is_entry_point_;
|
||||
|
||||
// True if current function is entry point and has no function calls.
|
||||
bool private_like_local_;
|
||||
|
||||
// Live Instruction Worklist. An instruction is added to this list
|
||||
// if it might have a side effect, either directly or indirectly.
|
||||
// If we don't know, then add it to this list. Instructions are
|
||||
// removed from this list as the algorithm traces side effects,
|
||||
// building up the live instructions set |live_insts_|.
|
||||
std::queue<ir::Instruction*> worklist_;
|
||||
|
||||
// Map from block to the branch instruction in the header of the most
|
||||
// immediate controlling structured if or loop. A loop header block points
|
||||
// to its own branch instruction. An if-selection block points to the branch
|
||||
// of an enclosing construct's header, if one exists.
|
||||
std::unordered_map<ir::BasicBlock*, ir::Instruction*> block2headerBranch_;
|
||||
|
||||
// Maps basic block to their index in the structured order traversal.
|
||||
std::unordered_map<ir::BasicBlock*, uint32_t> structured_order_index_;
|
||||
|
||||
// Map from branch to its associated merge instruction, if any
|
||||
std::unordered_map<ir::Instruction*, ir::Instruction*> branch2merge_;
|
||||
|
||||
// Store instructions to variables of private storage
|
||||
std::vector<ir::Instruction*> private_stores_;
|
||||
|
||||
// Live Instructions
|
||||
std::unordered_set<const ir::Instruction*> live_insts_;
|
||||
|
||||
// Live Local Variables
|
||||
std::unordered_set<uint32_t> live_local_vars_;
|
||||
|
||||
// List of instructions to delete. Deletion is delayed until debug and
|
||||
// annotation instructions are processed.
|
||||
std::vector<ir::Instruction*> to_kill_;
|
||||
|
||||
// Extensions supported by this pass.
|
||||
std::unordered_set<std::string> extensions_whitelist_;
|
||||
};
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_OPT_AGGRESSIVE_DCE_PASS_H_
|
228
3rdparty/spirv-tools/source/opt/basic_block.cpp
vendored
Normal file
228
3rdparty/spirv-tools/source/opt/basic_block.cpp
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "basic_block.h"
|
||||
#include "function.h"
|
||||
#include "ir_context.h"
|
||||
#include "module.h"
|
||||
#include "reflect.h"
|
||||
|
||||
#include "make_unique.h"
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace spvtools {
|
||||
namespace ir {
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kLoopMergeContinueBlockIdInIdx = 1;
|
||||
const uint32_t kLoopMergeMergeBlockIdInIdx = 0;
|
||||
const uint32_t kSelectionMergeMergeBlockIdInIdx = 0;
|
||||
|
||||
} // namespace
|
||||
|
||||
BasicBlock* BasicBlock::Clone(IRContext* context) const {
|
||||
BasicBlock* clone = new BasicBlock(
|
||||
std::unique_ptr<Instruction>(GetLabelInst()->Clone(context)));
|
||||
for (const auto& inst : insts_)
|
||||
// Use the incoming context
|
||||
clone->AddInstruction(std::unique_ptr<Instruction>(inst.Clone(context)));
|
||||
return clone;
|
||||
}
|
||||
|
||||
const Instruction* BasicBlock::GetMergeInst() const {
|
||||
const Instruction* result = nullptr;
|
||||
// If it exists, the merge instruction immediately precedes the
|
||||
// terminator.
|
||||
auto iter = ctail();
|
||||
if (iter != cbegin()) {
|
||||
--iter;
|
||||
const auto opcode = iter->opcode();
|
||||
if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
|
||||
result = &*iter;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Instruction* BasicBlock::GetMergeInst() {
|
||||
Instruction* result = nullptr;
|
||||
// If it exists, the merge instruction immediately precedes the
|
||||
// terminator.
|
||||
auto iter = tail();
|
||||
if (iter != begin()) {
|
||||
--iter;
|
||||
const auto opcode = iter->opcode();
|
||||
if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
|
||||
result = &*iter;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const Instruction* BasicBlock::GetLoopMergeInst() const {
|
||||
if (auto* merge = GetMergeInst()) {
|
||||
if (merge->opcode() == SpvOpLoopMerge) {
|
||||
return merge;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instruction* BasicBlock::GetLoopMergeInst() {
|
||||
if (auto* merge = GetMergeInst()) {
|
||||
if (merge->opcode() == SpvOpLoopMerge) {
|
||||
return merge;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void BasicBlock::KillAllInsts(bool killLabel) {
|
||||
ForEachInst([killLabel](ir::Instruction* ip) {
|
||||
if (killLabel || ip->opcode() != SpvOpLabel) {
|
||||
ip->context()->KillInst(ip);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void BasicBlock::ForEachSuccessorLabel(
|
||||
const std::function<void(const uint32_t)>& f) const {
|
||||
const auto br = &insts_.back();
|
||||
switch (br->opcode()) {
|
||||
case SpvOpBranch: {
|
||||
f(br->GetOperand(0).words[0]);
|
||||
} break;
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch: {
|
||||
bool is_first = true;
|
||||
br->ForEachInId([&is_first, &f](const uint32_t* idp) {
|
||||
if (!is_first) f(*idp);
|
||||
is_first = false;
|
||||
});
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BasicBlock::ForEachSuccessorLabel(
|
||||
const std::function<void(uint32_t*)>& f) {
|
||||
auto br = &insts_.back();
|
||||
switch (br->opcode()) {
|
||||
case SpvOpBranch: {
|
||||
uint32_t tmp_id = br->GetOperand(0).words[0];
|
||||
f(&tmp_id);
|
||||
if (tmp_id != br->GetOperand(0).words[0]) br->SetOperand(0, {tmp_id});
|
||||
} break;
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch: {
|
||||
bool is_first = true;
|
||||
br->ForEachInId([&is_first, &f](uint32_t* idp) {
|
||||
if (!is_first) f(idp);
|
||||
is_first = false;
|
||||
});
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicBlock::IsSuccessor(const ir::BasicBlock* block) const {
|
||||
uint32_t succId = block->id();
|
||||
bool isSuccessor = false;
|
||||
ForEachSuccessorLabel([&isSuccessor, succId](const uint32_t label) {
|
||||
if (label == succId) isSuccessor = true;
|
||||
});
|
||||
return isSuccessor;
|
||||
}
|
||||
|
||||
void BasicBlock::ForMergeAndContinueLabel(
|
||||
const std::function<void(const uint32_t)>& f) {
|
||||
auto ii = insts_.end();
|
||||
--ii;
|
||||
if (ii == insts_.begin()) return;
|
||||
--ii;
|
||||
if (ii->opcode() == SpvOpSelectionMerge || ii->opcode() == SpvOpLoopMerge) {
|
||||
ii->ForEachInId([&f](const uint32_t* idp) { f(*idp); });
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t BasicBlock::MergeBlockIdIfAny() const {
|
||||
auto merge_ii = cend();
|
||||
--merge_ii;
|
||||
uint32_t mbid = 0;
|
||||
if (merge_ii != cbegin()) {
|
||||
--merge_ii;
|
||||
if (merge_ii->opcode() == SpvOpLoopMerge) {
|
||||
mbid = merge_ii->GetSingleWordInOperand(kLoopMergeMergeBlockIdInIdx);
|
||||
} else if (merge_ii->opcode() == SpvOpSelectionMerge) {
|
||||
mbid = merge_ii->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
|
||||
}
|
||||
}
|
||||
|
||||
return mbid;
|
||||
}
|
||||
|
||||
uint32_t BasicBlock::ContinueBlockIdIfAny() const {
|
||||
auto merge_ii = cend();
|
||||
--merge_ii;
|
||||
uint32_t cbid = 0;
|
||||
if (merge_ii != cbegin()) {
|
||||
--merge_ii;
|
||||
if (merge_ii->opcode() == SpvOpLoopMerge) {
|
||||
cbid = merge_ii->GetSingleWordInOperand(kLoopMergeContinueBlockIdInIdx);
|
||||
}
|
||||
}
|
||||
return cbid;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& str, const BasicBlock& block) {
|
||||
str << block.PrettyPrint();
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string BasicBlock::PrettyPrint(uint32_t options) const {
|
||||
std::ostringstream str;
|
||||
ForEachInst([&str, options](const ir::Instruction* inst) {
|
||||
str << inst->PrettyPrint(options);
|
||||
if (!IsTerminatorInst(inst->opcode())) {
|
||||
str << std::endl;
|
||||
}
|
||||
});
|
||||
return str.str();
|
||||
}
|
||||
|
||||
BasicBlock* BasicBlock::SplitBasicBlock(IRContext* context, uint32_t label_id,
|
||||
iterator iter) {
|
||||
assert(!insts_.empty());
|
||||
|
||||
BasicBlock* new_block = new BasicBlock(MakeUnique<Instruction>(
|
||||
context, SpvOpLabel, 0, label_id, std::initializer_list<ir::Operand>{}));
|
||||
|
||||
new_block->insts_.Splice(new_block->end(), &insts_, iter, end());
|
||||
new_block->SetParent(GetParent());
|
||||
|
||||
if (context->AreAnalysesValid(ir::IRContext::kAnalysisInstrToBlockMapping)) {
|
||||
new_block->ForEachInst([new_block, context](ir::Instruction* inst) {
|
||||
context->set_instr_block(inst, new_block);
|
||||
});
|
||||
}
|
||||
|
||||
return new_block;
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace spvtools
|
300
3rdparty/spirv-tools/source/opt/basic_block.h
vendored
Normal file
300
3rdparty/spirv-tools/source/opt/basic_block.h
vendored
Normal file
@ -0,0 +1,300 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// This file defines the language constructs for representing a SPIR-V
|
||||
// module in memory.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_BASIC_BLOCK_H_
|
||||
#define LIBSPIRV_OPT_BASIC_BLOCK_H_
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "instruction.h"
|
||||
#include "instruction_list.h"
|
||||
#include "iterator.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace ir {
|
||||
|
||||
class Function;
|
||||
class IRContext;
|
||||
|
||||
// A SPIR-V basic block.
|
||||
class BasicBlock {
|
||||
public:
|
||||
using iterator = InstructionList::iterator;
|
||||
using const_iterator = InstructionList::const_iterator;
|
||||
|
||||
// Creates a basic block with the given starting |label|.
|
||||
inline explicit BasicBlock(std::unique_ptr<Instruction> label);
|
||||
|
||||
explicit BasicBlock(const BasicBlock& bb) = delete;
|
||||
|
||||
// Creates a clone of the basic block in the given |context|
|
||||
//
|
||||
// The parent function will default to null and needs to be explicitly set by
|
||||
// the user.
|
||||
BasicBlock* Clone(IRContext*) const;
|
||||
|
||||
// Sets the enclosing function for this basic block.
|
||||
void SetParent(Function* function) { function_ = function; }
|
||||
|
||||
// Return the enclosing function
|
||||
inline Function* GetParent() const { return function_; }
|
||||
|
||||
// Appends an instruction to this basic block.
|
||||
inline void AddInstruction(std::unique_ptr<Instruction> i);
|
||||
|
||||
// Appends all of block's instructions (except label) to this block
|
||||
inline void AddInstructions(BasicBlock* bp);
|
||||
|
||||
// The label starting this basic block.
|
||||
Instruction* GetLabelInst() { return label_.get(); }
|
||||
const Instruction* GetLabelInst() const { return label_.get(); }
|
||||
|
||||
// Returns the merge instruction in this basic block, if it exists.
|
||||
// Otherwise return null. May be used whenever tail() can be used.
|
||||
const Instruction* GetMergeInst() const;
|
||||
Instruction* GetMergeInst();
|
||||
|
||||
// Returns the OpLoopMerge instruciton in this basic block, if it exists.
|
||||
// Otherwise return null. May be used whenever tail() can be used.
|
||||
const Instruction* GetLoopMergeInst() const;
|
||||
Instruction* GetLoopMergeInst();
|
||||
|
||||
// Returns the id of the label at the top of this block
|
||||
inline uint32_t id() const { return label_->result_id(); }
|
||||
|
||||
iterator begin() { return insts_.begin(); }
|
||||
iterator end() { return insts_.end(); }
|
||||
const_iterator begin() const { return insts_.cbegin(); }
|
||||
const_iterator end() const { return insts_.cend(); }
|
||||
const_iterator cbegin() const { return insts_.cbegin(); }
|
||||
const_iterator cend() const { return insts_.cend(); }
|
||||
|
||||
// Returns an iterator pointing to the last instruction. This may only
|
||||
// be used if this block has an instruction other than the OpLabel
|
||||
// that defines it.
|
||||
iterator tail() {
|
||||
assert(!insts_.empty());
|
||||
return --end();
|
||||
}
|
||||
|
||||
// Returns a const iterator, but othewrise similar to tail().
|
||||
const_iterator ctail() const {
|
||||
assert(!insts_.empty());
|
||||
return --insts_.cend();
|
||||
}
|
||||
|
||||
// Returns true if the basic block has at least one successor.
|
||||
inline bool hasSuccessor() const { return ctail()->IsBranch(); }
|
||||
|
||||
// Runs the given function |f| on each instruction in this basic block, and
|
||||
// optionally on the debug line instructions that might precede them.
|
||||
inline void ForEachInst(const std::function<void(Instruction*)>& f,
|
||||
bool run_on_debug_line_insts = false);
|
||||
inline void ForEachInst(const std::function<void(const Instruction*)>& f,
|
||||
bool run_on_debug_line_insts = false) const;
|
||||
|
||||
// Runs the given function |f| on each instruction in this basic block, and
|
||||
// optionally on the debug line instructions that might precede them. If |f|
|
||||
// returns false, iteration is terminated and this function returns false.
|
||||
inline bool WhileEachInst(const std::function<bool(Instruction*)>& f,
|
||||
bool run_on_debug_line_insts = false);
|
||||
inline bool WhileEachInst(const std::function<bool(const Instruction*)>& f,
|
||||
bool run_on_debug_line_insts = false) const;
|
||||
|
||||
// Runs the given function |f| on each Phi instruction in this basic block,
|
||||
// and optionally on the debug line instructions that might precede them.
|
||||
inline void ForEachPhiInst(const std::function<void(Instruction*)>& f,
|
||||
bool run_on_debug_line_insts = false);
|
||||
|
||||
// Runs the given function |f| on each Phi instruction in this basic block,
|
||||
// and optionally on the debug line instructions that might precede them. If
|
||||
// |f| returns false, iteration is terminated and this function return false.
|
||||
inline bool WhileEachPhiInst(const std::function<bool(Instruction*)>& f,
|
||||
bool run_on_debug_line_insts = false);
|
||||
|
||||
// Runs the given function |f| on each label id of each successor block
|
||||
void ForEachSuccessorLabel(
|
||||
const std::function<void(const uint32_t)>& f) const;
|
||||
|
||||
// Runs the given function |f| on each label id of each successor block.
|
||||
// Modifying the pointed value will change the branch taken by the basic
|
||||
// block. It is the caller responsibility to update or invalidate the CFG.
|
||||
void ForEachSuccessorLabel(const std::function<void(uint32_t*)>& f);
|
||||
|
||||
// Returns true if |block| is a direct successor of |this|.
|
||||
bool IsSuccessor(const ir::BasicBlock* block) const;
|
||||
|
||||
// Runs the given function |f| on the merge and continue label, if any
|
||||
void ForMergeAndContinueLabel(const std::function<void(const uint32_t)>& f);
|
||||
|
||||
// Returns true if this basic block has any Phi instructions.
|
||||
bool HasPhiInstructions() {
|
||||
return !WhileEachPhiInst([](ir::Instruction*) { return false; });
|
||||
}
|
||||
|
||||
// Return true if this block is a loop header block.
|
||||
bool IsLoopHeader() const { return GetLoopMergeInst() != nullptr; }
|
||||
|
||||
// Returns the ID of the merge block declared by a merge instruction in this
|
||||
// block, if any. If none, returns zero.
|
||||
uint32_t MergeBlockIdIfAny() const;
|
||||
|
||||
// Returns the ID of the continue block declared by a merge instruction in
|
||||
// this block, if any. If none, returns zero.
|
||||
uint32_t ContinueBlockIdIfAny() const;
|
||||
|
||||
// Returns the terminator instruction. Assumes the terminator exists.
|
||||
Instruction* terminator() { return &*tail(); }
|
||||
const Instruction* terminator() const { return &*ctail(); }
|
||||
|
||||
// Returns true if this basic block exits this function and returns to its
|
||||
// caller.
|
||||
bool IsReturn() const { return ctail()->IsReturn(); }
|
||||
|
||||
// Returns true if this basic block exits this function or aborts execution.
|
||||
bool IsReturnOrAbort() const { return ctail()->IsReturnOrAbort(); }
|
||||
|
||||
// Kill all instructions in this block. Whether or not to kill the label is
|
||||
// indicated by |killLabel|.
|
||||
void KillAllInsts(bool killLabel);
|
||||
|
||||
// Splits this basic block into two. Returns a new basic block with label
|
||||
// |labelId| containing the instructions from |iter| onwards. Instructions
|
||||
// prior to |iter| remain in this basic block.
|
||||
BasicBlock* SplitBasicBlock(IRContext* context, uint32_t label_id,
|
||||
iterator iter);
|
||||
|
||||
// Pretty-prints this basic block into a std::string by printing every
|
||||
// instruction in it.
|
||||
//
|
||||
// |options| are the disassembly options. SPV_BINARY_TO_TEXT_OPTION_NO_HEADER
|
||||
// is always added to |options|.
|
||||
std::string PrettyPrint(uint32_t options = 0u) const;
|
||||
|
||||
private:
|
||||
// The enclosing function.
|
||||
Function* function_;
|
||||
// The label starting this basic block.
|
||||
std::unique_ptr<Instruction> label_;
|
||||
// Instructions inside this basic block, but not the OpLabel.
|
||||
InstructionList insts_;
|
||||
};
|
||||
|
||||
// Pretty-prints |block| to |str|. Returns |str|.
|
||||
std::ostream& operator<<(std::ostream& str, const BasicBlock& block);
|
||||
|
||||
inline BasicBlock::BasicBlock(std::unique_ptr<Instruction> label)
|
||||
: function_(nullptr), label_(std::move(label)) {}
|
||||
|
||||
inline void BasicBlock::AddInstruction(std::unique_ptr<Instruction> i) {
|
||||
insts_.push_back(std::move(i));
|
||||
}
|
||||
|
||||
inline void BasicBlock::AddInstructions(BasicBlock* bp) {
|
||||
auto bEnd = end();
|
||||
(void)bEnd.MoveBefore(&bp->insts_);
|
||||
}
|
||||
|
||||
inline bool BasicBlock::WhileEachInst(
|
||||
const std::function<bool(Instruction*)>& f, bool run_on_debug_line_insts) {
|
||||
if (label_) {
|
||||
if (!label_->WhileEachInst(f, run_on_debug_line_insts)) return false;
|
||||
}
|
||||
if (insts_.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Instruction* inst = &insts_.front();
|
||||
while (inst != nullptr) {
|
||||
Instruction* next_instruction = inst->NextNode();
|
||||
if (!inst->WhileEachInst(f, run_on_debug_line_insts)) return false;
|
||||
inst = next_instruction;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool BasicBlock::WhileEachInst(
|
||||
const std::function<bool(const Instruction*)>& f,
|
||||
bool run_on_debug_line_insts) const {
|
||||
if (label_) {
|
||||
if (!static_cast<const Instruction*>(label_.get())
|
||||
->WhileEachInst(f, run_on_debug_line_insts))
|
||||
return false;
|
||||
}
|
||||
for (const auto& inst : insts_) {
|
||||
if (!static_cast<const Instruction*>(&inst)->WhileEachInst(
|
||||
f, run_on_debug_line_insts))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void BasicBlock::ForEachInst(const std::function<void(Instruction*)>& f,
|
||||
bool run_on_debug_line_insts) {
|
||||
WhileEachInst(
|
||||
[&f](Instruction* inst) {
|
||||
f(inst);
|
||||
return true;
|
||||
},
|
||||
run_on_debug_line_insts);
|
||||
}
|
||||
|
||||
inline void BasicBlock::ForEachInst(
|
||||
const std::function<void(const Instruction*)>& f,
|
||||
bool run_on_debug_line_insts) const {
|
||||
WhileEachInst(
|
||||
[&f](const Instruction* inst) {
|
||||
f(inst);
|
||||
return true;
|
||||
},
|
||||
run_on_debug_line_insts);
|
||||
}
|
||||
|
||||
inline bool BasicBlock::WhileEachPhiInst(
|
||||
const std::function<bool(Instruction*)>& f, bool run_on_debug_line_insts) {
|
||||
if (insts_.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Instruction* inst = &insts_.front();
|
||||
while (inst != nullptr) {
|
||||
Instruction* next_instruction = inst->NextNode();
|
||||
if (inst->opcode() != SpvOpPhi) break;
|
||||
if (!inst->WhileEachInst(f, run_on_debug_line_insts)) return false;
|
||||
inst = next_instruction;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void BasicBlock::ForEachPhiInst(
|
||||
const std::function<void(Instruction*)>& f, bool run_on_debug_line_insts) {
|
||||
WhileEachPhiInst(
|
||||
[&f](Instruction* inst) {
|
||||
f(inst);
|
||||
return true;
|
||||
},
|
||||
run_on_debug_line_insts);
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_OPT_BASIC_BLOCK_H_
|
157
3rdparty/spirv-tools/source/opt/block_merge_pass.cpp
vendored
Normal file
157
3rdparty/spirv-tools/source/opt/block_merge_pass.cpp
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
// Copyright (c) 2017 Valve Corporation
|
||||
// Copyright (c) 2017 LunarG Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "block_merge_pass.h"
|
||||
|
||||
#include "ir_context.h"
|
||||
#include "iterator.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
void BlockMergePass::KillInstAndName(ir::Instruction* inst) {
|
||||
std::vector<ir::Instruction*> to_kill;
|
||||
get_def_use_mgr()->ForEachUser(inst, [&to_kill](ir::Instruction* user) {
|
||||
if (user->opcode() == SpvOpName) {
|
||||
to_kill.push_back(user);
|
||||
}
|
||||
});
|
||||
for (auto i : to_kill) {
|
||||
context()->KillInst(i);
|
||||
}
|
||||
context()->KillInst(inst);
|
||||
}
|
||||
|
||||
bool BlockMergePass::MergeBlocks(ir::Function* func) {
|
||||
bool modified = false;
|
||||
for (auto bi = func->begin(); bi != func->end();) {
|
||||
// Find block with single successor which has no other predecessors.
|
||||
auto ii = bi->end();
|
||||
--ii;
|
||||
ir::Instruction* br = &*ii;
|
||||
if (br->opcode() != SpvOpBranch) {
|
||||
++bi;
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint32_t lab_id = br->GetSingleWordInOperand(0);
|
||||
if (cfg()->preds(lab_id).size() != 1) {
|
||||
++bi;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool pred_is_header = IsHeader(&*bi);
|
||||
bool succ_is_header = IsHeader(lab_id);
|
||||
if (pred_is_header && succ_is_header) {
|
||||
// Cannot merge two headers together.
|
||||
++bi;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool pred_is_merge = IsMerge(&*bi);
|
||||
bool succ_is_merge = IsMerge(lab_id);
|
||||
if (pred_is_merge && succ_is_merge) {
|
||||
// Cannot merge two merges together.
|
||||
++bi;
|
||||
continue;
|
||||
}
|
||||
|
||||
ir::Instruction* merge_inst = bi->GetMergeInst();
|
||||
if (pred_is_header && lab_id != merge_inst->GetSingleWordInOperand(0u)) {
|
||||
// If this is a header block and the successor is not its merge, we must
|
||||
// be careful about which blocks we are willing to merge together.
|
||||
// OpLoopMerge must be followed by a conditional or unconditional branch.
|
||||
// The merge must be a loop merge because a selection merge cannot be
|
||||
// followed by an unconditional branch.
|
||||
ir::BasicBlock* succ_block = context()->get_instr_block(lab_id);
|
||||
SpvOp succ_term_op = succ_block->terminator()->opcode();
|
||||
assert(merge_inst->opcode() == SpvOpLoopMerge);
|
||||
if (succ_term_op != SpvOpBranch &&
|
||||
succ_term_op != SpvOpBranchConditional) {
|
||||
++bi;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge blocks.
|
||||
context()->KillInst(br);
|
||||
auto sbi = bi;
|
||||
for (; sbi != func->end(); ++sbi)
|
||||
if (sbi->id() == lab_id) break;
|
||||
// If bi is sbi's only predecessor, it dominates sbi and thus
|
||||
// sbi must follow bi in func's ordering.
|
||||
assert(sbi != func->end());
|
||||
bi->AddInstructions(&*sbi);
|
||||
if (merge_inst) {
|
||||
if (pred_is_header && lab_id == merge_inst->GetSingleWordInOperand(0u)) {
|
||||
// Merging the header and merge blocks, so remove the structured control
|
||||
// flow declaration.
|
||||
context()->KillInst(merge_inst);
|
||||
} else {
|
||||
// Move the merge instruction to just before the terminator.
|
||||
merge_inst->InsertBefore(bi->terminator());
|
||||
}
|
||||
}
|
||||
context()->ReplaceAllUsesWith(lab_id, bi->id());
|
||||
KillInstAndName(sbi->GetLabelInst());
|
||||
(void)sbi.Erase();
|
||||
// Reprocess block.
|
||||
modified = true;
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
bool BlockMergePass::IsHeader(ir::BasicBlock* block) {
|
||||
return block->GetMergeInst() != nullptr;
|
||||
}
|
||||
|
||||
bool BlockMergePass::IsHeader(uint32_t id) {
|
||||
return IsHeader(context()->get_instr_block(get_def_use_mgr()->GetDef(id)));
|
||||
}
|
||||
|
||||
bool BlockMergePass::IsMerge(uint32_t id) {
|
||||
return !get_def_use_mgr()->WhileEachUse(id, [](ir::Instruction* user,
|
||||
uint32_t index) {
|
||||
SpvOp op = user->opcode();
|
||||
if ((op == SpvOpLoopMerge || op == SpvOpSelectionMerge) && index == 0u) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool BlockMergePass::IsMerge(ir::BasicBlock* block) {
|
||||
return IsMerge(block->id());
|
||||
}
|
||||
|
||||
void BlockMergePass::Initialize(ir::IRContext* c) { InitializeProcessing(c); }
|
||||
|
||||
Pass::Status BlockMergePass::ProcessImpl() {
|
||||
// Process all entry point functions.
|
||||
ProcessFunction pfn = [this](ir::Function* fp) { return MergeBlocks(fp); };
|
||||
bool modified = ProcessEntryPointCallTree(pfn, get_module());
|
||||
return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
BlockMergePass::BlockMergePass() {}
|
||||
|
||||
Pass::Status BlockMergePass::Process(ir::IRContext* c) {
|
||||
Initialize(c);
|
||||
return ProcessImpl();
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
67
3rdparty/spirv-tools/source/opt/block_merge_pass.h
vendored
Normal file
67
3rdparty/spirv-tools/source/opt/block_merge_pass.h
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
// Copyright (c) 2017 Valve Corporation
|
||||
// Copyright (c) 2017 LunarG Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_BLOCK_MERGE_PASS_H_
|
||||
#define LIBSPIRV_OPT_BLOCK_MERGE_PASS_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
#include "basic_block.h"
|
||||
#include "def_use_manager.h"
|
||||
#include "ir_context.h"
|
||||
#include "module.h"
|
||||
#include "pass.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
// See optimizer.hpp for documentation.
|
||||
class BlockMergePass : public Pass {
|
||||
public:
|
||||
BlockMergePass();
|
||||
const char* name() const override { return "merge-blocks"; }
|
||||
Status Process(ir::IRContext*) override;
|
||||
|
||||
private:
|
||||
// Kill any OpName instruction referencing |inst|, then kill |inst|.
|
||||
void KillInstAndName(ir::Instruction* inst);
|
||||
|
||||
// Search |func| for blocks which have a single Branch to a block
|
||||
// with no other predecessors. Merge these blocks into a single block.
|
||||
bool MergeBlocks(ir::Function* func);
|
||||
|
||||
// Returns true if |block| (or |id|) contains a merge instruction.
|
||||
bool IsHeader(ir::BasicBlock* block);
|
||||
bool IsHeader(uint32_t id);
|
||||
|
||||
// Returns true if |block| (or |id|) is the merge target of a merge
|
||||
// instruction.
|
||||
bool IsMerge(ir::BasicBlock* block);
|
||||
bool IsMerge(uint32_t id);
|
||||
|
||||
void Initialize(ir::IRContext* c);
|
||||
Pass::Status ProcessImpl();
|
||||
};
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_OPT_BLOCK_MERGE_PASS_H_
|
77
3rdparty/spirv-tools/source/opt/build_module.cpp
vendored
Normal file
77
3rdparty/spirv-tools/source/opt/build_module.cpp
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "build_module.h"
|
||||
|
||||
#include "ir_context.h"
|
||||
#include "ir_loader.h"
|
||||
#include "make_unique.h"
|
||||
#include "table.h"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
namespace {
|
||||
|
||||
// Sets the module header for IrLoader. Meets the interface requirement of
|
||||
// spvBinaryParse().
|
||||
spv_result_t SetSpvHeader(void* builder, spv_endianness_t, uint32_t magic,
|
||||
uint32_t version, uint32_t generator,
|
||||
uint32_t id_bound, uint32_t reserved) {
|
||||
reinterpret_cast<ir::IrLoader*>(builder)->SetModuleHeader(
|
||||
magic, version, generator, id_bound, reserved);
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// Processes a parsed instruction for IrLoader. Meets the interface requirement
|
||||
// of spvBinaryParse().
|
||||
spv_result_t SetSpvInst(void* builder, const spv_parsed_instruction_t* inst) {
|
||||
if (reinterpret_cast<ir::IrLoader*>(builder)->AddInstruction(inst)) {
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
return SPV_ERROR_INVALID_BINARY;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<ir::IRContext> BuildModule(spv_target_env env,
|
||||
MessageConsumer consumer,
|
||||
const uint32_t* binary,
|
||||
const size_t size) {
|
||||
auto context = spvContextCreate(env);
|
||||
libspirv::SetContextMessageConsumer(context, consumer);
|
||||
|
||||
auto irContext = MakeUnique<ir::IRContext>(env, consumer);
|
||||
ir::IrLoader loader(consumer, irContext->module());
|
||||
|
||||
spv_result_t status = spvBinaryParse(context, &loader, binary, size,
|
||||
SetSpvHeader, SetSpvInst, nullptr);
|
||||
loader.EndModule();
|
||||
|
||||
spvContextDestroy(context);
|
||||
|
||||
return status == SPV_SUCCESS ? std::move(irContext) : nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<ir::IRContext> BuildModule(spv_target_env env,
|
||||
MessageConsumer consumer,
|
||||
const std::string& text,
|
||||
uint32_t assemble_options) {
|
||||
SpirvTools t(env);
|
||||
t.SetMessageConsumer(consumer);
|
||||
std::vector<uint32_t> binary;
|
||||
if (!t.Assemble(text, &binary, assemble_options)) return nullptr;
|
||||
return BuildModule(env, consumer, binary.data(), binary.size());
|
||||
}
|
||||
|
||||
} // namespace spvtools
|
45
3rdparty/spirv-tools/source/opt/build_module.h
vendored
Normal file
45
3rdparty/spirv-tools/source/opt/build_module.h
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2016 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SPIRV_TOOLS_OPT_BUILD_MODULE_H_
|
||||
#define SPIRV_TOOLS_OPT_BUILD_MODULE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "ir_context.h"
|
||||
#include "module.h"
|
||||
#include "spirv-tools/libspirv.hpp"
|
||||
|
||||
namespace spvtools {
|
||||
|
||||
// Builds an ir::Module returns the owning ir::IRContext from the given SPIR-V
|
||||
// |binary|. |size| specifies number of words in |binary|. The |binary| will be
|
||||
// decoded according to the given target |env|. Returns nullptr if errors occur
|
||||
// and sends the errors to |consumer|.
|
||||
std::unique_ptr<ir::IRContext> BuildModule(spv_target_env env,
|
||||
MessageConsumer consumer,
|
||||
const uint32_t* binary, size_t size);
|
||||
|
||||
// Builds an ir::Module and returns the owning ir::IRContext from the given
|
||||
// SPIR-V assembly |text|. The |text| will be encoded according to the given
|
||||
// target |env|. Returns nullptr if errors occur and sends the errors to
|
||||
// |consumer|.
|
||||
std::unique_ptr<ir::IRContext> BuildModule(
|
||||
spv_target_env env, MessageConsumer consumer, const std::string& text,
|
||||
uint32_t assemble_options = SpirvTools::kDefaultAssembleOption);
|
||||
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SPIRV_TOOLS_OPT_BUILD_MODULE_H_
|
330
3rdparty/spirv-tools/source/opt/ccp_pass.cpp
vendored
Normal file
330
3rdparty/spirv-tools/source/opt/ccp_pass.cpp
vendored
Normal file
@ -0,0 +1,330 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// This file implements conditional constant propagation as described in
|
||||
//
|
||||
// Constant propagation with conditional branches,
|
||||
// Wegman and Zadeck, ACM TOPLAS 13(2):181-210.
|
||||
#include "ccp_pass.h"
|
||||
#include "fold.h"
|
||||
#include "function.h"
|
||||
#include "module.h"
|
||||
#include "propagator.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
namespace {
|
||||
|
||||
// This SSA id is never defined nor referenced in the IR. It is a special ID
|
||||
// which represents varying values. When an ID is found to have a varying
|
||||
// value, its entry in the |values_| table maps to kVaryingSSAId.
|
||||
const uint32_t kVaryingSSAId = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
} // namespace
|
||||
|
||||
bool CCPPass::IsVaryingValue(uint32_t id) const { return id == kVaryingSSAId; }
|
||||
|
||||
SSAPropagator::PropStatus CCPPass::MarkInstructionVarying(
|
||||
ir::Instruction* instr) {
|
||||
assert(instr->result_id() != 0 &&
|
||||
"Instructions with no result cannot be marked varying.");
|
||||
values_[instr->result_id()] = kVaryingSSAId;
|
||||
return SSAPropagator::kVarying;
|
||||
}
|
||||
|
||||
SSAPropagator::PropStatus CCPPass::VisitPhi(ir::Instruction* phi) {
|
||||
uint32_t meet_val_id = 0;
|
||||
|
||||
// Implement the lattice meet operation. The result of this Phi instruction is
|
||||
// interesting only if the meet operation over arguments coming through
|
||||
// executable edges yields the same constant value.
|
||||
for (uint32_t i = 2; i < phi->NumOperands(); i += 2) {
|
||||
if (!propagator_->IsPhiArgExecutable(phi, i)) {
|
||||
// Ignore arguments coming through non-executable edges.
|
||||
continue;
|
||||
}
|
||||
uint32_t phi_arg_id = phi->GetSingleWordOperand(i);
|
||||
auto it = values_.find(phi_arg_id);
|
||||
if (it != values_.end()) {
|
||||
// We found an argument with a constant value. Apply the meet operation
|
||||
// with the previous arguments.
|
||||
if (it->second == kVaryingSSAId) {
|
||||
// The "constant" value is actually a placeholder for varying. Return
|
||||
// varying for this phi.
|
||||
return MarkInstructionVarying(phi);
|
||||
} else if (meet_val_id == 0) {
|
||||
// This is the first argument we find. Initialize the result to its
|
||||
// constant value id.
|
||||
meet_val_id = it->second;
|
||||
} else if (it->second == meet_val_id) {
|
||||
// The argument is the same constant value already computed. Continue
|
||||
// looking.
|
||||
continue;
|
||||
} else {
|
||||
// We either found a varying value, or another constant value different
|
||||
// from the previous computed meet value. This Phi will never be
|
||||
// constant.
|
||||
return MarkInstructionVarying(phi);
|
||||
}
|
||||
} else {
|
||||
// The incoming value has no recorded value and is therefore not
|
||||
// interesting. A not interesting value joined with any other value is the
|
||||
// other value.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no incoming executable edges, the meet ID will still be 0. In
|
||||
// that case, return not interesting to evaluate the Phi node again.
|
||||
if (meet_val_id == 0) {
|
||||
return SSAPropagator::kNotInteresting;
|
||||
}
|
||||
|
||||
// All the operands have the same constant value represented by |meet_val_id|.
|
||||
// Set the Phi's result to that value and declare it interesting.
|
||||
values_[phi->result_id()] = meet_val_id;
|
||||
return SSAPropagator::kInteresting;
|
||||
}
|
||||
|
||||
SSAPropagator::PropStatus CCPPass::VisitAssignment(ir::Instruction* instr) {
|
||||
assert(instr->result_id() != 0 &&
|
||||
"Expecting an instruction that produces a result");
|
||||
|
||||
// If this is a copy operation, and the RHS is a known constant, assign its
|
||||
// value to the LHS.
|
||||
if (instr->opcode() == SpvOpCopyObject) {
|
||||
uint32_t rhs_id = instr->GetSingleWordInOperand(0);
|
||||
auto it = values_.find(rhs_id);
|
||||
if (it != values_.end()) {
|
||||
if (IsVaryingValue(it->second)) {
|
||||
return MarkInstructionVarying(instr);
|
||||
} else {
|
||||
values_[instr->result_id()] = it->second;
|
||||
return SSAPropagator::kInteresting;
|
||||
}
|
||||
}
|
||||
return SSAPropagator::kNotInteresting;
|
||||
}
|
||||
|
||||
// Instructions with a RHS that cannot produce a constant are always varying.
|
||||
if (!instr->IsFoldable()) {
|
||||
return MarkInstructionVarying(instr);
|
||||
}
|
||||
|
||||
// See if the RHS of the assignment folds into a constant value.
|
||||
auto map_func = [this](uint32_t id) {
|
||||
auto it = values_.find(id);
|
||||
if (it == values_.end() || IsVaryingValue(it->second)) {
|
||||
return id;
|
||||
}
|
||||
return it->second;
|
||||
};
|
||||
ir::Instruction* folded_inst =
|
||||
opt::FoldInstructionToConstant(instr, map_func);
|
||||
if (folded_inst != nullptr) {
|
||||
// We do not want to change the body of the function by adding new
|
||||
// instructions. When folding we can only generate new constants.
|
||||
assert(folded_inst->IsConstant() && "CCP is only interested in constant.");
|
||||
values_[instr->result_id()] = folded_inst->result_id();
|
||||
return SSAPropagator::kInteresting;
|
||||
}
|
||||
|
||||
// Conservatively mark this instruction as varying if any input id is varying.
|
||||
if (!instr->WhileEachInId([this](uint32_t* op_id) {
|
||||
auto iter = values_.find(*op_id);
|
||||
if (iter != values_.end() && IsVaryingValue(iter->second)) return false;
|
||||
return true;
|
||||
})) {
|
||||
return MarkInstructionVarying(instr);
|
||||
}
|
||||
|
||||
// If not, see if there is a least one unknown operand to the instruction. If
|
||||
// so, we might be able to fold it later.
|
||||
if (!instr->WhileEachInId([this](uint32_t* op_id) {
|
||||
auto it = values_.find(*op_id);
|
||||
if (it == values_.end()) return false;
|
||||
return true;
|
||||
})) {
|
||||
return SSAPropagator::kNotInteresting;
|
||||
}
|
||||
|
||||
// Otherwise, we will never be able to fold this instruction, so mark it
|
||||
// varying.
|
||||
return MarkInstructionVarying(instr);
|
||||
}
|
||||
|
||||
SSAPropagator::PropStatus CCPPass::VisitBranch(ir::Instruction* instr,
|
||||
ir::BasicBlock** dest_bb) const {
|
||||
assert(instr->IsBranch() && "Expected a branch instruction.");
|
||||
|
||||
*dest_bb = nullptr;
|
||||
uint32_t dest_label = 0;
|
||||
if (instr->opcode() == SpvOpBranch) {
|
||||
// An unconditional jump always goes to its unique destination.
|
||||
dest_label = instr->GetSingleWordInOperand(0);
|
||||
} else if (instr->opcode() == SpvOpBranchConditional) {
|
||||
// For a conditional branch, determine whether the predicate selector has a
|
||||
// known value in |values_|. If it does, set the destination block
|
||||
// according to the selector's boolean value.
|
||||
uint32_t pred_id = instr->GetSingleWordOperand(0);
|
||||
auto it = values_.find(pred_id);
|
||||
if (it == values_.end() || IsVaryingValue(it->second)) {
|
||||
// The predicate has an unknown value, either branch could be taken.
|
||||
return SSAPropagator::kVarying;
|
||||
}
|
||||
|
||||
// Get the constant value for the predicate selector from the value table.
|
||||
// Use it to decide which branch will be taken.
|
||||
uint32_t pred_val_id = it->second;
|
||||
const analysis::Constant* c = const_mgr_->FindDeclaredConstant(pred_val_id);
|
||||
assert(c && "Expected to find a constant declaration for a known value.");
|
||||
// Undef values should have returned as varying above.
|
||||
assert(c->AsBoolConstant() || c->AsNullConstant());
|
||||
if (c->AsNullConstant()) {
|
||||
dest_label = instr->GetSingleWordOperand(2u);
|
||||
} else {
|
||||
const analysis::BoolConstant* val = c->AsBoolConstant();
|
||||
dest_label = val->value() ? instr->GetSingleWordOperand(1)
|
||||
: instr->GetSingleWordOperand(2);
|
||||
}
|
||||
} else {
|
||||
// For an OpSwitch, extract the value taken by the switch selector and check
|
||||
// which of the target literals it matches. The branch associated with that
|
||||
// literal is the taken branch.
|
||||
assert(instr->opcode() == SpvOpSwitch);
|
||||
if (instr->GetOperand(0).words.size() != 1) {
|
||||
// If the selector is wider than 32-bits, return varying. TODO(dnovillo):
|
||||
// Add support for wider constants.
|
||||
return SSAPropagator::kVarying;
|
||||
}
|
||||
uint32_t select_id = instr->GetSingleWordOperand(0);
|
||||
auto it = values_.find(select_id);
|
||||
if (it == values_.end() || IsVaryingValue(it->second)) {
|
||||
// The selector has an unknown value, any of the branches could be taken.
|
||||
return SSAPropagator::kVarying;
|
||||
}
|
||||
|
||||
// Get the constant value for the selector from the value table. Use it to
|
||||
// decide which branch will be taken.
|
||||
uint32_t select_val_id = it->second;
|
||||
const analysis::Constant* c =
|
||||
const_mgr_->FindDeclaredConstant(select_val_id);
|
||||
assert(c && "Expected to find a constant declaration for a known value.");
|
||||
// TODO: support 64-bit integer switches.
|
||||
uint32_t constant_cond = 0;
|
||||
if (const analysis::IntConstant* val = c->AsIntConstant()) {
|
||||
constant_cond = val->words()[0];
|
||||
} else {
|
||||
// Undef values should have returned varying above.
|
||||
assert(c->AsNullConstant());
|
||||
constant_cond = 0;
|
||||
}
|
||||
|
||||
// Start assuming that the selector will take the default value;
|
||||
dest_label = instr->GetSingleWordOperand(1);
|
||||
for (uint32_t i = 2; i < instr->NumOperands(); i += 2) {
|
||||
if (constant_cond == instr->GetSingleWordOperand(i)) {
|
||||
dest_label = instr->GetSingleWordOperand(i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(dest_label && "Destination label should be set at this point.");
|
||||
*dest_bb = context()->cfg()->block(dest_label);
|
||||
return SSAPropagator::kInteresting;
|
||||
}
|
||||
|
||||
SSAPropagator::PropStatus CCPPass::VisitInstruction(ir::Instruction* instr,
|
||||
ir::BasicBlock** dest_bb) {
|
||||
*dest_bb = nullptr;
|
||||
if (instr->opcode() == SpvOpPhi) {
|
||||
return VisitPhi(instr);
|
||||
} else if (instr->IsBranch()) {
|
||||
return VisitBranch(instr, dest_bb);
|
||||
} else if (instr->result_id()) {
|
||||
return VisitAssignment(instr);
|
||||
}
|
||||
return SSAPropagator::kVarying;
|
||||
}
|
||||
|
||||
bool CCPPass::ReplaceValues() {
|
||||
bool retval = false;
|
||||
for (const auto& it : values_) {
|
||||
uint32_t id = it.first;
|
||||
uint32_t cst_id = it.second;
|
||||
if (!IsVaryingValue(cst_id) && id != cst_id) {
|
||||
retval |= context()->ReplaceAllUsesWith(id, cst_id);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool CCPPass::PropagateConstants(ir::Function* fp) {
|
||||
// Mark function parameters as varying.
|
||||
fp->ForEachParam([this](const ir::Instruction* inst) {
|
||||
values_[inst->result_id()] = kVaryingSSAId;
|
||||
});
|
||||
|
||||
const auto visit_fn = [this](ir::Instruction* instr,
|
||||
ir::BasicBlock** dest_bb) {
|
||||
return VisitInstruction(instr, dest_bb);
|
||||
};
|
||||
|
||||
propagator_ =
|
||||
std::unique_ptr<SSAPropagator>(new SSAPropagator(context(), visit_fn));
|
||||
|
||||
if (propagator_->Run(fp)) {
|
||||
return ReplaceValues();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CCPPass::Initialize(ir::IRContext* c) {
|
||||
InitializeProcessing(c);
|
||||
|
||||
const_mgr_ = context()->get_constant_mgr();
|
||||
|
||||
// Populate the constant table with values from constant declarations in the
|
||||
// module. The values of each OpConstant declaration is the identity
|
||||
// assignment (i.e., each constant is its own value).
|
||||
for (const auto& inst : get_module()->types_values()) {
|
||||
// Record compile time constant ids. Treat all other global values as
|
||||
// varying.
|
||||
if (inst.IsConstant()) {
|
||||
values_[inst.result_id()] = inst.result_id();
|
||||
} else {
|
||||
values_[inst.result_id()] = kVaryingSSAId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pass::Status CCPPass::Process(ir::IRContext* c) {
|
||||
Initialize(c);
|
||||
|
||||
// Process all entry point functions.
|
||||
ProcessFunction pfn = [this](ir::Function* fp) {
|
||||
return PropagateConstants(fp);
|
||||
};
|
||||
bool modified = ProcessReachableCallTree(pfn, context());
|
||||
return modified ? Pass::Status::SuccessWithChange
|
||||
: Pass::Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
100
3rdparty/spirv-tools/source/opt/ccp_pass.h
vendored
Normal file
100
3rdparty/spirv-tools/source/opt/ccp_pass.h
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_CCP_PASS_H_
|
||||
#define LIBSPIRV_OPT_CCP_PASS_H_
|
||||
|
||||
#include "constants.h"
|
||||
#include "function.h"
|
||||
#include "ir_context.h"
|
||||
#include "mem_pass.h"
|
||||
#include "module.h"
|
||||
#include "propagator.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
class CCPPass : public MemPass {
|
||||
public:
|
||||
CCPPass() = default;
|
||||
const char* name() const override { return "ccp"; }
|
||||
Status Process(ir::IRContext* c) override;
|
||||
|
||||
private:
|
||||
// Initializes the pass.
|
||||
void Initialize(ir::IRContext* c);
|
||||
|
||||
// Runs constant propagation on the given function |fp|. Returns true if any
|
||||
// constants were propagated and the IR modified.
|
||||
bool PropagateConstants(ir::Function* fp);
|
||||
|
||||
// Visits a single instruction |instr|. If the instruction is a conditional
|
||||
// branch that always jumps to the same basic block, it sets the destination
|
||||
// block in |dest_bb|.
|
||||
SSAPropagator::PropStatus VisitInstruction(ir::Instruction* instr,
|
||||
ir::BasicBlock** dest_bb);
|
||||
|
||||
// Visits an OpPhi instruction |phi|. This applies the meet operator for the
|
||||
// CCP lattice. Essentially, if all the operands in |phi| have the same
|
||||
// constant value C, the result for |phi| gets assigned the value C.
|
||||
SSAPropagator::PropStatus VisitPhi(ir::Instruction* phi);
|
||||
|
||||
// Visits an SSA assignment instruction |instr|. If the RHS of |instr| folds
|
||||
// into a constant value C, then the LHS of |instr| is assigned the value C in
|
||||
// |values_|.
|
||||
SSAPropagator::PropStatus VisitAssignment(ir::Instruction* instr);
|
||||
|
||||
// Visits a branch instruction |instr|. If the branch is conditional
|
||||
// (OpBranchConditional or OpSwitch), and the value of its selector is known,
|
||||
// |dest_bb| will be set to the corresponding destination block. Unconditional
|
||||
// branches always set |dest_bb| to the single destination block.
|
||||
SSAPropagator::PropStatus VisitBranch(ir::Instruction* instr,
|
||||
ir::BasicBlock** dest_bb) const;
|
||||
|
||||
// Replaces all operands used in |fp| with the corresponding constant values
|
||||
// in |values_|. Returns true if any operands were replaced, and false
|
||||
// otherwise.
|
||||
bool ReplaceValues();
|
||||
|
||||
// Marks |instr| as varying by registering a varying value for its result
|
||||
// into the |values_| table. Returns SSAPropagator::kVarying.
|
||||
SSAPropagator::PropStatus MarkInstructionVarying(ir::Instruction* instr);
|
||||
|
||||
// Returns true if |id| is the special SSA id that corresponds to a varying
|
||||
// value.
|
||||
bool IsVaryingValue(uint32_t id) const;
|
||||
|
||||
// Constant manager for the parent IR context. Used to record new constants
|
||||
// generated during propagation.
|
||||
analysis::ConstantManager* const_mgr_;
|
||||
|
||||
// Constant value table. Each entry <id, const_decl_id> in this map
|
||||
// represents the compile-time constant value for |id| as declared by
|
||||
// |const_decl_id|. Each |const_decl_id| in this table is an OpConstant
|
||||
// declaration for the current module.
|
||||
//
|
||||
// Additionally, this table keeps track of SSA IDs with varying values. If an
|
||||
// SSA ID is found to have a varying value, it will have an entry in this
|
||||
// table that maps to the special SSA id kVaryingSSAId. These values are
|
||||
// never replaced in the IR, they are used by CCP during propagation.
|
||||
std::unordered_map<uint32_t, uint32_t> values_;
|
||||
|
||||
// Propagator engine used.
|
||||
std::unique_ptr<SSAPropagator> propagator_;
|
||||
};
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif
|
310
3rdparty/spirv-tools/source/opt/cfg.cpp
vendored
Normal file
310
3rdparty/spirv-tools/source/opt/cfg.cpp
vendored
Normal file
@ -0,0 +1,310 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "cfg.h"
|
||||
#include "cfa.h"
|
||||
#include "ir_builder.h"
|
||||
#include "ir_context.h"
|
||||
#include "module.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace ir {
|
||||
|
||||
namespace {
|
||||
|
||||
// Universal Limit of ResultID + 1
|
||||
const int kInvalidId = 0x400000;
|
||||
|
||||
} // namespace
|
||||
|
||||
CFG::CFG(ir::Module* module)
|
||||
: module_(module),
|
||||
pseudo_entry_block_(std::unique_ptr<ir::Instruction>(
|
||||
new ir::Instruction(module->context(), SpvOpLabel, 0, 0, {}))),
|
||||
pseudo_exit_block_(std::unique_ptr<ir::Instruction>(new ir::Instruction(
|
||||
module->context(), SpvOpLabel, 0, kInvalidId, {}))) {
|
||||
for (auto& fn : *module) {
|
||||
for (auto& blk : fn) {
|
||||
RegisterBlock(&blk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CFG::AddEdges(ir::BasicBlock* blk) {
|
||||
uint32_t blk_id = blk->id();
|
||||
// Force the creation of an entry, not all basic block have predecessors
|
||||
// (such as the entry blocks and some unreachables).
|
||||
label2preds_[blk_id];
|
||||
const auto* const_blk = blk;
|
||||
const_blk->ForEachSuccessorLabel(
|
||||
[blk_id, this](const uint32_t succ_id) { AddEdge(blk_id, succ_id); });
|
||||
}
|
||||
|
||||
void CFG::RemoveNonExistingEdges(uint32_t blk_id) {
|
||||
std::vector<uint32_t> updated_pred_list;
|
||||
for (uint32_t id : preds(blk_id)) {
|
||||
const ir::BasicBlock* pred_blk = block(id);
|
||||
bool has_branch = false;
|
||||
pred_blk->ForEachSuccessorLabel([&has_branch, blk_id](uint32_t succ) {
|
||||
if (succ == blk_id) {
|
||||
has_branch = true;
|
||||
}
|
||||
});
|
||||
if (has_branch) updated_pred_list.push_back(id);
|
||||
}
|
||||
|
||||
label2preds_.at(blk_id) = std::move(updated_pred_list);
|
||||
}
|
||||
|
||||
void CFG::ComputeStructuredOrder(ir::Function* func, ir::BasicBlock* root,
|
||||
std::list<ir::BasicBlock*>* order) {
|
||||
assert(module_->context()->get_feature_mgr()->HasCapability(
|
||||
SpvCapabilityShader) &&
|
||||
"This only works on structured control flow");
|
||||
|
||||
// Compute structured successors and do DFS.
|
||||
ComputeStructuredSuccessors(func);
|
||||
auto ignore_block = [](cbb_ptr) {};
|
||||
auto ignore_edge = [](cbb_ptr, cbb_ptr) {};
|
||||
auto get_structured_successors = [this](const ir::BasicBlock* b) {
|
||||
return &(block2structured_succs_[b]);
|
||||
};
|
||||
|
||||
// TODO(greg-lunarg): Get rid of const_cast by making moving const
|
||||
// out of the cfa.h prototypes and into the invoking code.
|
||||
auto post_order = [&](cbb_ptr b) {
|
||||
order->push_front(const_cast<ir::BasicBlock*>(b));
|
||||
};
|
||||
spvtools::CFA<ir::BasicBlock>::DepthFirstTraversal(
|
||||
root, get_structured_successors, ignore_block, post_order, ignore_edge);
|
||||
}
|
||||
|
||||
void CFG::ForEachBlockInReversePostOrder(
|
||||
BasicBlock* bb, const std::function<void(BasicBlock*)>& f) {
|
||||
std::vector<BasicBlock*> po;
|
||||
std::unordered_set<BasicBlock*> seen;
|
||||
ComputePostOrderTraversal(bb, &po, &seen);
|
||||
|
||||
for (auto current_bb = po.rbegin(); current_bb != po.rend(); ++current_bb) {
|
||||
if (!IsPseudoExitBlock(*current_bb) && !IsPseudoEntryBlock(*current_bb)) {
|
||||
f(*current_bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CFG::ComputeStructuredSuccessors(ir::Function* func) {
|
||||
block2structured_succs_.clear();
|
||||
for (auto& blk : *func) {
|
||||
// If no predecessors in function, make successor to pseudo entry.
|
||||
if (label2preds_[blk.id()].size() == 0)
|
||||
block2structured_succs_[&pseudo_entry_block_].push_back(&blk);
|
||||
|
||||
// If header, make merge block first successor and continue block second
|
||||
// successor if there is one.
|
||||
uint32_t mbid = blk.MergeBlockIdIfAny();
|
||||
if (mbid != 0) {
|
||||
block2structured_succs_[&blk].push_back(block(mbid));
|
||||
uint32_t cbid = blk.ContinueBlockIdIfAny();
|
||||
if (cbid != 0) {
|
||||
block2structured_succs_[&blk].push_back(block(cbid));
|
||||
}
|
||||
}
|
||||
|
||||
// Add true successors.
|
||||
const auto& const_blk = blk;
|
||||
const_blk.ForEachSuccessorLabel([&blk, this](const uint32_t sbid) {
|
||||
block2structured_succs_[&blk].push_back(block(sbid));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void CFG::ComputePostOrderTraversal(BasicBlock* bb, vector<BasicBlock*>* order,
|
||||
unordered_set<BasicBlock*>* seen) {
|
||||
seen->insert(bb);
|
||||
static_cast<const BasicBlock*>(bb)->ForEachSuccessorLabel(
|
||||
[&order, &seen, this](const uint32_t sbid) {
|
||||
BasicBlock* succ_bb = id2block_[sbid];
|
||||
if (!seen->count(succ_bb)) {
|
||||
ComputePostOrderTraversal(succ_bb, order, seen);
|
||||
}
|
||||
});
|
||||
order->push_back(bb);
|
||||
}
|
||||
|
||||
BasicBlock* CFG::SplitLoopHeader(ir::BasicBlock* bb) {
|
||||
assert(bb->GetLoopMergeInst() && "Expecting bb to be the header of a loop.");
|
||||
|
||||
Function* fn = bb->GetParent();
|
||||
IRContext* context = fn->context();
|
||||
|
||||
// Find the insertion point for the new bb.
|
||||
Function::iterator header_it = std::find_if(
|
||||
fn->begin(), fn->end(),
|
||||
[bb](BasicBlock& block_in_func) { return &block_in_func == bb; });
|
||||
assert(header_it != fn->end());
|
||||
|
||||
const std::vector<uint32_t>& pred = preds(bb->id());
|
||||
// Find the back edge
|
||||
ir::BasicBlock* latch_block = nullptr;
|
||||
Function::iterator latch_block_iter = header_it;
|
||||
while (++latch_block_iter != fn->end()) {
|
||||
// If blocks are in the proper order, then the only branch that appears
|
||||
// after the header is the latch.
|
||||
if (std::find(pred.begin(), pred.end(), latch_block_iter->id()) !=
|
||||
pred.end()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(latch_block_iter != fn->end() && "Could not find the latch.");
|
||||
latch_block = &*latch_block_iter;
|
||||
|
||||
RemoveSuccessorEdges(bb);
|
||||
|
||||
// Create the new header bb basic bb.
|
||||
// Leave the phi instructions behind.
|
||||
auto iter = bb->begin();
|
||||
while (iter->opcode() == SpvOpPhi) {
|
||||
++iter;
|
||||
}
|
||||
|
||||
std::unique_ptr<ir::BasicBlock> newBlock(
|
||||
bb->SplitBasicBlock(context, context->TakeNextId(), iter));
|
||||
|
||||
// Insert the new bb in the correct position
|
||||
auto insert_pos = header_it;
|
||||
++insert_pos;
|
||||
ir::BasicBlock* new_header = &*insert_pos.InsertBefore(std::move(newBlock));
|
||||
new_header->SetParent(fn);
|
||||
uint32_t new_header_id = new_header->id();
|
||||
context->AnalyzeDefUse(new_header->GetLabelInst());
|
||||
|
||||
// Update cfg
|
||||
RegisterBlock(new_header);
|
||||
|
||||
// Update bb mappings.
|
||||
context->set_instr_block(new_header->GetLabelInst(), new_header);
|
||||
new_header->ForEachInst([new_header, context](ir::Instruction* inst) {
|
||||
context->set_instr_block(inst, new_header);
|
||||
});
|
||||
|
||||
// Adjust the OpPhi instructions as needed.
|
||||
bb->ForEachPhiInst([latch_block, bb, new_header, context](Instruction* phi) {
|
||||
std::vector<uint32_t> preheader_phi_ops;
|
||||
std::vector<Operand> header_phi_ops;
|
||||
|
||||
// Identify where the original inputs to original OpPhi belong: header or
|
||||
// preheader.
|
||||
for (uint32_t i = 0; i < phi->NumInOperands(); i += 2) {
|
||||
uint32_t def_id = phi->GetSingleWordInOperand(i);
|
||||
uint32_t branch_id = phi->GetSingleWordInOperand(i + 1);
|
||||
if (branch_id == latch_block->id()) {
|
||||
header_phi_ops.push_back({SPV_OPERAND_TYPE_ID, {def_id}});
|
||||
header_phi_ops.push_back({SPV_OPERAND_TYPE_ID, {branch_id}});
|
||||
} else {
|
||||
preheader_phi_ops.push_back(def_id);
|
||||
preheader_phi_ops.push_back(branch_id);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a phi instruction if and only if the preheader_phi_ops has more
|
||||
// than one pair.
|
||||
if (preheader_phi_ops.size() > 2) {
|
||||
opt::InstructionBuilder builder(
|
||||
context, &*bb->begin(),
|
||||
ir::IRContext::kAnalysisDefUse |
|
||||
ir::IRContext::kAnalysisInstrToBlockMapping);
|
||||
|
||||
ir::Instruction* new_phi =
|
||||
builder.AddPhi(phi->type_id(), preheader_phi_ops);
|
||||
|
||||
// Add the OpPhi to the header bb.
|
||||
header_phi_ops.push_back({SPV_OPERAND_TYPE_ID, {new_phi->result_id()}});
|
||||
header_phi_ops.push_back({SPV_OPERAND_TYPE_ID, {bb->id()}});
|
||||
} else {
|
||||
// An OpPhi with a single entry is just a copy. In this case use the same
|
||||
// instruction in the new header.
|
||||
header_phi_ops.push_back({SPV_OPERAND_TYPE_ID, {preheader_phi_ops[0]}});
|
||||
header_phi_ops.push_back({SPV_OPERAND_TYPE_ID, {bb->id()}});
|
||||
}
|
||||
|
||||
phi->RemoveFromList();
|
||||
std::unique_ptr<ir::Instruction> phi_owner(phi);
|
||||
phi->SetInOperands(std::move(header_phi_ops));
|
||||
new_header->begin()->InsertBefore(std::move(phi_owner));
|
||||
context->set_instr_block(phi, new_header);
|
||||
context->AnalyzeUses(phi);
|
||||
});
|
||||
|
||||
// Add a branch to the new header.
|
||||
opt::InstructionBuilder branch_builder(
|
||||
context, bb,
|
||||
ir::IRContext::kAnalysisDefUse |
|
||||
ir::IRContext::kAnalysisInstrToBlockMapping);
|
||||
bb->AddInstruction(MakeUnique<ir::Instruction>(
|
||||
context, SpvOpBranch, 0, 0,
|
||||
std::initializer_list<ir::Operand>{
|
||||
{SPV_OPERAND_TYPE_ID, {new_header->id()}}}));
|
||||
context->AnalyzeUses(bb->terminator());
|
||||
context->set_instr_block(bb->terminator(), bb);
|
||||
label2preds_[new_header->id()].push_back(bb->id());
|
||||
|
||||
// Update the latch to branch to the new header.
|
||||
latch_block->ForEachSuccessorLabel([bb, new_header_id](uint32_t* id) {
|
||||
if (*id == bb->id()) {
|
||||
*id = new_header_id;
|
||||
}
|
||||
});
|
||||
ir::Instruction* latch_branch = latch_block->terminator();
|
||||
context->AnalyzeUses(latch_branch);
|
||||
label2preds_[new_header->id()].push_back(latch_block->id());
|
||||
|
||||
auto& block_preds = label2preds_[bb->id()];
|
||||
auto latch_pos =
|
||||
std::find(block_preds.begin(), block_preds.end(), latch_block->id());
|
||||
assert(latch_pos != block_preds.end() && "The cfg was invalid.");
|
||||
block_preds.erase(latch_pos);
|
||||
|
||||
// Update the loop descriptors
|
||||
if (context->AreAnalysesValid(ir::IRContext::kAnalysisLoopAnalysis)) {
|
||||
LoopDescriptor* loop_desc = context->GetLoopDescriptor(bb->GetParent());
|
||||
Loop* loop = (*loop_desc)[bb->id()];
|
||||
|
||||
loop->AddBasicBlock(new_header_id);
|
||||
loop->SetHeaderBlock(new_header);
|
||||
loop_desc->SetBasicBlockToLoop(new_header_id, loop);
|
||||
|
||||
loop->RemoveBasicBlock(bb->id());
|
||||
loop->SetPreHeaderBlock(bb);
|
||||
|
||||
Loop* parent_loop = loop->GetParent();
|
||||
if (parent_loop != nullptr) {
|
||||
parent_loop->AddBasicBlock(bb->id());
|
||||
loop_desc->SetBasicBlockToLoop(bb->id(), parent_loop);
|
||||
} else {
|
||||
loop_desc->SetBasicBlockToLoop(bb->id(), nullptr);
|
||||
}
|
||||
}
|
||||
return new_header;
|
||||
}
|
||||
|
||||
unordered_set<BasicBlock*> CFG::FindReachableBlocks(BasicBlock* start) {
|
||||
std::unordered_set<BasicBlock*> reachable_blocks;
|
||||
ForEachBlockInReversePostOrder(start, [&reachable_blocks](BasicBlock* bb) {
|
||||
reachable_blocks.insert(bb);
|
||||
});
|
||||
return reachable_blocks;
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace spvtools
|
175
3rdparty/spirv-tools/source/opt/cfg.h
vendored
Normal file
175
3rdparty/spirv-tools/source/opt/cfg.h
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_CFG_H_
|
||||
#define LIBSPIRV_OPT_CFG_H_
|
||||
|
||||
#include "basic_block.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace spvtools {
|
||||
namespace ir {
|
||||
|
||||
class CFG {
|
||||
public:
|
||||
CFG(ir::Module* module);
|
||||
|
||||
// Return the module described by this CFG.
|
||||
ir::Module* get_module() const { return module_; }
|
||||
|
||||
// Return the list of predecesors for basic block with label |blkid|.
|
||||
// TODO(dnovillo): Move this to ir::BasicBlock.
|
||||
const std::vector<uint32_t>& preds(uint32_t blk_id) const {
|
||||
assert(label2preds_.count(blk_id));
|
||||
return label2preds_.at(blk_id);
|
||||
}
|
||||
|
||||
// Return a pointer to the basic block instance corresponding to the label
|
||||
// |blk_id|.
|
||||
ir::BasicBlock* block(uint32_t blk_id) const { return id2block_.at(blk_id); }
|
||||
|
||||
// Return the pseudo entry and exit blocks.
|
||||
const ir::BasicBlock* pseudo_entry_block() const {
|
||||
return &pseudo_entry_block_;
|
||||
}
|
||||
ir::BasicBlock* pseudo_entry_block() { return &pseudo_entry_block_; }
|
||||
|
||||
const ir::BasicBlock* pseudo_exit_block() const {
|
||||
return &pseudo_exit_block_;
|
||||
}
|
||||
ir::BasicBlock* pseudo_exit_block() { return &pseudo_exit_block_; }
|
||||
|
||||
// Return true if |block_ptr| is the pseudo-entry block.
|
||||
bool IsPseudoEntryBlock(ir::BasicBlock* block_ptr) const {
|
||||
return block_ptr == &pseudo_entry_block_;
|
||||
}
|
||||
|
||||
// Return true if |block_ptr| is the pseudo-exit block.
|
||||
bool IsPseudoExitBlock(ir::BasicBlock* block_ptr) const {
|
||||
return block_ptr == &pseudo_exit_block_;
|
||||
}
|
||||
|
||||
// Compute structured block order into |order| for |func| starting at |root|.
|
||||
// This order has the property that dominators come before all blocks they
|
||||
// dominate and merge blocks come after all blocks that are in the control
|
||||
// constructs of their header.
|
||||
void ComputeStructuredOrder(ir::Function* func, ir::BasicBlock* root,
|
||||
std::list<ir::BasicBlock*>* order);
|
||||
|
||||
// Applies |f| to the basic block in reverse post order starting with |bb|.
|
||||
// Note that basic blocks that cannot be reached from |bb| node will not be
|
||||
// processed.
|
||||
void ForEachBlockInReversePostOrder(
|
||||
BasicBlock* bb, const std::function<void(BasicBlock*)>& f);
|
||||
|
||||
// Registers |blk| as a basic block in the cfg, this also updates the
|
||||
// predecessor lists of each successor of |blk|.
|
||||
void RegisterBlock(ir::BasicBlock* blk) {
|
||||
uint32_t blk_id = blk->id();
|
||||
id2block_[blk_id] = blk;
|
||||
AddEdges(blk);
|
||||
}
|
||||
|
||||
// Removes from the CFG any mapping for the basic block id |blk_id|.
|
||||
void ForgetBlock(const ir::BasicBlock* blk) {
|
||||
id2block_.erase(blk->id());
|
||||
label2preds_.erase(blk->id());
|
||||
RemoveSuccessorEdges(blk);
|
||||
}
|
||||
|
||||
void RemoveEdge(uint32_t pred_blk_id, uint32_t succ_blk_id) {
|
||||
auto pred_it = label2preds_.find(succ_blk_id);
|
||||
if (pred_it == label2preds_.end()) return;
|
||||
auto& preds_list = pred_it->second;
|
||||
auto it = std::find(preds_list.begin(), preds_list.end(), pred_blk_id);
|
||||
if (it != preds_list.end()) preds_list.erase(it);
|
||||
}
|
||||
|
||||
// Registers |blk| to all of its successors.
|
||||
void AddEdges(ir::BasicBlock* blk);
|
||||
|
||||
// Registers the basic block id |pred_blk_id| as being a predecessor of the
|
||||
// basic block id |succ_blk_id|.
|
||||
void AddEdge(uint32_t pred_blk_id, uint32_t succ_blk_id) {
|
||||
label2preds_[succ_blk_id].push_back(pred_blk_id);
|
||||
}
|
||||
|
||||
// Removes any edges that no longer exist from the predecessor mapping for
|
||||
// the basic block id |blk_id|.
|
||||
void RemoveNonExistingEdges(uint32_t blk_id);
|
||||
|
||||
// Remove all edges that leave |bb|.
|
||||
void RemoveSuccessorEdges(const ir::BasicBlock* bb) {
|
||||
bb->ForEachSuccessorLabel(
|
||||
[bb, this](uint32_t succ_id) { RemoveEdge(bb->id(), succ_id); });
|
||||
}
|
||||
|
||||
// Divides |block| into two basic blocks. The first block will have the same
|
||||
// id as |block| and will become a preheader for the loop. The other block
|
||||
// is a new block that will be the new loop header.
|
||||
//
|
||||
// Returns a pointer to the new loop header.
|
||||
BasicBlock* SplitLoopHeader(ir::BasicBlock* bb);
|
||||
|
||||
std::unordered_set<BasicBlock*> FindReachableBlocks(BasicBlock* start);
|
||||
|
||||
private:
|
||||
using cbb_ptr = const ir::BasicBlock*;
|
||||
|
||||
// Compute structured successors for function |func|. A block's structured
|
||||
// successors are the blocks it branches to together with its declared merge
|
||||
// block and continue block if it has them. When order matters, the merge
|
||||
// block and continue block always appear first. This assures correct depth
|
||||
// first search in the presence of early returns and kills. If the successor
|
||||
// vector contain duplicates of the merge or continue blocks, they are safely
|
||||
// ignored by DFS.
|
||||
void ComputeStructuredSuccessors(ir::Function* func);
|
||||
|
||||
// Computes the post-order traversal of the cfg starting at |bb| skipping
|
||||
// nodes in |seen|. The order of the traversal is appended to |order|, and
|
||||
// all nodes in the traversal are added to |seen|.
|
||||
void ComputePostOrderTraversal(BasicBlock* bb,
|
||||
std::vector<BasicBlock*>* order,
|
||||
std::unordered_set<BasicBlock*>* seen);
|
||||
|
||||
// Module for this CFG.
|
||||
ir::Module* module_;
|
||||
|
||||
// Map from block to its structured successor blocks. See
|
||||
// ComputeStructuredSuccessors() for definition.
|
||||
std::unordered_map<const ir::BasicBlock*, std::vector<ir::BasicBlock*>>
|
||||
block2structured_succs_;
|
||||
|
||||
// Extra block whose successors are all blocks with no predecessors
|
||||
// in function.
|
||||
ir::BasicBlock pseudo_entry_block_;
|
||||
|
||||
// Augmented CFG Exit Block.
|
||||
ir::BasicBlock pseudo_exit_block_;
|
||||
|
||||
// Map from block's label id to its predecessor blocks ids
|
||||
std::unordered_map<uint32_t, std::vector<uint32_t>> label2preds_;
|
||||
|
||||
// Map from block's label id to block.
|
||||
std::unordered_map<uint32_t, ir::BasicBlock*> id2block_;
|
||||
};
|
||||
|
||||
} // namespace ir
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // LIBSPIRV_OPT_CFG_H_
|
43
3rdparty/spirv-tools/source/opt/cfg_cleanup_pass.cpp
vendored
Normal file
43
3rdparty/spirv-tools/source/opt/cfg_cleanup_pass.cpp
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// This file implements a pass to cleanup the CFG to remove superfluous
|
||||
// constructs (e.g., unreachable basic blocks, empty control flow structures,
|
||||
// etc)
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "cfg_cleanup_pass.h"
|
||||
|
||||
#include "function.h"
|
||||
#include "module.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
void CFGCleanupPass::Initialize(ir::IRContext* c) { InitializeProcessing(c); }
|
||||
|
||||
Pass::Status CFGCleanupPass::Process(ir::IRContext* c) {
|
||||
Initialize(c);
|
||||
|
||||
// Process all entry point functions.
|
||||
ProcessFunction pfn = [this](ir::Function* fp) { return CFGCleanup(fp); };
|
||||
bool modified = ProcessReachableCallTree(pfn, context());
|
||||
return modified ? Pass::Status::SuccessWithChange
|
||||
: Pass::Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
43
3rdparty/spirv-tools/source/opt/cfg_cleanup_pass.h
vendored
Normal file
43
3rdparty/spirv-tools/source/opt/cfg_cleanup_pass.h
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2017 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef LIBSPIRV_OPT_CFG_CLEANUP_PASS_H_
|
||||
#define LIBSPIRV_OPT_CFG_CLEANUP_PASS_H_
|
||||
|
||||
#include "function.h"
|
||||
#include "mem_pass.h"
|
||||
#include "module.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
class CFGCleanupPass : public MemPass {
|
||||
public:
|
||||
CFGCleanupPass() = default;
|
||||
const char* name() const override { return "cfg-cleanup"; }
|
||||
Status Process(ir::IRContext* c) override;
|
||||
|
||||
ir::IRContext::Analysis GetPreservedAnalyses() override {
|
||||
return ir::IRContext::kAnalysisDefUse;
|
||||
}
|
||||
|
||||
private:
|
||||
// Initialize the pass.
|
||||
void Initialize(ir::IRContext* c);
|
||||
};
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
||||
|
||||
#endif
|
581
3rdparty/spirv-tools/source/opt/common_uniform_elim_pass.cpp
vendored
Normal file
581
3rdparty/spirv-tools/source/opt/common_uniform_elim_pass.cpp
vendored
Normal file
@ -0,0 +1,581 @@
|
||||
// Copyright (c) 2017 The Khronos Group Inc.
|
||||
// Copyright (c) 2017 Valve Corporation
|
||||
// Copyright (c) 2017 LunarG Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "common_uniform_elim_pass.h"
|
||||
#include "cfa.h"
|
||||
#include "ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kAccessChainPtrIdInIdx = 0;
|
||||
const uint32_t kTypePointerStorageClassInIdx = 0;
|
||||
const uint32_t kTypePointerTypeIdInIdx = 1;
|
||||
const uint32_t kConstantValueInIdx = 0;
|
||||
const uint32_t kExtractCompositeIdInIdx = 0;
|
||||
const uint32_t kExtractIdx0InIdx = 1;
|
||||
const uint32_t kStorePtrIdInIdx = 0;
|
||||
const uint32_t kLoadPtrIdInIdx = 0;
|
||||
const uint32_t kCopyObjectOperandInIdx = 0;
|
||||
const uint32_t kTypeIntWidthInIdx = 0;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool CommonUniformElimPass::IsNonPtrAccessChain(const SpvOp opcode) const {
|
||||
return opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain;
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::IsSamplerOrImageType(
|
||||
const ir::Instruction* typeInst) const {
|
||||
switch (typeInst->opcode()) {
|
||||
case SpvOpTypeSampler:
|
||||
case SpvOpTypeImage:
|
||||
case SpvOpTypeSampledImage:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (typeInst->opcode() != SpvOpTypeStruct) return false;
|
||||
// Return true if any member is a sampler or image
|
||||
return !typeInst->WhileEachInId([this](const uint32_t* tid) {
|
||||
const ir::Instruction* compTypeInst = get_def_use_mgr()->GetDef(*tid);
|
||||
if (IsSamplerOrImageType(compTypeInst)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::IsSamplerOrImageVar(uint32_t varId) const {
|
||||
const ir::Instruction* varInst = get_def_use_mgr()->GetDef(varId);
|
||||
assert(varInst->opcode() == SpvOpVariable);
|
||||
const uint32_t varTypeId = varInst->type_id();
|
||||
const ir::Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
|
||||
const uint32_t varPteTypeId =
|
||||
varTypeInst->GetSingleWordInOperand(kTypePointerTypeIdInIdx);
|
||||
ir::Instruction* varPteTypeInst = get_def_use_mgr()->GetDef(varPteTypeId);
|
||||
return IsSamplerOrImageType(varPteTypeInst);
|
||||
}
|
||||
|
||||
ir::Instruction* CommonUniformElimPass::GetPtr(ir::Instruction* ip,
|
||||
uint32_t* objId) {
|
||||
const SpvOp op = ip->opcode();
|
||||
assert(op == SpvOpStore || op == SpvOpLoad);
|
||||
*objId = ip->GetSingleWordInOperand(op == SpvOpStore ? kStorePtrIdInIdx
|
||||
: kLoadPtrIdInIdx);
|
||||
ir::Instruction* ptrInst = get_def_use_mgr()->GetDef(*objId);
|
||||
while (ptrInst->opcode() == SpvOpCopyObject) {
|
||||
*objId = ptrInst->GetSingleWordInOperand(kCopyObjectOperandInIdx);
|
||||
ptrInst = get_def_use_mgr()->GetDef(*objId);
|
||||
}
|
||||
ir::Instruction* objInst = ptrInst;
|
||||
while (objInst->opcode() != SpvOpVariable &&
|
||||
objInst->opcode() != SpvOpFunctionParameter) {
|
||||
if (IsNonPtrAccessChain(objInst->opcode())) {
|
||||
*objId = objInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx);
|
||||
} else {
|
||||
assert(objInst->opcode() == SpvOpCopyObject);
|
||||
*objId = objInst->GetSingleWordInOperand(kCopyObjectOperandInIdx);
|
||||
}
|
||||
objInst = get_def_use_mgr()->GetDef(*objId);
|
||||
}
|
||||
return ptrInst;
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::IsVolatileStruct(uint32_t type_id) {
|
||||
assert(get_def_use_mgr()->GetDef(type_id)->opcode() == SpvOpTypeStruct);
|
||||
return !get_decoration_mgr()->WhileEachDecoration(
|
||||
type_id, SpvDecorationVolatile,
|
||||
[](const ir::Instruction&) { return false; });
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::IsAccessChainToVolatileStructType(
|
||||
const ir::Instruction& AccessChainInst) {
|
||||
assert(AccessChainInst.opcode() == SpvOpAccessChain);
|
||||
|
||||
uint32_t ptr_id = AccessChainInst.GetSingleWordInOperand(0);
|
||||
const ir::Instruction* ptr_inst = get_def_use_mgr()->GetDef(ptr_id);
|
||||
uint32_t pointee_type_id = GetPointeeTypeId(ptr_inst);
|
||||
const uint32_t num_operands = AccessChainInst.NumOperands();
|
||||
|
||||
// walk the type tree:
|
||||
for (uint32_t idx = 3; idx < num_operands; ++idx) {
|
||||
ir::Instruction* pointee_type = get_def_use_mgr()->GetDef(pointee_type_id);
|
||||
|
||||
switch (pointee_type->opcode()) {
|
||||
case SpvOpTypeMatrix:
|
||||
case SpvOpTypeVector:
|
||||
case SpvOpTypeArray:
|
||||
case SpvOpTypeRuntimeArray:
|
||||
pointee_type_id = pointee_type->GetSingleWordOperand(1);
|
||||
break;
|
||||
case SpvOpTypeStruct:
|
||||
// check for volatile decorations:
|
||||
if (IsVolatileStruct(pointee_type_id)) return true;
|
||||
|
||||
if (idx < num_operands - 1) {
|
||||
const uint32_t index_id = AccessChainInst.GetSingleWordOperand(idx);
|
||||
const ir::Instruction* index_inst =
|
||||
get_def_use_mgr()->GetDef(index_id);
|
||||
uint32_t index_value = index_inst->GetSingleWordOperand(
|
||||
2); // TODO: replace with GetUintValueFromConstant()
|
||||
pointee_type_id = pointee_type->GetSingleWordInOperand(index_value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(false && "Unhandled pointee type.");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::IsVolatileLoad(const ir::Instruction& loadInst) {
|
||||
assert(loadInst.opcode() == SpvOpLoad);
|
||||
// Check if this Load instruction has Volatile Memory Access flag
|
||||
if (loadInst.NumOperands() == 4) {
|
||||
uint32_t memory_access_mask = loadInst.GetSingleWordOperand(3);
|
||||
if (memory_access_mask & SpvMemoryAccessVolatileMask) return true;
|
||||
}
|
||||
// If we load a struct directly (result type is struct),
|
||||
// check if the struct is decorated volatile
|
||||
uint32_t type_id = loadInst.type_id();
|
||||
if (get_def_use_mgr()->GetDef(type_id)->opcode() == SpvOpTypeStruct)
|
||||
return IsVolatileStruct(type_id);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::IsUniformVar(uint32_t varId) {
|
||||
const ir::Instruction* varInst =
|
||||
get_def_use_mgr()->id_to_defs().find(varId)->second;
|
||||
if (varInst->opcode() != SpvOpVariable) return false;
|
||||
const uint32_t varTypeId = varInst->type_id();
|
||||
const ir::Instruction* varTypeInst =
|
||||
get_def_use_mgr()->id_to_defs().find(varTypeId)->second;
|
||||
return varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) ==
|
||||
SpvStorageClassUniform ||
|
||||
varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) ==
|
||||
SpvStorageClassUniformConstant;
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::HasUnsupportedDecorates(uint32_t id) const {
|
||||
return !get_def_use_mgr()->WhileEachUser(id, [this](ir::Instruction* user) {
|
||||
if (IsNonTypeDecorate(user->opcode())) return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::HasOnlyNamesAndDecorates(uint32_t id) const {
|
||||
return get_def_use_mgr()->WhileEachUser(id, [this](ir::Instruction* user) {
|
||||
SpvOp op = user->opcode();
|
||||
if (op != SpvOpName && !IsNonTypeDecorate(op)) return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void CommonUniformElimPass::DeleteIfUseless(ir::Instruction* inst) {
|
||||
const uint32_t resId = inst->result_id();
|
||||
assert(resId != 0);
|
||||
if (HasOnlyNamesAndDecorates(resId)) {
|
||||
context()->KillInst(inst);
|
||||
}
|
||||
}
|
||||
|
||||
ir::Instruction* CommonUniformElimPass::ReplaceAndDeleteLoad(
|
||||
ir::Instruction* loadInst, uint32_t replId, ir::Instruction* ptrInst) {
|
||||
const uint32_t loadId = loadInst->result_id();
|
||||
context()->KillNamesAndDecorates(loadId);
|
||||
(void)context()->ReplaceAllUsesWith(loadId, replId);
|
||||
// remove load instruction
|
||||
ir::Instruction* next_instruction = context()->KillInst(loadInst);
|
||||
// if access chain, see if it can be removed as well
|
||||
if (IsNonPtrAccessChain(ptrInst->opcode())) DeleteIfUseless(ptrInst);
|
||||
return next_instruction;
|
||||
}
|
||||
|
||||
void CommonUniformElimPass::GenACLoadRepl(
|
||||
const ir::Instruction* ptrInst,
|
||||
std::vector<std::unique_ptr<ir::Instruction>>* newInsts,
|
||||
uint32_t* resultId) {
|
||||
// Build and append Load
|
||||
const uint32_t ldResultId = TakeNextId();
|
||||
const uint32_t varId =
|
||||
ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx);
|
||||
const ir::Instruction* varInst = get_def_use_mgr()->GetDef(varId);
|
||||
assert(varInst->opcode() == SpvOpVariable);
|
||||
const uint32_t varPteTypeId = GetPointeeTypeId(varInst);
|
||||
std::vector<ir::Operand> load_in_operands;
|
||||
load_in_operands.push_back(
|
||||
ir::Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID,
|
||||
std::initializer_list<uint32_t>{varId}));
|
||||
std::unique_ptr<ir::Instruction> newLoad(new ir::Instruction(
|
||||
context(), SpvOpLoad, varPteTypeId, ldResultId, load_in_operands));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*newLoad);
|
||||
newInsts->emplace_back(std::move(newLoad));
|
||||
|
||||
// Build and append Extract
|
||||
const uint32_t extResultId = TakeNextId();
|
||||
const uint32_t ptrPteTypeId = GetPointeeTypeId(ptrInst);
|
||||
std::vector<ir::Operand> ext_in_opnds;
|
||||
ext_in_opnds.push_back(
|
||||
ir::Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID,
|
||||
std::initializer_list<uint32_t>{ldResultId}));
|
||||
uint32_t iidIdx = 0;
|
||||
ptrInst->ForEachInId([&iidIdx, &ext_in_opnds, this](const uint32_t* iid) {
|
||||
if (iidIdx > 0) {
|
||||
const ir::Instruction* cInst = get_def_use_mgr()->GetDef(*iid);
|
||||
uint32_t val = cInst->GetSingleWordInOperand(kConstantValueInIdx);
|
||||
ext_in_opnds.push_back(
|
||||
ir::Operand(spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
std::initializer_list<uint32_t>{val}));
|
||||
}
|
||||
++iidIdx;
|
||||
});
|
||||
std::unique_ptr<ir::Instruction> newExt(
|
||||
new ir::Instruction(context(), SpvOpCompositeExtract, ptrPteTypeId,
|
||||
extResultId, ext_in_opnds));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*newExt);
|
||||
newInsts->emplace_back(std::move(newExt));
|
||||
*resultId = extResultId;
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::IsConstantIndexAccessChain(ir::Instruction* acp) {
|
||||
uint32_t inIdx = 0;
|
||||
return acp->WhileEachInId([&inIdx, this](uint32_t* tid) {
|
||||
if (inIdx > 0) {
|
||||
ir::Instruction* opInst = get_def_use_mgr()->GetDef(*tid);
|
||||
if (opInst->opcode() != SpvOpConstant) return false;
|
||||
}
|
||||
++inIdx;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::UniformAccessChainConvert(ir::Function* func) {
|
||||
bool modified = false;
|
||||
for (auto bi = func->begin(); bi != func->end(); ++bi) {
|
||||
for (ir::Instruction* inst = &*bi->begin(); inst; inst = inst->NextNode()) {
|
||||
if (inst->opcode() != SpvOpLoad) continue;
|
||||
uint32_t varId;
|
||||
ir::Instruction* ptrInst = GetPtr(inst, &varId);
|
||||
if (!IsNonPtrAccessChain(ptrInst->opcode())) continue;
|
||||
// Do not convert nested access chains
|
||||
if (ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx) != varId)
|
||||
continue;
|
||||
if (!IsUniformVar(varId)) continue;
|
||||
if (!IsConstantIndexAccessChain(ptrInst)) continue;
|
||||
if (HasUnsupportedDecorates(inst->result_id())) continue;
|
||||
if (HasUnsupportedDecorates(ptrInst->result_id())) continue;
|
||||
if (IsVolatileLoad(*inst)) continue;
|
||||
if (IsAccessChainToVolatileStructType(*ptrInst)) continue;
|
||||
std::vector<std::unique_ptr<ir::Instruction>> newInsts;
|
||||
uint32_t replId;
|
||||
GenACLoadRepl(ptrInst, &newInsts, &replId);
|
||||
inst = ReplaceAndDeleteLoad(inst, replId, ptrInst);
|
||||
inst = inst->InsertBefore(std::move(newInsts));
|
||||
modified = true;
|
||||
};
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
void CommonUniformElimPass::ComputeStructuredSuccessors(ir::Function* func) {
|
||||
block2structured_succs_.clear();
|
||||
for (auto& blk : *func) {
|
||||
// If header, make merge block first successor.
|
||||
uint32_t mbid = blk.MergeBlockIdIfAny();
|
||||
if (mbid != 0) {
|
||||
block2structured_succs_[&blk].push_back(cfg()->block(mbid));
|
||||
uint32_t cbid = blk.ContinueBlockIdIfAny();
|
||||
if (cbid != 0) {
|
||||
block2structured_succs_[&blk].push_back(cfg()->block(mbid));
|
||||
}
|
||||
}
|
||||
// add true successors
|
||||
const auto& const_blk = blk;
|
||||
const_blk.ForEachSuccessorLabel([&blk, this](const uint32_t sbid) {
|
||||
block2structured_succs_[&blk].push_back(cfg()->block(sbid));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void CommonUniformElimPass::ComputeStructuredOrder(
|
||||
ir::Function* func, std::list<ir::BasicBlock*>* order) {
|
||||
// Compute structured successors and do DFS
|
||||
ComputeStructuredSuccessors(func);
|
||||
auto ignore_block = [](cbb_ptr) {};
|
||||
auto ignore_edge = [](cbb_ptr, cbb_ptr) {};
|
||||
auto get_structured_successors = [this](const ir::BasicBlock* block) {
|
||||
return &(block2structured_succs_[block]);
|
||||
};
|
||||
// TODO(greg-lunarg): Get rid of const_cast by making moving const
|
||||
// out of the cfa.h prototypes and into the invoking code.
|
||||
auto post_order = [&](cbb_ptr b) {
|
||||
order->push_front(const_cast<ir::BasicBlock*>(b));
|
||||
};
|
||||
|
||||
order->clear();
|
||||
spvtools::CFA<ir::BasicBlock>::DepthFirstTraversal(
|
||||
&*func->begin(), get_structured_successors, ignore_block, post_order,
|
||||
ignore_edge);
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::CommonUniformLoadElimination(ir::Function* func) {
|
||||
// Process all blocks in structured order. This is just one way (the
|
||||
// simplest?) to keep track of the most recent block outside of control
|
||||
// flow, used to copy common instructions, guaranteed to dominate all
|
||||
// following load sites.
|
||||
std::list<ir::BasicBlock*> structuredOrder;
|
||||
ComputeStructuredOrder(func, &structuredOrder);
|
||||
uniform2load_id_.clear();
|
||||
bool modified = false;
|
||||
// Find insertion point in first block to copy non-dominating loads.
|
||||
auto insertItr = func->begin()->begin();
|
||||
while (insertItr->opcode() == SpvOpVariable ||
|
||||
insertItr->opcode() == SpvOpNop)
|
||||
++insertItr;
|
||||
uint32_t mergeBlockId = 0;
|
||||
for (auto bi = structuredOrder.begin(); bi != structuredOrder.end(); ++bi) {
|
||||
ir::BasicBlock* bp = *bi;
|
||||
// Check if we are exiting outermost control construct. If so, remember
|
||||
// new load insertion point. Trying to keep register pressure down.
|
||||
if (mergeBlockId == bp->id()) {
|
||||
mergeBlockId = 0;
|
||||
insertItr = bp->begin();
|
||||
}
|
||||
for (ir::Instruction* inst = &*bp->begin(); inst; inst = inst->NextNode()) {
|
||||
if (inst->opcode() != SpvOpLoad) continue;
|
||||
uint32_t varId;
|
||||
ir::Instruction* ptrInst = GetPtr(inst, &varId);
|
||||
if (ptrInst->opcode() != SpvOpVariable) continue;
|
||||
if (!IsUniformVar(varId)) continue;
|
||||
if (IsSamplerOrImageVar(varId)) continue;
|
||||
if (HasUnsupportedDecorates(inst->result_id())) continue;
|
||||
if (IsVolatileLoad(*inst)) continue;
|
||||
uint32_t replId;
|
||||
const auto uItr = uniform2load_id_.find(varId);
|
||||
if (uItr != uniform2load_id_.end()) {
|
||||
replId = uItr->second;
|
||||
} else {
|
||||
if (mergeBlockId == 0) {
|
||||
// Load is in dominating block; just remember it
|
||||
uniform2load_id_[varId] = inst->result_id();
|
||||
continue;
|
||||
} else {
|
||||
// Copy load into most recent dominating block and remember it
|
||||
replId = TakeNextId();
|
||||
std::unique_ptr<ir::Instruction> newLoad(new ir::Instruction(
|
||||
context(), SpvOpLoad, inst->type_id(), replId,
|
||||
{{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {varId}}}));
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*newLoad);
|
||||
insertItr = insertItr.InsertBefore(std::move(newLoad));
|
||||
++insertItr;
|
||||
uniform2load_id_[varId] = replId;
|
||||
}
|
||||
}
|
||||
inst = ReplaceAndDeleteLoad(inst, replId, ptrInst);
|
||||
modified = true;
|
||||
}
|
||||
// If we are outside of any control construct and entering one, remember
|
||||
// the id of the merge block
|
||||
if (mergeBlockId == 0) {
|
||||
mergeBlockId = bp->MergeBlockIdIfAny();
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::CommonUniformLoadElimBlock(ir::Function* func) {
|
||||
bool modified = false;
|
||||
for (auto& blk : *func) {
|
||||
uniform2load_id_.clear();
|
||||
for (ir::Instruction* inst = &*blk.begin(); inst; inst = inst->NextNode()) {
|
||||
if (inst->opcode() != SpvOpLoad) continue;
|
||||
uint32_t varId;
|
||||
ir::Instruction* ptrInst = GetPtr(inst, &varId);
|
||||
if (ptrInst->opcode() != SpvOpVariable) continue;
|
||||
if (!IsUniformVar(varId)) continue;
|
||||
if (!IsSamplerOrImageVar(varId)) continue;
|
||||
if (HasUnsupportedDecorates(inst->result_id())) continue;
|
||||
if (IsVolatileLoad(*inst)) continue;
|
||||
uint32_t replId;
|
||||
const auto uItr = uniform2load_id_.find(varId);
|
||||
if (uItr != uniform2load_id_.end()) {
|
||||
replId = uItr->second;
|
||||
} else {
|
||||
uniform2load_id_[varId] = inst->result_id();
|
||||
continue;
|
||||
}
|
||||
inst = ReplaceAndDeleteLoad(inst, replId, ptrInst);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::CommonExtractElimination(ir::Function* func) {
|
||||
// Find all composite ids with duplicate extracts.
|
||||
for (auto bi = func->begin(); bi != func->end(); ++bi) {
|
||||
for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
|
||||
if (ii->opcode() != SpvOpCompositeExtract) continue;
|
||||
// TODO(greg-lunarg): Support multiple indices
|
||||
if (ii->NumInOperands() > 2) continue;
|
||||
if (HasUnsupportedDecorates(ii->result_id())) continue;
|
||||
uint32_t compId = ii->GetSingleWordInOperand(kExtractCompositeIdInIdx);
|
||||
uint32_t idx = ii->GetSingleWordInOperand(kExtractIdx0InIdx);
|
||||
comp2idx2inst_[compId][idx].push_back(&*ii);
|
||||
}
|
||||
}
|
||||
// For all defs of ids with duplicate extracts, insert new extracts
|
||||
// after def, and replace and delete old extracts
|
||||
bool modified = false;
|
||||
for (auto bi = func->begin(); bi != func->end(); ++bi) {
|
||||
for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
|
||||
const auto cItr = comp2idx2inst_.find(ii->result_id());
|
||||
if (cItr == comp2idx2inst_.end()) continue;
|
||||
for (auto idxItr : cItr->second) {
|
||||
if (idxItr.second.size() < 2) continue;
|
||||
uint32_t replId = TakeNextId();
|
||||
std::unique_ptr<ir::Instruction> newExtract(
|
||||
idxItr.second.front()->Clone(context()));
|
||||
newExtract->SetResultId(replId);
|
||||
get_def_use_mgr()->AnalyzeInstDefUse(&*newExtract);
|
||||
++ii;
|
||||
ii = ii.InsertBefore(std::move(newExtract));
|
||||
for (auto instItr : idxItr.second) {
|
||||
uint32_t resId = instItr->result_id();
|
||||
context()->KillNamesAndDecorates(resId);
|
||||
(void)context()->ReplaceAllUsesWith(resId, replId);
|
||||
context()->KillInst(instItr);
|
||||
}
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::EliminateCommonUniform(ir::Function* func) {
|
||||
bool modified = false;
|
||||
modified |= UniformAccessChainConvert(func);
|
||||
modified |= CommonUniformLoadElimination(func);
|
||||
modified |= CommonExtractElimination(func);
|
||||
|
||||
modified |= CommonUniformLoadElimBlock(func);
|
||||
return modified;
|
||||
}
|
||||
|
||||
void CommonUniformElimPass::Initialize(ir::IRContext* c) {
|
||||
InitializeProcessing(c);
|
||||
|
||||
// Clear collections.
|
||||
comp2idx2inst_.clear();
|
||||
|
||||
// Initialize extension whitelist
|
||||
InitExtensions();
|
||||
}
|
||||
|
||||
bool CommonUniformElimPass::AllExtensionsSupported() const {
|
||||
// If any extension not in whitelist, return false
|
||||
for (auto& ei : get_module()->extensions()) {
|
||||
const char* extName =
|
||||
reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
|
||||
if (extensions_whitelist_.find(extName) == extensions_whitelist_.end())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Pass::Status CommonUniformElimPass::ProcessImpl() {
|
||||
// Assumes all control flow structured.
|
||||
// TODO(greg-lunarg): Do SSA rewrite for non-structured control flow
|
||||
if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
|
||||
return Status::SuccessWithoutChange;
|
||||
// Assumes logical addressing only
|
||||
// TODO(greg-lunarg): Add support for physical addressing
|
||||
if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
|
||||
return Status::SuccessWithoutChange;
|
||||
// Do not process if any disallowed extensions are enabled
|
||||
if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
|
||||
// Do not process if module contains OpGroupDecorate. Additional
|
||||
// support required in KillNamesAndDecorates().
|
||||
// TODO(greg-lunarg): Add support for OpGroupDecorate
|
||||
for (auto& ai : get_module()->annotations())
|
||||
if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange;
|
||||
// If non-32-bit integer type in module, terminate processing
|
||||
// TODO(): Handle non-32-bit integer constants in access chains
|
||||
for (const ir::Instruction& inst : get_module()->types_values())
|
||||
if (inst.opcode() == SpvOpTypeInt &&
|
||||
inst.GetSingleWordInOperand(kTypeIntWidthInIdx) != 32)
|
||||
return Status::SuccessWithoutChange;
|
||||
// Process entry point functions
|
||||
ProcessFunction pfn = [this](ir::Function* fp) {
|
||||
return EliminateCommonUniform(fp);
|
||||
};
|
||||
bool modified = ProcessEntryPointCallTree(pfn, get_module());
|
||||
return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
|
||||
}
|
||||
|
||||
CommonUniformElimPass::CommonUniformElimPass() {}
|
||||
|
||||
Pass::Status CommonUniformElimPass::Process(ir::IRContext* c) {
|
||||
Initialize(c);
|
||||
return ProcessImpl();
|
||||
}
|
||||
|
||||
void CommonUniformElimPass::InitExtensions() {
|
||||
extensions_whitelist_.clear();
|
||||
extensions_whitelist_.insert({
|
||||
"SPV_AMD_shader_explicit_vertex_parameter",
|
||||
"SPV_AMD_shader_trinary_minmax",
|
||||
"SPV_AMD_gcn_shader",
|
||||
"SPV_KHR_shader_ballot",
|
||||
"SPV_AMD_shader_ballot",
|
||||
"SPV_AMD_gpu_shader_half_float",
|
||||
"SPV_KHR_shader_draw_parameters",
|
||||
"SPV_KHR_subgroup_vote",
|
||||
"SPV_KHR_16bit_storage",
|
||||
"SPV_KHR_device_group",
|
||||
"SPV_KHR_multiview",
|
||||
"SPV_NVX_multiview_per_view_attributes",
|
||||
"SPV_NV_viewport_array2",
|
||||
"SPV_NV_stereo_view_rendering",
|
||||
"SPV_NV_sample_mask_override_coverage",
|
||||
"SPV_NV_geometry_shader_passthrough",
|
||||
"SPV_AMD_texture_gather_bias_lod",
|
||||
"SPV_KHR_storage_buffer_storage_class",
|
||||
// SPV_KHR_variable_pointers
|
||||
// Currently do not support extended pointer expressions
|
||||
"SPV_AMD_gpu_shader_int16",
|
||||
"SPV_KHR_post_depth_coverage",
|
||||
"SPV_KHR_shader_atomic_counter_ops",
|
||||
"SPV_EXT_shader_stencil_export",
|
||||
"SPV_EXT_shader_viewport_index_layer",
|
||||
"SPV_AMD_shader_image_load_store_lod",
|
||||
"SPV_AMD_shader_fragment_mask",
|
||||
"SPV_EXT_fragment_fully_covered",
|
||||
"SPV_AMD_gpu_shader_half_float_fetch",
|
||||
"SPV_GOOGLE_decorate_string",
|
||||
"SPV_GOOGLE_hlsl_functionality1",
|
||||
"SPV_NV_shader_subgroup_partitioned",
|
||||
"SPV_EXT_descriptor_indexing",
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace opt
|
||||
} // namespace spvtools
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user