diff --git a/3rdparty/glslang/.clang-format b/3rdparty/glslang/.clang-format deleted file mode 100644 index 8c73a52f..00000000 --- a/3rdparty/glslang/.clang-format +++ /dev/null @@ -1,13 +0,0 @@ -Language: Cpp -IndentWidth: 4 -PointerAlignment: Left -BreakBeforeBraces: Custom -BraceWrapping: { AfterFunction: true, AfterControlStatement: false } -IndentCaseLabels: false -ReflowComments: false -ColumnLimit: 120 -AccessModifierOffset: -4 -AlignTrailingComments: true -AllowShortBlocksOnASingleLine: false -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false diff --git a/3rdparty/glslang/CHANGES.md b/3rdparty/glslang/CHANGES.md deleted file mode 100644 index 8a97ff4f..00000000 --- a/3rdparty/glslang/CHANGES.md +++ /dev/null @@ -1,222 +0,0 @@ -# Revision history for `glslang` - -All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](https://semver.org/). - -## 13.1.1 2023-10-16 -* Initialize compile_only field in C interface - -## 13.1.0 2023-10-13 -* Support GL_EXT_texture_shadow_lod -* Support GL_NV_displacement_micromap -* Fix ByteAddressBuffer when used a function parameter -* Add more verbose messages if SPIRV-Tools is not found -* Fix names for explicitly sized types when emitting nonsemantic debug info -* Emit error for r-value arguments in atomic memory operations -* Add --no-link option -* Beautify preprocessor output format -* Fix race condition in glslangValidator -* Only set LocalSizeId mode when necessary -* Don't emit invalid debug info for buffer references - -## 13.0.0 2023-08-23 - -### Breaking changes -* Simplify PoolAlloc via thread_local - * Remove InitializeDLL functions - * Remove OSDependent TLS functions -* Remove GLSLANG_WEB and GLSLANG_WEB_DEVEL code paths - -### Other changes -* Raise CMAKE minimum to 3.17.2 -* Support GL_KHR_cooperative_matrix -* Support GL_QCOM_image_processing_support -* Support outputting each module to a filename with spirv-remap -* Generate an error when gl_PrimitiveShaderRateEXT is used without enabling the extension -* Improve layout checking when GL_EXT_spirv_intrinsics is enabled - -## 12.3.1 2023-07-20 - -### Other changes -* Improve backward compatibility for glslangValidator rename on Windows - -## 12.3.0 2023-07-19 - -### Other changes -* Rename glslangValidator to glslang and create glslangValidator symlink -* Support HLSL binary literals -* Add missing initialization members for web -* Improve push_constant upgrading -* Fix race condition in spirv remap -* Support pre and post HLSL qualifier validation -* Force generateDebugInfo when non-semantic debug info is enabled -* Exit with error if output file cannot be written -* Fix struct member buffer reference decorations - -## 12.2.0 2023-05-17 - -### Other changes -* Support GLSL_EXT_shader_tile_image -* Support GL_EXT_ray_tracing_position_fetch -* Support custom include callbacks via the C API -* Add preamble-text command-line option -* Accept variables as parameters of spirv_decorate_id -* Fix generation of conditionals with a struct result -* Fix double expansion of macros -* Fix DebugCompilationUnit scope -* Improve line information - -## 12.1.0 2023-03-21 - -### Other changes -* Reject non-float inputs/outputs for version less than 120 -* Fix invalid BufferBlock decoration for SPIR-V 1.3 and above -* Add HLSL relaxed-precision float/int matrix expansions -* Block decorate Vulkan structs with RuntimeArrays -* Support InterlockedAdd on float types - -## 12.0.0 2023-01-18 - -### Breaking changes -* An ABI was accidentally broken in #3014. Consequently, we have incremented the major revision number. - -### Other changes -* Add support for ARB_bindless_texture. -* Add support for GL_NV_shader_invocation_reorder. -* Fix const parameter debug types when using NonSemantic.Shader.DebugInfo.100. -* Fix NonSemantic.Shader.DebugInfo.100 disassembly. -* Fix MaxDualSourceDrawBuffersEXT usage. -* Fix structure member reference crash. - -## 11.13.0 2022-12-06 - -### Other changes -* Make HelperInvocation accesses volatile for SPIR-V 1.6. -* Improve forward compatibility of ResourceLimits interface -* Remove GLSLANG_ANGLE - -## 11.12.0 2022-10-12 - -### Other changes -* Update generator version -* Add support for GL_EXT_mesh_shader -* Add support for NonSemantic.Shader.DebugInfo.100 -* Make OpEmitMeshTasksEXT a terminal instruction -* Make gl_SubGroupARB a flat in int in Vulkan -* Add support for GL_EXT_opacity_micromap -* Add preamble support to C interface - -## 11.11.0 2022-08-11 - -### Other changes -* Add OpSource support to C interface -* Deprecate samplerBuffer for spirv1.6 and later -* Add support for SPV_AMD_shader_early_and_late_fragment_tests - -## 11.10.0 2022-06-02 - -### Other changes -* Generate OpLine before OpFunction -* Add support for VK_EXT_fragment_shader_barycentric -* Add whitelist filtering for debug comments in SPIRV-Remap -* Add support for GL_EXT_ray_cull_mask - -## 11.9.0 2022-04-06 - -### Other changes -* Add GLSL version override functionality -* Add eliminate-dead-input-components to -Os -* Add enhanced-msgs option -* Explicitly use Python 3 for builds - -## 11.8.0 2022-01-27 - -### Other changes -* Add support for SPIR-V 1.6 -* Add support for Vulkan 1.3 -* Add --hlsl-dx-position-w option - -## 11.7.0 2021-11-11 - -### Other changes -* Add support for targeting Vulkan 1.2 in the C API - -## 11.6.0 2021-08-25 - -### Other changes -* Atomic memory function only for shader storage block member or shared variable -* Add support for gl_MaxVaryingVectors for ogl -* Fix loading bool arrays from interface blocks -* Generate separate stores for partially swizzled memory stores -* Allow layout(std430) uniform with GL_EXT_scalar_block_layout -* Support for pragma STDGL invariant(all) -* Support for GL_NV_ray_tracing_motion_blur - -## 11.5.0 2021-06-23 - -### Other changes -* Implement GLSL_EXT_shader_atomic_float2 -* Implement GL_EXT_spirv_intrinsics -* Fixed SPIR-V remapper not remapping OpExtInst instruction set IDs -* only declare compatibility gl_ variables in compatibility mode -* Add support for float spec const vector initialization -* Implement GL_EXT_subgroup_uniform_control_flow. -* Fix arrays dimensioned with spec constant sized gl_WorkGroupSize -* Add support for 64bit integer scalar and vector types to bitCount() builtin - -## 11.4.0 2021-04-22 - -### Other changes -* Fix to keep source compatible with CMake 3.10.2 - -## 11.3.0 2021-04-21 - -### Other changes -* Added --depfile -* Added --auto-sampled-textures -* Now supports InterpolateAt-based functions -* Supports cross-stage automatic IO mapping -* Supports GL_EXT_vulkan_glsl_relaxed (-R option) - -## 11.2.0 2021-02-18 - -### Other changes -* Removed Python requirement when not building with spirv-tools -* Add support for GL_EXT_shared_memory_block -* Implement GL_EXT_null_initializer -* Add CMake support for Fuschia - -## 11.1.0 2020-12-07 - -### Other changes -* Added ray-tracing extension support - -## 11.0.0 2020-07-20 - -### Breaking changes - -#### Visual Studio 2013 is no longer supported - -[As scheduled](https://github.com/KhronosGroup/glslang/blob/9eef54b2513ca6b40b47b07d24f453848b65c0df/README.md#planned-deprecationsremovals), -Microsoft Visual Studio 2013 is no longer officially supported. Please upgrade -to at least Visual Studio 2015. - -## 10.15.3847 2020-07-20 - -### Breaking changes - -* The following files have been removed: - * `glslang/include/revision.h` - * `glslang/include/revision.template` - -The `GLSLANG_MINOR_VERSION` and `GLSLANG_PATCH_LEVEL` defines have been removed -from the public headers. \ -Instead each build script now uses the new `build_info.py` -script along with the `build_info.h.tmpl` and this `CHANGES.md` file to generate -the glslang build-time generated header `glslang/build_info.h`. - -The new public API to obtain the `glslang` version is `glslang::GetVersion()`. - -### Other changes -* `glslang` shared objects produced by CMake are now `SONAME` versioned using - [Semantic Versioning 2.0.0](https://semver.org/). diff --git a/3rdparty/glslang/CMakeLists.txt b/3rdparty/glslang/CMakeLists.txt deleted file mode 100644 index 5cdd3e31..00000000 --- a/3rdparty/glslang/CMakeLists.txt +++ /dev/null @@ -1,375 +0,0 @@ -# Copyright (C) 2020-2023 The Khronos Group Inc. -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# Neither the name of The Khronos Group Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -cmake_minimum_required(VERSION 3.17.2) -project(glslang) - -if (CMAKE_VERSION VERSION_LESS "3.21") - # https://cmake.org/cmake/help/latest/variable/PROJECT_IS_TOP_LEVEL.html - string(COMPARE EQUAL ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} PROJECT_IS_TOP_LEVEL) -endif() - -set_property(GLOBAL PROPERTY USE_FOLDERS ON) - -# Adhere to GNU filesystem layout conventions -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) - -# Needed for CMAKE_DEPENDENT_OPTION macro -include(CMakeDependentOption) - -option(BUILD_SHARED_LIBS "Build Shared Libraries") -option(BUILD_EXTERNAL "Build external dependencies in /External" ON) -option(BUILD_WERROR "Enable warnings as errors (default is OFF)" OFF) - -set(LIB_TYPE STATIC) - -if(BUILD_SHARED_LIBS) - set(LIB_TYPE SHARED) -endif() - -if ("${CMAKE_BUILD_TYPE}" STREQUAL "") - # This logic inside SPIRV-Tools, which can upset build target dependencies - # if changed after targets are already defined. To prevent these issues, - # ensure CMAKE_BUILD_TYPE is assigned early and at the glslang root scope. - message(STATUS "No build type selected, default to Debug") - set(CMAKE_BUILD_TYPE "Debug") -endif() - -# Currently iOS and Android are very similar. -# They both have their own packaging (APP/APK). -# Which makes regular executables/testing problematic. -# -# Currently the only deliverables for these platforms are -# libraries (either STATIC or SHARED). -# -# Furthermore testing is equally problematic. -if (IOS OR ANDROID) - set(ENABLE_GLSLANG_BINARIES OFF) - set(GLSLANG_TESTS OFF) -endif() - -option(ENABLE_SPVREMAPPER "Enables building of SPVRemapper" ON) - -option(ENABLE_GLSLANG_BINARIES "Builds glslang and spirv-remap" ON) - -option(ENABLE_GLSLANG_JS "If using Emscripten, build glslang.js. Otherwise, builds a sample executable for binary-size testing.") -CMAKE_DEPENDENT_OPTION(ENABLE_EMSCRIPTEN_SINGLE_FILE - "If using Emscripten, enables SINGLE_FILE build" - OFF "ENABLE_GLSLANG_JS AND EMSCRIPTEN" - OFF) -CMAKE_DEPENDENT_OPTION(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE - "If using Emscripten, builds to run on Node instead of Web" - OFF "ENABLE_GLSLANG_JS AND EMSCRIPTEN" - OFF) - -option(ENABLE_HLSL "Enables HLSL input support" ON) -option(ENABLE_RTTI "Enables RTTI") -option(ENABLE_EXCEPTIONS "Enables Exceptions") -option(ENABLE_OPT "Enables spirv-opt capability if present" ON) - -if(MINGW OR (APPLE AND ${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")) - # Workaround for CMake behavior on Mac OS with gcc, cmake generates -Xarch_* arguments - # which gcc rejects - set(ENABLE_PCH OFF) - message(NOTICE "Disabling PCH") -endif() - -option(ENABLE_PCH "Enables Precompiled header" ON) - -if(ENABLE_HLSL) - add_compile_definitions(ENABLE_HLSL) -endif() - -if(WIN32) - set(CMAKE_DEBUG_POSTFIX "d") - add_definitions(-DGLSLANG_OSINCLUDE_WIN32) -elseif(UNIX OR ANDROID) - add_definitions(-DGLSLANG_OSINCLUDE_UNIX) -else() - message("unknown platform") -endif() - -if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") - add_compile_options(-Wall -Wmaybe-uninitialized -Wuninitialized -Wunused -Wunused-local-typedefs - -Wunused-parameter -Wunused-value -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable -fno-exceptions) - if(NOT ENABLE_RTTI) - add_compile_options(-fno-rtti) - endif() - if(NOT ENABLE_EXCEPTIONS) - add_compile_options(-fno-exceptions) - endif() - if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0.0") - add_compile_options(-Werror=deprecated-copy) - endif() - - if(NOT (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")) - if (NOT APPLE) - # Error if there's symbols that are not found at link time. - add_link_options("-Wl,--no-undefined") - endif() - endif() -elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC) - add_compile_options(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs - -Wunused-parameter -Wunused-value -Wunused-variable) - if(NOT ENABLE_RTTI) - add_compile_options(-fno-rtti) - endif() - if(NOT ENABLE_EXCEPTIONS) - add_compile_options(-fno-exceptions) - endif() - - if(NOT (CMAKE_SYSTEM_NAME MATCHES "OpenBSD|Emscripten")) - # Error if there's symbols that are not found at link time. Some linkers do not support this flag. - if(NOT APPLE) - add_link_options("-Wl,--no-undefined") - endif() - endif() -elseif(MSVC) - if(NOT ENABLE_RTTI) - string(FIND "${CMAKE_CXX_FLAGS}" "/GR" MSVC_HAS_GR) - if(MSVC_HAS_GR) - string(REGEX REPLACE "/GR" "/GR-" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") - else() - add_compile_options(/GR-) # Disable RTTI - endif() - endif() - if(ENABLE_EXCEPTIONS) - add_compile_options(/EHsc) # Enable Exceptions - else() - string(REGEX REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") # Try to remove default /EHsc cxx_flag - add_compile_options(/D_HAS_EXCEPTIONS=0) - endif() -endif() - -# NOTE we could potentially replace this logic with COMPILE_WARNING_AS_ERROR if cmake minimum is bumped to >= 3.24 -if (BUILD_WERROR) - if (NOT MSVC) - add_compile_options(-Werror) - else() - add_compile_options(/WX) - endif() -endif() - -if(ENABLE_GLSLANG_JS) - if(MSVC) - add_compile_options(/Os /GR-) - else() - add_compile_options(-Os -fno-rtti -fno-exceptions) - if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC) - add_compile_options(-Wno-unused-parameter) - add_compile_options(-Wno-unused-variable -Wno-unused-const-variable) - endif() - endif() -endif() - -# Request C++17 -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -function(glslang_set_link_args TARGET) - # For MinGW compiles, statically link against the GCC and C++ runtimes. - # This avoids the need to ship those runtimes as DLLs. - # This is supported by GCC and Clang. - if(WIN32 AND NOT MSVC) - set_target_properties(${TARGET} PROPERTIES - LINK_FLAGS "-static -static-libgcc -static-libstdc++") - endif() -endfunction(glslang_set_link_args) - -# Root directory for build-time generated include files -set(GLSLANG_GENERATED_INCLUDEDIR "${CMAKE_BINARY_DIR}/include") - -################################################################################ -# Build version information generation -################################################################################ -include(parse_version.cmake) -set(GLSLANG_CHANGES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES.md") -set(GLSLANG_BUILD_INFO_H_TMPL "${CMAKE_CURRENT_SOURCE_DIR}/build_info.h.tmpl") -set(GLSLANG_BUILD_INFO_H "${GLSLANG_GENERATED_INCLUDEDIR}/glslang/build_info.h") - -parse_version(${GLSLANG_CHANGES_FILE} GLSLANG) - -function(configurate_version) - set(major ${GLSLANG_VERSION_MAJOR}) - set(minor ${GLSLANG_VERSION_MINOR}) - set(patch ${GLSLANG_VERSION_PATCH}) - set(flavor ${GLSLANG_VERSION_FLAVOR}) - configure_file(${GLSLANG_BUILD_INFO_H_TMPL} ${GLSLANG_BUILD_INFO_H} @ONLY) -endfunction() - -configurate_version() - -# glslang_add_build_info_dependency() adds the glslang-build-info dependency and -# generated include directories to target. -function(glslang_add_build_info_dependency target) - target_include_directories(${target} PUBLIC $) -endfunction() - -# glslang_only_export_explicit_symbols() makes the symbol visibility hidden by -# default for when building shared libraries, and sets the -# GLSLANG_IS_SHARED_LIBRARY define, and GLSLANG_EXPORTING to 1 when specifically -# building . -function(glslang_only_export_explicit_symbols target) - if(BUILD_SHARED_LIBS) - target_compile_definitions(${target} PUBLIC "GLSLANG_IS_SHARED_LIBRARY=1") - set_target_properties(${target} PROPERTIES CMAKE_CXX_VISIBILITY_PRESET hidden) - if(WIN32) - target_compile_definitions(${target} PRIVATE "GLSLANG_EXPORTING=1") - endif() - endif() -endfunction() - -# glslang_pch() adds precompiled header rules to for the pre-compiled -# header file . As target_precompile_headers() was added in CMake 3.16, -# this is a no-op if called on earlier versions of CMake. -function(glslang_pch target pch) - if(ENABLE_PCH) - target_precompile_headers(${target} PRIVATE ${pch}) - endif() -endfunction() - -if(BUILD_EXTERNAL AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/External) - # We depend on these for later projects, so they should come first. - add_subdirectory(External) -endif() - -option(ALLOW_EXTERNAL_SPIRV_TOOLS "Allows to build against installed SPIRV-Tools-opt") -if(NOT TARGET SPIRV-Tools-opt) - if(ALLOW_EXTERNAL_SPIRV_TOOLS) - # Look for external SPIR-V Tools build, if not building in-tree - message(STATUS "Trying to find local SPIR-V tools") - find_package(SPIRV-Tools-opt) - if(NOT TARGET SPIRV-Tools-opt) - if(ENABLE_OPT) - message(WARNING "ENABLE_OPT set but SPIR-V tools not found! Disabling SPIR-V optimization.") - endif() - set(ENABLE_OPT OFF) - endif() - else() - if(ENABLE_OPT) - message(SEND_ERROR "ENABLE_OPT set but SPIR-V tools not found. Please run update_glslang_sources.py, " - "set the ALLOW_EXTERNAL_SPIRV_TOOLS option to use a local install of SPIRV-Tools, or set ENABLE_OPT=0.") - endif() - endif() -endif() - -if(ENABLE_OPT) - message(STATUS "optimizer enabled") - add_definitions(-DENABLE_OPT=1) -else() - if(ENABLE_HLSL) - message(STATUS "spirv-tools not linked - illegal SPIRV may be generated for HLSL") - endif() - add_definitions(-DENABLE_OPT=0) -endif() - -add_subdirectory(glslang) -if(ENABLE_GLSLANG_BINARIES) - add_subdirectory(StandAlone) -endif() -add_subdirectory(SPIRV) - -# Testing / installation only makes sense when the project is top level. -# -# Otherwise add_subdirectory users have a harder time consuming the library. -# Since glslang will pollute the installation and add undesirable testing. -if(PROJECT_IS_TOP_LEVEL) - option(GLSLANG_TESTS "Enable glslang testing") - if(GLSLANG_TESTS) - enable_testing() - add_subdirectory(gtests) - - # glslang-testsuite runs a bash script on Windows. - # Make sure to use '-o igncr' flag to ignore carriage returns (\r). - set(IGNORE_CR_FLAG "") - if(WIN32) - set(IGNORE_CR_FLAG -o igncr) - endif() - - if (CMAKE_CONFIGURATION_TYPES) - set(RESULTS_PATH ${CMAKE_CURRENT_BINARY_DIR}/$/localResults) - set(VALIDATOR_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/$/glslang) - set(REMAP_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/$/spirv-remap) - else() - set(RESULTS_PATH ${CMAKE_CURRENT_BINARY_DIR}/localResults) - set(VALIDATOR_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/glslang) - set(REMAP_PATH ${CMAKE_CURRENT_BINARY_DIR}/StandAlone/spirv-remap) - endif() - - add_test(NAME glslang-testsuite - COMMAND bash ${IGNORE_CR_FLAG} runtests ${RESULTS_PATH} ${VALIDATOR_PATH} ${REMAP_PATH} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Test/) - endif() - - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/glslang-config.cmake.in" [=[ - @PACKAGE_INIT@ - @INSTALL_CONFIG_UNIX@ - include("@PACKAGE_PATH_EXPORT_TARGETS@") - ]=]) - - set(PATH_EXPORT_TARGETS "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/glslang-targets.cmake") - if(UNIX OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia") - set(INSTALL_CONFIG_UNIX [=[ - include(CMakeFindDependencyMacro) - set(THREADS_PREFER_PTHREAD_FLAG ON) - find_dependency(Threads REQUIRED) - ]=]) - endif() - configure_package_config_file( - "${CMAKE_CURRENT_BINARY_DIR}/glslang-config.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/glslang-config.cmake" - PATH_VARS - PATH_EXPORT_TARGETS - INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} - ) - - write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/glslang-config-version.cmake" - VERSION ${GLSLANG_VERSION} - COMPATIBILITY SameMajorVersion - ) - - install( - EXPORT glslang-targets - NAMESPACE "glslang::" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" - ) - - install( - FILES - "${CMAKE_CURRENT_BINARY_DIR}/glslang-config.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/glslang-config-version.cmake" - DESTINATION - "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" - ) -endif() diff --git a/3rdparty/glslang/External/CMakeLists.txt b/3rdparty/glslang/External/CMakeLists.txt deleted file mode 100644 index 46284fd5..00000000 --- a/3rdparty/glslang/External/CMakeLists.txt +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (C) 2020 The Khronos Group Inc. -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# Neither the name of The Khronos Group Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -# Suppress all warnings from external projects. -set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS -w) - -if(GLSLANG_TESTS) - if(TARGET gmock) - message(STATUS "Google Mock already configured - use it") - elseif(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/googletest) - # We need to make sure Google Test does not mess up with the - # global CRT settings on Windows. - if(WIN32) - set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - endif(WIN32) - # EXCLUDE_FROM_ALL keeps the install target from installing GTEST files. - add_subdirectory(googletest EXCLUDE_FROM_ALL) - set(GTEST_TARGETS - gtest - gtest_main - gmock - gmock_main) - foreach(target ${GTEST_TARGETS}) - set_property(TARGET ${target} PROPERTY FOLDER gtest) - endforeach() - mark_as_advanced(gmock_build_tests - BUILD_GMOCK - BUILD_GTEST - BUILD_SHARED_LIBS - gtest_build_samples - gtest_build_tests - gtest_disable_pthreads - gtest_force_shared_crt - gtest_hide_internal_symbols) - else() - message(STATUS - "Google Mock was not found - tests based on that will not build") - endif() -endif() - -if(ENABLE_OPT AND NOT TARGET SPIRV-Tools-opt) - if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/spirv-tools) - set(SPIRV_SKIP_TESTS ON CACHE BOOL "Skip building SPIRV-Tools tests") - add_subdirectory(spirv-tools) - endif() -endif() - diff --git a/3rdparty/glslang/README-spirv-remap.txt b/3rdparty/glslang/README-spirv-remap.txt deleted file mode 100644 index f3efee83..00000000 --- a/3rdparty/glslang/README-spirv-remap.txt +++ /dev/null @@ -1,137 +0,0 @@ - -VERSION --------------------------------------------------------------------------------- -spirv-remap 0.97 - -INTRO: --------------------------------------------------------------------------------- -spirv-remap is a utility to improve compression of SPIR-V binary files via -entropy reduction, plus optional stripping of debug information and -load/store optimization. It transforms SPIR-V to SPIR-V, remapping IDs. The -resulting modules have an increased ID range (IDs are not as tightly packed -around zero), but will compress better when multiple modules are compressed -together, since compressor's dictionary can find better cross module -commonality. - -Remapping is accomplished via canonicalization. Thus, modules can be -compressed one at a time with no loss of quality relative to operating on -many modules at once. The command line tool operates on multiple modules -only in the trivial repetition sense, for ease of use. The remapper API -only accepts a single module at a time. - -There are two modes of use: command line, and a C++11 API. Both are -described below. - -spirv-remap is currently in an alpha state. Although there are no known -remapping defects, it has only been exercised on one real world game shader -workload. - - -FEEDBACK --------------------------------------------------------------------------------- -Report defects, enhancements requests, code improvements, etc to: - spvremapper@lunarg.com - - -COMMAND LINE USAGE: --------------------------------------------------------------------------------- -Examples are given with a verbosity of one (-v), but more verbosity can be -had via -vv, -vvv, etc, or an integer parameter to --verbose, such as -"--verbose 4". With no verbosity, the command is silent and returns 0 on -success, and a positive integer error on failure. - -Pre-built binaries for several OSs are available. Examples presented are -for Linux. Command line arguments can be provided in any order. - -1. Basic ID remapping - -Perform ID remapping on all shaders in "*.spv", writing new files with -the same basenames to /tmp/out_dir. - - spirv-remap -v --map all --input *.spv --output /tmp/out_dir - -2. Perform all possible size reductions - - spirv-remap-linux-64 -v --do-everything --input *.spv --output /tmp/out_dir - -Note that --do-everything is a synonym for: - - --map all --dce all --opt all --strip all - -API USAGE: --------------------------------------------------------------------------------- - -The public interface to the remapper is defined in SPIRV/SPVRemapper.h as follows: - -namespace spv { - -class spirvbin_t -{ -public: - enum Options { ... }; - spirvbin_t(int verbose = 0); // construct - - // remap an existing binary in memory - void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); - - // Type for error/log handler functions - typedef std::function errorfn_t; - typedef std::function logfn_t; - - // Register error/log handling functions (can be c/c++ fn, lambda fn, or functor) - static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } - static void registerLogHandler(logfn_t handler) { logHandler = handler; } -}; - -} // namespace spv - -The class definition is in SPVRemapper.cpp. - -remap() accepts an std::vector of SPIR-V words, modifies them per the -request given in 'opts', and leaves the 'spv' container with the result. -It is safe to instantiate one spirvbin_t per thread and process a different -SPIR-V in each. - -The "opts" parameter to remap() accepts a bit mask of desired remapping -options. See REMAPPING AND OPTIMIZATION OPTIONS. - -On error, the function supplied to registerErrorHandler() will be invoked. -This can be a standard C/C++ function, a lambda function, or a functor. -The default handler simply calls exit(5); The error handler is a static -member, so need only be set up once, not once per spirvbin_t instance. - -Log messages are supplied to registerLogHandler(). By default, log -messages are eaten silently. The log handler is also a static member. - -BUILD DEPENDENCIES: --------------------------------------------------------------------------------- - 1. C++11 compatible compiler - 2. cmake - 3. glslang - - -BUILDING --------------------------------------------------------------------------------- -The standalone remapper is built along side glslang through its -normal build process. - - -REMAPPING AND OPTIMIZATION OPTIONS --------------------------------------------------------------------------------- -API: - These are bits defined under spv::spirvbin_t::, and can be - bitwise or-ed together as desired. - - MAP_TYPES = canonicalize type IDs - MAP_NAMES = canonicalize named data - MAP_FUNCS = canonicalize function bodies - DCE_FUNCS = remove dead functions - DCE_VARS = remove dead variables - DCE_TYPES = remove dead types - OPT_LOADSTORE = optimize unneeded load/stores - MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS) - DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES) - OPT_ALL = (OPT_LOADSTORE) - ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL) - DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) - diff --git a/3rdparty/glslang/README.md b/3rdparty/glslang/README.md deleted file mode 100644 index 44388108..00000000 --- a/3rdparty/glslang/README.md +++ /dev/null @@ -1,537 +0,0 @@ -![Continuous Integration](https://github.com/KhronosGroup/glslang/actions/workflows/continuous_integration.yml/badge.svg) -![Continuous Deployment](https://github.com/KhronosGroup/glslang/actions/workflows/continuous_deployment.yml/badge.svg) -[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/KhronosGroup/glslang/badge)](https://securityscorecards.dev/viewer/?uri=github.com/KhronosGroup/glslang) - -# News - -1. `OGLCompiler` and `HLSL` stub libraries have been fully removed from the build. - -2. `OVERRIDE_MSVCCRT` has been removed in favor of `CMAKE_MSVC_RUNTIME_LIBRARY` - -Users are encouraged to utilize the standard approach via [CMAKE_MSVC_RUNTIME_LIBRARY](https://cmake.org/cmake/help/latest/variable/CMAKE_MSVC_RUNTIME_LIBRARY.html). - -# Glslang Components and Status - -There are several components: - -### Reference Validator and GLSL/ESSL -> AST Front End - -An OpenGL GLSL and OpenGL|ES GLSL (ESSL) front-end for reference validation and translation of GLSL/ESSL into an internal abstract syntax tree (AST). - -**Status**: Virtually complete, with results carrying similar weight as the specifications. - -### HLSL -> AST Front End - -An HLSL front-end for translation of an approximation of HLSL to glslang's AST form. - -**Status**: Partially complete. Semantics are not reference quality and input is not validated. -This is in contrast to the [DXC project](https://github.com/Microsoft/DirectXShaderCompiler), which receives a much larger investment and attempts to have definitive/reference-level semantics. - -See [issue 362](https://github.com/KhronosGroup/glslang/issues/362) and [issue 701](https://github.com/KhronosGroup/glslang/issues/701) for current status. - -### AST -> SPIR-V Back End - -Translates glslang's AST to the Khronos-specified SPIR-V intermediate language. - -**Status**: Virtually complete. - -### Reflector - -An API for getting reflection information from the AST, reflection types/variables/etc. from the HLL source (not the SPIR-V). - -**Status**: There is a large amount of functionality present, but no specification/goal to measure completeness against. It is accurate for the input HLL and AST, but only approximate for what would later be emitted for SPIR-V. - -### Standalone Wrapper - -`glslang` is command-line tool for accessing the functionality above. - -Status: Complete. - -Tasks waiting to be done are documented as GitHub issues. - -## Other References - -Also see the Khronos landing page for glslang as a reference front end: - -https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/ - -The above page, while not kept up to date, includes additional information regarding glslang as a reference validator. - -# How to Use Glslang - -## Execution of Standalone Wrapper - -To use the standalone binary form, execute `glslang`, and it will print -a usage statement. Basic operation is to give it a file containing a shader, -and it will print out warnings/errors and optionally an AST. - -The applied stage-specific rules are based on the file extension: -* `.vert` for a vertex shader -* `.tesc` for a tessellation control shader -* `.tese` for a tessellation evaluation shader -* `.geom` for a geometry shader -* `.frag` for a fragment shader -* `.comp` for a compute shader - -For ray tracing pipeline shaders: -* `.rgen` for a ray generation shader -* `.rint` for a ray intersection shader -* `.rahit` for a ray any-hit shader -* `.rchit` for a ray closest-hit shader -* `.rmiss` for a ray miss shader -* `.rcall` for a callable shader - -There is also a non-shader extension: -* `.conf` for a configuration file of limits, see usage statement for example - -## Building (CMake) - -Instead of building manually, you can also download the binaries for your -platform directly from the [main-tot release][main-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 main -branch. - -### Dependencies - -* A C++17 compiler. - (For MSVS: use 2019 or later.) -* [CMake][cmake]: for generating compilation targets. -* make: _Linux_, ninja is an alternative, if configured. -* [Python 3.x][python]: for executing SPIRV-Tools scripts. (Optional if not using SPIRV-Tools and the 'External' subdirectory does not exist.) -* [bison][bison]: _optional_, but needed when changing the grammar (glslang.y). -* [googletest][googletest]: _optional_, but should use if making any changes to glslang. - -### Build steps - -The following steps assume a Bash shell. On Windows, that could be the Git Bash -shell or some other shell of your choosing. - -#### 1) Check-Out this project - -```bash -cd -git clone https://github.com/KhronosGroup/glslang.git -``` - -#### 2) Check-Out External Projects - -```bash -./update_glslang_sources.py -``` - -#### 3) Configure - -Assume the source directory is `$SOURCE_DIR` and the build directory is -`$BUILD_DIR`. First ensure the build directory exists, then navigate to it: - -```bash -mkdir -p $BUILD_DIR -cd $BUILD_DIR -``` - -For building on Linux: - -```bash -cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$(pwd)/install" $SOURCE_DIR -# "Release" (for CMAKE_BUILD_TYPE) could also be "Debug" or "RelWithDebInfo" -``` - -For building on Android: -```bash -cmake $SOURCE_DIR -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DANDROID_ABI=arm64-v8a -DCMAKE_BUILD_TYPE=Release -DANDROID_STL=c++_static -DANDROID_PLATFORM=android-24 -DCMAKE_SYSTEM_NAME=Android -DANDROID_TOOLCHAIN=clang -DANDROID_ARM_MODE=arm -DCMAKE_MAKE_PROGRAM=$ANDROID_NDK_HOME/prebuilt/linux-x86_64/bin/make -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake -# If on Windows will be -DCMAKE_MAKE_PROGRAM=%ANDROID_NDK_HOME%\prebuilt\windows-x86_64\bin\make.exe -# -G is needed for building on Windows -# -DANDROID_ABI can also be armeabi-v7a for 32 bit -``` - -For building on Windows: - -```bash -cmake $SOURCE_DIR -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -# The CMAKE_INSTALL_PREFIX part is for testing (explained later). -``` - -The CMake GUI also works for Windows (version 3.4.1 tested). - -Also, consider using `git config --global core.fileMode false` (or with `--local`) on Windows -to prevent the addition of execution permission on files. - -#### 4) Build and Install - -```bash -# for Linux: -make -j4 install - -# for Windows: -cmake --build . --config Release --target install -# "Release" (for --config) could also be "Debug", "MinSizeRel", or "RelWithDebInfo" -``` - -If using MSVC, after running CMake to configure, use the -Configuration Manager to check the `INSTALL` project. - -If you want to enable testing via CMake set `GLSLANG_TESTS=ON` when configuring the build. - -`GLSLANG_TESTS` is off by default to streamline the packaging / Vulkan SDK process. - -### Building (GN) - -glslang can also be built with the [GN build system](https://gn.googlesource.com/gn/). - -#### 1) Install `depot_tools` - -Download [depot_tools.zip](https://storage.googleapis.com/chrome-infra/depot_tools.zip), -extract to a directory, and add this directory to your `PATH`. - -#### 2) Synchronize dependencies and generate build files - -This only needs to be done once after updating `glslang`. - -With the current directory set to your `glslang` checkout, type: - -```bash -./update_glslang_sources.py -gclient sync --gclientfile=standalone.gclient -gn gen out/Default -``` - -#### 3) Build - -With the current directory set to your `glslang` checkout, type: - -```bash -cd out/Default -ninja -``` - -### If you need to change the GLSL grammar - -The grammar in `glslang/MachineIndependent/glslang.y` has to be recompiled with -bison if it changes, the output files are committed to the repo to avoid every -developer needing to have bison configured to compile the project when grammar -changes are quite infrequent. For windows you can get binaries from -[GnuWin32][bison-gnu-win32]. - -The command to rebuild is: - -```bash -bison --defines=MachineIndependent/glslang_tab.cpp.h - -t MachineIndependent/glslang.y - -o MachineIndependent/glslang_tab.cpp -``` - -The above command is also available in the bash script in `updateGrammar`, -when executed from the glslang subdirectory of the glslang repository. - -### Building to WASM for the Web and Node -### Building a standalone JS/WASM library for the Web and Node - -Use the steps in [Build Steps](#build-steps), with the following notes/exceptions: -* `emsdk` needs to be present in your executable search path, *PATH* for - Bash-like environments: - + [Instructions located here](https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install) -* Wrap cmake call: `emcmake cmake` -* Set `-DENABLE_OPT=OFF`. -* Set `-DENABLE_HLSL=OFF` if HLSL is not needed. -* For a standalone JS/WASM library, turn on `-DENABLE_GLSLANG_JS=ON`. -* To get a fully minimized build, make sure to use `brotli` to compress the .js - and .wasm files - -Example: - -```sh -emcmake cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GLSLANG_JS=ON \ - -DENABLE_HLSL=OFF -DENABLE_OPT=OFF .. -``` - -## Building glslang - Using vcpkg - -You can download and install glslang using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: - - git clone https://github.com/Microsoft/vcpkg.git - cd vcpkg - ./bootstrap-vcpkg.sh - ./vcpkg integrate install - ./vcpkg install glslang - -The glslang port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. - -## Testing - -Right now, there are two test harnesses existing in glslang: one is [Google -Test](gtests/), one is the [`runtests` script](Test/runtests). The former -runs unit tests and single-shader single-threaded integration tests, while -the latter runs multiple-shader linking tests and multi-threaded tests. - -### Running tests - -The [`runtests` script](Test/runtests) requires compiled binaries to be -installed into `$BUILD_DIR/install`. Please make sure you have supplied the -correct configuration to CMake (using `-DCMAKE_INSTALL_PREFIX`) when building; -otherwise, you may want to modify the path in the `runtests` script. - -Running Google Test-backed tests: - -```bash -cd $BUILD_DIR - -# for Linux: -ctest - -# for Windows: -ctest -C {Debug|Release|RelWithDebInfo|MinSizeRel} - -# or, run the test binary directly -# (which gives more fine-grained control like filtering): -/glslangtests -``` - -Running `runtests` script-backed tests: - -```bash -cd $SOURCE_DIR/Test && ./runtests -``` - -If some tests fail with validation errors, there may be a mismatch between the -version of `spirv-val` on the system and the version of glslang. In this -case, it is necessary to run `update_glslang_sources.py`. See "Check-Out -External Projects" above for more details. - -### Contributing tests - -Test results should always be included with a pull request that modifies -functionality. - -If you are writing unit tests, please use the Google Test framework and -place the tests under the `gtests/` directory. - -Integration tests are placed in the `Test/` directory. It contains test input -and a subdirectory `baseResults/` that contains the expected results of the -tests. Both the tests and `baseResults/` are under source-code control. - -Google Test runs those integration tests by reading the test input, compiling -them, and then compare against the expected results in `baseResults/`. The -integration tests to run via Google Test is registered in various -`gtests/*.FromFile.cpp` source files. `glslangtests` provides a command-line -option `--update-mode`, which, if supplied, will overwrite the golden files -under the `baseResults/` directory with real output from that invocation. -For more information, please check `gtests/` directory's -[README](gtests/README.md). - -For the `runtests` script, it will generate current results in the -`localResults/` directory and `diff` them against the `baseResults/`. -When you want to update the tracked test results, they need to be -copied from `localResults/` to `baseResults/`. This can be done by -the `bump` shell script. - -You can add your own private list of tests, not tracked publicly, by using -`localtestlist` to list non-tracked tests. This is automatically read -by `runtests` and included in the `diff` and `bump` process. - -## Programmatic Interfaces - -Another piece of software can programmatically translate shaders to an AST -using one of two different interfaces: -* A new C++ class-oriented interface, or -* The original C functional interface - -The `main()` in `StandAlone/StandAlone.cpp` shows examples using both styles. - -### C++ Class Interface (new, preferred) - -This interface is in roughly the last 1/3 of `ShaderLang.h`. It is in the -glslang namespace and contains the following, here with suggested calls -for generating SPIR-V: - -```cxx -const char* GetEsslVersionString(); -const char* GetGlslVersionString(); -bool InitializeProcess(); -void FinalizeProcess(); - -class TShader - setStrings(...); - setEnvInput(EShSourceHlsl or EShSourceGlsl, stage, EShClientVulkan or EShClientOpenGL, 100); - setEnvClient(EShClientVulkan or EShClientOpenGL, EShTargetVulkan_1_0 or EShTargetVulkan_1_1 or EShTargetOpenGL_450); - setEnvTarget(EShTargetSpv, EShTargetSpv_1_0 or EShTargetSpv_1_3); - bool parse(...); - const char* getInfoLog(); - -class TProgram - void addShader(...); - bool link(...); - const char* getInfoLog(); - Reflection queries -``` - -For just validating (not generating code), substitute these calls: - -```cxx - setEnvInput(EShSourceHlsl or EShSourceGlsl, stage, EShClientNone, 0); - setEnvClient(EShClientNone, 0); - setEnvTarget(EShTargetNone, 0); -``` - -See `ShaderLang.h` and the usage of it in `StandAlone/StandAlone.cpp` for more -details. There is a block comment giving more detail above the calls for -`setEnvInput, setEnvClient, and setEnvTarget`. - -### C Functional Interface (original) - -This interface is in roughly the first 2/3 of `ShaderLang.h`, and referred to -as the `Sh*()` interface, as all the entry points start `Sh`. - -The `Sh*()` interface takes a "compiler" call-back object, which it calls after -building call back that is passed the AST and can then execute a back end on it. - -The following is a simplified resulting run-time call stack: - -```c -ShCompile(shader, compiler) -> compiler(AST) -> -``` - -In practice, `ShCompile()` takes shader strings, default version, and -warning/error and other options for controlling compilation. - -### C Functional Interface (new) - -This interface is located `glslang_c_interface.h` and exposes functionality similar to the C++ interface. The following snippet is a complete example showing how to compile GLSL into SPIR-V 1.5 for Vulkan 1.2. - -```c -#include - -// Required for use of glslang_default_resource -#include - -typedef struct SpirVBinary { - uint32_t *words; // SPIR-V words - int size; // number of words in SPIR-V binary -} SpirVBinary; - -SpirVBinary compileShaderToSPIRV_Vulkan(glslang_stage_t stage, const char* shaderSource, const char* fileName) { - const glslang_input_t input = { - .language = GLSLANG_SOURCE_GLSL, - .stage = stage, - .client = GLSLANG_CLIENT_VULKAN, - .client_version = GLSLANG_TARGET_VULKAN_1_2, - .target_language = GLSLANG_TARGET_SPV, - .target_language_version = GLSLANG_TARGET_SPV_1_5, - .code = shaderSource, - .default_version = 100, - .default_profile = GLSLANG_NO_PROFILE, - .force_default_version_and_profile = false, - .forward_compatible = false, - .messages = GLSLANG_MSG_DEFAULT_BIT, - .resource = glslang_default_resource(), - }; - - glslang_shader_t* shader = glslang_shader_create(&input); - - SpirVBinary bin = { - .words = NULL, - .size = 0, - }; - if (!glslang_shader_preprocess(shader, &input)) { - printf("GLSL preprocessing failed %s\n", fileName); - printf("%s\n", glslang_shader_get_info_log(shader)); - printf("%s\n", glslang_shader_get_info_debug_log(shader)); - printf("%s\n", input.code); - glslang_shader_delete(shader); - return bin; - } - - if (!glslang_shader_parse(shader, &input)) { - printf("GLSL parsing failed %s\n", fileName); - printf("%s\n", glslang_shader_get_info_log(shader)); - printf("%s\n", glslang_shader_get_info_debug_log(shader)); - printf("%s\n", glslang_shader_get_preprocessed_code(shader)); - glslang_shader_delete(shader); - return bin; - } - - glslang_program_t* program = glslang_program_create(); - glslang_program_add_shader(program, shader); - - if (!glslang_program_link(program, GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT)) { - printf("GLSL linking failed %s\n", fileName); - printf("%s\n", glslang_program_get_info_log(program)); - printf("%s\n", glslang_program_get_info_debug_log(program)); - glslang_program_delete(program); - glslang_shader_delete(shader); - return bin; - } - - glslang_program_SPIRV_generate(program, stage); - - bin.size = glslang_program_SPIRV_get_size(program); - bin.words = malloc(bin.size * sizeof(uint32_t)); - glslang_program_SPIRV_get(program, bin.words); - - const char* spirv_messages = glslang_program_SPIRV_get_messages(program); - if (spirv_messages) - printf("(%s) %s\b", fileName, spirv_messages); - - glslang_program_delete(program); - glslang_shader_delete(shader); - - return bin; -} -``` - -## Basic Internal Operation - -* Initial lexical analysis is done by the preprocessor in - `MachineIndependent/Preprocessor`, and then refined by a GLSL scanner - in `MachineIndependent/Scan.cpp`. There is currently no use of flex. - -* Code is parsed using bison on `MachineIndependent/glslang.y` with the - aid of a symbol table and an AST. The symbol table is not passed on to - the back-end; the intermediate representation stands on its own. - The tree is built by the grammar productions, many of which are - offloaded into `ParseHelper.cpp`, and by `Intermediate.cpp`. - -* The intermediate representation is very high-level, and represented - as an in-memory tree. This serves to lose no information from the - original program, and to have efficient transfer of the result from - parsing to the back-end. In the AST, constants are propagated and - folded, and a very small amount of dead code is eliminated. - - To aid linking and reflection, the last top-level branch in the AST - lists all global symbols. - -* The primary algorithm of the back-end compiler is to traverse the - tree (high-level intermediate representation), and create an internal - object code representation. There is an example of how to do this - in `MachineIndependent/intermOut.cpp`. - -* Reduction of the tree to a linear byte-code style low-level intermediate - representation is likely a good way to generate fully optimized code. - -* There is currently some dead old-style linker-type code still lying around. - -* Memory pool: parsing uses types derived from C++ `std` types, using a - custom allocator that puts them in a memory pool. This makes allocation - of individual container/contents just few cycles and deallocation free. - This pool is popped after the AST is made and processed. - - The use is simple: if you are going to call `new`, there are three cases: - - - the object comes from the pool (its base class has the macro - `POOL_ALLOCATOR_NEW_DELETE` in it) and you do not have to call `delete` - - - it is a `TString`, in which case call `NewPoolTString()`, which gets - it from the pool, and there is no corresponding `delete` - - - the object does not come from the pool, and you have to do normal - C++ memory management of what you `new` - -* Features can be protected by version/extension/stage/profile: - See the comment in `glslang/MachineIndependent/Versions.cpp`. - -[cmake]: https://cmake.org/ -[python]: https://www.python.org/ -[bison]: https://www.gnu.org/software/bison/ -[googletest]: https://github.com/google/googletest -[bison-gnu-win32]: http://gnuwin32.sourceforge.net/packages/bison.htm -[main-tot-release]: https://github.com/KhronosGroup/glslang/releases/tag/main-tot diff --git a/3rdparty/glslang/SPIRV/CInterface/spirv_c_interface.cpp b/3rdparty/glslang/SPIRV/CInterface/spirv_c_interface.cpp deleted file mode 100644 index f421ea5a..00000000 --- a/3rdparty/glslang/SPIRV/CInterface/spirv_c_interface.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/** - This code is based on the glslang_c_interface implementation by Viktor Latypov -**/ - -/** -BSD 2-Clause License - -Copyright (c) 2019, Viktor Latypov -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**/ - -#include "glslang/Include/glslang_c_interface.h" - -#include "SPIRV/GlslangToSpv.h" -#include "SPIRV/Logger.h" -#include "SPIRV/SpvTools.h" - -static_assert(sizeof(glslang_spv_options_t) == sizeof(glslang::SpvOptions), ""); - -typedef struct glslang_program_s { - glslang::TProgram* program; - std::vector spirv; - std::string loggerMessages; -} glslang_program_t; - -static EShLanguage c_shader_stage(glslang_stage_t stage) -{ - switch (stage) { - case GLSLANG_STAGE_VERTEX: - return EShLangVertex; - case GLSLANG_STAGE_TESSCONTROL: - return EShLangTessControl; - case GLSLANG_STAGE_TESSEVALUATION: - return EShLangTessEvaluation; - case GLSLANG_STAGE_GEOMETRY: - return EShLangGeometry; - case GLSLANG_STAGE_FRAGMENT: - return EShLangFragment; - case GLSLANG_STAGE_COMPUTE: - return EShLangCompute; - case GLSLANG_STAGE_RAYGEN: - return EShLangRayGen; - case GLSLANG_STAGE_INTERSECT: - return EShLangIntersect; - case GLSLANG_STAGE_ANYHIT: - return EShLangAnyHit; - case GLSLANG_STAGE_CLOSESTHIT: - return EShLangClosestHit; - case GLSLANG_STAGE_MISS: - return EShLangMiss; - case GLSLANG_STAGE_CALLABLE: - return EShLangCallable; - case GLSLANG_STAGE_TASK: - return EShLangTask; - case GLSLANG_STAGE_MESH: - return EShLangMesh; - default: - break; - } - return EShLangCount; -} - -GLSLANG_EXPORT void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage) -{ - glslang_spv_options_t spv_options {}; - spv_options.disable_optimizer = true; - spv_options.validate = true; - - glslang_program_SPIRV_generate_with_options(program, stage, &spv_options); -} - -GLSLANG_EXPORT void glslang_program_SPIRV_generate_with_options(glslang_program_t* program, glslang_stage_t stage, glslang_spv_options_t* spv_options) { - spv::SpvBuildLogger logger; - - const glslang::TIntermediate* intermediate = program->program->getIntermediate(c_shader_stage(stage)); - - glslang::GlslangToSpv(*intermediate, program->spirv, &logger, reinterpret_cast(spv_options)); - - program->loggerMessages = logger.getAllMessages(); -} - -GLSLANG_EXPORT size_t glslang_program_SPIRV_get_size(glslang_program_t* program) { return program->spirv.size(); } - -GLSLANG_EXPORT void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int* out) -{ - memcpy(out, program->spirv.data(), program->spirv.size() * sizeof(unsigned int)); -} - -GLSLANG_EXPORT unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program) -{ - return program->spirv.data(); -} - -GLSLANG_EXPORT const char* glslang_program_SPIRV_get_messages(glslang_program_t* program) -{ - return program->loggerMessages.empty() ? nullptr : program->loggerMessages.c_str(); -} diff --git a/3rdparty/glslang/SPIRV/CMakeLists.txt b/3rdparty/glslang/SPIRV/CMakeLists.txt deleted file mode 100644 index 61c7a266..00000000 --- a/3rdparty/glslang/SPIRV/CMakeLists.txt +++ /dev/null @@ -1,154 +0,0 @@ -# Copyright (C) 2020 The Khronos Group Inc. -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# Neither the name of The Khronos Group Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -set(SOURCES - GlslangToSpv.cpp - InReadableOrder.cpp - Logger.cpp - SpvBuilder.cpp - SpvPostProcess.cpp - doc.cpp - SpvTools.cpp - disassemble.cpp - CInterface/spirv_c_interface.cpp) - -set(SPVREMAP_SOURCES - SPVRemapper.cpp - doc.cpp) - -set(HEADERS - bitutils.h - spirv.hpp - GLSL.std.450.h - GLSL.ext.EXT.h - GLSL.ext.KHR.h - GlslangToSpv.h - hex_float.h - Logger.h - SpvBuilder.h - spvIR.h - doc.h - SpvTools.h - disassemble.h - GLSL.ext.AMD.h - GLSL.ext.NV.h - GLSL.ext.ARM.h - NonSemanticDebugPrintf.h - NonSemanticShaderDebugInfo100.h) - -set(SPVREMAP_HEADERS - SPVRemapper.h - doc.h) - -set(PUBLIC_HEADERS - GlslangToSpv.h - disassemble.h - Logger.h - spirv.hpp - SPVRemapper.h) - -add_library(SPIRV ${LIB_TYPE} ${SOURCES} ${HEADERS}) -set_target_properties(SPIRV PROPERTIES - FOLDER glslang - POSITION_INDEPENDENT_CODE ON - VERSION "${GLSLANG_VERSION}" - SOVERSION "${GLSLANG_VERSION_MAJOR}") -target_include_directories(SPIRV PUBLIC - $ - $) - -glslang_add_build_info_dependency(SPIRV) - -if (ENABLE_SPVREMAPPER) - add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) - set_target_properties(SPVRemapper PROPERTIES - FOLDER glslang - POSITION_INDEPENDENT_CODE ON - VERSION "${GLSLANG_VERSION}" - SOVERSION "${GLSLANG_VERSION_MAJOR}") -endif() - -if(WIN32 AND BUILD_SHARED_LIBS) - set_target_properties(SPIRV PROPERTIES PREFIX "") - if (ENABLE_SPVREMAPPER) - set_target_properties(SPVRemapper PROPERTIES PREFIX "") - endif() -endif() - -if(ENABLE_OPT) - target_link_libraries(SPIRV PRIVATE MachineIndependent PUBLIC SPIRV-Tools-opt) - target_include_directories(SPIRV PUBLIC - $) -else() - target_link_libraries(SPIRV PRIVATE MachineIndependent) -endif() - -if(WIN32) - source_group("Source" FILES ${SOURCES} ${HEADERS}) - source_group("Source" FILES ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) -endif() - -if(PROJECT_IS_TOP_LEVEL) - if (ENABLE_SPVREMAPPER) - install(TARGETS SPVRemapper EXPORT glslang-targets) - endif() - - install(TARGETS SPIRV EXPORT glslang-targets) - - # Backward compatibility - if (ENABLE_SPVREMAPPER) - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/SPVRemapperTargets.cmake" " - message(WARNING \"Using `SPVRemapperTargets.cmake` is deprecated: use `find_package(glslang)` to find glslang CMake targets.\") - - if (NOT TARGET glslang::SPVRemapper) - include(\"${CMAKE_INSTALL_FULL_LIBDIR}/cmake/${PROJECT_NAME}/glslang-targets.cmake\") - endif() - - add_library(SPVRemapper ALIAS glslang::SPVRemapper) - ") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/SPVRemapperTargets.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) - endif() - - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/SPIRVTargets.cmake" " - message(WARNING \"Using `SPIRVTargets.cmake` is deprecated: use `find_package(glslang)` to find glslang CMake targets.\") - - if (NOT TARGET glslang::SPIRV) - include(\"${CMAKE_INSTALL_FULL_LIBDIR}/cmake/${PROJECT_NAME}/glslang-targets.cmake\") - endif() - - add_library(SPIRV ALIAS glslang::SPIRV) - ") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/SPIRVTargets.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) - - install(FILES ${PUBLIC_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/SPIRV/) -endif() diff --git a/3rdparty/glslang/SPIRV/GLSL.ext.AMD.h b/3rdparty/glslang/SPIRV/GLSL.ext.AMD.h deleted file mode 100644 index 009d2f1c..00000000 --- a/3rdparty/glslang/SPIRV/GLSL.ext.AMD.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextAMD_H -#define GLSLextAMD_H - -static const int GLSLextAMDVersion = 100; -static const int GLSLextAMDRevision = 7; - -// SPV_AMD_shader_ballot -static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot"; - -enum ShaderBallotAMD { - ShaderBallotBadAMD = 0, // Don't use - - SwizzleInvocationsAMD = 1, - SwizzleInvocationsMaskedAMD = 2, - WriteInvocationAMD = 3, - MbcntAMD = 4, - - ShaderBallotCountAMD -}; - -// SPV_AMD_shader_trinary_minmax -static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax"; - -enum ShaderTrinaryMinMaxAMD { - ShaderTrinaryMinMaxBadAMD = 0, // Don't use - - FMin3AMD = 1, - UMin3AMD = 2, - SMin3AMD = 3, - FMax3AMD = 4, - UMax3AMD = 5, - SMax3AMD = 6, - FMid3AMD = 7, - UMid3AMD = 8, - SMid3AMD = 9, - - ShaderTrinaryMinMaxCountAMD -}; - -// SPV_AMD_shader_explicit_vertex_parameter -static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter"; - -enum ShaderExplicitVertexParameterAMD { - ShaderExplicitVertexParameterBadAMD = 0, // Don't use - - InterpolateAtVertexAMD = 1, - - ShaderExplicitVertexParameterCountAMD -}; - -// SPV_AMD_gcn_shader -static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader"; - -enum GcnShaderAMD { - GcnShaderBadAMD = 0, // Don't use - - CubeFaceIndexAMD = 1, - CubeFaceCoordAMD = 2, - TimeAMD = 3, - - GcnShaderCountAMD -}; - -// SPV_AMD_gpu_shader_half_float -static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float"; - -// SPV_AMD_texture_gather_bias_lod -static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod"; - -// SPV_AMD_gpu_shader_int16 -static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16"; - -// SPV_AMD_shader_image_load_store_lod -static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod"; - -// SPV_AMD_shader_fragment_mask -static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask"; - -// SPV_AMD_gpu_shader_half_float_fetch -static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch"; - -#endif // #ifndef GLSLextAMD_H diff --git a/3rdparty/glslang/SPIRV/GLSL.ext.ARM.h b/3rdparty/glslang/SPIRV/GLSL.ext.ARM.h deleted file mode 100644 index 14425be1..00000000 --- a/3rdparty/glslang/SPIRV/GLSL.ext.ARM.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -** Copyright (c) 2022 ARM Limited -** -** 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 GLSLextARM_H -#define GLSLextARM_H - -static const int GLSLextARMVersion = 100; -static const int GLSLextARMRevision = 1; - -static const char * const E_SPV_ARM_core_builtins = "SPV_ARM_core_builtins"; - -#endif // #ifndef GLSLextARM_H diff --git a/3rdparty/glslang/SPIRV/GLSL.ext.EXT.h b/3rdparty/glslang/SPIRV/GLSL.ext.EXT.h deleted file mode 100644 index caab2793..00000000 --- a/3rdparty/glslang/SPIRV/GLSL.ext.EXT.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLextEXT_H -#define GLSLextEXT_H - -static const int GLSLextEXTVersion = 100; -static const int GLSLextEXTRevision = 2; - -static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export"; -static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer"; -static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; -static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density"; -static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation"; -static const char* const E_SPV_EXT_shader_atomic_float_add = "SPV_EXT_shader_atomic_float_add"; -static const char* const E_SPV_EXT_shader_atomic_float16_add = "SPV_EXT_shader_atomic_float16_add"; -static const char* const E_SPV_EXT_shader_atomic_float_min_max = "SPV_EXT_shader_atomic_float_min_max"; -static const char* const E_SPV_EXT_shader_image_int64 = "SPV_EXT_shader_image_int64"; -static const char* const E_SPV_EXT_shader_tile_image = "SPV_EXT_shader_tile_image"; -static const char* const E_SPV_EXT_mesh_shader = "SPV_EXT_mesh_shader"; - -#endif // #ifndef GLSLextEXT_H diff --git a/3rdparty/glslang/SPIRV/GLSL.ext.KHR.h b/3rdparty/glslang/SPIRV/GLSL.ext.KHR.h deleted file mode 100644 index 121defa1..00000000 --- a/3rdparty/glslang/SPIRV/GLSL.ext.KHR.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -** Copyright (c) 2014-2020 The Khronos Group Inc. -** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -** -** 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 GLSLextKHR_H -#define GLSLextKHR_H - -static const int GLSLextKHRVersion = 100; -static const int GLSLextKHRRevision = 3; - -static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot"; -static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote"; -static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group"; -static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview"; -static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters"; -static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage"; -static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage"; -static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; -static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; -static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model"; -static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer"; -static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer"; -static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock"; -static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock"; -static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info"; -static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing"; -static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query"; -static const char* const E_SPV_KHR_fragment_shading_rate = "SPV_KHR_fragment_shading_rate"; -static const char* const E_SPV_KHR_terminate_invocation = "SPV_KHR_terminate_invocation"; -static const char* const E_SPV_KHR_workgroup_memory_explicit_layout = "SPV_KHR_workgroup_memory_explicit_layout"; -static const char* const E_SPV_KHR_subgroup_uniform_control_flow = "SPV_KHR_subgroup_uniform_control_flow"; -static const char* const E_SPV_KHR_fragment_shader_barycentric = "SPV_KHR_fragment_shader_barycentric"; -static const char* const E_SPV_AMD_shader_early_and_late_fragment_tests = "SPV_AMD_shader_early_and_late_fragment_tests"; -static const char* const E_SPV_KHR_ray_tracing_position_fetch = "SPV_KHR_ray_tracing_position_fetch"; -static const char* const E_SPV_KHR_cooperative_matrix = "SPV_KHR_cooperative_matrix"; - -#endif // #ifndef GLSLextKHR_H diff --git a/3rdparty/glslang/SPIRV/GLSL.ext.NV.h b/3rdparty/glslang/SPIRV/GLSL.ext.NV.h deleted file mode 100644 index 9889bc9f..00000000 --- a/3rdparty/glslang/SPIRV/GLSL.ext.NV.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -** Copyright (c) 2014-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 GLSLextNV_H -#define GLSLextNV_H - -enum BuiltIn; -enum Decoration; -enum Op; -enum Capability; - -static const int GLSLextNVVersion = 100; -static const int GLSLextNVRevision = 11; - -//SPV_NV_sample_mask_override_coverage -const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; - -//SPV_NV_geometry_shader_passthrough -const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough"; - -//SPV_NV_viewport_array2 -const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2"; -const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array"; - -//SPV_NV_stereo_view_rendering -const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering"; - -//SPV_NVX_multiview_per_view_attributes -const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes"; - -//SPV_NV_shader_subgroup_partitioned -const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; - -//SPV_NV_fragment_shader_barycentric -const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric"; - -//SPV_NV_compute_shader_derivatives -const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives"; - -//SPV_NV_shader_image_footprint -const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint"; - -//SPV_NV_mesh_shader -const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader"; - -//SPV_NV_raytracing -const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; - -//SPV_NV_ray_tracing_motion_blur -const char* const E_SPV_NV_ray_tracing_motion_blur = "SPV_NV_ray_tracing_motion_blur"; - -//SPV_NV_shading_rate -const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; - -//SPV_NV_cooperative_matrix -const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix"; - -//SPV_NV_shader_sm_builtins -const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins"; - -//SPV_NV_shader_execution_reorder -const char* const E_SPV_NV_shader_invocation_reorder = "SPV_NV_shader_invocation_reorder"; - -//SPV_NV_displacement_micromap -const char* const E_SPV_NV_displacement_micromap = "SPV_NV_displacement_micromap"; - -#endif // #ifndef GLSLextNV_H diff --git a/3rdparty/glslang/SPIRV/GLSL.ext.QCOM.h b/3rdparty/glslang/SPIRV/GLSL.ext.QCOM.h deleted file mode 100644 index f13bb693..00000000 --- a/3rdparty/glslang/SPIRV/GLSL.ext.QCOM.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -** Copyright (c) 2021 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 GLSLextQCOM_H -#define GLSLextQCOM_H - -enum BuiltIn; -enum Decoration; -enum Op; -enum Capability; - -static const int GLSLextQCOMVersion = 100; -static const int GLSLextQCOMRevision = 1; - -//SPV_QCOM_image_processing -const char* const E_SPV_QCOM_image_processing = "SPV_QCOM_image_processing"; - -#endif // #ifndef GLSLextQCOM_H diff --git a/3rdparty/glslang/SPIRV/GLSL.std.450.h b/3rdparty/glslang/SPIRV/GLSL.std.450.h deleted file mode 100644 index 86d3da80..00000000 --- a/3rdparty/glslang/SPIRV/GLSL.std.450.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -** Copyright (c) 2014-2016 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a copy -** of this software and/or associated documentation files (the "Materials"), -** to deal in the Materials without restriction, including without limitation -** the rights to use, copy, modify, merge, publish, distribute, sublicense, -** and/or sell copies of the Materials, and to permit persons to whom the -** Materials are furnished to do so, subject to the following conditions: -** -** The above copyright notice and this permission notice shall be included in -** all copies or substantial portions of the Materials. -** -** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS -** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND -** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS -** IN THE MATERIALS. -*/ - -#ifndef GLSLstd450_H -#define GLSLstd450_H - -static const int GLSLstd450Version = 100; -static const int GLSLstd450Revision = 1; - -enum GLSLstd450 { - GLSLstd450Bad = 0, // Don't use - - GLSLstd450Round = 1, - GLSLstd450RoundEven = 2, - GLSLstd450Trunc = 3, - GLSLstd450FAbs = 4, - GLSLstd450SAbs = 5, - GLSLstd450FSign = 6, - GLSLstd450SSign = 7, - GLSLstd450Floor = 8, - GLSLstd450Ceil = 9, - GLSLstd450Fract = 10, - - GLSLstd450Radians = 11, - GLSLstd450Degrees = 12, - GLSLstd450Sin = 13, - GLSLstd450Cos = 14, - GLSLstd450Tan = 15, - GLSLstd450Asin = 16, - GLSLstd450Acos = 17, - GLSLstd450Atan = 18, - GLSLstd450Sinh = 19, - GLSLstd450Cosh = 20, - GLSLstd450Tanh = 21, - GLSLstd450Asinh = 22, - GLSLstd450Acosh = 23, - GLSLstd450Atanh = 24, - GLSLstd450Atan2 = 25, - - GLSLstd450Pow = 26, - GLSLstd450Exp = 27, - GLSLstd450Log = 28, - GLSLstd450Exp2 = 29, - GLSLstd450Log2 = 30, - GLSLstd450Sqrt = 31, - GLSLstd450InverseSqrt = 32, - - GLSLstd450Determinant = 33, - GLSLstd450MatrixInverse = 34, - - GLSLstd450Modf = 35, // second operand needs an OpVariable to write to - GLSLstd450ModfStruct = 36, // no OpVariable operand - GLSLstd450FMin = 37, - GLSLstd450UMin = 38, - GLSLstd450SMin = 39, - GLSLstd450FMax = 40, - GLSLstd450UMax = 41, - GLSLstd450SMax = 42, - GLSLstd450FClamp = 43, - GLSLstd450UClamp = 44, - GLSLstd450SClamp = 45, - GLSLstd450FMix = 46, - GLSLstd450IMix = 47, // Reserved - GLSLstd450Step = 48, - GLSLstd450SmoothStep = 49, - - GLSLstd450Fma = 50, - GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to - GLSLstd450FrexpStruct = 52, // no OpVariable operand - GLSLstd450Ldexp = 53, - - GLSLstd450PackSnorm4x8 = 54, - GLSLstd450PackUnorm4x8 = 55, - GLSLstd450PackSnorm2x16 = 56, - GLSLstd450PackUnorm2x16 = 57, - GLSLstd450PackHalf2x16 = 58, - GLSLstd450PackDouble2x32 = 59, - GLSLstd450UnpackSnorm2x16 = 60, - GLSLstd450UnpackUnorm2x16 = 61, - GLSLstd450UnpackHalf2x16 = 62, - GLSLstd450UnpackSnorm4x8 = 63, - GLSLstd450UnpackUnorm4x8 = 64, - GLSLstd450UnpackDouble2x32 = 65, - - GLSLstd450Length = 66, - GLSLstd450Distance = 67, - GLSLstd450Cross = 68, - GLSLstd450Normalize = 69, - GLSLstd450FaceForward = 70, - GLSLstd450Reflect = 71, - GLSLstd450Refract = 72, - - GLSLstd450FindILsb = 73, - GLSLstd450FindSMsb = 74, - GLSLstd450FindUMsb = 75, - - GLSLstd450InterpolateAtCentroid = 76, - GLSLstd450InterpolateAtSample = 77, - GLSLstd450InterpolateAtOffset = 78, - - GLSLstd450NMin = 79, - GLSLstd450NMax = 80, - GLSLstd450NClamp = 81, - - GLSLstd450Count -}; - -#endif // #ifndef GLSLstd450_H diff --git a/3rdparty/glslang/SPIRV/GlslangToSpv.cpp b/3rdparty/glslang/SPIRV/GlslangToSpv.cpp deleted file mode 100644 index ec40f663..00000000 --- a/3rdparty/glslang/SPIRV/GlslangToSpv.cpp +++ /dev/null @@ -1,10211 +0,0 @@ -// -// Copyright (C) 2014-2016 LunarG, Inc. -// Copyright (C) 2015-2020 Google, Inc. -// Copyright (C) 2017 ARM Limited. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Visit the nodes in the glslang intermediate tree representation to -// translate them to SPIR-V. -// - -#include "spirv.hpp" -#include "GlslangToSpv.h" -#include "SpvBuilder.h" -#include "SpvTools.h" -namespace spv { - #include "GLSL.std.450.h" - #include "GLSL.ext.KHR.h" - #include "GLSL.ext.EXT.h" - #include "GLSL.ext.AMD.h" - #include "GLSL.ext.NV.h" - #include "GLSL.ext.ARM.h" - #include "GLSL.ext.QCOM.h" - #include "NonSemanticDebugPrintf.h" -} - -// Glslang includes -#include "../glslang/MachineIndependent/localintermediate.h" -#include "../glslang/MachineIndependent/SymbolTable.h" -#include "../glslang/Include/Common.h" - -// Build-time generated includes -#include "glslang/build_info.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace { - -namespace { -class SpecConstantOpModeGuard { -public: - SpecConstantOpModeGuard(spv::Builder* builder) - : builder_(builder) { - previous_flag_ = builder->isInSpecConstCodeGenMode(); - } - ~SpecConstantOpModeGuard() { - previous_flag_ ? builder_->setToSpecConstCodeGenMode() - : builder_->setToNormalCodeGenMode(); - } - void turnOnSpecConstantOpMode() { - builder_->setToSpecConstCodeGenMode(); - } - -private: - spv::Builder* builder_; - bool previous_flag_; -}; - -struct OpDecorations { - public: - OpDecorations(spv::Decoration precision, spv::Decoration noContraction, spv::Decoration nonUniform) : - precision(precision) - , - noContraction(noContraction), - nonUniform(nonUniform) - { } - - spv::Decoration precision; - - void addNoContraction(spv::Builder& builder, spv::Id t) { builder.addDecoration(t, noContraction); } - void addNonUniform(spv::Builder& builder, spv::Id t) { builder.addDecoration(t, nonUniform); } - protected: - spv::Decoration noContraction; - spv::Decoration nonUniform; -}; - -} // namespace - -// -// The main holder of information for translating glslang to SPIR-V. -// -// Derives from the AST walking base class. -// -class TGlslangToSpvTraverser : public glslang::TIntermTraverser { -public: - TGlslangToSpvTraverser(unsigned int spvVersion, const glslang::TIntermediate*, spv::SpvBuildLogger* logger, - glslang::SpvOptions& options); - virtual ~TGlslangToSpvTraverser() { } - - bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*); - bool visitBinary(glslang::TVisit, glslang::TIntermBinary*); - void visitConstantUnion(glslang::TIntermConstantUnion*); - bool visitSelection(glslang::TVisit, glslang::TIntermSelection*); - bool visitSwitch(glslang::TVisit, glslang::TIntermSwitch*); - void visitSymbol(glslang::TIntermSymbol* symbol); - bool visitUnary(glslang::TVisit, glslang::TIntermUnary*); - bool visitLoop(glslang::TVisit, glslang::TIntermLoop*); - bool visitBranch(glslang::TVisit visit, glslang::TIntermBranch*); - - void finishSpv(bool compileOnly); - void dumpSpv(std::vector& out); - -protected: - TGlslangToSpvTraverser(TGlslangToSpvTraverser&); - TGlslangToSpvTraverser& operator=(TGlslangToSpvTraverser&); - - spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qualifier); - spv::Decoration TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier); - spv::Decoration TranslateNonUniformDecoration(const glslang::TQualifier& qualifier); - spv::Decoration TranslateNonUniformDecoration(const spv::Builder::AccessChain::CoherentFlags& coherentFlags); - spv::Builder::AccessChain::CoherentFlags TranslateCoherent(const glslang::TType& type); - spv::MemoryAccessMask TranslateMemoryAccess(const spv::Builder::AccessChain::CoherentFlags &coherentFlags); - spv::ImageOperandsMask TranslateImageOperands(const spv::Builder::AccessChain::CoherentFlags &coherentFlags); - spv::Scope TranslateMemoryScope(const spv::Builder::AccessChain::CoherentFlags &coherentFlags); - spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable, bool memberDeclaration); - spv::ImageFormat TranslateImageFormat(const glslang::TType& type); - spv::SelectionControlMask TranslateSelectionControl(const glslang::TIntermSelection&) const; - spv::SelectionControlMask TranslateSwitchControl(const glslang::TIntermSwitch&) const; - spv::LoopControlMask TranslateLoopControl(const glslang::TIntermLoop&, std::vector& operands) const; - spv::StorageClass TranslateStorageClass(const glslang::TType&); - void TranslateLiterals(const glslang::TVector&, std::vector&) const; - void addIndirectionIndexCapabilities(const glslang::TType& baseType, const glslang::TType& indexType); - spv::Id createSpvVariable(const glslang::TIntermSymbol*, spv::Id forcedType); - spv::Id getSampledType(const glslang::TSampler&); - spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&); - spv::Id createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped&, spv::Id parentResult); - void convertSwizzle(const glslang::TIntermAggregate&, std::vector& swizzle); - spv::Id convertGlslangToSpvType(const glslang::TType& type, bool forwardReferenceOnly = false); - spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&, - bool lastBufferBlockMember, bool forwardReferenceOnly = false); - void applySpirvDecorate(const glslang::TType& type, spv::Id id, std::optional member); - bool filterMember(const glslang::TType& member); - spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct, - glslang::TLayoutPacking, const glslang::TQualifier&); - spv::LinkageType convertGlslangLinkageToSpv(glslang::TLinkType glslangLinkType); - void decorateStructType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking, - const glslang::TQualifier&, spv::Id, const std::vector& spvMembers); - spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim, bool allowZero = false); - spv::Id accessChainLoad(const glslang::TType& type); - void accessChainStore(const glslang::TType& type, spv::Id rvalue); - void multiTypeStore(const glslang::TType&, spv::Id rValue); - spv::Id convertLoadedBoolInUniformToUint(const glslang::TType& type, spv::Id nominalTypeId, spv::Id loadedId); - glslang::TLayoutPacking getExplicitLayout(const glslang::TType& type) const; - int getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking, glslang::TLayoutMatrix); - int getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking, glslang::TLayoutMatrix); - void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, - int& nextOffset, glslang::TLayoutPacking, glslang::TLayoutMatrix); - void declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember); - - bool isShaderEntryPoint(const glslang::TIntermAggregate* node); - bool writableParam(glslang::TStorageQualifier) const; - bool originalParam(glslang::TStorageQualifier, const glslang::TType&, bool implicitThisParam); - void makeFunctions(const glslang::TIntermSequence&); - void makeGlobalInitializers(const glslang::TIntermSequence&); - void collectRayTracingLinkerObjects(); - void visitFunctions(const glslang::TIntermSequence&); - void handleFunctionEntry(const glslang::TIntermAggregate* node); - void translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, - spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); - void translateArguments(glslang::TIntermUnary& node, std::vector& arguments); - spv::Id createImageTextureFunctionCall(glslang::TIntermOperator* node); - spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*); - - spv::Id createBinaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right, - glslang::TBasicType typeProxy, bool reduceComparison = true); - spv::Id createBinaryMatrixOperation(spv::Op, OpDecorations&, spv::Id typeId, spv::Id left, spv::Id right); - spv::Id createUnaryOperation(glslang::TOperator op, OpDecorations&, spv::Id typeId, spv::Id operand, - glslang::TBasicType typeProxy, - const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); - spv::Id createUnaryMatrixOperation(spv::Op op, OpDecorations&, spv::Id typeId, spv::Id operand, - glslang::TBasicType typeProxy); - spv::Id createConversion(glslang::TOperator op, OpDecorations&, spv::Id destTypeId, spv::Id operand, - glslang::TBasicType typeProxy); - spv::Id createIntWidthConversion(glslang::TOperator op, spv::Id operand, int vectorSize, spv::Id destType); - spv::Id makeSmearedConstant(spv::Id constant, int vectorSize); - spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, - std::vector& operands, glslang::TBasicType typeProxy, - const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags); - spv::Id createInvocationsOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, - glslang::TBasicType typeProxy); - spv::Id CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, - spv::Id typeId, std::vector& operands); - spv::Id createSubgroupOperation(glslang::TOperator op, spv::Id typeId, std::vector& operands, - glslang::TBasicType typeProxy); - spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, - std::vector& operands, glslang::TBasicType typeProxy); - spv::Id createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId); - spv::Id getSymbolId(const glslang::TIntermSymbol* node); - void addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier & qualifier); - void addImageProcessingQCOMDecoration(spv::Id id, spv::Decoration decor); - spv::Id createSpvConstant(const glslang::TIntermTyped&); - spv::Id createSpvConstantFromConstUnionArray(const glslang::TType& type, const glslang::TConstUnionArray&, - int& nextConst, bool specConstant); - bool isTrivialLeaf(const glslang::TIntermTyped* node); - bool isTrivial(const glslang::TIntermTyped* node); - spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right); - spv::Id getExtBuiltins(const char* name); - std::pair getForcedType(glslang::TBuiltInVariable builtIn, const glslang::TType&); - spv::Id translateForcedType(spv::Id object); - spv::Id createCompositeConstruct(spv::Id typeId, std::vector constituents); - - glslang::SpvOptions& options; - spv::Function* shaderEntry; - spv::Function* currentFunction; - spv::Instruction* entryPoint; - int sequenceDepth; - - spv::SpvBuildLogger* logger; - - // There is a 1:1 mapping between a spv builder and a module; this is thread safe - spv::Builder builder; - bool inEntryPoint; - bool entryPointTerminated; - bool linkageOnly; // true when visiting the set of objects in the AST present only for - // establishing interface, whether or not they were statically used - std::set iOSet; // all input/output variables from either static use or declaration of interface - const glslang::TIntermediate* glslangIntermediate; - bool nanMinMaxClamp; // true if use NMin/NMax/NClamp instead of FMin/FMax/FClamp - spv::Id stdBuiltins; - spv::Id nonSemanticDebugPrintf; - std::unordered_map extBuiltinMap; - - std::unordered_map symbolValues; - std::unordered_map builtInVariableIds; - std::unordered_set rValueParameters; // set of formal function parameters passed as rValues, - // rather than a pointer - std::unordered_map functionMap; - std::unordered_map structMap[glslang::ElpCount][glslang::ElmCount]; - // for mapping glslang block indices to spv indices (e.g., due to hidden members): - std::unordered_map> memberRemapper; - // for mapping glslang symbol struct to symbol Id - std::unordered_map glslangTypeToIdMap; - std::stack breakForLoop; // false means break for switch - std::unordered_map counterOriginator; - // Map pointee types for EbtReference to their forward pointers - std::map forwardPointers; - // Type forcing, for when SPIR-V wants a different type than the AST, - // requiring local translation to and from SPIR-V type on every access. - // Maps AST-required-type-id> - std::unordered_map forceType; - // Used by Task shader while generating opearnds for OpEmitMeshTasksEXT - spv::Id taskPayloadID; - // Used later for generating OpTraceKHR/OpExecuteCallableKHR/OpHitObjectRecordHit*/OpHitObjectGetShaderBindingTableData - std::unordered_map locationToSymbol[4]; -}; - -// -// Helper functions for translating glslang representations to SPIR-V enumerants. -// - -// Translate glslang profile to SPIR-V source language. -spv::SourceLanguage TranslateSourceLanguage(glslang::EShSource source, EProfile profile) -{ - switch (source) { - case glslang::EShSourceGlsl: - switch (profile) { - case ENoProfile: - case ECoreProfile: - case ECompatibilityProfile: - return spv::SourceLanguageGLSL; - case EEsProfile: - return spv::SourceLanguageESSL; - default: - return spv::SourceLanguageUnknown; - } - case glslang::EShSourceHlsl: - return spv::SourceLanguageHLSL; - default: - return spv::SourceLanguageUnknown; - } -} - -// Translate glslang language (stage) to SPIR-V execution model. -spv::ExecutionModel TranslateExecutionModel(EShLanguage stage, bool isMeshShaderEXT = false) -{ - switch (stage) { - case EShLangVertex: return spv::ExecutionModelVertex; - case EShLangFragment: return spv::ExecutionModelFragment; - case EShLangCompute: return spv::ExecutionModelGLCompute; - case EShLangTessControl: return spv::ExecutionModelTessellationControl; - case EShLangTessEvaluation: return spv::ExecutionModelTessellationEvaluation; - case EShLangGeometry: return spv::ExecutionModelGeometry; - case EShLangRayGen: return spv::ExecutionModelRayGenerationKHR; - case EShLangIntersect: return spv::ExecutionModelIntersectionKHR; - case EShLangAnyHit: return spv::ExecutionModelAnyHitKHR; - case EShLangClosestHit: return spv::ExecutionModelClosestHitKHR; - case EShLangMiss: return spv::ExecutionModelMissKHR; - case EShLangCallable: return spv::ExecutionModelCallableKHR; - case EShLangTask: return (isMeshShaderEXT)? spv::ExecutionModelTaskEXT : spv::ExecutionModelTaskNV; - case EShLangMesh: return (isMeshShaderEXT)? spv::ExecutionModelMeshEXT: spv::ExecutionModelMeshNV; - default: - assert(0); - return spv::ExecutionModelFragment; - } -} - -// Translate glslang sampler type to SPIR-V dimensionality. -spv::Dim TranslateDimensionality(const glslang::TSampler& sampler) -{ - switch (sampler.dim) { - case glslang::Esd1D: return spv::Dim1D; - case glslang::Esd2D: return spv::Dim2D; - case glslang::Esd3D: return spv::Dim3D; - case glslang::EsdCube: return spv::DimCube; - case glslang::EsdRect: return spv::DimRect; - case glslang::EsdBuffer: return spv::DimBuffer; - case glslang::EsdSubpass: return spv::DimSubpassData; - case glslang::EsdAttachmentEXT: return spv::DimTileImageDataEXT; - default: - assert(0); - return spv::Dim2D; - } -} - -// Translate glslang precision to SPIR-V precision decorations. -spv::Decoration TranslatePrecisionDecoration(glslang::TPrecisionQualifier glslangPrecision) -{ - switch (glslangPrecision) { - case glslang::EpqLow: return spv::DecorationRelaxedPrecision; - case glslang::EpqMedium: return spv::DecorationRelaxedPrecision; - default: - return spv::NoPrecision; - } -} - -// Translate glslang type to SPIR-V precision decorations. -spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type) -{ - return TranslatePrecisionDecoration(type.getQualifier().precision); -} - -// Translate glslang type to SPIR-V block decorations. -spv::Decoration TranslateBlockDecoration(const glslang::TStorageQualifier storage, bool useStorageBuffer) -{ - switch (storage) { - case glslang::EvqUniform: return spv::DecorationBlock; - case glslang::EvqBuffer: return useStorageBuffer ? spv::DecorationBlock : spv::DecorationBufferBlock; - case glslang::EvqVaryingIn: return spv::DecorationBlock; - case glslang::EvqVaryingOut: return spv::DecorationBlock; - case glslang::EvqShared: return spv::DecorationBlock; - case glslang::EvqPayload: return spv::DecorationBlock; - case glslang::EvqPayloadIn: return spv::DecorationBlock; - case glslang::EvqHitAttr: return spv::DecorationBlock; - case glslang::EvqCallableData: return spv::DecorationBlock; - case glslang::EvqCallableDataIn: return spv::DecorationBlock; - case glslang::EvqHitObjectAttrNV: return spv::DecorationBlock; - default: - assert(0); - break; - } - - return spv::DecorationMax; -} - -// Translate glslang type to SPIR-V memory decorations. -void TranslateMemoryDecoration(const glslang::TQualifier& qualifier, std::vector& memory, - bool useVulkanMemoryModel) -{ - if (!useVulkanMemoryModel) { - if (qualifier.isCoherent()) - memory.push_back(spv::DecorationCoherent); - if (qualifier.isVolatile()) { - memory.push_back(spv::DecorationVolatile); - memory.push_back(spv::DecorationCoherent); - } - } - if (qualifier.isRestrict()) - memory.push_back(spv::DecorationRestrict); - if (qualifier.isReadOnly()) - memory.push_back(spv::DecorationNonWritable); - if (qualifier.isWriteOnly()) - memory.push_back(spv::DecorationNonReadable); -} - -// Translate glslang type to SPIR-V layout decorations. -spv::Decoration TranslateLayoutDecoration(const glslang::TType& type, glslang::TLayoutMatrix matrixLayout) -{ - if (type.isMatrix()) { - switch (matrixLayout) { - case glslang::ElmRowMajor: - return spv::DecorationRowMajor; - case glslang::ElmColumnMajor: - return spv::DecorationColMajor; - default: - // opaque layouts don't need a majorness - return spv::DecorationMax; - } - } else { - switch (type.getBasicType()) { - default: - return spv::DecorationMax; - break; - case glslang::EbtBlock: - switch (type.getQualifier().storage) { - case glslang::EvqShared: - case glslang::EvqUniform: - case glslang::EvqBuffer: - switch (type.getQualifier().layoutPacking) { - case glslang::ElpShared: return spv::DecorationGLSLShared; - case glslang::ElpPacked: return spv::DecorationGLSLPacked; - default: - return spv::DecorationMax; - } - case glslang::EvqVaryingIn: - case glslang::EvqVaryingOut: - if (type.getQualifier().isTaskMemory()) { - switch (type.getQualifier().layoutPacking) { - case glslang::ElpShared: return spv::DecorationGLSLShared; - case glslang::ElpPacked: return spv::DecorationGLSLPacked; - default: break; - } - } else { - assert(type.getQualifier().layoutPacking == glslang::ElpNone); - } - return spv::DecorationMax; - case glslang::EvqPayload: - case glslang::EvqPayloadIn: - case glslang::EvqHitAttr: - case glslang::EvqCallableData: - case glslang::EvqCallableDataIn: - case glslang::EvqHitObjectAttrNV: - return spv::DecorationMax; - default: - assert(0); - return spv::DecorationMax; - } - } - } -} - -// Translate glslang type to SPIR-V interpolation decorations. -// Returns spv::DecorationMax when no decoration -// should be applied. -spv::Decoration TGlslangToSpvTraverser::TranslateInterpolationDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.smooth) - // Smooth decoration doesn't exist in SPIR-V 1.0 - return spv::DecorationMax; - else if (qualifier.isNonPerspective()) - return spv::DecorationNoPerspective; - else if (qualifier.flat) - return spv::DecorationFlat; - else if (qualifier.isExplicitInterpolation()) { - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::DecorationExplicitInterpAMD; - } - else - return spv::DecorationMax; -} - -// Translate glslang type to SPIR-V auxiliary storage decorations. -// Returns spv::DecorationMax when no decoration -// should be applied. -spv::Decoration TGlslangToSpvTraverser::TranslateAuxiliaryStorageDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.centroid) - return spv::DecorationCentroid; - else if (qualifier.patch) - return spv::DecorationPatch; - else if (qualifier.sample) { - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::DecorationSample; - } - - return spv::DecorationMax; -} - -// If glslang type is invariant, return SPIR-V invariant decoration. -spv::Decoration TranslateInvariantDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.invariant) - return spv::DecorationInvariant; - else - return spv::DecorationMax; -} - -// If glslang type is noContraction, return SPIR-V NoContraction decoration. -spv::Decoration TranslateNoContractionDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.isNoContraction()) - return spv::DecorationNoContraction; - else - return spv::DecorationMax; -} - -// If glslang type is nonUniform, return SPIR-V NonUniform decoration. -spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration(const glslang::TQualifier& qualifier) -{ - if (qualifier.isNonUniform()) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityShaderNonUniformEXT); - return spv::DecorationNonUniformEXT; - } else - return spv::DecorationMax; -} - -// If lvalue flags contains nonUniform, return SPIR-V NonUniform decoration. -spv::Decoration TGlslangToSpvTraverser::TranslateNonUniformDecoration( - const spv::Builder::AccessChain::CoherentFlags& coherentFlags) -{ - if (coherentFlags.isNonUniform()) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityShaderNonUniformEXT); - return spv::DecorationNonUniformEXT; - } else - return spv::DecorationMax; -} - -spv::MemoryAccessMask TGlslangToSpvTraverser::TranslateMemoryAccess( - const spv::Builder::AccessChain::CoherentFlags &coherentFlags) -{ - spv::MemoryAccessMask mask = spv::MemoryAccessMaskNone; - - if (!glslangIntermediate->usingVulkanMemoryModel() || coherentFlags.isImage) - return mask; - - if (coherentFlags.isVolatile() || coherentFlags.anyCoherent()) { - mask = mask | spv::MemoryAccessMakePointerAvailableKHRMask | - spv::MemoryAccessMakePointerVisibleKHRMask; - } - - if (coherentFlags.nonprivate) { - mask = mask | spv::MemoryAccessNonPrivatePointerKHRMask; - } - if (coherentFlags.volatil) { - mask = mask | spv::MemoryAccessVolatileMask; - } - if (mask != spv::MemoryAccessMaskNone) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - - return mask; -} - -spv::ImageOperandsMask TGlslangToSpvTraverser::TranslateImageOperands( - const spv::Builder::AccessChain::CoherentFlags &coherentFlags) -{ - spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; - - if (!glslangIntermediate->usingVulkanMemoryModel()) - return mask; - - if (coherentFlags.volatil || - coherentFlags.anyCoherent()) { - mask = mask | spv::ImageOperandsMakeTexelAvailableKHRMask | - spv::ImageOperandsMakeTexelVisibleKHRMask; - } - if (coherentFlags.nonprivate) { - mask = mask | spv::ImageOperandsNonPrivateTexelKHRMask; - } - if (coherentFlags.volatil) { - mask = mask | spv::ImageOperandsVolatileTexelKHRMask; - } - if (mask != spv::ImageOperandsMaskNone) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - - return mask; -} - -spv::Builder::AccessChain::CoherentFlags TGlslangToSpvTraverser::TranslateCoherent(const glslang::TType& type) -{ - spv::Builder::AccessChain::CoherentFlags flags = {}; - flags.coherent = type.getQualifier().coherent; - flags.devicecoherent = type.getQualifier().devicecoherent; - flags.queuefamilycoherent = type.getQualifier().queuefamilycoherent; - // shared variables are implicitly workgroupcoherent in GLSL. - flags.workgroupcoherent = type.getQualifier().workgroupcoherent || - type.getQualifier().storage == glslang::EvqShared; - flags.subgroupcoherent = type.getQualifier().subgroupcoherent; - flags.shadercallcoherent = type.getQualifier().shadercallcoherent; - flags.volatil = type.getQualifier().volatil; - // *coherent variables are implicitly nonprivate in GLSL - flags.nonprivate = type.getQualifier().nonprivate || - flags.anyCoherent() || - flags.volatil; - flags.isImage = type.getBasicType() == glslang::EbtSampler; - flags.nonUniform = type.getQualifier().nonUniform; - return flags; -} - -spv::Scope TGlslangToSpvTraverser::TranslateMemoryScope( - const spv::Builder::AccessChain::CoherentFlags &coherentFlags) -{ - spv::Scope scope = spv::ScopeMax; - - if (coherentFlags.volatil || coherentFlags.coherent) { - // coherent defaults to Device scope in the old model, QueueFamilyKHR scope in the new model - scope = glslangIntermediate->usingVulkanMemoryModel() ? spv::ScopeQueueFamilyKHR : spv::ScopeDevice; - } else if (coherentFlags.devicecoherent) { - scope = spv::ScopeDevice; - } else if (coherentFlags.queuefamilycoherent) { - scope = spv::ScopeQueueFamilyKHR; - } else if (coherentFlags.workgroupcoherent) { - scope = spv::ScopeWorkgroup; - } else if (coherentFlags.subgroupcoherent) { - scope = spv::ScopeSubgroup; - } else if (coherentFlags.shadercallcoherent) { - scope = spv::ScopeShaderCallKHR; - } - if (glslangIntermediate->usingVulkanMemoryModel() && scope == spv::ScopeDevice) { - builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); - } - - return scope; -} - -// Translate a glslang built-in variable to a SPIR-V built in decoration. Also generate -// associated capabilities when required. For some built-in variables, a capability -// is generated only when using the variable in an executable instruction, but not when -// just declaring a struct member variable with it. This is true for PointSize, -// ClipDistance, and CullDistance. -spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn, - bool memberDeclaration) -{ - switch (builtIn) { - case glslang::EbvPointSize: - // Defer adding the capability until the built-in is actually used. - if (! memberDeclaration) { - switch (glslangIntermediate->getStage()) { - case EShLangGeometry: - builder.addCapability(spv::CapabilityGeometryPointSize); - break; - case EShLangTessControl: - case EShLangTessEvaluation: - builder.addCapability(spv::CapabilityTessellationPointSize); - break; - default: - break; - } - } - return spv::BuiltInPointSize; - - case glslang::EbvPosition: return spv::BuiltInPosition; - case glslang::EbvVertexId: return spv::BuiltInVertexId; - case glslang::EbvInstanceId: return spv::BuiltInInstanceId; - case glslang::EbvVertexIndex: return spv::BuiltInVertexIndex; - case glslang::EbvInstanceIndex: return spv::BuiltInInstanceIndex; - - case glslang::EbvFragCoord: return spv::BuiltInFragCoord; - case glslang::EbvPointCoord: return spv::BuiltInPointCoord; - case glslang::EbvFace: return spv::BuiltInFrontFacing; - case glslang::EbvFragDepth: return spv::BuiltInFragDepth; - - case glslang::EbvNumWorkGroups: return spv::BuiltInNumWorkgroups; - case glslang::EbvWorkGroupSize: return spv::BuiltInWorkgroupSize; - case glslang::EbvWorkGroupId: return spv::BuiltInWorkgroupId; - case glslang::EbvLocalInvocationId: return spv::BuiltInLocalInvocationId; - case glslang::EbvLocalInvocationIndex: return spv::BuiltInLocalInvocationIndex; - case glslang::EbvGlobalInvocationId: return spv::BuiltInGlobalInvocationId; - - // These *Distance capabilities logically belong here, but if the member is declared and - // then never used, consumers of SPIR-V prefer the capability not be declared. - // They are now generated when used, rather than here when declared. - // Potentially, the specification should be more clear what the minimum - // use needed is to trigger the capability. - // - case glslang::EbvClipDistance: - if (!memberDeclaration) - builder.addCapability(spv::CapabilityClipDistance); - return spv::BuiltInClipDistance; - - case glslang::EbvCullDistance: - if (!memberDeclaration) - builder.addCapability(spv::CapabilityCullDistance); - return spv::BuiltInCullDistance; - - case glslang::EbvViewportIndex: - if (glslangIntermediate->getStage() == EShLangGeometry || - glslangIntermediate->getStage() == EShLangFragment) { - builder.addCapability(spv::CapabilityMultiViewport); - } - if (glslangIntermediate->getStage() == EShLangVertex || - glslangIntermediate->getStage() == EShLangTessControl || - glslangIntermediate->getStage() == EShLangTessEvaluation) { - - if (builder.getSpvVersion() < spv::Spv_1_5) { - builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5); - builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); - } - else - builder.addCapability(spv::CapabilityShaderViewportIndex); - } - return spv::BuiltInViewportIndex; - - case glslang::EbvSampleId: - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::BuiltInSampleId; - - case glslang::EbvSamplePosition: - builder.addCapability(spv::CapabilitySampleRateShading); - return spv::BuiltInSamplePosition; - - case glslang::EbvSampleMask: - return spv::BuiltInSampleMask; - - case glslang::EbvLayer: - if (glslangIntermediate->getStage() == EShLangMesh) { - return spv::BuiltInLayer; - } - if (glslangIntermediate->getStage() == EShLangGeometry || - glslangIntermediate->getStage() == EShLangFragment) { - builder.addCapability(spv::CapabilityGeometry); - } - if (glslangIntermediate->getStage() == EShLangVertex || - glslangIntermediate->getStage() == EShLangTessControl || - glslangIntermediate->getStage() == EShLangTessEvaluation) { - - if (builder.getSpvVersion() < spv::Spv_1_5) { - builder.addIncorporatedExtension(spv::E_SPV_EXT_shader_viewport_index_layer, spv::Spv_1_5); - builder.addCapability(spv::CapabilityShaderViewportIndexLayerEXT); - } else - builder.addCapability(spv::CapabilityShaderLayer); - } - return spv::BuiltInLayer; - - case glslang::EbvBaseVertex: - builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInBaseVertex; - - case glslang::EbvBaseInstance: - builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInBaseInstance; - - case glslang::EbvDrawId: - builder.addIncorporatedExtension(spv::E_SPV_KHR_shader_draw_parameters, spv::Spv_1_3); - builder.addCapability(spv::CapabilityDrawParameters); - return spv::BuiltInDrawIndex; - - case glslang::EbvPrimitiveId: - if (glslangIntermediate->getStage() == EShLangFragment) - builder.addCapability(spv::CapabilityGeometry); - return spv::BuiltInPrimitiveId; - - case glslang::EbvFragStencilRef: - builder.addExtension(spv::E_SPV_EXT_shader_stencil_export); - builder.addCapability(spv::CapabilityStencilExportEXT); - return spv::BuiltInFragStencilRefEXT; - - case glslang::EbvShadingRateKHR: - builder.addExtension(spv::E_SPV_KHR_fragment_shading_rate); - builder.addCapability(spv::CapabilityFragmentShadingRateKHR); - return spv::BuiltInShadingRateKHR; - - case glslang::EbvPrimitiveShadingRateKHR: - builder.addExtension(spv::E_SPV_KHR_fragment_shading_rate); - builder.addCapability(spv::CapabilityFragmentShadingRateKHR); - return spv::BuiltInPrimitiveShadingRateKHR; - - case glslang::EbvInvocationId: return spv::BuiltInInvocationId; - case glslang::EbvTessLevelInner: return spv::BuiltInTessLevelInner; - case glslang::EbvTessLevelOuter: return spv::BuiltInTessLevelOuter; - case glslang::EbvTessCoord: return spv::BuiltInTessCoord; - case glslang::EbvPatchVertices: return spv::BuiltInPatchVertices; - case glslang::EbvHelperInvocation: return spv::BuiltInHelperInvocation; - - case glslang::EbvSubGroupSize: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupSize; - - case glslang::EbvSubGroupInvocation: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLocalInvocationId; - - case glslang::EbvSubGroupEqMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupEqMask; - - case glslang::EbvSubGroupGeMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupGeMask; - - case glslang::EbvSubGroupGtMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupGtMask; - - case glslang::EbvSubGroupLeMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLeMask; - - case glslang::EbvSubGroupLtMask: - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - return spv::BuiltInSubgroupLtMask; - - case glslang::EbvNumSubgroups: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInNumSubgroups; - - case glslang::EbvSubgroupID: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInSubgroupId; - - case glslang::EbvSubgroupSize2: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInSubgroupSize; - - case glslang::EbvSubgroupInvocation2: - builder.addCapability(spv::CapabilityGroupNonUniform); - return spv::BuiltInSubgroupLocalInvocationId; - - case glslang::EbvSubgroupEqMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupEqMask; - - case glslang::EbvSubgroupGeMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupGeMask; - - case glslang::EbvSubgroupGtMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupGtMask; - - case glslang::EbvSubgroupLeMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupLeMask; - - case glslang::EbvSubgroupLtMask2: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - return spv::BuiltInSubgroupLtMask; - - case glslang::EbvBaryCoordNoPersp: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspAMD; - - case glslang::EbvBaryCoordNoPerspCentroid: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspCentroidAMD; - - case glslang::EbvBaryCoordNoPerspSample: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordNoPerspSampleAMD; - - case glslang::EbvBaryCoordSmooth: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothAMD; - - case glslang::EbvBaryCoordSmoothCentroid: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothCentroidAMD; - - case glslang::EbvBaryCoordSmoothSample: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordSmoothSampleAMD; - - case glslang::EbvBaryCoordPullModel: - builder.addExtension(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - return spv::BuiltInBaryCoordPullModelAMD; - - case glslang::EbvDeviceIndex: - builder.addIncorporatedExtension(spv::E_SPV_KHR_device_group, spv::Spv_1_3); - builder.addCapability(spv::CapabilityDeviceGroup); - return spv::BuiltInDeviceIndex; - - case glslang::EbvViewIndex: - builder.addIncorporatedExtension(spv::E_SPV_KHR_multiview, spv::Spv_1_3); - builder.addCapability(spv::CapabilityMultiView); - return spv::BuiltInViewIndex; - - case glslang::EbvFragSizeEXT: - builder.addExtension(spv::E_SPV_EXT_fragment_invocation_density); - builder.addCapability(spv::CapabilityFragmentDensityEXT); - return spv::BuiltInFragSizeEXT; - - case glslang::EbvFragInvocationCountEXT: - builder.addExtension(spv::E_SPV_EXT_fragment_invocation_density); - builder.addCapability(spv::CapabilityFragmentDensityEXT); - return spv::BuiltInFragInvocationCountEXT; - - case glslang::EbvViewportMaskNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_viewport_array2); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - } - return spv::BuiltInViewportMaskNV; - case glslang::EbvSecondaryPositionNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - } - return spv::BuiltInSecondaryPositionNV; - case glslang::EbvSecondaryViewportMaskNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - } - return spv::BuiltInSecondaryViewportMaskNV; - case glslang::EbvPositionPerViewNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes); - builder.addCapability(spv::CapabilityPerViewAttributesNV); - } - return spv::BuiltInPositionPerViewNV; - case glslang::EbvViewportMaskPerViewNV: - if (!memberDeclaration) { - builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes); - builder.addCapability(spv::CapabilityPerViewAttributesNV); - } - return spv::BuiltInViewportMaskPerViewNV; - case glslang::EbvFragFullyCoveredNV: - builder.addExtension(spv::E_SPV_EXT_fragment_fully_covered); - builder.addCapability(spv::CapabilityFragmentFullyCoveredEXT); - return spv::BuiltInFullyCoveredEXT; - case glslang::EbvFragmentSizeNV: - builder.addExtension(spv::E_SPV_NV_shading_rate); - builder.addCapability(spv::CapabilityShadingRateNV); - return spv::BuiltInFragmentSizeNV; - case glslang::EbvInvocationsPerPixelNV: - builder.addExtension(spv::E_SPV_NV_shading_rate); - builder.addCapability(spv::CapabilityShadingRateNV); - return spv::BuiltInInvocationsPerPixelNV; - - // ray tracing - case glslang::EbvLaunchId: - return spv::BuiltInLaunchIdKHR; - case glslang::EbvLaunchSize: - return spv::BuiltInLaunchSizeKHR; - case glslang::EbvWorldRayOrigin: - return spv::BuiltInWorldRayOriginKHR; - case glslang::EbvWorldRayDirection: - return spv::BuiltInWorldRayDirectionKHR; - case glslang::EbvObjectRayOrigin: - return spv::BuiltInObjectRayOriginKHR; - case glslang::EbvObjectRayDirection: - return spv::BuiltInObjectRayDirectionKHR; - case glslang::EbvRayTmin: - return spv::BuiltInRayTminKHR; - case glslang::EbvRayTmax: - return spv::BuiltInRayTmaxKHR; - case glslang::EbvCullMask: - return spv::BuiltInCullMaskKHR; - case glslang::EbvPositionFetch: - return spv::BuiltInHitTriangleVertexPositionsKHR; - case glslang::EbvInstanceCustomIndex: - return spv::BuiltInInstanceCustomIndexKHR; - case glslang::EbvHitT: - { - // this is a GLSL alias of RayTmax - // in SPV_NV_ray_tracing it has a dedicated builtin - // but in SPV_KHR_ray_tracing it gets mapped to RayTmax - auto& extensions = glslangIntermediate->getRequestedExtensions(); - if (extensions.find("GL_NV_ray_tracing") != extensions.end()) { - return spv::BuiltInHitTNV; - } else { - return spv::BuiltInRayTmaxKHR; - } - } - case glslang::EbvHitKind: - return spv::BuiltInHitKindKHR; - case glslang::EbvObjectToWorld: - case glslang::EbvObjectToWorld3x4: - return spv::BuiltInObjectToWorldKHR; - case glslang::EbvWorldToObject: - case glslang::EbvWorldToObject3x4: - return spv::BuiltInWorldToObjectKHR; - case glslang::EbvIncomingRayFlags: - return spv::BuiltInIncomingRayFlagsKHR; - case glslang::EbvGeometryIndex: - return spv::BuiltInRayGeometryIndexKHR; - case glslang::EbvCurrentRayTimeNV: - builder.addExtension(spv::E_SPV_NV_ray_tracing_motion_blur); - builder.addCapability(spv::CapabilityRayTracingMotionBlurNV); - return spv::BuiltInCurrentRayTimeNV; - case glslang::EbvMicroTrianglePositionNV: - builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); - builder.addExtension("SPV_NV_displacement_micromap"); - return spv::BuiltInHitMicroTriangleVertexPositionsNV; - case glslang::EbvMicroTriangleBaryNV: - builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); - builder.addExtension("SPV_NV_displacement_micromap"); - return spv::BuiltInHitMicroTriangleVertexBarycentricsNV; - case glslang::EbvHitKindFrontFacingMicroTriangleNV: - builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); - builder.addExtension("SPV_NV_displacement_micromap"); - return spv::BuiltInHitKindFrontFacingMicroTriangleNV; - case glslang::EbvHitKindBackFacingMicroTriangleNV: - builder.addCapability(spv::CapabilityRayTracingDisplacementMicromapNV); - builder.addExtension("SPV_NV_displacement_micromap"); - return spv::BuiltInHitKindBackFacingMicroTriangleNV; - - // barycentrics - case glslang::EbvBaryCoordNV: - builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric); - builder.addCapability(spv::CapabilityFragmentBarycentricNV); - return spv::BuiltInBaryCoordNV; - case glslang::EbvBaryCoordNoPerspNV: - builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric); - builder.addCapability(spv::CapabilityFragmentBarycentricNV); - return spv::BuiltInBaryCoordNoPerspNV; - - case glslang::EbvBaryCoordEXT: - builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric); - builder.addCapability(spv::CapabilityFragmentBarycentricKHR); - return spv::BuiltInBaryCoordKHR; - case glslang::EbvBaryCoordNoPerspEXT: - builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric); - builder.addCapability(spv::CapabilityFragmentBarycentricKHR); - return spv::BuiltInBaryCoordNoPerspKHR; - - // mesh shaders - case glslang::EbvTaskCountNV: - return spv::BuiltInTaskCountNV; - case glslang::EbvPrimitiveCountNV: - return spv::BuiltInPrimitiveCountNV; - case glslang::EbvPrimitiveIndicesNV: - return spv::BuiltInPrimitiveIndicesNV; - case glslang::EbvClipDistancePerViewNV: - return spv::BuiltInClipDistancePerViewNV; - case glslang::EbvCullDistancePerViewNV: - return spv::BuiltInCullDistancePerViewNV; - case glslang::EbvLayerPerViewNV: - return spv::BuiltInLayerPerViewNV; - case glslang::EbvMeshViewCountNV: - return spv::BuiltInMeshViewCountNV; - case glslang::EbvMeshViewIndicesNV: - return spv::BuiltInMeshViewIndicesNV; - - // SPV_EXT_mesh_shader - case glslang::EbvPrimitivePointIndicesEXT: - return spv::BuiltInPrimitivePointIndicesEXT; - case glslang::EbvPrimitiveLineIndicesEXT: - return spv::BuiltInPrimitiveLineIndicesEXT; - case glslang::EbvPrimitiveTriangleIndicesEXT: - return spv::BuiltInPrimitiveTriangleIndicesEXT; - case glslang::EbvCullPrimitiveEXT: - return spv::BuiltInCullPrimitiveEXT; - - // sm builtins - case glslang::EbvWarpsPerSM: - builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); - builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); - return spv::BuiltInWarpsPerSMNV; - case glslang::EbvSMCount: - builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); - builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); - return spv::BuiltInSMCountNV; - case glslang::EbvWarpID: - builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); - builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); - return spv::BuiltInWarpIDNV; - case glslang::EbvSMID: - builder.addExtension(spv::E_SPV_NV_shader_sm_builtins); - builder.addCapability(spv::CapabilityShaderSMBuiltinsNV); - return spv::BuiltInSMIDNV; - - // ARM builtins - case glslang::EbvCoreCountARM: - builder.addExtension(spv::E_SPV_ARM_core_builtins); - builder.addCapability(spv::CapabilityCoreBuiltinsARM); - return spv::BuiltInCoreCountARM; - case glslang::EbvCoreIDARM: - builder.addExtension(spv::E_SPV_ARM_core_builtins); - builder.addCapability(spv::CapabilityCoreBuiltinsARM); - return spv::BuiltInCoreIDARM; - case glslang::EbvCoreMaxIDARM: - builder.addExtension(spv::E_SPV_ARM_core_builtins); - builder.addCapability(spv::CapabilityCoreBuiltinsARM); - return spv::BuiltInCoreMaxIDARM; - case glslang::EbvWarpIDARM: - builder.addExtension(spv::E_SPV_ARM_core_builtins); - builder.addCapability(spv::CapabilityCoreBuiltinsARM); - return spv::BuiltInWarpIDARM; - case glslang::EbvWarpMaxIDARM: - builder.addExtension(spv::E_SPV_ARM_core_builtins); - builder.addCapability(spv::CapabilityCoreBuiltinsARM); - return spv::BuiltInWarpMaxIDARM; - - default: - return spv::BuiltInMax; - } -} - -// Translate glslang image layout format to SPIR-V image format. -spv::ImageFormat TGlslangToSpvTraverser::TranslateImageFormat(const glslang::TType& type) -{ - assert(type.getBasicType() == glslang::EbtSampler); - - // Check for capabilities - switch (type.getQualifier().getFormat()) { - case glslang::ElfRg32f: - case glslang::ElfRg16f: - case glslang::ElfR11fG11fB10f: - case glslang::ElfR16f: - case glslang::ElfRgba16: - case glslang::ElfRgb10A2: - case glslang::ElfRg16: - case glslang::ElfRg8: - case glslang::ElfR16: - case glslang::ElfR8: - case glslang::ElfRgba16Snorm: - case glslang::ElfRg16Snorm: - case glslang::ElfRg8Snorm: - case glslang::ElfR16Snorm: - case glslang::ElfR8Snorm: - - case glslang::ElfRg32i: - case glslang::ElfRg16i: - case glslang::ElfRg8i: - case glslang::ElfR16i: - case glslang::ElfR8i: - - case glslang::ElfRgb10a2ui: - case glslang::ElfRg32ui: - case glslang::ElfRg16ui: - case glslang::ElfRg8ui: - case glslang::ElfR16ui: - case glslang::ElfR8ui: - builder.addCapability(spv::CapabilityStorageImageExtendedFormats); - break; - - case glslang::ElfR64ui: - case glslang::ElfR64i: - builder.addExtension(spv::E_SPV_EXT_shader_image_int64); - builder.addCapability(spv::CapabilityInt64ImageEXT); - default: - break; - } - - // do the translation - switch (type.getQualifier().getFormat()) { - case glslang::ElfNone: return spv::ImageFormatUnknown; - case glslang::ElfRgba32f: return spv::ImageFormatRgba32f; - case glslang::ElfRgba16f: return spv::ImageFormatRgba16f; - case glslang::ElfR32f: return spv::ImageFormatR32f; - case glslang::ElfRgba8: return spv::ImageFormatRgba8; - case glslang::ElfRgba8Snorm: return spv::ImageFormatRgba8Snorm; - case glslang::ElfRg32f: return spv::ImageFormatRg32f; - case glslang::ElfRg16f: return spv::ImageFormatRg16f; - case glslang::ElfR11fG11fB10f: return spv::ImageFormatR11fG11fB10f; - case glslang::ElfR16f: return spv::ImageFormatR16f; - case glslang::ElfRgba16: return spv::ImageFormatRgba16; - case glslang::ElfRgb10A2: return spv::ImageFormatRgb10A2; - case glslang::ElfRg16: return spv::ImageFormatRg16; - case glslang::ElfRg8: return spv::ImageFormatRg8; - case glslang::ElfR16: return spv::ImageFormatR16; - case glslang::ElfR8: return spv::ImageFormatR8; - case glslang::ElfRgba16Snorm: return spv::ImageFormatRgba16Snorm; - case glslang::ElfRg16Snorm: return spv::ImageFormatRg16Snorm; - case glslang::ElfRg8Snorm: return spv::ImageFormatRg8Snorm; - case glslang::ElfR16Snorm: return spv::ImageFormatR16Snorm; - case glslang::ElfR8Snorm: return spv::ImageFormatR8Snorm; - case glslang::ElfRgba32i: return spv::ImageFormatRgba32i; - case glslang::ElfRgba16i: return spv::ImageFormatRgba16i; - case glslang::ElfRgba8i: return spv::ImageFormatRgba8i; - case glslang::ElfR32i: return spv::ImageFormatR32i; - case glslang::ElfRg32i: return spv::ImageFormatRg32i; - case glslang::ElfRg16i: return spv::ImageFormatRg16i; - case glslang::ElfRg8i: return spv::ImageFormatRg8i; - case glslang::ElfR16i: return spv::ImageFormatR16i; - case glslang::ElfR8i: return spv::ImageFormatR8i; - case glslang::ElfRgba32ui: return spv::ImageFormatRgba32ui; - case glslang::ElfRgba16ui: return spv::ImageFormatRgba16ui; - case glslang::ElfRgba8ui: return spv::ImageFormatRgba8ui; - case glslang::ElfR32ui: return spv::ImageFormatR32ui; - case glslang::ElfRg32ui: return spv::ImageFormatRg32ui; - case glslang::ElfRg16ui: return spv::ImageFormatRg16ui; - case glslang::ElfRgb10a2ui: return spv::ImageFormatRgb10a2ui; - case glslang::ElfRg8ui: return spv::ImageFormatRg8ui; - case glslang::ElfR16ui: return spv::ImageFormatR16ui; - case glslang::ElfR8ui: return spv::ImageFormatR8ui; - case glslang::ElfR64ui: return spv::ImageFormatR64ui; - case glslang::ElfR64i: return spv::ImageFormatR64i; - default: return spv::ImageFormatMax; - } -} - -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSelectionControl( - const glslang::TIntermSelection& selectionNode) const -{ - if (selectionNode.getFlatten()) - return spv::SelectionControlFlattenMask; - if (selectionNode.getDontFlatten()) - return spv::SelectionControlDontFlattenMask; - return spv::SelectionControlMaskNone; -} - -spv::SelectionControlMask TGlslangToSpvTraverser::TranslateSwitchControl(const glslang::TIntermSwitch& switchNode) - const -{ - if (switchNode.getFlatten()) - return spv::SelectionControlFlattenMask; - if (switchNode.getDontFlatten()) - return spv::SelectionControlDontFlattenMask; - return spv::SelectionControlMaskNone; -} - -// return a non-0 dependency if the dependency argument must be set -spv::LoopControlMask TGlslangToSpvTraverser::TranslateLoopControl(const glslang::TIntermLoop& loopNode, - std::vector& operands) const -{ - spv::LoopControlMask control = spv::LoopControlMaskNone; - - if (loopNode.getDontUnroll()) - control = control | spv::LoopControlDontUnrollMask; - if (loopNode.getUnroll()) - control = control | spv::LoopControlUnrollMask; - if (unsigned(loopNode.getLoopDependency()) == glslang::TIntermLoop::dependencyInfinite) - control = control | spv::LoopControlDependencyInfiniteMask; - else if (loopNode.getLoopDependency() > 0) { - control = control | spv::LoopControlDependencyLengthMask; - operands.push_back((unsigned int)loopNode.getLoopDependency()); - } - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) { - if (loopNode.getMinIterations() > 0) { - control = control | spv::LoopControlMinIterationsMask; - operands.push_back(loopNode.getMinIterations()); - } - if (loopNode.getMaxIterations() < glslang::TIntermLoop::iterationsInfinite) { - control = control | spv::LoopControlMaxIterationsMask; - operands.push_back(loopNode.getMaxIterations()); - } - if (loopNode.getIterationMultiple() > 1) { - control = control | spv::LoopControlIterationMultipleMask; - operands.push_back(loopNode.getIterationMultiple()); - } - if (loopNode.getPeelCount() > 0) { - control = control | spv::LoopControlPeelCountMask; - operands.push_back(loopNode.getPeelCount()); - } - if (loopNode.getPartialCount() > 0) { - control = control | spv::LoopControlPartialCountMask; - operands.push_back(loopNode.getPartialCount()); - } - } - - return control; -} - -// Translate glslang type to SPIR-V storage class. -spv::StorageClass TGlslangToSpvTraverser::TranslateStorageClass(const glslang::TType& type) -{ - if (type.getBasicType() == glslang::EbtRayQuery || type.getBasicType() == glslang::EbtHitObjectNV) - return spv::StorageClassPrivate; - if (type.getQualifier().isSpirvByReference()) { - if (type.getQualifier().isParamInput() || type.getQualifier().isParamOutput()) - return spv::StorageClassFunction; - } - if (type.getQualifier().isPipeInput()) - return spv::StorageClassInput; - if (type.getQualifier().isPipeOutput()) - return spv::StorageClassOutput; - if (type.getQualifier().storage == glslang::EvqTileImageEXT || type.isAttachmentEXT()) { - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - builder.addCapability(spv::CapabilityTileImageColorReadAccessEXT); - return spv::StorageClassTileImageEXT; - } - - if (glslangIntermediate->getSource() != glslang::EShSourceHlsl || - type.getQualifier().storage == glslang::EvqUniform) { - if (type.isAtomic()) - return spv::StorageClassAtomicCounter; - if (type.containsOpaque() && !glslangIntermediate->getBindlessMode()) - return spv::StorageClassUniformConstant; - } - - if (type.getQualifier().isUniformOrBuffer() && - type.getQualifier().isShaderRecord()) { - return spv::StorageClassShaderRecordBufferKHR; - } - - if (glslangIntermediate->usingStorageBuffer() && type.getQualifier().storage == glslang::EvqBuffer) { - builder.addIncorporatedExtension(spv::E_SPV_KHR_storage_buffer_storage_class, spv::Spv_1_3); - return spv::StorageClassStorageBuffer; - } - - if (type.getQualifier().isUniformOrBuffer()) { - if (type.getQualifier().isPushConstant()) - return spv::StorageClassPushConstant; - if (type.getBasicType() == glslang::EbtBlock) - return spv::StorageClassUniform; - return spv::StorageClassUniformConstant; - } - - if (type.getQualifier().storage == glslang::EvqShared && type.getBasicType() == glslang::EbtBlock) { - builder.addExtension(spv::E_SPV_KHR_workgroup_memory_explicit_layout); - builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR); - return spv::StorageClassWorkgroup; - } - - switch (type.getQualifier().storage) { - case glslang::EvqGlobal: return spv::StorageClassPrivate; - case glslang::EvqConstReadOnly: return spv::StorageClassFunction; - case glslang::EvqTemporary: return spv::StorageClassFunction; - case glslang::EvqShared: return spv::StorageClassWorkgroup; - case glslang::EvqPayload: return spv::StorageClassRayPayloadKHR; - case glslang::EvqPayloadIn: return spv::StorageClassIncomingRayPayloadKHR; - case glslang::EvqHitAttr: return spv::StorageClassHitAttributeKHR; - case glslang::EvqCallableData: return spv::StorageClassCallableDataKHR; - case glslang::EvqCallableDataIn: return spv::StorageClassIncomingCallableDataKHR; - case glslang::EvqtaskPayloadSharedEXT : return spv::StorageClassTaskPayloadWorkgroupEXT; - case glslang::EvqHitObjectAttrNV: return spv::StorageClassHitObjectAttributeNV; - case glslang::EvqSpirvStorageClass: return static_cast(type.getQualifier().spirvStorageClass); - default: - assert(0); - break; - } - - return spv::StorageClassFunction; -} - -// Translate glslang constants to SPIR-V literals -void TGlslangToSpvTraverser::TranslateLiterals(const glslang::TVector& constants, - std::vector& literals) const -{ - for (auto constant : constants) { - if (constant->getBasicType() == glslang::EbtFloat) { - float floatValue = static_cast(constant->getConstArray()[0].getDConst()); - unsigned literal; - static_assert(sizeof(literal) == sizeof(floatValue), "sizeof(unsigned) != sizeof(float)"); - memcpy(&literal, &floatValue, sizeof(literal)); - literals.push_back(literal); - } else if (constant->getBasicType() == glslang::EbtInt) { - unsigned literal = constant->getConstArray()[0].getIConst(); - literals.push_back(literal); - } else if (constant->getBasicType() == glslang::EbtUint) { - unsigned literal = constant->getConstArray()[0].getUConst(); - literals.push_back(literal); - } else if (constant->getBasicType() == glslang::EbtBool) { - unsigned literal = constant->getConstArray()[0].getBConst(); - literals.push_back(literal); - } else if (constant->getBasicType() == glslang::EbtString) { - auto str = constant->getConstArray()[0].getSConst()->c_str(); - unsigned literal = 0; - char* literalPtr = reinterpret_cast(&literal); - unsigned charCount = 0; - char ch = 0; - do { - ch = *(str++); - *(literalPtr++) = ch; - ++charCount; - if (charCount == 4) { - literals.push_back(literal); - literalPtr = reinterpret_cast(&literal); - charCount = 0; - } - } while (ch != 0); - - // Partial literal is padded with 0 - if (charCount > 0) { - for (; charCount < 4; ++charCount) - *(literalPtr++) = 0; - literals.push_back(literal); - } - } else - assert(0); // Unexpected type - } -} - -// Add capabilities pertaining to how an array is indexed. -void TGlslangToSpvTraverser::addIndirectionIndexCapabilities(const glslang::TType& baseType, - const glslang::TType& indexType) -{ - if (indexType.getQualifier().isNonUniform()) { - // deal with an asserted non-uniform index - // SPV_EXT_descriptor_indexing already added in TranslateNonUniformDecoration - if (baseType.getBasicType() == glslang::EbtSampler) { - if (baseType.getQualifier().hasAttachment()) - builder.addCapability(spv::CapabilityInputAttachmentArrayNonUniformIndexingEXT); - else if (baseType.isImage() && baseType.getSampler().isBuffer()) - builder.addCapability(spv::CapabilityStorageTexelBufferArrayNonUniformIndexingEXT); - else if (baseType.isTexture() && baseType.getSampler().isBuffer()) - builder.addCapability(spv::CapabilityUniformTexelBufferArrayNonUniformIndexingEXT); - else if (baseType.isImage()) - builder.addCapability(spv::CapabilityStorageImageArrayNonUniformIndexingEXT); - else if (baseType.isTexture()) - builder.addCapability(spv::CapabilitySampledImageArrayNonUniformIndexingEXT); - } else if (baseType.getBasicType() == glslang::EbtBlock) { - if (baseType.getQualifier().storage == glslang::EvqBuffer) - builder.addCapability(spv::CapabilityStorageBufferArrayNonUniformIndexingEXT); - else if (baseType.getQualifier().storage == glslang::EvqUniform) - builder.addCapability(spv::CapabilityUniformBufferArrayNonUniformIndexingEXT); - } - } else { - // assume a dynamically uniform index - if (baseType.getBasicType() == glslang::EbtSampler) { - if (baseType.getQualifier().hasAttachment()) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityInputAttachmentArrayDynamicIndexingEXT); - } else if (baseType.isImage() && baseType.getSampler().isBuffer()) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityStorageTexelBufferArrayDynamicIndexingEXT); - } else if (baseType.isTexture() && baseType.getSampler().isBuffer()) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityUniformTexelBufferArrayDynamicIndexingEXT); - } - } - } -} - -// Return whether or not the given type is something that should be tied to a -// descriptor set. -bool IsDescriptorResource(const glslang::TType& type) -{ - // uniform and buffer blocks are included, unless it is a push_constant - if (type.getBasicType() == glslang::EbtBlock) - return type.getQualifier().isUniformOrBuffer() && - ! type.getQualifier().isShaderRecord() && - ! type.getQualifier().isPushConstant(); - - // non block... - // basically samplerXXX/subpass/sampler/texture are all included - // if they are the global-scope-class, not the function parameter - // (or local, if they ever exist) class. - if (type.getBasicType() == glslang::EbtSampler || - type.getBasicType() == glslang::EbtAccStruct) - return type.getQualifier().isUniformOrBuffer(); - - // None of the above. - return false; -} - -void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& parent) -{ - if (child.layoutMatrix == glslang::ElmNone) - child.layoutMatrix = parent.layoutMatrix; - - if (parent.invariant) - child.invariant = true; - if (parent.flat) - child.flat = true; - if (parent.centroid) - child.centroid = true; - if (parent.nopersp) - child.nopersp = true; - if (parent.explicitInterp) - child.explicitInterp = true; - if (parent.perPrimitiveNV) - child.perPrimitiveNV = true; - if (parent.perViewNV) - child.perViewNV = true; - if (parent.perTaskNV) - child.perTaskNV = true; - if (parent.storage == glslang::EvqtaskPayloadSharedEXT) - child.storage = glslang::EvqtaskPayloadSharedEXT; - if (parent.patch) - child.patch = true; - if (parent.sample) - child.sample = true; - if (parent.coherent) - child.coherent = true; - if (parent.devicecoherent) - child.devicecoherent = true; - if (parent.queuefamilycoherent) - child.queuefamilycoherent = true; - if (parent.workgroupcoherent) - child.workgroupcoherent = true; - if (parent.subgroupcoherent) - child.subgroupcoherent = true; - if (parent.shadercallcoherent) - child.shadercallcoherent = true; - if (parent.nonprivate) - child.nonprivate = true; - if (parent.volatil) - child.volatil = true; - if (parent.restrict) - child.restrict = true; - if (parent.readonly) - child.readonly = true; - if (parent.writeonly) - child.writeonly = true; - if (parent.nonUniform) - child.nonUniform = true; -} - -bool HasNonLayoutQualifiers(const glslang::TType& type, const glslang::TQualifier& qualifier) -{ - // This should list qualifiers that simultaneous satisfy: - // - struct members might inherit from a struct declaration - // (note that non-block structs don't explicitly inherit, - // only implicitly, meaning no decoration involved) - // - affect decorations on the struct members - // (note smooth does not, and expecting something like volatile - // to effect the whole object) - // - are not part of the offset/st430/etc or row/column-major layout - return qualifier.invariant || (qualifier.hasLocation() && type.getBasicType() == glslang::EbtBlock); -} - -// -// Implement the TGlslangToSpvTraverser class. -// - -TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, - const glslang::TIntermediate* glslangIntermediate, - spv::SpvBuildLogger* buildLogger, glslang::SpvOptions& options) : - TIntermTraverser(true, false, true), - options(options), - shaderEntry(nullptr), currentFunction(nullptr), - sequenceDepth(0), logger(buildLogger), - builder(spvVersion, (glslang::GetKhronosToolId() << 16) | glslang::GetSpirvGeneratorVersion(), logger), - inEntryPoint(false), entryPointTerminated(false), linkageOnly(false), - glslangIntermediate(glslangIntermediate), - nanMinMaxClamp(glslangIntermediate->getNanMinMaxClamp()), - nonSemanticDebugPrintf(0), - taskPayloadID(0) -{ - bool isMeshShaderExt = (glslangIntermediate->getRequestedExtensions().find(glslang::E_GL_EXT_mesh_shader) != - glslangIntermediate->getRequestedExtensions().end()); - spv::ExecutionModel executionModel = TranslateExecutionModel(glslangIntermediate->getStage(), isMeshShaderExt); - - builder.clearAccessChain(); - builder.setSource(TranslateSourceLanguage(glslangIntermediate->getSource(), glslangIntermediate->getProfile()), - glslangIntermediate->getVersion()); - - if (options.emitNonSemanticShaderDebugSource) - this->options.emitNonSemanticShaderDebugInfo = true; - if (options.emitNonSemanticShaderDebugInfo) - this->options.generateDebugInfo = true; - - if (this->options.generateDebugInfo) { - builder.setEmitOpLines(); - builder.setSourceFile(glslangIntermediate->getSourceFile()); - - // Set the source shader's text. If for SPV version 1.0, include - // a preamble in comments stating the OpModuleProcessed instructions. - // Otherwise, emit those as actual instructions. - std::string text; - const std::vector& processes = glslangIntermediate->getProcesses(); - for (int p = 0; p < (int)processes.size(); ++p) { - if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_1) { - text.append("// OpModuleProcessed "); - text.append(processes[p]); - text.append("\n"); - } else - builder.addModuleProcessed(processes[p]); - } - if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_1 && (int)processes.size() > 0) - text.append("#line 1\n"); - text.append(glslangIntermediate->getSourceText()); - builder.setSourceText(text); - // Pass name and text for all included files - const std::map& include_txt = glslangIntermediate->getIncludeText(); - for (auto iItr = include_txt.begin(); iItr != include_txt.end(); ++iItr) - builder.addInclude(iItr->first, iItr->second); - } - - builder.setEmitNonSemanticShaderDebugInfo(this->options.emitNonSemanticShaderDebugInfo); - builder.setEmitNonSemanticShaderDebugSource(this->options.emitNonSemanticShaderDebugSource); - - stdBuiltins = builder.import("GLSL.std.450"); - - spv::AddressingModel addressingModel = spv::AddressingModelLogical; - spv::MemoryModel memoryModel = spv::MemoryModelGLSL450; - - if (glslangIntermediate->usingPhysicalStorageBuffer()) { - addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT; - builder.addIncorporatedExtension(spv::E_SPV_KHR_physical_storage_buffer, spv::Spv_1_5); - builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT); - } - if (glslangIntermediate->usingVulkanMemoryModel()) { - memoryModel = spv::MemoryModelVulkanKHR; - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - builder.addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5); - } - builder.setMemoryModel(addressingModel, memoryModel); - - if (glslangIntermediate->usingVariablePointers()) { - builder.addCapability(spv::CapabilityVariablePointers); - } - - // If not linking, there is no entry point - if (!options.compileOnly) { - shaderEntry = builder.makeEntryPoint(glslangIntermediate->getEntryPointName().c_str()); - entryPoint = - builder.addEntryPoint(executionModel, shaderEntry, glslangIntermediate->getEntryPointName().c_str()); - } - - // Add the source extensions - const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); - for (auto it = sourceExtensions.begin(); it != sourceExtensions.end(); ++it) - builder.addSourceExtension(it->c_str()); - - // Add the top-level modes for this shader. - - if (glslangIntermediate->getXfbMode()) { - builder.addCapability(spv::CapabilityTransformFeedback); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeXfb); - } - - if (glslangIntermediate->getLayoutPrimitiveCulling()) { - builder.addCapability(spv::CapabilityRayTraversalPrimitiveCullingKHR); - } - - if (glslangIntermediate->getSubgroupUniformControlFlow()) { - builder.addExtension(spv::E_SPV_KHR_subgroup_uniform_control_flow); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeSubgroupUniformControlFlowKHR); - } - - unsigned int mode; - switch (glslangIntermediate->getStage()) { - case EShLangVertex: - builder.addCapability(spv::CapabilityShader); - break; - - case EShLangFragment: - builder.addCapability(spv::CapabilityShader); - if (glslangIntermediate->getPixelCenterInteger()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger); - - if (glslangIntermediate->getOriginUpperLeft()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft); - else - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft); - - if (glslangIntermediate->getEarlyFragmentTests()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyFragmentTests); - - if (glslangIntermediate->getEarlyAndLateFragmentTestsAMD()) - { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeEarlyAndLateFragmentTestsAMD); - builder.addExtension(spv::E_SPV_AMD_shader_early_and_late_fragment_tests); - } - - if (glslangIntermediate->getPostDepthCoverage()) { - builder.addCapability(spv::CapabilitySampleMaskPostDepthCoverage); - builder.addExecutionMode(shaderEntry, spv::ExecutionModePostDepthCoverage); - builder.addExtension(spv::E_SPV_KHR_post_depth_coverage); - } - - if (glslangIntermediate->getNonCoherentColorAttachmentReadEXT()) { - builder.addCapability(spv::CapabilityTileImageColorReadAccessEXT); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeNonCoherentColorAttachmentReadEXT); - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - } - - if (glslangIntermediate->getNonCoherentDepthAttachmentReadEXT()) { - builder.addCapability(spv::CapabilityTileImageDepthReadAccessEXT); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeNonCoherentDepthAttachmentReadEXT); - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - } - - if (glslangIntermediate->getNonCoherentStencilAttachmentReadEXT()) { - builder.addCapability(spv::CapabilityTileImageStencilReadAccessEXT); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeNonCoherentStencilAttachmentReadEXT); - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - } - - if (glslangIntermediate->isDepthReplacing()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeDepthReplacing); - - if (glslangIntermediate->isStencilReplacing()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModeStencilRefReplacingEXT); - - switch(glslangIntermediate->getDepth()) { - case glslang::EldGreater: mode = spv::ExecutionModeDepthGreater; break; - case glslang::EldLess: mode = spv::ExecutionModeDepthLess; break; - case glslang::EldUnchanged: mode = spv::ExecutionModeDepthUnchanged; break; - default: mode = spv::ExecutionModeMax; break; - } - - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - switch (glslangIntermediate->getStencil()) { - case glslang::ElsRefUnchangedFrontAMD: mode = spv::ExecutionModeStencilRefUnchangedFrontAMD; break; - case glslang::ElsRefGreaterFrontAMD: mode = spv::ExecutionModeStencilRefGreaterFrontAMD; break; - case glslang::ElsRefLessFrontAMD: mode = spv::ExecutionModeStencilRefLessFrontAMD; break; - case glslang::ElsRefUnchangedBackAMD: mode = spv::ExecutionModeStencilRefUnchangedBackAMD; break; - case glslang::ElsRefGreaterBackAMD: mode = spv::ExecutionModeStencilRefGreaterBackAMD; break; - case glslang::ElsRefLessBackAMD: mode = spv::ExecutionModeStencilRefLessBackAMD; break; - default: mode = spv::ExecutionModeMax; break; - } - - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - switch (glslangIntermediate->getInterlockOrdering()) { - case glslang::EioPixelInterlockOrdered: mode = spv::ExecutionModePixelInterlockOrderedEXT; - break; - case glslang::EioPixelInterlockUnordered: mode = spv::ExecutionModePixelInterlockUnorderedEXT; - break; - case glslang::EioSampleInterlockOrdered: mode = spv::ExecutionModeSampleInterlockOrderedEXT; - break; - case glslang::EioSampleInterlockUnordered: mode = spv::ExecutionModeSampleInterlockUnorderedEXT; - break; - case glslang::EioShadingRateInterlockOrdered: mode = spv::ExecutionModeShadingRateInterlockOrderedEXT; - break; - case glslang::EioShadingRateInterlockUnordered: mode = spv::ExecutionModeShadingRateInterlockUnorderedEXT; - break; - default: mode = spv::ExecutionModeMax; - break; - } - if (mode != spv::ExecutionModeMax) { - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - if (mode == spv::ExecutionModeShadingRateInterlockOrderedEXT || - mode == spv::ExecutionModeShadingRateInterlockUnorderedEXT) { - builder.addCapability(spv::CapabilityFragmentShaderShadingRateInterlockEXT); - } else if (mode == spv::ExecutionModePixelInterlockOrderedEXT || - mode == spv::ExecutionModePixelInterlockUnorderedEXT) { - builder.addCapability(spv::CapabilityFragmentShaderPixelInterlockEXT); - } else { - builder.addCapability(spv::CapabilityFragmentShaderSampleInterlockEXT); - } - builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock); - } - break; - - case EShLangCompute: { - builder.addCapability(spv::CapabilityShader); - bool needSizeId = false; - for (int dim = 0; dim < 3; ++dim) { - if ((glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet)) { - needSizeId = true; - break; - } - } - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6 && needSizeId) { - std::vector dimConstId; - for (int dim = 0; dim < 3; ++dim) { - bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); - dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); - if (specConst) { - builder.addDecoration(dimConstId.back(), spv::DecorationSpecId, - glslangIntermediate->getLocalSizeSpecId(dim)); - needSizeId = true; - } - } - builder.addExecutionModeId(shaderEntry, spv::ExecutionModeLocalSizeId, dimConstId); - } else { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), - glslangIntermediate->getLocalSize(1), - glslangIntermediate->getLocalSize(2)); - } - if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupQuads) { - builder.addCapability(spv::CapabilityComputeDerivativeGroupQuadsNV); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupQuadsNV); - builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives); - } else if (glslangIntermediate->getLayoutDerivativeModeNone() == glslang::LayoutDerivativeGroupLinear) { - builder.addCapability(spv::CapabilityComputeDerivativeGroupLinearNV); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeDerivativeGroupLinearNV); - builder.addExtension(spv::E_SPV_NV_compute_shader_derivatives); - } - break; - } - case EShLangTessEvaluation: - case EShLangTessControl: - builder.addCapability(spv::CapabilityTessellation); - - glslang::TLayoutGeometry primitive; - - if (glslangIntermediate->getStage() == EShLangTessControl) { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, - glslangIntermediate->getVertices()); - primitive = glslangIntermediate->getOutputPrimitive(); - } else { - primitive = glslangIntermediate->getInputPrimitive(); - } - - switch (primitive) { - case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break; - case glslang::ElgQuads: mode = spv::ExecutionModeQuads; break; - case glslang::ElgIsolines: mode = spv::ExecutionModeIsolines; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - switch (glslangIntermediate->getVertexSpacing()) { - case glslang::EvsEqual: mode = spv::ExecutionModeSpacingEqual; break; - case glslang::EvsFractionalEven: mode = spv::ExecutionModeSpacingFractionalEven; break; - case glslang::EvsFractionalOdd: mode = spv::ExecutionModeSpacingFractionalOdd; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - switch (glslangIntermediate->getVertexOrder()) { - case glslang::EvoCw: mode = spv::ExecutionModeVertexOrderCw; break; - case glslang::EvoCcw: mode = spv::ExecutionModeVertexOrderCcw; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - if (glslangIntermediate->getPointMode()) - builder.addExecutionMode(shaderEntry, spv::ExecutionModePointMode); - break; - - case EShLangGeometry: - builder.addCapability(spv::CapabilityGeometry); - switch (glslangIntermediate->getInputPrimitive()) { - case glslang::ElgPoints: mode = spv::ExecutionModeInputPoints; break; - case glslang::ElgLines: mode = spv::ExecutionModeInputLines; break; - case glslang::ElgLinesAdjacency: mode = spv::ExecutionModeInputLinesAdjacency; break; - case glslang::ElgTriangles: mode = spv::ExecutionModeTriangles; break; - case glslang::ElgTrianglesAdjacency: mode = spv::ExecutionModeInputTrianglesAdjacency; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - - builder.addExecutionMode(shaderEntry, spv::ExecutionModeInvocations, glslangIntermediate->getInvocations()); - - switch (glslangIntermediate->getOutputPrimitive()) { - case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break; - case glslang::ElgLineStrip: mode = spv::ExecutionModeOutputLineStrip; break; - case glslang::ElgTriangleStrip: mode = spv::ExecutionModeOutputTriangleStrip; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices()); - break; - - case EShLangRayGen: - case EShLangIntersect: - case EShLangAnyHit: - case EShLangClosestHit: - case EShLangMiss: - case EShLangCallable: - { - auto& extensions = glslangIntermediate->getRequestedExtensions(); - if (extensions.find("GL_NV_ray_tracing") == extensions.end()) { - builder.addCapability(spv::CapabilityRayTracingKHR); - builder.addExtension("SPV_KHR_ray_tracing"); - } - else { - builder.addCapability(spv::CapabilityRayTracingNV); - builder.addExtension("SPV_NV_ray_tracing"); - } - if (glslangIntermediate->getStage() != EShLangRayGen && glslangIntermediate->getStage() != EShLangCallable) { - if (extensions.find("GL_EXT_ray_cull_mask") != extensions.end()) { - builder.addCapability(spv::CapabilityRayCullMaskKHR); - builder.addExtension("SPV_KHR_ray_cull_mask"); - } - if (extensions.find("GL_EXT_ray_tracing_position_fetch") != extensions.end()) { - builder.addCapability(spv::CapabilityRayTracingPositionFetchKHR); - builder.addExtension("SPV_KHR_ray_tracing_position_fetch"); - } - } - break; - } - case EShLangTask: - case EShLangMesh: - if(isMeshShaderExt) { - builder.addCapability(spv::CapabilityMeshShadingEXT); - builder.addExtension(spv::E_SPV_EXT_mesh_shader); - } else { - builder.addCapability(spv::CapabilityMeshShadingNV); - builder.addExtension(spv::E_SPV_NV_mesh_shader); - } - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) { - std::vector dimConstId; - for (int dim = 0; dim < 3; ++dim) { - bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); - dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); - if (specConst) { - builder.addDecoration(dimConstId.back(), spv::DecorationSpecId, - glslangIntermediate->getLocalSizeSpecId(dim)); - } - } - builder.addExecutionModeId(shaderEntry, spv::ExecutionModeLocalSizeId, dimConstId); - } else { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeLocalSize, glslangIntermediate->getLocalSize(0), - glslangIntermediate->getLocalSize(1), - glslangIntermediate->getLocalSize(2)); - } - if (glslangIntermediate->getStage() == EShLangMesh) { - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, - glslangIntermediate->getVertices()); - builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputPrimitivesNV, - glslangIntermediate->getPrimitives()); - - switch (glslangIntermediate->getOutputPrimitive()) { - case glslang::ElgPoints: mode = spv::ExecutionModeOutputPoints; break; - case glslang::ElgLines: mode = spv::ExecutionModeOutputLinesNV; break; - case glslang::ElgTriangles: mode = spv::ExecutionModeOutputTrianglesNV; break; - default: mode = spv::ExecutionModeMax; break; - } - if (mode != spv::ExecutionModeMax) - builder.addExecutionMode(shaderEntry, (spv::ExecutionMode)mode); - } - break; - - default: - break; - } - - // - // Add SPIR-V requirements (GL_EXT_spirv_intrinsics) - // - if (glslangIntermediate->hasSpirvRequirement()) { - const glslang::TSpirvRequirement& spirvRequirement = glslangIntermediate->getSpirvRequirement(); - - // Add SPIR-V extension requirement - for (auto& extension : spirvRequirement.extensions) - builder.addExtension(extension.c_str()); - - // Add SPIR-V capability requirement - for (auto capability : spirvRequirement.capabilities) - builder.addCapability(static_cast(capability)); - } - - // - // Add SPIR-V execution mode qualifiers (GL_EXT_spirv_intrinsics) - // - if (glslangIntermediate->hasSpirvExecutionMode()) { - const glslang::TSpirvExecutionMode spirvExecutionMode = glslangIntermediate->getSpirvExecutionMode(); - - // Add spirv_execution_mode - for (auto& mode : spirvExecutionMode.modes) { - if (!mode.second.empty()) { - std::vector literals; - TranslateLiterals(mode.second, literals); - builder.addExecutionMode(shaderEntry, static_cast(mode.first), literals); - } else - builder.addExecutionMode(shaderEntry, static_cast(mode.first)); - } - - // Add spirv_execution_mode_id - for (auto& modeId : spirvExecutionMode.modeIds) { - std::vector operandIds; - assert(!modeId.second.empty()); - for (auto extraOperand : modeId.second) { - if (extraOperand->getType().getQualifier().isSpecConstant()) - operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode())); - else - operandIds.push_back(createSpvConstant(*extraOperand)); - } - builder.addExecutionModeId(shaderEntry, static_cast(modeId.first), operandIds); - } - } -} - -// Finish creating SPV, after the traversal is complete. -void TGlslangToSpvTraverser::finishSpv(bool compileOnly) -{ - // If not linking, an entry point is not expected - if (!compileOnly) { - // Finish the entry point function - if (!entryPointTerminated) { - builder.setBuildPoint(shaderEntry->getLastBlock()); - builder.leaveFunction(); - } - - // finish off the entry-point SPV instruction by adding the Input/Output - for (auto it = iOSet.cbegin(); it != iOSet.cend(); ++it) - entryPoint->addIdOperand(*it); - } - - // Add capabilities, extensions, remove unneeded decorations, etc., - // based on the resulting SPIR-V. - // Note: WebGPU code generation must have the opportunity to aggressively - // prune unreachable merge blocks and continue targets. - builder.postProcess(compileOnly); -} - -// Write the SPV into 'out'. -void TGlslangToSpvTraverser::dumpSpv(std::vector& out) -{ - builder.dump(out); -} - -// -// Implement the traversal functions. -// -// Return true from interior nodes to have the external traversal -// continue on to children. Return false if children were -// already processed. -// - -// -// Symbols can turn into -// - uniform/input reads -// - output writes -// - complex lvalue base setups: foo.bar[3].... , where we see foo and start up an access chain -// - something simple that degenerates into the last bullet -// -void TGlslangToSpvTraverser::visitSymbol(glslang::TIntermSymbol* symbol) -{ - // We update the line information even though no code might be generated here - // This is helpful to yield correct lines for control flow instructions - builder.setLine(symbol->getLoc().line, symbol->getLoc().getFilename()); - - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (symbol->getType().isStruct()) - glslangTypeToIdMap[symbol->getType().getStruct()] = symbol->getId(); - - if (symbol->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); -#ifdef ENABLE_HLSL - // Skip symbol handling if it is string-typed - if (symbol->getBasicType() == glslang::EbtString) - return; -#endif - - // getSymbolId() will set up all the IO decorations on the first call. - // Formal function parameters were mapped during makeFunctions(). - spv::Id id = getSymbolId(symbol); - - if (symbol->getType().getQualifier().isTaskPayload()) - taskPayloadID = id; // cache the taskPayloadID to be used it as operand for OpEmitMeshTasksEXT - - if (builder.isPointer(id)) { - if (!symbol->getType().getQualifier().isParamInput() && - !symbol->getType().getQualifier().isParamOutput()) { - // Include all "static use" and "linkage only" interface variables on the OpEntryPoint instruction - // Consider adding to the OpEntryPoint interface list. - // Only looking at structures if they have at least one member. - if (!symbol->getType().isStruct() || symbol->getType().getStruct()->size() > 0) { - spv::StorageClass sc = builder.getStorageClass(id); - // Before SPIR-V 1.4, we only want to include Input and Output. - // Starting with SPIR-V 1.4, we want all globals. - if ((glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4 && builder.isGlobalVariable(id)) || - (sc == spv::StorageClassInput || sc == spv::StorageClassOutput)) { - iOSet.insert(id); - } - } - } - - // If the SPIR-V type is required to be different than the AST type - // (for ex SubgroupMasks or 3x4 ObjectToWorld/WorldToObject matrices), - // translate now from the SPIR-V type to the AST type, for the consuming - // operation. - // Note this turns it from an l-value to an r-value. - // Currently, all symbols needing this are inputs; avoid the map lookup when non-input. - if (symbol->getType().getQualifier().storage == glslang::EvqVaryingIn) - id = translateForcedType(id); - } - - // Only process non-linkage-only nodes for generating actual static uses - if (! linkageOnly || symbol->getQualifier().isSpecConstant()) { - // Prepare to generate code for the access - - // L-value chains will be computed left to right. We're on the symbol now, - // which is the left-most part of the access chain, so now is "clear" time, - // followed by setting the base. - builder.clearAccessChain(); - - // For now, we consider all user variables as being in memory, so they are pointers, - // except for - // A) R-Value arguments to a function, which are an intermediate object. - // See comments in handleUserFunctionCall(). - // B) Specialization constants (normal constants don't even come in as a variable), - // These are also pure R-values. - // C) R-Values from type translation, see above call to translateForcedType() - glslang::TQualifier qualifier = symbol->getQualifier(); - if (qualifier.isSpecConstant() || rValueParameters.find(symbol->getId()) != rValueParameters.end() || - !builder.isPointerType(builder.getTypeId(id))) - builder.setAccessChainRValue(id); - else - builder.setAccessChainLValue(id); - } - -#ifdef ENABLE_HLSL - // Process linkage-only nodes for any special additional interface work. - if (linkageOnly) { - if (glslangIntermediate->getHlslFunctionality1()) { - // Map implicit counter buffers to their originating buffers, which should have been - // seen by now, given earlier pruning of unused counters, and preservation of order - // of declaration. - if (symbol->getType().getQualifier().isUniformOrBuffer()) { - if (!glslangIntermediate->hasCounterBufferName(symbol->getName())) { - // Save possible originating buffers for counter buffers, keyed by - // making the potential counter-buffer name. - std::string keyName = symbol->getName().c_str(); - keyName = glslangIntermediate->addCounterBufferName(keyName); - counterOriginator[keyName] = symbol; - } else { - // Handle a counter buffer, by finding the saved originating buffer. - std::string keyName = symbol->getName().c_str(); - auto it = counterOriginator.find(keyName); - if (it != counterOriginator.end()) { - id = getSymbolId(it->second); - if (id != spv::NoResult) { - spv::Id counterId = getSymbolId(symbol); - if (counterId != spv::NoResult) { - builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); - builder.addDecorationId(id, spv::DecorationHlslCounterBufferGOOGLE, counterId); - } - } - } - } - } - } - } -#endif -} - -bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::TIntermBinary* node) -{ - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - if (node->getLeft()->getAsSymbolNode() != nullptr && node->getLeft()->getType().isStruct()) { - glslangTypeToIdMap[node->getLeft()->getType().getStruct()] = node->getLeft()->getAsSymbolNode()->getId(); - } - if (node->getRight()->getAsSymbolNode() != nullptr && node->getRight()->getType().isStruct()) { - glslangTypeToIdMap[node->getRight()->getType().getStruct()] = node->getRight()->getAsSymbolNode()->getId(); - } - - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - // First, handle special cases - switch (node->getOp()) { - case glslang::EOpAssign: - case glslang::EOpAddAssign: - case glslang::EOpSubAssign: - case glslang::EOpMulAssign: - case glslang::EOpVectorTimesMatrixAssign: - case glslang::EOpVectorTimesScalarAssign: - case glslang::EOpMatrixTimesScalarAssign: - case glslang::EOpMatrixTimesMatrixAssign: - case glslang::EOpDivAssign: - case glslang::EOpModAssign: - case glslang::EOpAndAssign: - case glslang::EOpInclusiveOrAssign: - case glslang::EOpExclusiveOrAssign: - case glslang::EOpLeftShiftAssign: - case glslang::EOpRightShiftAssign: - // A bin-op assign "a += b" means the same thing as "a = a + b" - // where a is evaluated before b. For a simple assignment, GLSL - // says to evaluate the left before the right. So, always, left - // node then right node. - { - // get the left l-value, save it away - builder.clearAccessChain(); - node->getLeft()->traverse(this); - spv::Builder::AccessChain lValue = builder.getAccessChain(); - - // evaluate the right - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id rValue = accessChainLoad(node->getRight()->getType()); - - // reset line number for assignment - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - - if (node->getOp() != glslang::EOpAssign) { - // the left is also an r-value - builder.setAccessChain(lValue); - spv::Id leftRValue = accessChainLoad(node->getLeft()->getType()); - - // do the operation - spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent(node->getLeft()->getType()); - coherentFlags |= TranslateCoherent(node->getRight()->getType()); - OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()), - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(coherentFlags) }; - rValue = createBinaryOperation(node->getOp(), decorations, - convertGlslangToSpvType(node->getType()), leftRValue, rValue, - node->getType().getBasicType()); - - // these all need their counterparts in createBinaryOperation() - assert(rValue != spv::NoResult); - } - - // store the result - builder.setAccessChain(lValue); - multiTypeStore(node->getLeft()->getType(), rValue); - - // assignments are expressions having an rValue after they are evaluated... - builder.clearAccessChain(); - builder.setAccessChainRValue(rValue); - } - return false; - case glslang::EOpIndexDirect: - case glslang::EOpIndexDirectStruct: - { - // Structure, array, matrix, or vector indirection with statically known index. - // Get the left part of the access chain. - node->getLeft()->traverse(this); - - // Add the next element in the chain - - const int glslangIndex = node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (! node->getLeft()->getType().isArray() && - node->getLeft()->getType().isVector() && - node->getOp() == glslang::EOpIndexDirect) { - // Swizzle is uniform so propagate uniform into access chain - spv::Builder::AccessChain::CoherentFlags coherentFlags = TranslateCoherent(node->getLeft()->getType()); - coherentFlags.nonUniform = 0; - // This is essentially a hard-coded vector swizzle of size 1, - // so short circuit the access-chain stuff with a swizzle. - std::vector swizzle; - swizzle.push_back(glslangIndex); - int dummySize; - builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()), - coherentFlags, - glslangIntermediate->getBaseAlignmentScalar( - node->getLeft()->getType(), dummySize)); - } else { - - // Load through a block reference is performed with a dot operator that - // is mapped to EOpIndexDirectStruct. When we get to the actual reference, - // do a load and reset the access chain. - if (node->getLeft()->isReference() && - !node->getLeft()->getType().isArray() && - node->getOp() == glslang::EOpIndexDirectStruct) - { - spv::Id left = accessChainLoad(node->getLeft()->getType()); - builder.clearAccessChain(); - builder.setAccessChainLValue(left); - } - - int spvIndex = glslangIndex; - if (node->getLeft()->getBasicType() == glslang::EbtBlock && - node->getOp() == glslang::EOpIndexDirectStruct) - { - // This may be, e.g., an anonymous block-member selection, which generally need - // index remapping due to hidden members in anonymous blocks. - long long glslangId = glslangTypeToIdMap[node->getLeft()->getType().getStruct()]; - if (memberRemapper.find(glslangId) != memberRemapper.end()) { - std::vector& remapper = memberRemapper[glslangId]; - assert(remapper.size() > 0); - spvIndex = remapper[glslangIndex]; - } - } - - // Struct reference propagates uniform lvalue - spv::Builder::AccessChain::CoherentFlags coherentFlags = - TranslateCoherent(node->getLeft()->getType()); - coherentFlags.nonUniform = 0; - - // normal case for indexing array or structure or block - builder.accessChainPush(builder.makeIntConstant(spvIndex), - coherentFlags, - node->getLeft()->getType().getBufferReferenceAlignment()); - - // Add capabilities here for accessing PointSize and clip/cull distance. - // We have deferred generation of associated capabilities until now. - if (node->getLeft()->getType().isStruct() && ! node->getLeft()->getType().isArray()) - declareUseOfStructMember(*(node->getLeft()->getType().getStruct()), glslangIndex); - } - } - return false; - case glslang::EOpIndexIndirect: - { - // Array, matrix, or vector indirection with variable index. - // Will use native SPIR-V access-chain for and array indirection; - // matrices are arrays of vectors, so will also work for a matrix. - // Will use the access chain's 'component' for variable index into a vector. - - // This adapter is building access chains left to right. - // Set up the access chain to the left. - node->getLeft()->traverse(this); - - // save it so that computing the right side doesn't trash it - spv::Builder::AccessChain partial = builder.getAccessChain(); - - // compute the next index in the chain - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id index = accessChainLoad(node->getRight()->getType()); - - addIndirectionIndexCapabilities(node->getLeft()->getType(), node->getRight()->getType()); - - // restore the saved access chain - builder.setAccessChain(partial); - - // Only if index is nonUniform should we propagate nonUniform into access chain - spv::Builder::AccessChain::CoherentFlags index_flags = TranslateCoherent(node->getRight()->getType()); - spv::Builder::AccessChain::CoherentFlags coherent_flags = TranslateCoherent(node->getLeft()->getType()); - coherent_flags.nonUniform = index_flags.nonUniform; - - if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector()) { - int dummySize; - builder.accessChainPushComponent( - index, convertGlslangToSpvType(node->getLeft()->getType()), coherent_flags, - glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), - dummySize)); - } else - builder.accessChainPush(index, coherent_flags, - node->getLeft()->getType().getBufferReferenceAlignment()); - } - return false; - case glslang::EOpVectorSwizzle: - { - node->getLeft()->traverse(this); - std::vector swizzle; - convertSwizzle(*node->getRight()->getAsAggregate(), swizzle); - int dummySize; - builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()), - TranslateCoherent(node->getLeft()->getType()), - glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), - dummySize)); - } - return false; - case glslang::EOpMatrixSwizzle: - logger->missingFunctionality("matrix swizzle"); - return true; - case glslang::EOpLogicalOr: - case glslang::EOpLogicalAnd: - { - - // These may require short circuiting, but can sometimes be done as straight - // binary operations. The right operand must be short circuited if it has - // side effects, and should probably be if it is complex. - if (isTrivial(node->getRight()->getAsTyped())) - break; // handle below as a normal binary operation - // otherwise, we need to do dynamic short circuiting on the right operand - spv::Id result = createShortCircuit(node->getOp(), *node->getLeft()->getAsTyped(), - *node->getRight()->getAsTyped()); - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - } - return false; - default: - break; - } - - // Assume generic binary op... - - // get right operand - builder.clearAccessChain(); - node->getLeft()->traverse(this); - spv::Id left = accessChainLoad(node->getLeft()->getType()); - - // get left operand - builder.clearAccessChain(); - node->getRight()->traverse(this); - spv::Id right = accessChainLoad(node->getRight()->getType()); - - // get result - OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()), - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - spv::Id result = createBinaryOperation(node->getOp(), decorations, - convertGlslangToSpvType(node->getType()), left, right, - node->getLeft()->getType().getBasicType()); - - builder.clearAccessChain(); - if (! result) { - logger->missingFunctionality("unknown glslang binary operation"); - return true; // pick up a child as the place-holder result - } else { - builder.setAccessChainRValue(result); - return false; - } -} - -spv::Id TGlslangToSpvTraverser::convertLoadedBoolInUniformToUint(const glslang::TType& type, - spv::Id nominalTypeId, - spv::Id loadedId) -{ - if (builder.isScalarType(nominalTypeId)) { - // Conversion for bool - spv::Id boolType = builder.makeBoolType(); - if (nominalTypeId != boolType) - return builder.createBinOp(spv::OpINotEqual, boolType, loadedId, builder.makeUintConstant(0)); - } else if (builder.isVectorType(nominalTypeId)) { - // Conversion for bvec - int vecSize = builder.getNumTypeComponents(nominalTypeId); - spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize); - if (nominalTypeId != bvecType) - loadedId = builder.createBinOp(spv::OpINotEqual, bvecType, loadedId, - makeSmearedConstant(builder.makeUintConstant(0), vecSize)); - } else if (builder.isArrayType(nominalTypeId)) { - // Conversion for bool array - spv::Id boolArrayTypeId = convertGlslangToSpvType(type); - if (nominalTypeId != boolArrayTypeId) - { - // Use OpCopyLogical from SPIR-V 1.4 if available. - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) - return builder.createUnaryOp(spv::OpCopyLogical, boolArrayTypeId, loadedId); - - glslang::TType glslangElementType(type, 0); - spv::Id elementNominalTypeId = builder.getContainedTypeId(nominalTypeId); - std::vector constituents; - for (int index = 0; index < type.getOuterArraySize(); ++index) { - // get the element - spv::Id elementValue = builder.createCompositeExtract(loadedId, elementNominalTypeId, index); - - // recursively convert it - spv::Id elementConvertedValue = convertLoadedBoolInUniformToUint(glslangElementType, elementNominalTypeId, elementValue); - constituents.push_back(elementConvertedValue); - } - return builder.createCompositeConstruct(boolArrayTypeId, constituents); - } - } - - return loadedId; -} - -// Figure out what, if any, type changes are needed when accessing a specific built-in. -// Returns . -// Also see comment for 'forceType', regarding tracking SPIR-V-required types. -std::pair TGlslangToSpvTraverser::getForcedType(glslang::TBuiltInVariable glslangBuiltIn, - const glslang::TType& glslangType) -{ - switch(glslangBuiltIn) - { - case glslang::EbvSubGroupEqMask: - case glslang::EbvSubGroupGeMask: - case glslang::EbvSubGroupGtMask: - case glslang::EbvSubGroupLeMask: - case glslang::EbvSubGroupLtMask: { - // these require changing a 64-bit scaler -> a vector of 32-bit components - if (glslangType.isVector()) - break; - spv::Id ivec4_type = builder.makeVectorType(builder.makeUintType(32), 4); - spv::Id uint64_type = builder.makeUintType(64); - std::pair ret(ivec4_type, uint64_type); - return ret; - } - // There are no SPIR-V builtins defined for these and map onto original non-transposed - // builtins. During visitBinary we insert a transpose - case glslang::EbvWorldToObject3x4: - case glslang::EbvObjectToWorld3x4: { - spv::Id mat43 = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); - spv::Id mat34 = builder.makeMatrixType(builder.makeFloatType(32), 3, 4); - std::pair ret(mat43, mat34); - return ret; - } - default: - break; - } - - std::pair ret(spv::NoType, spv::NoType); - return ret; -} - -// For an object previously identified (see getForcedType() and forceType) -// as needing type translations, do the translation needed for a load, turning -// an L-value into in R-value. -spv::Id TGlslangToSpvTraverser::translateForcedType(spv::Id object) -{ - const auto forceIt = forceType.find(object); - if (forceIt == forceType.end()) - return object; - - spv::Id desiredTypeId = forceIt->second; - spv::Id objectTypeId = builder.getTypeId(object); - assert(builder.isPointerType(objectTypeId)); - objectTypeId = builder.getContainedTypeId(objectTypeId); - if (builder.isVectorType(objectTypeId) && - builder.getScalarTypeWidth(builder.getContainedTypeId(objectTypeId)) == 32) { - if (builder.getScalarTypeWidth(desiredTypeId) == 64) { - // handle 32-bit v.xy* -> 64-bit - builder.clearAccessChain(); - builder.setAccessChainLValue(object); - object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId); - std::vector components; - components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 0)); - components.push_back(builder.createCompositeExtract(object, builder.getContainedTypeId(objectTypeId), 1)); - - spv::Id vecType = builder.makeVectorType(builder.getContainedTypeId(objectTypeId), 2); - return builder.createUnaryOp(spv::OpBitcast, desiredTypeId, - builder.createCompositeConstruct(vecType, components)); - } else { - logger->missingFunctionality("forcing 32-bit vector type to non 64-bit scalar"); - } - } else if (builder.isMatrixType(objectTypeId)) { - // There are no SPIR-V builtins defined for 3x4 variants of ObjectToWorld/WorldToObject - // and we insert a transpose after loading the original non-transposed builtins - builder.clearAccessChain(); - builder.setAccessChainLValue(object); - object = builder.accessChainLoad(spv::NoPrecision, spv::DecorationMax, spv::DecorationMax, objectTypeId); - return builder.createUnaryOp(spv::OpTranspose, desiredTypeId, object); - - } else { - logger->missingFunctionality("forcing non 32-bit vector type"); - } - - return object; -} - -bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) -{ - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - spv::Id result = spv::NoResult; - - // try texturing first - result = createImageTextureFunctionCall(node); - if (result != spv::NoResult) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; // done with this node - } - - // Non-texturing. - - if (node->getOp() == glslang::EOpArrayLength) { - // Quite special; won't want to evaluate the operand. - - // Currently, the front-end does not allow .length() on an array until it is sized, - // except for the last block membeor of an SSBO. - // TODO: If this changes, link-time sized arrays might show up here, and need their - // size extracted. - - // Normal .length() would have been constant folded by the front-end. - // So, this has to be block.lastMember.length(). - // SPV wants "block" and member number as the operands, go get them. - - spv::Id length; - if (node->getOperand()->getType().isCoopMat()) { - spv::Id typeId = convertGlslangToSpvType(node->getOperand()->getType()); - assert(builder.isCooperativeMatrixType(typeId)); - - if (node->getOperand()->getType().isCoopMatKHR()) { - length = builder.createCooperativeMatrixLengthKHR(typeId); - } else { - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - length = builder.createCooperativeMatrixLengthNV(typeId); - } - } else { - glslang::TIntermTyped* block = node->getOperand()->getAsBinaryNode()->getLeft(); - block->traverse(this); - unsigned int member = node->getOperand()->getAsBinaryNode()->getRight()->getAsConstantUnion() - ->getConstArray()[0].getUConst(); - length = builder.createArrayLength(builder.accessChainGetLValue(), member); - } - - // GLSL semantics say the result of .length() is an int, while SPIR-V says - // signedness must be 0. So, convert from SPIR-V unsigned back to GLSL's - // AST expectation of a signed result. - if (glslangIntermediate->getSource() == glslang::EShSourceGlsl) { - if (builder.isInSpecConstCodeGenMode()) { - length = builder.createBinOp(spv::OpIAdd, builder.makeIntType(32), length, builder.makeIntConstant(0)); - } else { - length = builder.createUnaryOp(spv::OpBitcast, builder.makeIntType(32), length); - } - } - - builder.clearAccessChain(); - builder.setAccessChainRValue(length); - - return false; - } - - // Force variable declaration - Debug Mode Only - if (node->getOp() == glslang::EOpDeclare) { - builder.clearAccessChain(); - node->getOperand()->traverse(this); - builder.clearAccessChain(); - return false; - } - - // Start by evaluating the operand - - // Does it need a swizzle inversion? If so, evaluation is inverted; - // operate first on the swizzle base, then apply the swizzle. - spv::Id invertedType = spv::NoType; - auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? - invertedType : convertGlslangToSpvType(node->getType()); }; - if (node->getOp() == glslang::EOpInterpolateAtCentroid) - invertedType = getInvertedSwizzleType(*node->getOperand()); - - builder.clearAccessChain(); - TIntermNode *operandNode; - if (invertedType != spv::NoType) - operandNode = node->getOperand()->getAsBinaryNode()->getLeft(); - else - operandNode = node->getOperand(); - - operandNode->traverse(this); - - spv::Id operand = spv::NoResult; - - spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags; - - const auto hitObjectOpsWithLvalue = [](glslang::TOperator op) { - switch(op) { - case glslang::EOpReorderThreadNV: - case glslang::EOpHitObjectGetCurrentTimeNV: - case glslang::EOpHitObjectGetHitKindNV: - case glslang::EOpHitObjectGetPrimitiveIndexNV: - case glslang::EOpHitObjectGetGeometryIndexNV: - case glslang::EOpHitObjectGetInstanceIdNV: - case glslang::EOpHitObjectGetInstanceCustomIndexNV: - case glslang::EOpHitObjectGetObjectRayDirectionNV: - case glslang::EOpHitObjectGetObjectRayOriginNV: - case glslang::EOpHitObjectGetWorldRayDirectionNV: - case glslang::EOpHitObjectGetWorldRayOriginNV: - case glslang::EOpHitObjectGetWorldToObjectNV: - case glslang::EOpHitObjectGetObjectToWorldNV: - case glslang::EOpHitObjectGetRayTMaxNV: - case glslang::EOpHitObjectGetRayTMinNV: - case glslang::EOpHitObjectIsEmptyNV: - case glslang::EOpHitObjectIsHitNV: - case glslang::EOpHitObjectIsMissNV: - case glslang::EOpHitObjectRecordEmptyNV: - case glslang::EOpHitObjectGetShaderBindingTableRecordIndexNV: - case glslang::EOpHitObjectGetShaderRecordBufferHandleNV: - return true; - default: - return false; - } - }; - - if (node->getOp() == glslang::EOpAtomicCounterIncrement || - node->getOp() == glslang::EOpAtomicCounterDecrement || - node->getOp() == glslang::EOpAtomicCounter || - (node->getOp() == glslang::EOpInterpolateAtCentroid && - glslangIntermediate->getSource() != glslang::EShSourceHlsl) || - node->getOp() == glslang::EOpRayQueryProceed || - node->getOp() == glslang::EOpRayQueryGetRayTMin || - node->getOp() == glslang::EOpRayQueryGetRayFlags || - node->getOp() == glslang::EOpRayQueryGetWorldRayOrigin || - node->getOp() == glslang::EOpRayQueryGetWorldRayDirection || - node->getOp() == glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque || - node->getOp() == glslang::EOpRayQueryTerminate || - node->getOp() == glslang::EOpRayQueryConfirmIntersection || - (node->getOp() == glslang::EOpSpirvInst && operandNode->getAsTyped()->getQualifier().isSpirvByReference()) || - hitObjectOpsWithLvalue(node->getOp())) { - operand = builder.accessChainGetLValue(); // Special case l-value operands - lvalueCoherentFlags = builder.getAccessChain().coherentFlags; - lvalueCoherentFlags |= TranslateCoherent(operandNode->getAsTyped()->getType()); - } else if (operandNode->getAsTyped()->getQualifier().isSpirvLiteral()) { - // Will be translated to a literal value, make a placeholder here - operand = spv::NoResult; - } else { - operand = accessChainLoad(node->getOperand()->getType()); - } - - OpDecorations decorations = { TranslatePrecisionDecoration(node->getOperationPrecision()), - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - - // it could be a conversion - if (! result) - result = createConversion(node->getOp(), decorations, resultType(), operand, - node->getOperand()->getBasicType()); - - // if not, then possibly an operation - if (! result) - result = createUnaryOperation(node->getOp(), decorations, resultType(), operand, - node->getOperand()->getBasicType(), lvalueCoherentFlags); - - // it could be attached to a SPIR-V intruction - if (!result) { - if (node->getOp() == glslang::EOpSpirvInst) { - const auto& spirvInst = node->getSpirvInstruction(); - if (spirvInst.set == "") { - spv::IdImmediate idImmOp = {true, operand}; - if (operandNode->getAsTyped()->getQualifier().isSpirvLiteral()) { - // Translate the constant to a literal value - std::vector literals; - glslang::TVector constants; - constants.push_back(operandNode->getAsConstantUnion()); - TranslateLiterals(constants, literals); - idImmOp = {false, literals[0]}; - } - - if (node->getBasicType() == glslang::EbtVoid) - builder.createNoResultOp(static_cast(spirvInst.id), {idImmOp}); - else - result = builder.createOp(static_cast(spirvInst.id), resultType(), {idImmOp}); - } else { - result = builder.createBuiltinCall( - resultType(), spirvInst.set == "GLSL.std.450" ? stdBuiltins : getExtBuiltins(spirvInst.set.c_str()), - spirvInst.id, {operand}); - } - - if (node->getBasicType() == glslang::EbtVoid) - return false; // done with this node - } - } - - if (result) { - if (invertedType) { - result = createInvertedSwizzle(decorations.precision, *node->getOperand(), result); - decorations.addNonUniform(builder, result); - } - - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; // done with this node - } - - // it must be a special case, check... - switch (node->getOp()) { - case glslang::EOpPostIncrement: - case glslang::EOpPostDecrement: - case glslang::EOpPreIncrement: - case glslang::EOpPreDecrement: - { - // we need the integer value "1" or the floating point "1.0" to add/subtract - spv::Id one = 0; - if (node->getBasicType() == glslang::EbtFloat) - one = builder.makeFloatConstant(1.0F); - else if (node->getBasicType() == glslang::EbtDouble) - one = builder.makeDoubleConstant(1.0); - else if (node->getBasicType() == glslang::EbtFloat16) - one = builder.makeFloat16Constant(1.0F); - else if (node->getBasicType() == glslang::EbtInt8 || node->getBasicType() == glslang::EbtUint8) - one = builder.makeInt8Constant(1); - else if (node->getBasicType() == glslang::EbtInt16 || node->getBasicType() == glslang::EbtUint16) - one = builder.makeInt16Constant(1); - else if (node->getBasicType() == glslang::EbtInt64 || node->getBasicType() == glslang::EbtUint64) - one = builder.makeInt64Constant(1); - else - one = builder.makeIntConstant(1); - glslang::TOperator op; - if (node->getOp() == glslang::EOpPreIncrement || - node->getOp() == glslang::EOpPostIncrement) - op = glslang::EOpAdd; - else - op = glslang::EOpSub; - - spv::Id result = createBinaryOperation(op, decorations, - convertGlslangToSpvType(node->getType()), operand, one, - node->getType().getBasicType()); - assert(result != spv::NoResult); - - // The result of operation is always stored, but conditionally the - // consumed result. The consumed result is always an r-value. - builder.accessChainStore(result, - TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags)); - builder.clearAccessChain(); - if (node->getOp() == glslang::EOpPreIncrement || - node->getOp() == glslang::EOpPreDecrement) - builder.setAccessChainRValue(result); - else - builder.setAccessChainRValue(operand); - } - - return false; - - case glslang::EOpEmitStreamVertex: - builder.createNoResultOp(spv::OpEmitStreamVertex, operand); - return false; - case glslang::EOpEndStreamPrimitive: - builder.createNoResultOp(spv::OpEndStreamPrimitive, operand); - return false; - case glslang::EOpRayQueryTerminate: - builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operand); - return false; - case glslang::EOpRayQueryConfirmIntersection: - builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operand); - return false; - case glslang::EOpReorderThreadNV: - builder.createNoResultOp(spv::OpReorderThreadWithHitObjectNV, operand); - return false; - case glslang::EOpHitObjectRecordEmptyNV: - builder.createNoResultOp(spv::OpHitObjectRecordEmptyNV, operand); - return false; - - default: - logger->missingFunctionality("unknown glslang unary"); - return true; // pick up operand as placeholder result - } -} - -// Construct a composite object, recursively copying members if their types don't match -spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, std::vector constituents) -{ - for (int c = 0; c < (int)constituents.size(); ++c) { - spv::Id& constituent = constituents[c]; - spv::Id lType = builder.getContainedTypeId(resultTypeId, c); - spv::Id rType = builder.getTypeId(constituent); - if (lType != rType) { - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) { - constituent = builder.createUnaryOp(spv::OpCopyLogical, lType, constituent); - } else if (builder.isStructType(rType)) { - std::vector rTypeConstituents; - int numrTypeConstituents = builder.getNumTypeConstituents(rType); - for (int i = 0; i < numrTypeConstituents; ++i) { - rTypeConstituents.push_back(builder.createCompositeExtract(constituent, - builder.getContainedTypeId(rType, i), i)); - } - constituents[c] = createCompositeConstruct(lType, rTypeConstituents); - } else { - assert(builder.isArrayType(rType)); - std::vector rTypeConstituents; - int numrTypeConstituents = builder.getNumTypeConstituents(rType); - - spv::Id elementRType = builder.getContainedTypeId(rType); - for (int i = 0; i < numrTypeConstituents; ++i) { - rTypeConstituents.push_back(builder.createCompositeExtract(constituent, elementRType, i)); - } - constituents[c] = createCompositeConstruct(lType, rTypeConstituents); - } - } - } - return builder.createCompositeConstruct(resultTypeId, constituents); -} - -bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node) -{ - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - - spv::Id result = spv::NoResult; - spv::Id invertedType = spv::NoType; // to use to override the natural type of the node - std::vector complexLvalues; // for holding swizzling l-values too complex for - // SPIR-V, for an out parameter - std::vector temporaryLvalues; // temporaries to pass, as proxies for complexLValues - - auto resultType = [&invertedType, &node, this](){ return invertedType != spv::NoType ? - invertedType : - convertGlslangToSpvType(node->getType()); }; - - // try texturing - result = createImageTextureFunctionCall(node); - if (result != spv::NoResult) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; - } else if (node->getOp() == glslang::EOpImageStore || - node->getOp() == glslang::EOpImageStoreLod || - node->getOp() == glslang::EOpImageAtomicStore) { - // "imageStore" is a special case, which has no result - return false; - } - - glslang::TOperator binOp = glslang::EOpNull; - bool reduceComparison = true; - bool isMatrix = false; - bool noReturnValue = false; - bool atomic = false; - - spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags; - - assert(node->getOp()); - - spv::Decoration precision = TranslatePrecisionDecoration(node->getOperationPrecision()); - - switch (node->getOp()) { - case glslang::EOpScope: - case glslang::EOpSequence: - { - if (visit == glslang::EvPreVisit) { - ++sequenceDepth; - if (sequenceDepth == 1) { - // If this is the parent node of all the functions, we want to see them - // early, so all call points have actual SPIR-V functions to reference. - // In all cases, still let the traverser visit the children for us. - makeFunctions(node->getAsAggregate()->getSequence()); - - // Global initializers is specific to the shader entry point, which does not exist in compile-only mode - if (!options.compileOnly) { - // Also, we want all globals initializers to go into the beginning of the entry point, before - // anything else gets there, so visit out of order, doing them all now. - makeGlobalInitializers(node->getAsAggregate()->getSequence()); - } - - //Pre process linker objects for ray tracing stages - if (glslangIntermediate->isRayTracingStage()) - collectRayTracingLinkerObjects(); - - // Initializers are done, don't want to visit again, but functions and link objects need to be processed, - // so do them manually. - visitFunctions(node->getAsAggregate()->getSequence()); - - return false; - } else { - if (node->getOp() == glslang::EOpScope) - builder.enterScope(0); - } - } else { - if (sequenceDepth > 1 && node->getOp() == glslang::EOpScope) - builder.leaveScope(); - --sequenceDepth; - } - - return true; - } - case glslang::EOpLinkerObjects: - { - if (visit == glslang::EvPreVisit) - linkageOnly = true; - else - linkageOnly = false; - - return true; - } - case glslang::EOpComma: - { - // processing from left to right naturally leaves the right-most - // lying around in the access chain - glslang::TIntermSequence& glslangOperands = node->getSequence(); - for (int i = 0; i < (int)glslangOperands.size(); ++i) - glslangOperands[i]->traverse(this); - - return false; - } - case glslang::EOpFunction: - if (visit == glslang::EvPreVisit) { - if (isShaderEntryPoint(node)) { - inEntryPoint = true; - builder.setBuildPoint(shaderEntry->getLastBlock()); - builder.enterFunction(shaderEntry); - currentFunction = shaderEntry; - } else { - handleFunctionEntry(node); - } - if (options.generateDebugInfo) { - const auto& loc = node->getLoc(); - const char* sourceFileName = loc.getFilename(); - spv::Id sourceFileId = sourceFileName ? builder.getStringId(sourceFileName) : builder.getSourceFile(); - currentFunction->setDebugLineInfo(sourceFileId, loc.line, loc.column); - } - } else { - if (inEntryPoint) - entryPointTerminated = true; - builder.leaveFunction(); - inEntryPoint = false; - } - - return true; - case glslang::EOpParameters: - // Parameters will have been consumed by EOpFunction processing, but not - // the body, so we still visited the function node's children, making this - // child redundant. - return false; - case glslang::EOpFunctionCall: - { - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - if (node->isUserDefined()) - result = handleUserFunctionCall(node); - if (result) { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - } else - logger->missingFunctionality("missing user function; linker needs to catch that"); - - return false; - } - case glslang::EOpConstructMat2x2: - case glslang::EOpConstructMat2x3: - case glslang::EOpConstructMat2x4: - case glslang::EOpConstructMat3x2: - case glslang::EOpConstructMat3x3: - case glslang::EOpConstructMat3x4: - case glslang::EOpConstructMat4x2: - case glslang::EOpConstructMat4x3: - case glslang::EOpConstructMat4x4: - case glslang::EOpConstructDMat2x2: - case glslang::EOpConstructDMat2x3: - case glslang::EOpConstructDMat2x4: - case glslang::EOpConstructDMat3x2: - case glslang::EOpConstructDMat3x3: - case glslang::EOpConstructDMat3x4: - case glslang::EOpConstructDMat4x2: - case glslang::EOpConstructDMat4x3: - case glslang::EOpConstructDMat4x4: - case glslang::EOpConstructIMat2x2: - case glslang::EOpConstructIMat2x3: - case glslang::EOpConstructIMat2x4: - case glslang::EOpConstructIMat3x2: - case glslang::EOpConstructIMat3x3: - case glslang::EOpConstructIMat3x4: - case glslang::EOpConstructIMat4x2: - case glslang::EOpConstructIMat4x3: - case glslang::EOpConstructIMat4x4: - case glslang::EOpConstructUMat2x2: - case glslang::EOpConstructUMat2x3: - case glslang::EOpConstructUMat2x4: - case glslang::EOpConstructUMat3x2: - case glslang::EOpConstructUMat3x3: - case glslang::EOpConstructUMat3x4: - case glslang::EOpConstructUMat4x2: - case glslang::EOpConstructUMat4x3: - case glslang::EOpConstructUMat4x4: - case glslang::EOpConstructBMat2x2: - case glslang::EOpConstructBMat2x3: - case glslang::EOpConstructBMat2x4: - case glslang::EOpConstructBMat3x2: - case glslang::EOpConstructBMat3x3: - case glslang::EOpConstructBMat3x4: - case glslang::EOpConstructBMat4x2: - case glslang::EOpConstructBMat4x3: - case glslang::EOpConstructBMat4x4: - case glslang::EOpConstructF16Mat2x2: - case glslang::EOpConstructF16Mat2x3: - case glslang::EOpConstructF16Mat2x4: - case glslang::EOpConstructF16Mat3x2: - case glslang::EOpConstructF16Mat3x3: - case glslang::EOpConstructF16Mat3x4: - case glslang::EOpConstructF16Mat4x2: - case glslang::EOpConstructF16Mat4x3: - case glslang::EOpConstructF16Mat4x4: - isMatrix = true; - // fall through - case glslang::EOpConstructFloat: - case glslang::EOpConstructVec2: - case glslang::EOpConstructVec3: - case glslang::EOpConstructVec4: - case glslang::EOpConstructDouble: - case glslang::EOpConstructDVec2: - case glslang::EOpConstructDVec3: - case glslang::EOpConstructDVec4: - case glslang::EOpConstructFloat16: - case glslang::EOpConstructF16Vec2: - case glslang::EOpConstructF16Vec3: - case glslang::EOpConstructF16Vec4: - case glslang::EOpConstructBool: - case glslang::EOpConstructBVec2: - case glslang::EOpConstructBVec3: - case glslang::EOpConstructBVec4: - case glslang::EOpConstructInt8: - case glslang::EOpConstructI8Vec2: - case glslang::EOpConstructI8Vec3: - case glslang::EOpConstructI8Vec4: - case glslang::EOpConstructUint8: - case glslang::EOpConstructU8Vec2: - case glslang::EOpConstructU8Vec3: - case glslang::EOpConstructU8Vec4: - case glslang::EOpConstructInt16: - case glslang::EOpConstructI16Vec2: - case glslang::EOpConstructI16Vec3: - case glslang::EOpConstructI16Vec4: - case glslang::EOpConstructUint16: - case glslang::EOpConstructU16Vec2: - case glslang::EOpConstructU16Vec3: - case glslang::EOpConstructU16Vec4: - case glslang::EOpConstructInt: - case glslang::EOpConstructIVec2: - case glslang::EOpConstructIVec3: - case glslang::EOpConstructIVec4: - case glslang::EOpConstructUint: - case glslang::EOpConstructUVec2: - case glslang::EOpConstructUVec3: - case glslang::EOpConstructUVec4: - case glslang::EOpConstructInt64: - case glslang::EOpConstructI64Vec2: - case glslang::EOpConstructI64Vec3: - case glslang::EOpConstructI64Vec4: - case glslang::EOpConstructUint64: - case glslang::EOpConstructU64Vec2: - case glslang::EOpConstructU64Vec3: - case glslang::EOpConstructU64Vec4: - case glslang::EOpConstructStruct: - case glslang::EOpConstructTextureSampler: - case glslang::EOpConstructReference: - case glslang::EOpConstructCooperativeMatrixNV: - case glslang::EOpConstructCooperativeMatrixKHR: - { - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - std::vector arguments; - translateArguments(*node, arguments, lvalueCoherentFlags); - spv::Id constructed; - if (node->getOp() == glslang::EOpConstructTextureSampler) { - const glslang::TType& texType = node->getSequence()[0]->getAsTyped()->getType(); - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6 && - texType.getSampler().isBuffer()) { - // SamplerBuffer is not supported in spirv1.6 so - // `samplerBuffer(textureBuffer, sampler)` is a no-op - // and textureBuffer is the result going forward - constructed = arguments[0]; - } else - constructed = builder.createOp(spv::OpSampledImage, resultType(), arguments); - } else if (node->getOp() == glslang::EOpConstructStruct || - node->getOp() == glslang::EOpConstructCooperativeMatrixNV || - node->getOp() == glslang::EOpConstructCooperativeMatrixKHR || - node->getType().isArray()) { - std::vector constituents; - for (int c = 0; c < (int)arguments.size(); ++c) - constituents.push_back(arguments[c]); - constructed = createCompositeConstruct(resultType(), constituents); - } else if (isMatrix) - constructed = builder.createMatrixConstructor(precision, arguments, resultType()); - else - constructed = builder.createConstructor(precision, arguments, resultType()); - - if (node->getType().getQualifier().isNonUniform()) { - builder.addDecoration(constructed, spv::DecorationNonUniformEXT); - } - - builder.clearAccessChain(); - builder.setAccessChainRValue(constructed); - - return false; - } - - // These six are component-wise compares with component-wise results. - // Forward on to createBinaryOperation(), requesting a vector result. - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpVectorEqual: - case glslang::EOpVectorNotEqual: - { - // Map the operation to a binary - binOp = node->getOp(); - reduceComparison = false; - switch (node->getOp()) { - case glslang::EOpVectorEqual: binOp = glslang::EOpVectorEqual; break; - case glslang::EOpVectorNotEqual: binOp = glslang::EOpVectorNotEqual; break; - default: binOp = node->getOp(); break; - } - - break; - } - case glslang::EOpMul: - // component-wise matrix multiply - binOp = glslang::EOpMul; - break; - case glslang::EOpOuterProduct: - // two vectors multiplied to make a matrix - binOp = glslang::EOpOuterProduct; - break; - case glslang::EOpDot: - { - // for scalar dot product, use multiply - glslang::TIntermSequence& glslangOperands = node->getSequence(); - if (glslangOperands[0]->getAsTyped()->getVectorSize() == 1) - binOp = glslang::EOpMul; - break; - } - case glslang::EOpMod: - // when an aggregate, this is the floating-point mod built-in function, - // which can be emitted by the one in createBinaryOperation() - binOp = glslang::EOpMod; - break; - - case glslang::EOpEmitVertex: - case glslang::EOpEndPrimitive: - case glslang::EOpBarrier: - case glslang::EOpMemoryBarrier: - case glslang::EOpMemoryBarrierAtomicCounter: - case glslang::EOpMemoryBarrierBuffer: - case glslang::EOpMemoryBarrierImage: - case glslang::EOpMemoryBarrierShared: - case glslang::EOpGroupMemoryBarrier: - case glslang::EOpDeviceMemoryBarrier: - case glslang::EOpAllMemoryBarrierWithGroupSync: - case glslang::EOpDeviceMemoryBarrierWithGroupSync: - case glslang::EOpWorkgroupMemoryBarrier: - case glslang::EOpWorkgroupMemoryBarrierWithGroupSync: - case glslang::EOpSubgroupBarrier: - case glslang::EOpSubgroupMemoryBarrier: - case glslang::EOpSubgroupMemoryBarrierBuffer: - case glslang::EOpSubgroupMemoryBarrierImage: - case glslang::EOpSubgroupMemoryBarrierShared: - noReturnValue = true; - // These all have 0 operands and will naturally finish up in the code below for 0 operands - break; - - case glslang::EOpAtomicAdd: - case glslang::EOpAtomicSubtract: - case glslang::EOpAtomicMin: - case glslang::EOpAtomicMax: - case glslang::EOpAtomicAnd: - case glslang::EOpAtomicOr: - case glslang::EOpAtomicXor: - case glslang::EOpAtomicExchange: - case glslang::EOpAtomicCompSwap: - atomic = true; - break; - - case glslang::EOpAtomicStore: - noReturnValue = true; - // fallthrough - case glslang::EOpAtomicLoad: - atomic = true; - break; - - case glslang::EOpAtomicCounterAdd: - case glslang::EOpAtomicCounterSubtract: - case glslang::EOpAtomicCounterMin: - case glslang::EOpAtomicCounterMax: - case glslang::EOpAtomicCounterAnd: - case glslang::EOpAtomicCounterOr: - case glslang::EOpAtomicCounterXor: - case glslang::EOpAtomicCounterExchange: - case glslang::EOpAtomicCounterCompSwap: - builder.addExtension("SPV_KHR_shader_atomic_counter_ops"); - builder.addCapability(spv::CapabilityAtomicStorageOps); - atomic = true; - break; - - case glslang::EOpAbsDifference: - case glslang::EOpAddSaturate: - case glslang::EOpSubSaturate: - case glslang::EOpAverage: - case glslang::EOpAverageRounded: - case glslang::EOpMul32x16: - builder.addCapability(spv::CapabilityIntegerFunctions2INTEL); - builder.addExtension("SPV_INTEL_shader_integer_functions2"); - binOp = node->getOp(); - break; - - case glslang::EOpIgnoreIntersectionNV: - case glslang::EOpTerminateRayNV: - case glslang::EOpTraceNV: - case glslang::EOpTraceRayMotionNV: - case glslang::EOpTraceKHR: - case glslang::EOpExecuteCallableNV: - case glslang::EOpExecuteCallableKHR: - case glslang::EOpWritePackedPrimitiveIndices4x8NV: - case glslang::EOpEmitMeshTasksEXT: - case glslang::EOpSetMeshOutputsEXT: - noReturnValue = true; - break; - case glslang::EOpRayQueryInitialize: - case glslang::EOpRayQueryTerminate: - case glslang::EOpRayQueryGenerateIntersection: - case glslang::EOpRayQueryConfirmIntersection: - builder.addExtension("SPV_KHR_ray_query"); - builder.addCapability(spv::CapabilityRayQueryKHR); - noReturnValue = true; - break; - case glslang::EOpRayQueryProceed: - case glslang::EOpRayQueryGetIntersectionType: - case glslang::EOpRayQueryGetRayTMin: - case glslang::EOpRayQueryGetRayFlags: - case glslang::EOpRayQueryGetIntersectionT: - case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: - case glslang::EOpRayQueryGetIntersectionInstanceId: - case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: - case glslang::EOpRayQueryGetIntersectionGeometryIndex: - case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: - case glslang::EOpRayQueryGetIntersectionBarycentrics: - case glslang::EOpRayQueryGetIntersectionFrontFace: - case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: - case glslang::EOpRayQueryGetIntersectionObjectRayDirection: - case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: - case glslang::EOpRayQueryGetWorldRayDirection: - case glslang::EOpRayQueryGetWorldRayOrigin: - case glslang::EOpRayQueryGetIntersectionObjectToWorld: - case glslang::EOpRayQueryGetIntersectionWorldToObject: - builder.addExtension("SPV_KHR_ray_query"); - builder.addCapability(spv::CapabilityRayQueryKHR); - break; - case glslang::EOpCooperativeMatrixLoad: - case glslang::EOpCooperativeMatrixStore: - case glslang::EOpCooperativeMatrixLoadNV: - case glslang::EOpCooperativeMatrixStoreNV: - noReturnValue = true; - break; - case glslang::EOpBeginInvocationInterlock: - case glslang::EOpEndInvocationInterlock: - builder.addExtension(spv::E_SPV_EXT_fragment_shader_interlock); - noReturnValue = true; - break; - - case glslang::EOpHitObjectTraceRayNV: - case glslang::EOpHitObjectTraceRayMotionNV: - case glslang::EOpHitObjectGetAttributesNV: - case glslang::EOpHitObjectExecuteShaderNV: - case glslang::EOpHitObjectRecordEmptyNV: - case glslang::EOpHitObjectRecordMissNV: - case glslang::EOpHitObjectRecordMissMotionNV: - case glslang::EOpHitObjectRecordHitNV: - case glslang::EOpHitObjectRecordHitMotionNV: - case glslang::EOpHitObjectRecordHitWithIndexNV: - case glslang::EOpHitObjectRecordHitWithIndexMotionNV: - case glslang::EOpReorderThreadNV: - noReturnValue = true; - //Fallthrough - case glslang::EOpHitObjectIsEmptyNV: - case glslang::EOpHitObjectIsMissNV: - case glslang::EOpHitObjectIsHitNV: - case glslang::EOpHitObjectGetRayTMinNV: - case glslang::EOpHitObjectGetRayTMaxNV: - case glslang::EOpHitObjectGetObjectRayOriginNV: - case glslang::EOpHitObjectGetObjectRayDirectionNV: - case glslang::EOpHitObjectGetWorldRayOriginNV: - case glslang::EOpHitObjectGetWorldRayDirectionNV: - case glslang::EOpHitObjectGetObjectToWorldNV: - case glslang::EOpHitObjectGetWorldToObjectNV: - case glslang::EOpHitObjectGetInstanceCustomIndexNV: - case glslang::EOpHitObjectGetInstanceIdNV: - case glslang::EOpHitObjectGetGeometryIndexNV: - case glslang::EOpHitObjectGetPrimitiveIndexNV: - case glslang::EOpHitObjectGetHitKindNV: - case glslang::EOpHitObjectGetCurrentTimeNV: - case glslang::EOpHitObjectGetShaderBindingTableRecordIndexNV: - case glslang::EOpHitObjectGetShaderRecordBufferHandleNV: - builder.addExtension(spv::E_SPV_NV_shader_invocation_reorder); - builder.addCapability(spv::CapabilityShaderInvocationReorderNV); - break; - case glslang::EOpRayQueryGetIntersectionTriangleVertexPositionsEXT: - builder.addExtension(spv::E_SPV_KHR_ray_tracing_position_fetch); - builder.addCapability(spv::CapabilityRayQueryPositionFetchKHR); - noReturnValue = true; - break; - - case glslang::EOpImageSampleWeightedQCOM: - builder.addCapability(spv::CapabilityTextureSampleWeightedQCOM); - builder.addExtension(spv::E_SPV_QCOM_image_processing); - break; - case glslang::EOpImageBoxFilterQCOM: - builder.addCapability(spv::CapabilityTextureBoxFilterQCOM); - builder.addExtension(spv::E_SPV_QCOM_image_processing); - break; - case glslang::EOpImageBlockMatchSADQCOM: - case glslang::EOpImageBlockMatchSSDQCOM: - builder.addCapability(spv::CapabilityTextureBlockMatchQCOM); - builder.addExtension(spv::E_SPV_QCOM_image_processing); - break; - - case glslang::EOpFetchMicroTriangleVertexPositionNV: - case glslang::EOpFetchMicroTriangleVertexBarycentricNV: - builder.addExtension(spv::E_SPV_NV_displacement_micromap); - builder.addCapability(spv::CapabilityDisplacementMicromapNV); - break; - - case glslang::EOpDebugPrintf: - noReturnValue = true; - break; - - default: - break; - } - - // - // See if it maps to a regular operation. - // - if (binOp != glslang::EOpNull) { - glslang::TIntermTyped* left = node->getSequence()[0]->getAsTyped(); - glslang::TIntermTyped* right = node->getSequence()[1]->getAsTyped(); - assert(left && right); - - builder.clearAccessChain(); - left->traverse(this); - spv::Id leftId = accessChainLoad(left->getType()); - - builder.clearAccessChain(); - right->traverse(this); - spv::Id rightId = accessChainLoad(right->getType()); - - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - OpDecorations decorations = { precision, - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - result = createBinaryOperation(binOp, decorations, - resultType(), leftId, rightId, - left->getType().getBasicType(), reduceComparison); - - // code above should only make binOp that exists in createBinaryOperation - assert(result != spv::NoResult); - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - - return false; - } - - // - // Create the list of operands. - // - glslang::TIntermSequence& glslangOperands = node->getSequence(); - std::vector operands; - std::vector memoryAccessOperands; - for (int arg = 0; arg < (int)glslangOperands.size(); ++arg) { - // special case l-value operands; there are just a few - bool lvalue = false; - switch (node->getOp()) { - case glslang::EOpModf: - if (arg == 1) - lvalue = true; - break; - - - - case glslang::EOpHitObjectRecordHitNV: - case glslang::EOpHitObjectRecordHitMotionNV: - case glslang::EOpHitObjectRecordHitWithIndexNV: - case glslang::EOpHitObjectRecordHitWithIndexMotionNV: - case glslang::EOpHitObjectTraceRayNV: - case glslang::EOpHitObjectTraceRayMotionNV: - case glslang::EOpHitObjectExecuteShaderNV: - case glslang::EOpHitObjectRecordMissNV: - case glslang::EOpHitObjectRecordMissMotionNV: - case glslang::EOpHitObjectGetAttributesNV: - if (arg == 0) - lvalue = true; - break; - - case glslang::EOpRayQueryInitialize: - case glslang::EOpRayQueryTerminate: - case glslang::EOpRayQueryConfirmIntersection: - case glslang::EOpRayQueryProceed: - case glslang::EOpRayQueryGenerateIntersection: - case glslang::EOpRayQueryGetIntersectionType: - case glslang::EOpRayQueryGetIntersectionT: - case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: - case glslang::EOpRayQueryGetIntersectionInstanceId: - case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: - case glslang::EOpRayQueryGetIntersectionGeometryIndex: - case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: - case glslang::EOpRayQueryGetIntersectionBarycentrics: - case glslang::EOpRayQueryGetIntersectionFrontFace: - case glslang::EOpRayQueryGetIntersectionObjectRayDirection: - case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: - case glslang::EOpRayQueryGetIntersectionObjectToWorld: - case glslang::EOpRayQueryGetIntersectionWorldToObject: - if (arg == 0) - lvalue = true; - break; - - case glslang::EOpAtomicAdd: - case glslang::EOpAtomicSubtract: - case glslang::EOpAtomicMin: - case glslang::EOpAtomicMax: - case glslang::EOpAtomicAnd: - case glslang::EOpAtomicOr: - case glslang::EOpAtomicXor: - case glslang::EOpAtomicExchange: - case glslang::EOpAtomicCompSwap: - if (arg == 0) - lvalue = true; - break; - - case glslang::EOpFrexp: - if (arg == 1) - lvalue = true; - break; - case glslang::EOpInterpolateAtSample: - case glslang::EOpInterpolateAtOffset: - case glslang::EOpInterpolateAtVertex: - if (arg == 0) { - // If GLSL, use the address of the interpolant argument. - // If HLSL, use an internal version of OpInterolates that takes - // the rvalue of the interpolant. A fixup pass in spirv-opt - // legalization will remove the OpLoad and convert to an lvalue. - // Had to do this because legalization will only propagate a - // builtin into an rvalue. - lvalue = glslangIntermediate->getSource() != glslang::EShSourceHlsl; - - // Does it need a swizzle inversion? If so, evaluation is inverted; - // operate first on the swizzle base, then apply the swizzle. - // That is, we transform - // - // interpolate(v.zy) -> interpolate(v).zy - // - if (glslangOperands[0]->getAsOperator() && - glslangOperands[0]->getAsOperator()->getOp() == glslang::EOpVectorSwizzle) - invertedType = convertGlslangToSpvType( - glslangOperands[0]->getAsBinaryNode()->getLeft()->getType()); - } - break; - case glslang::EOpAtomicLoad: - case glslang::EOpAtomicStore: - case glslang::EOpAtomicCounterAdd: - case glslang::EOpAtomicCounterSubtract: - case glslang::EOpAtomicCounterMin: - case glslang::EOpAtomicCounterMax: - case glslang::EOpAtomicCounterAnd: - case glslang::EOpAtomicCounterOr: - case glslang::EOpAtomicCounterXor: - case glslang::EOpAtomicCounterExchange: - case glslang::EOpAtomicCounterCompSwap: - if (arg == 0) - lvalue = true; - break; - case glslang::EOpAddCarry: - case glslang::EOpSubBorrow: - if (arg == 2) - lvalue = true; - break; - case glslang::EOpUMulExtended: - case glslang::EOpIMulExtended: - if (arg >= 2) - lvalue = true; - break; - case glslang::EOpCooperativeMatrixLoad: - case glslang::EOpCooperativeMatrixLoadNV: - if (arg == 0 || arg == 1) - lvalue = true; - break; - case glslang::EOpCooperativeMatrixStore: - case glslang::EOpCooperativeMatrixStoreNV: - if (arg == 1) - lvalue = true; - break; - case glslang::EOpSpirvInst: - if (glslangOperands[arg]->getAsTyped()->getQualifier().isSpirvByReference()) - lvalue = true; - break; - case glslang::EOpReorderThreadNV: - //Three variants of reorderThreadNV, two of them use hitObjectNV - if (arg == 0 && glslangOperands.size() != 2) - lvalue = true; - break; - case glslang::EOpRayQueryGetIntersectionTriangleVertexPositionsEXT: - if (arg == 0 || arg == 2) - lvalue = true; - break; - default: - break; - } - builder.clearAccessChain(); - if (invertedType != spv::NoType && arg == 0) - glslangOperands[0]->getAsBinaryNode()->getLeft()->traverse(this); - else - glslangOperands[arg]->traverse(this); - - if (node->getOp() == glslang::EOpCooperativeMatrixLoad || - node->getOp() == glslang::EOpCooperativeMatrixStore || - node->getOp() == glslang::EOpCooperativeMatrixLoadNV || - node->getOp() == glslang::EOpCooperativeMatrixStoreNV) { - - if (arg == 1) { - // fold "element" parameter into the access chain - spv::Builder::AccessChain save = builder.getAccessChain(); - builder.clearAccessChain(); - glslangOperands[2]->traverse(this); - - spv::Id elementId = accessChainLoad(glslangOperands[2]->getAsTyped()->getType()); - - builder.setAccessChain(save); - - // Point to the first element of the array. - builder.accessChainPush(elementId, - TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()), - glslangOperands[arg]->getAsTyped()->getType().getBufferReferenceAlignment()); - - spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags; - unsigned int alignment = builder.getAccessChain().alignment; - - int memoryAccess = TranslateMemoryAccess(coherentFlags); - if (node->getOp() == glslang::EOpCooperativeMatrixLoad || - node->getOp() == glslang::EOpCooperativeMatrixLoadNV) - memoryAccess &= ~spv::MemoryAccessMakePointerAvailableKHRMask; - if (node->getOp() == glslang::EOpCooperativeMatrixStore || - node->getOp() == glslang::EOpCooperativeMatrixStoreNV) - memoryAccess &= ~spv::MemoryAccessMakePointerVisibleKHRMask; - if (builder.getStorageClass(builder.getAccessChain().base) == - spv::StorageClassPhysicalStorageBufferEXT) { - memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); - } - - memoryAccessOperands.push_back(spv::IdImmediate(false, memoryAccess)); - - if (memoryAccess & spv::MemoryAccessAlignedMask) { - memoryAccessOperands.push_back(spv::IdImmediate(false, alignment)); - } - - if (memoryAccess & - (spv::MemoryAccessMakePointerAvailableKHRMask | spv::MemoryAccessMakePointerVisibleKHRMask)) { - memoryAccessOperands.push_back(spv::IdImmediate(true, - builder.makeUintConstant(TranslateMemoryScope(coherentFlags)))); - } - } else if (arg == 2) { - continue; - } - } - - // for l-values, pass the address, for r-values, pass the value - if (lvalue) { - if (invertedType == spv::NoType && !builder.isSpvLvalue()) { - // SPIR-V cannot represent an l-value containing a swizzle that doesn't - // reduce to a simple access chain. So, we need a temporary vector to - // receive the result, and must later swizzle that into the original - // l-value. - complexLvalues.push_back(builder.getAccessChain()); - temporaryLvalues.push_back(builder.createVariable( - spv::NoPrecision, spv::StorageClassFunction, - builder.accessChainGetInferredType(), "swizzleTemp")); - operands.push_back(temporaryLvalues.back()); - } else { - operands.push_back(builder.accessChainGetLValue()); - } - lvalueCoherentFlags = builder.getAccessChain().coherentFlags; - lvalueCoherentFlags |= TranslateCoherent(glslangOperands[arg]->getAsTyped()->getType()); - } else { - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - glslang::TOperator glslangOp = node->getOp(); - if (arg == 1 && - (glslangOp == glslang::EOpRayQueryGetIntersectionType || - glslangOp == glslang::EOpRayQueryGetIntersectionT || - glslangOp == glslang::EOpRayQueryGetIntersectionInstanceCustomIndex || - glslangOp == glslang::EOpRayQueryGetIntersectionInstanceId || - glslangOp == glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset || - glslangOp == glslang::EOpRayQueryGetIntersectionGeometryIndex || - glslangOp == glslang::EOpRayQueryGetIntersectionPrimitiveIndex || - glslangOp == glslang::EOpRayQueryGetIntersectionBarycentrics || - glslangOp == glslang::EOpRayQueryGetIntersectionFrontFace || - glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayDirection || - glslangOp == glslang::EOpRayQueryGetIntersectionObjectRayOrigin || - glslangOp == glslang::EOpRayQueryGetIntersectionObjectToWorld || - glslangOp == glslang::EOpRayQueryGetIntersectionWorldToObject || - glslangOp == glslang::EOpRayQueryGetIntersectionTriangleVertexPositionsEXT - )) { - bool cond = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getBConst(); - operands.push_back(builder.makeIntConstant(cond ? 1 : 0)); - } else if ((arg == 10 && glslangOp == glslang::EOpTraceKHR) || - (arg == 11 && glslangOp == glslang::EOpTraceRayMotionNV) || - (arg == 1 && glslangOp == glslang::EOpExecuteCallableKHR) || - (arg == 1 && glslangOp == glslang::EOpHitObjectExecuteShaderNV) || - (arg == 11 && glslangOp == glslang::EOpHitObjectTraceRayNV) || - (arg == 12 && glslangOp == glslang::EOpHitObjectTraceRayMotionNV)) { - const int set = glslangOp == glslang::EOpExecuteCallableKHR ? 1 : 0; - const int location = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getUConst(); - auto itNode = locationToSymbol[set].find(location); - visitSymbol(itNode->second); - spv::Id symId = getSymbolId(itNode->second); - operands.push_back(symId); - } else if ((arg == 12 && glslangOp == glslang::EOpHitObjectRecordHitNV) || - (arg == 13 && glslangOp == glslang::EOpHitObjectRecordHitMotionNV) || - (arg == 11 && glslangOp == glslang::EOpHitObjectRecordHitWithIndexNV) || - (arg == 12 && glslangOp == glslang::EOpHitObjectRecordHitWithIndexMotionNV) || - (arg == 1 && glslangOp == glslang::EOpHitObjectGetAttributesNV)) { - const int location = glslangOperands[arg]->getAsConstantUnion()->getConstArray()[0].getUConst(); - const int set = 2; - auto itNode = locationToSymbol[set].find(location); - visitSymbol(itNode->second); - spv::Id symId = getSymbolId(itNode->second); - operands.push_back(symId); - } else if (glslangOperands[arg]->getAsTyped()->getQualifier().isSpirvLiteral()) { - // Will be translated to a literal value, make a placeholder here - operands.push_back(spv::NoResult); - } else { - operands.push_back(accessChainLoad(glslangOperands[arg]->getAsTyped()->getType())); - } - } - } - - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - if (node->getOp() == glslang::EOpCooperativeMatrixLoad || - node->getOp() == glslang::EOpCooperativeMatrixLoadNV) { - std::vector idImmOps; - - idImmOps.push_back(spv::IdImmediate(true, operands[1])); // buf - if (node->getOp() == glslang::EOpCooperativeMatrixLoad) { - idImmOps.push_back(spv::IdImmediate(true, operands[3])); // matrixLayout - idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride - } else { - idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride - idImmOps.push_back(spv::IdImmediate(true, operands[3])); // colMajor - } - idImmOps.insert(idImmOps.end(), memoryAccessOperands.begin(), memoryAccessOperands.end()); - // get the pointee type - spv::Id typeId = builder.getContainedTypeId(builder.getTypeId(operands[0])); - assert(builder.isCooperativeMatrixType(typeId)); - // do the op - spv::Id result = node->getOp() == glslang::EOpCooperativeMatrixLoad - ? builder.createOp(spv::OpCooperativeMatrixLoadKHR, typeId, idImmOps) - : builder.createOp(spv::OpCooperativeMatrixLoadNV, typeId, idImmOps); - // store the result to the pointer (out param 'm') - builder.createStore(result, operands[0]); - result = 0; - } else if (node->getOp() == glslang::EOpCooperativeMatrixStore || - node->getOp() == glslang::EOpCooperativeMatrixStoreNV) { - std::vector idImmOps; - - idImmOps.push_back(spv::IdImmediate(true, operands[1])); // buf - idImmOps.push_back(spv::IdImmediate(true, operands[0])); // object - if (node->getOp() == glslang::EOpCooperativeMatrixStore) { - idImmOps.push_back(spv::IdImmediate(true, operands[3])); // matrixLayout - idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride - } else { - idImmOps.push_back(spv::IdImmediate(true, operands[2])); // stride - idImmOps.push_back(spv::IdImmediate(true, operands[3])); // colMajor - } - idImmOps.insert(idImmOps.end(), memoryAccessOperands.begin(), memoryAccessOperands.end()); - - if (node->getOp() == glslang::EOpCooperativeMatrixStore) - builder.createNoResultOp(spv::OpCooperativeMatrixStoreKHR, idImmOps); - else - builder.createNoResultOp(spv::OpCooperativeMatrixStoreNV, idImmOps); - result = 0; - } else if (node->getOp() == glslang::EOpRayQueryGetIntersectionTriangleVertexPositionsEXT) { - std::vector idImmOps; - - idImmOps.push_back(spv::IdImmediate(true, operands[0])); // q - idImmOps.push_back(spv::IdImmediate(true, operands[1])); // committed - - spv::Id typeId = builder.makeArrayType(builder.makeVectorType(builder.makeFloatType(32), 3), - builder.makeUintConstant(3), 0); - // do the op - - spv::Op spvOp = spv::OpRayQueryGetIntersectionTriangleVertexPositionsKHR; - - spv::Id result = builder.createOp(spvOp, typeId, idImmOps); - // store the result to the pointer (out param 'm') - builder.createStore(result, operands[2]); - result = 0; - } else if (node->getOp() == glslang::EOpCooperativeMatrixMulAdd) { - uint32_t matrixOperands = 0; - - // If the optional operand is present, initialize matrixOperands to that value. - if (glslangOperands.size() == 4 && glslangOperands[3]->getAsConstantUnion()) { - matrixOperands = glslangOperands[3]->getAsConstantUnion()->getConstArray()[0].getIConst(); - } - - // Determine Cooperative Matrix Operands bits from the signedness of the types. - if (isTypeSignedInt(glslangOperands[0]->getAsTyped()->getBasicType())) - matrixOperands |= spv::CooperativeMatrixOperandsMatrixASignedComponentsKHRMask; - if (isTypeSignedInt(glslangOperands[1]->getAsTyped()->getBasicType())) - matrixOperands |= spv::CooperativeMatrixOperandsMatrixBSignedComponentsKHRMask; - if (isTypeSignedInt(glslangOperands[2]->getAsTyped()->getBasicType())) - matrixOperands |= spv::CooperativeMatrixOperandsMatrixCSignedComponentsKHRMask; - if (isTypeSignedInt(node->getBasicType())) - matrixOperands |= spv::CooperativeMatrixOperandsMatrixResultSignedComponentsKHRMask; - - std::vector idImmOps; - idImmOps.push_back(spv::IdImmediate(true, operands[0])); - idImmOps.push_back(spv::IdImmediate(true, operands[1])); - idImmOps.push_back(spv::IdImmediate(true, operands[2])); - if (matrixOperands != 0) - idImmOps.push_back(spv::IdImmediate(false, matrixOperands)); - - result = builder.createOp(spv::OpCooperativeMatrixMulAddKHR, resultType(), idImmOps); - } else if (atomic) { - // Handle all atomics - glslang::TBasicType typeProxy = (node->getOp() == glslang::EOpAtomicStore) - ? node->getSequence()[0]->getAsTyped()->getBasicType() : node->getBasicType(); - result = createAtomicOperation(node->getOp(), precision, resultType(), operands, typeProxy, - lvalueCoherentFlags); - } else if (node->getOp() == glslang::EOpSpirvInst) { - const auto& spirvInst = node->getSpirvInstruction(); - if (spirvInst.set == "") { - std::vector idImmOps; - for (unsigned int i = 0; i < glslangOperands.size(); ++i) { - if (glslangOperands[i]->getAsTyped()->getQualifier().isSpirvLiteral()) { - // Translate the constant to a literal value - std::vector literals; - glslang::TVector constants; - constants.push_back(glslangOperands[i]->getAsConstantUnion()); - TranslateLiterals(constants, literals); - idImmOps.push_back({false, literals[0]}); - } else - idImmOps.push_back({true, operands[i]}); - } - - if (node->getBasicType() == glslang::EbtVoid) - builder.createNoResultOp(static_cast(spirvInst.id), idImmOps); - else - result = builder.createOp(static_cast(spirvInst.id), resultType(), idImmOps); - } else { - result = builder.createBuiltinCall( - resultType(), spirvInst.set == "GLSL.std.450" ? stdBuiltins : getExtBuiltins(spirvInst.set.c_str()), - spirvInst.id, operands); - } - noReturnValue = node->getBasicType() == glslang::EbtVoid; - } else if (node->getOp() == glslang::EOpDebugPrintf) { - if (!nonSemanticDebugPrintf) { - nonSemanticDebugPrintf = builder.import("NonSemantic.DebugPrintf"); - } - result = builder.createBuiltinCall(builder.makeVoidType(), nonSemanticDebugPrintf, spv::NonSemanticDebugPrintfDebugPrintf, operands); - builder.addExtension(spv::E_SPV_KHR_non_semantic_info); - } else { - // Pass through to generic operations. - switch (glslangOperands.size()) { - case 0: - result = createNoArgOperation(node->getOp(), precision, resultType()); - break; - case 1: - { - OpDecorations decorations = { precision, - TranslateNoContractionDecoration(node->getType().getQualifier()), - TranslateNonUniformDecoration(node->getType().getQualifier()) }; - result = createUnaryOperation( - node->getOp(), decorations, - resultType(), operands.front(), - glslangOperands[0]->getAsTyped()->getBasicType(), lvalueCoherentFlags); - } - break; - default: - result = createMiscOperation(node->getOp(), precision, resultType(), operands, node->getBasicType()); - break; - } - - if (invertedType != spv::NoResult) - result = createInvertedSwizzle(precision, *glslangOperands[0]->getAsBinaryNode(), result); - - for (unsigned int i = 0; i < temporaryLvalues.size(); ++i) { - builder.setAccessChain(complexLvalues[i]); - builder.accessChainStore(builder.createLoad(temporaryLvalues[i], spv::NoPrecision), - TranslateNonUniformDecoration(complexLvalues[i].coherentFlags)); - } - } - - if (noReturnValue) - return false; - - if (! result) { - logger->missingFunctionality("unknown glslang aggregate"); - return true; // pick up a child as a placeholder operand - } else { - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - return false; - } -} - -// This path handles both if-then-else and ?: -// The if-then-else has a node type of void, while -// ?: has either a void or a non-void node type -// -// Leaving the result, when not void: -// GLSL only has r-values as the result of a :?, but -// if we have an l-value, that can be more efficient if it will -// become the base of a complex r-value expression, because the -// next layer copies r-values into memory to use the access-chain mechanism -bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node) -{ - // see if OpSelect can handle it - const auto isOpSelectable = [&]() { - if (node->getBasicType() == glslang::EbtVoid) - return false; - // OpSelect can do all other types starting with SPV 1.4 - if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4) { - // pre-1.4, only scalars and vectors can be handled - if ((!node->getType().isScalar() && !node->getType().isVector())) - return false; - } - return true; - }; - - // See if it simple and safe, or required, to execute both sides. - // Crucially, side effects must be either semantically required or avoided, - // and there are performance trade-offs. - // Return true if required or a good idea (and safe) to execute both sides, - // false otherwise. - const auto bothSidesPolicy = [&]() -> bool { - // do we have both sides? - if (node->getTrueBlock() == nullptr || - node->getFalseBlock() == nullptr) - return false; - - // required? (unless we write additional code to look for side effects - // and make performance trade-offs if none are present) - if (!node->getShortCircuit()) - return true; - - // if not required to execute both, decide based on performance/practicality... - - if (!isOpSelectable()) - return false; - - assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() && - node->getType() == node->getFalseBlock()->getAsTyped()->getType()); - - // return true if a single operand to ? : is okay for OpSelect - const auto operandOkay = [](glslang::TIntermTyped* node) { - return node->getAsSymbolNode() || node->getType().getQualifier().isConstant(); - }; - - return operandOkay(node->getTrueBlock() ->getAsTyped()) && - operandOkay(node->getFalseBlock()->getAsTyped()); - }; - - spv::Id result = spv::NoResult; // upcoming result selecting between trueValue and falseValue - // emit the condition before doing anything with selection - node->getCondition()->traverse(this); - spv::Id condition = accessChainLoad(node->getCondition()->getType()); - - // Find a way of executing both sides and selecting the right result. - const auto executeBothSides = [&]() -> void { - // execute both sides - spv::Id resultType = convertGlslangToSpvType(node->getType()); - node->getTrueBlock()->traverse(this); - spv::Id trueValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()); - node->getFalseBlock()->traverse(this); - spv::Id falseValue = accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()); - - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - - // done if void - if (node->getBasicType() == glslang::EbtVoid) - return; - - // emit code to select between trueValue and falseValue - // see if OpSelect can handle the result type, and that the SPIR-V types - // of the inputs match the result type. - if (isOpSelectable()) { - // Emit OpSelect for this selection. - - // smear condition to vector, if necessary (AST is always scalar) - // Before 1.4, smear like for mix(), starting with 1.4, keep it scalar - if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4 && builder.isVector(trueValue)) { - condition = builder.smearScalar(spv::NoPrecision, condition, - builder.makeVectorType(builder.makeBoolType(), - builder.getNumComponents(trueValue))); - } - - // If the types do not match, it is because of mismatched decorations on aggregates. - // Since isOpSelectable only lets us get here for SPIR-V >= 1.4, we can use OpCopyObject - // to get matching types. - if (builder.getTypeId(trueValue) != resultType) { - trueValue = builder.createUnaryOp(spv::OpCopyLogical, resultType, trueValue); - } - if (builder.getTypeId(falseValue) != resultType) { - falseValue = builder.createUnaryOp(spv::OpCopyLogical, resultType, falseValue); - } - - // OpSelect - result = builder.createTriOp(spv::OpSelect, resultType, condition, trueValue, falseValue); - - builder.clearAccessChain(); - builder.setAccessChainRValue(result); - } else { - // We need control flow to select the result. - // TODO: Once SPIR-V OpSelect allows arbitrary types, eliminate this path. - result = builder.createVariable(TranslatePrecisionDecoration(node->getType()), - spv::StorageClassFunction, resultType); - - // Selection control: - const spv::SelectionControlMask control = TranslateSelectionControl(*node); - - // make an "if" based on the value created by the condition - spv::Builder::If ifBuilder(condition, control, builder); - - // emit the "then" statement - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - multiTypeStore(node->getType(), trueValue); - - ifBuilder.makeBeginElse(); - // emit the "else" statement - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - multiTypeStore(node->getType(), falseValue); - - // finish off the control flow - ifBuilder.makeEndIf(); - - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - } - }; - - // Execute the one side needed, as per the condition - const auto executeOneSide = [&]() { - // Always emit control flow. - if (node->getBasicType() != glslang::EbtVoid) { - result = builder.createVariable(TranslatePrecisionDecoration(node->getType()), spv::StorageClassFunction, - convertGlslangToSpvType(node->getType())); - } - - // Selection control: - const spv::SelectionControlMask control = TranslateSelectionControl(*node); - - // make an "if" based on the value created by the condition - spv::Builder::If ifBuilder(condition, control, builder); - - // emit the "then" statement - if (node->getTrueBlock() != nullptr) { - node->getTrueBlock()->traverse(this); - if (result != spv::NoResult) { - spv::Id load = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()); - - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - multiTypeStore(node->getType(), load); - } - } - - if (node->getFalseBlock() != nullptr) { - ifBuilder.makeBeginElse(); - // emit the "else" statement - node->getFalseBlock()->traverse(this); - if (result != spv::NoResult) { - spv::Id load = accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()); - - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - multiTypeStore(node->getType(), load); - } - } - - // finish off the control flow - ifBuilder.makeEndIf(); - - if (result != spv::NoResult) { - builder.clearAccessChain(); - builder.setAccessChainLValue(result); - } - }; - - // Try for OpSelect (or a requirement to execute both sides) - if (bothSidesPolicy()) { - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - if (node->getType().getQualifier().isSpecConstant()) - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - executeBothSides(); - } else - executeOneSide(); - - return false; -} - -bool TGlslangToSpvTraverser::visitSwitch(glslang::TVisit /* visit */, glslang::TIntermSwitch* node) -{ - // emit and get the condition before doing anything with switch - node->getCondition()->traverse(this); - spv::Id selector = accessChainLoad(node->getCondition()->getAsTyped()->getType()); - - // Selection control: - const spv::SelectionControlMask control = TranslateSwitchControl(*node); - - // browse the children to sort out code segments - int defaultSegment = -1; - std::vector codeSegments; - glslang::TIntermSequence& sequence = node->getBody()->getSequence(); - std::vector caseValues; - std::vector valueIndexToSegment(sequence.size()); // note: probably not all are used, it is an overestimate - for (glslang::TIntermSequence::iterator c = sequence.begin(); c != sequence.end(); ++c) { - TIntermNode* child = *c; - if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpDefault) - defaultSegment = (int)codeSegments.size(); - else if (child->getAsBranchNode() && child->getAsBranchNode()->getFlowOp() == glslang::EOpCase) { - valueIndexToSegment[caseValues.size()] = (int)codeSegments.size(); - caseValues.push_back(child->getAsBranchNode()->getExpression()->getAsConstantUnion() - ->getConstArray()[0].getIConst()); - } else - codeSegments.push_back(child); - } - - // handle the case where the last code segment is missing, due to no code - // statements between the last case and the end of the switch statement - if ((caseValues.size() && (int)codeSegments.size() == valueIndexToSegment[caseValues.size() - 1]) || - (int)codeSegments.size() == defaultSegment) - codeSegments.push_back(nullptr); - - // make the switch statement - std::vector segmentBlocks; // returned, as the blocks allocated in the call - builder.makeSwitch(selector, control, (int)codeSegments.size(), caseValues, valueIndexToSegment, defaultSegment, - segmentBlocks); - - // emit all the code in the segments - breakForLoop.push(false); - for (unsigned int s = 0; s < codeSegments.size(); ++s) { - builder.nextSwitchSegment(segmentBlocks, s); - if (codeSegments[s]) - codeSegments[s]->traverse(this); - else - builder.addSwitchBreak(); - } - breakForLoop.pop(); - - builder.endSwitch(segmentBlocks); - - return false; -} - -void TGlslangToSpvTraverser::visitConstantUnion(glslang::TIntermConstantUnion* node) -{ - if (node->getQualifier().isSpirvLiteral()) - return; // Translated to a literal value, skip further processing - - int nextConst = 0; - spv::Id constant = createSpvConstantFromConstUnionArray(node->getType(), node->getConstArray(), nextConst, false); - - builder.clearAccessChain(); - builder.setAccessChainRValue(constant); -} - -bool TGlslangToSpvTraverser::visitLoop(glslang::TVisit /* visit */, glslang::TIntermLoop* node) -{ - auto blocks = builder.makeNewLoop(); - builder.createBranch(&blocks.head); - - // Loop control: - std::vector operands; - const spv::LoopControlMask control = TranslateLoopControl(*node, operands); - - // Spec requires back edges to target header blocks, and every header block - // must dominate its merge block. Make a header block first to ensure these - // conditions are met. By definition, it will contain OpLoopMerge, followed - // by a block-ending branch. But we don't want to put any other body/test - // instructions in it, since the body/test may have arbitrary instructions, - // including merges of its own. - builder.setBuildPoint(&blocks.head); - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - builder.createLoopMerge(&blocks.merge, &blocks.continue_target, control, operands); - if (node->testFirst() && node->getTest()) { - spv::Block& test = builder.makeNewBlock(); - builder.createBranch(&test); - - builder.setBuildPoint(&test); - node->getTest()->traverse(this); - spv::Id condition = accessChainLoad(node->getTest()->getType()); - builder.createConditionalBranch(condition, &blocks.body, &blocks.merge); - - builder.setBuildPoint(&blocks.body); - breakForLoop.push(true); - if (node->getBody()) - node->getBody()->traverse(this); - builder.createBranch(&blocks.continue_target); - breakForLoop.pop(); - - builder.setBuildPoint(&blocks.continue_target); - if (node->getTerminal()) - node->getTerminal()->traverse(this); - builder.createBranch(&blocks.head); - } else { - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - builder.createBranch(&blocks.body); - - breakForLoop.push(true); - builder.setBuildPoint(&blocks.body); - if (node->getBody()) - node->getBody()->traverse(this); - builder.createBranch(&blocks.continue_target); - breakForLoop.pop(); - - builder.setBuildPoint(&blocks.continue_target); - if (node->getTerminal()) - node->getTerminal()->traverse(this); - if (node->getTest()) { - node->getTest()->traverse(this); - spv::Id condition = - accessChainLoad(node->getTest()->getType()); - builder.createConditionalBranch(condition, &blocks.head, &blocks.merge); - } else { - // TODO: unless there was a break/return/discard instruction - // somewhere in the body, this is an infinite loop, so we should - // issue a warning. - builder.createBranch(&blocks.head); - } - } - builder.setBuildPoint(&blocks.merge); - builder.closeLoop(); - return false; -} - -bool TGlslangToSpvTraverser::visitBranch(glslang::TVisit /* visit */, glslang::TIntermBranch* node) -{ - if (node->getExpression()) - node->getExpression()->traverse(this); - - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - - switch (node->getFlowOp()) { - case glslang::EOpKill: - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) { - if (glslangIntermediate->getSource() == glslang::EShSourceHlsl) { - builder.addCapability(spv::CapabilityDemoteToHelperInvocation); - builder.createNoResultOp(spv::OpDemoteToHelperInvocationEXT); - } else { - builder.makeStatementTerminator(spv::OpTerminateInvocation, "post-terminate-invocation"); - } - } else { - builder.makeStatementTerminator(spv::OpKill, "post-discard"); - } - break; - case glslang::EOpTerminateInvocation: - builder.addExtension(spv::E_SPV_KHR_terminate_invocation); - builder.makeStatementTerminator(spv::OpTerminateInvocation, "post-terminate-invocation"); - break; - case glslang::EOpBreak: - if (breakForLoop.top()) - builder.createLoopExit(); - else - builder.addSwitchBreak(); - break; - case glslang::EOpContinue: - builder.createLoopContinue(); - break; - case glslang::EOpReturn: - if (node->getExpression() != nullptr) { - const glslang::TType& glslangReturnType = node->getExpression()->getType(); - spv::Id returnId = accessChainLoad(glslangReturnType); - if (builder.getTypeId(returnId) != currentFunction->getReturnType() || - TranslatePrecisionDecoration(glslangReturnType) != currentFunction->getReturnPrecision()) { - builder.clearAccessChain(); - spv::Id copyId = builder.createVariable(currentFunction->getReturnPrecision(), - spv::StorageClassFunction, currentFunction->getReturnType()); - builder.setAccessChainLValue(copyId); - multiTypeStore(glslangReturnType, returnId); - returnId = builder.createLoad(copyId, currentFunction->getReturnPrecision()); - } - builder.makeReturn(false, returnId); - } else - builder.makeReturn(false); - - builder.clearAccessChain(); - break; - - case glslang::EOpDemote: - builder.createNoResultOp(spv::OpDemoteToHelperInvocationEXT); - builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation); - builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT); - break; - case glslang::EOpTerminateRayKHR: - builder.makeStatementTerminator(spv::OpTerminateRayKHR, "post-terminateRayKHR"); - break; - case glslang::EOpIgnoreIntersectionKHR: - builder.makeStatementTerminator(spv::OpIgnoreIntersectionKHR, "post-ignoreIntersectionKHR"); - break; - - default: - assert(0); - break; - } - - return false; -} - -spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* node, spv::Id forcedType) -{ - // First, steer off constants, which are not SPIR-V variables, but - // can still have a mapping to a SPIR-V Id. - // This includes specialization constants. - if (node->getQualifier().isConstant()) { - spv::Id result = createSpvConstant(*node); - if (result != spv::NoResult) - return result; - } - - // Now, handle actual variables - spv::StorageClass storageClass = TranslateStorageClass(node->getType()); - spv::Id spvType = forcedType == spv::NoType ? convertGlslangToSpvType(node->getType()) - : forcedType; - - const bool contains16BitType = node->getType().contains16BitFloat() || - node->getType().contains16BitInt(); - if (contains16BitType) { - switch (storageClass) { - case spv::StorageClassInput: - case spv::StorageClassOutput: - builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); - builder.addCapability(spv::CapabilityStorageInputOutput16); - break; - case spv::StorageClassUniform: - builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); - if (node->getType().getQualifier().storage == glslang::EvqBuffer) - builder.addCapability(spv::CapabilityStorageUniformBufferBlock16); - else - builder.addCapability(spv::CapabilityStorageUniform16); - break; - case spv::StorageClassPushConstant: - builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); - builder.addCapability(spv::CapabilityStoragePushConstant16); - break; - case spv::StorageClassStorageBuffer: - case spv::StorageClassPhysicalStorageBufferEXT: - builder.addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); - builder.addCapability(spv::CapabilityStorageUniformBufferBlock16); - break; - default: - if (storageClass == spv::StorageClassWorkgroup && - node->getType().getBasicType() == glslang::EbtBlock) { - builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR); - break; - } - if (node->getType().contains16BitFloat()) - builder.addCapability(spv::CapabilityFloat16); - if (node->getType().contains16BitInt()) - builder.addCapability(spv::CapabilityInt16); - break; - } - } - - if (node->getType().contains8BitInt()) { - if (storageClass == spv::StorageClassPushConstant) { - builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); - builder.addCapability(spv::CapabilityStoragePushConstant8); - } else if (storageClass == spv::StorageClassUniform) { - builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); - builder.addCapability(spv::CapabilityUniformAndStorageBuffer8BitAccess); - } else if (storageClass == spv::StorageClassStorageBuffer) { - builder.addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); - builder.addCapability(spv::CapabilityStorageBuffer8BitAccess); - } else if (storageClass == spv::StorageClassWorkgroup && - node->getType().getBasicType() == glslang::EbtBlock) { - builder.addCapability(spv::CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR); - } else { - builder.addCapability(spv::CapabilityInt8); - } - } - - const char* name = node->getName().c_str(); - if (glslang::IsAnonymous(name)) - name = ""; - - spv::Id initializer = spv::NoResult; - - if (node->getType().getQualifier().storage == glslang::EvqUniform && !node->getConstArray().empty()) { - int nextConst = 0; - initializer = createSpvConstantFromConstUnionArray(node->getType(), - node->getConstArray(), - nextConst, - false /* specConst */); - } else if (node->getType().getQualifier().isNullInit()) { - initializer = builder.makeNullConstant(spvType); - } - - return builder.createVariable(spv::NoPrecision, storageClass, spvType, name, initializer, false); -} - -// Return type Id of the sampled type. -spv::Id TGlslangToSpvTraverser::getSampledType(const glslang::TSampler& sampler) -{ - switch (sampler.type) { - case glslang::EbtInt: return builder.makeIntType(32); - case glslang::EbtUint: return builder.makeUintType(32); - case glslang::EbtFloat: return builder.makeFloatType(32); - case glslang::EbtFloat16: - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float_fetch); - builder.addCapability(spv::CapabilityFloat16ImageAMD); - return builder.makeFloatType(16); - case glslang::EbtInt64: - builder.addExtension(spv::E_SPV_EXT_shader_image_int64); - builder.addCapability(spv::CapabilityInt64ImageEXT); - return builder.makeIntType(64); - case glslang::EbtUint64: - builder.addExtension(spv::E_SPV_EXT_shader_image_int64); - builder.addCapability(spv::CapabilityInt64ImageEXT); - return builder.makeUintType(64); - default: - assert(0); - return builder.makeFloatType(32); - } -} - -// If node is a swizzle operation, return the type that should be used if -// the swizzle base is first consumed by another operation, before the swizzle -// is applied. -spv::Id TGlslangToSpvTraverser::getInvertedSwizzleType(const glslang::TIntermTyped& node) -{ - if (node.getAsOperator() && - node.getAsOperator()->getOp() == glslang::EOpVectorSwizzle) - return convertGlslangToSpvType(node.getAsBinaryNode()->getLeft()->getType()); - else - return spv::NoType; -} - -// When inverting a swizzle with a parent op, this function -// will apply the swizzle operation to a completed parent operation. -spv::Id TGlslangToSpvTraverser::createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped& node, - spv::Id parentResult) -{ - std::vector swizzle; - convertSwizzle(*node.getAsBinaryNode()->getRight()->getAsAggregate(), swizzle); - return builder.createRvalueSwizzle(precision, convertGlslangToSpvType(node.getType()), parentResult, swizzle); -} - -// Convert a glslang AST swizzle node to a swizzle vector for building SPIR-V. -void TGlslangToSpvTraverser::convertSwizzle(const glslang::TIntermAggregate& node, std::vector& swizzle) -{ - const glslang::TIntermSequence& swizzleSequence = node.getSequence(); - for (int i = 0; i < (int)swizzleSequence.size(); ++i) - swizzle.push_back(swizzleSequence[i]->getAsConstantUnion()->getConstArray()[0].getIConst()); -} - -// Convert from a glslang type to an SPV type, by calling into a -// recursive version of this function. This establishes the inherited -// layout state rooted from the top-level type. -spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, bool forwardReferenceOnly) -{ - return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier(), false, forwardReferenceOnly); -} - -spv::LinkageType TGlslangToSpvTraverser::convertGlslangLinkageToSpv(glslang::TLinkType linkType) -{ - switch (linkType) { - case glslang::ELinkExport: - return spv::LinkageTypeExport; - default: - return spv::LinkageTypeMax; - } -} - -// Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id. -// explicitLayout can be kept the same throughout the hierarchical recursive walk. -// Mutually recursive with convertGlslangStructToSpvType(). -spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, - glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier, - bool lastBufferBlockMember, bool forwardReferenceOnly) -{ - spv::Id spvType = spv::NoResult; - - switch (type.getBasicType()) { - case glslang::EbtVoid: - spvType = builder.makeVoidType(); - assert (! type.isArray()); - break; - case glslang::EbtBool: - // "transparent" bool doesn't exist in SPIR-V. The GLSL convention is - // a 32-bit int where non-0 means true. - if (explicitLayout != glslang::ElpNone) - spvType = builder.makeUintType(32); - else - spvType = builder.makeBoolType(); - break; - case glslang::EbtInt: - spvType = builder.makeIntType(32); - break; - case glslang::EbtUint: - spvType = builder.makeUintType(32); - break; - case glslang::EbtFloat: - spvType = builder.makeFloatType(32); - break; - case glslang::EbtDouble: - spvType = builder.makeFloatType(64); - break; - case glslang::EbtFloat16: - spvType = builder.makeFloatType(16); - break; - case glslang::EbtInt8: - spvType = builder.makeIntType(8); - break; - case glslang::EbtUint8: - spvType = builder.makeUintType(8); - break; - case glslang::EbtInt16: - spvType = builder.makeIntType(16); - break; - case glslang::EbtUint16: - spvType = builder.makeUintType(16); - break; - case glslang::EbtInt64: - spvType = builder.makeIntType(64); - break; - case glslang::EbtUint64: - spvType = builder.makeUintType(64); - break; - case glslang::EbtAtomicUint: - builder.addCapability(spv::CapabilityAtomicStorage); - spvType = builder.makeUintType(32); - break; - case glslang::EbtAccStruct: - switch (glslangIntermediate->getStage()) { - case EShLangRayGen: - case EShLangIntersect: - case EShLangAnyHit: - case EShLangClosestHit: - case EShLangMiss: - case EShLangCallable: - // these all should have the RayTracingNV/KHR capability already - break; - default: - { - auto& extensions = glslangIntermediate->getRequestedExtensions(); - if (extensions.find("GL_EXT_ray_query") != extensions.end()) { - builder.addExtension(spv::E_SPV_KHR_ray_query); - builder.addCapability(spv::CapabilityRayQueryKHR); - } - } - break; - } - spvType = builder.makeAccelerationStructureType(); - break; - case glslang::EbtRayQuery: - { - auto& extensions = glslangIntermediate->getRequestedExtensions(); - if (extensions.find("GL_EXT_ray_query") != extensions.end()) { - builder.addExtension(spv::E_SPV_KHR_ray_query); - builder.addCapability(spv::CapabilityRayQueryKHR); - } - spvType = builder.makeRayQueryType(); - } - break; - case glslang::EbtReference: - { - // Make the forward pointer, then recurse to convert the structure type, then - // patch up the forward pointer with a real pointer type. - if (forwardPointers.find(type.getReferentType()) == forwardPointers.end()) { - spv::Id forwardId = builder.makeForwardPointer(spv::StorageClassPhysicalStorageBufferEXT); - forwardPointers[type.getReferentType()] = forwardId; - } - spvType = forwardPointers[type.getReferentType()]; - if (!forwardReferenceOnly) { - spv::Id referentType = convertGlslangToSpvType(*type.getReferentType()); - builder.makePointerFromForwardPointer(spv::StorageClassPhysicalStorageBufferEXT, - forwardPointers[type.getReferentType()], - referentType); - } - } - break; - case glslang::EbtSampler: - { - const glslang::TSampler& sampler = type.getSampler(); - if (sampler.isPureSampler()) { - spvType = builder.makeSamplerType(); - } else { - // an image is present, make its type - spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), - sampler.isShadow(), sampler.isArrayed(), sampler.isMultiSample(), - sampler.isImageClass() ? 2 : 1, TranslateImageFormat(type)); - if (sampler.isCombined() && - (!sampler.isBuffer() || glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_6)) { - // Already has both image and sampler, make the combined type. Only combine sampler to - // buffer if before SPIR-V 1.6. - spvType = builder.makeSampledImageType(spvType); - } - } - } - break; - case glslang::EbtStruct: - case glslang::EbtBlock: - { - // If we've seen this struct type, return it - const glslang::TTypeList* glslangMembers = type.getStruct(); - - // Try to share structs for different layouts, but not yet for other - // kinds of qualification (primarily not yet including interpolant qualification). - if (! HasNonLayoutQualifiers(type, qualifier)) - spvType = structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers]; - if (spvType != spv::NoResult) - break; - - // else, we haven't seen it... - if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangTypeToIdMap[glslangMembers]].resize(glslangMembers->size()); - spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier); - } - break; - case glslang::EbtString: - // no type used for OpString - return 0; - - case glslang::EbtHitObjectNV: { - builder.addExtension(spv::E_SPV_NV_shader_invocation_reorder); - builder.addCapability(spv::CapabilityShaderInvocationReorderNV); - spvType = builder.makeHitObjectNVType(); - } - break; - case glslang::EbtSpirvType: { - // GL_EXT_spirv_intrinsics - const auto& spirvType = type.getSpirvType(); - const auto& spirvInst = spirvType.spirvInst; - - std::vector operands; - for (const auto& typeParam : spirvType.typeParams) { - if (typeParam.getAsConstant() != nullptr) { - // Constant expression - auto constant = typeParam.getAsConstant(); - if (constant->isLiteral()) { - if (constant->getBasicType() == glslang::EbtFloat) { - float floatValue = static_cast(constant->getConstArray()[0].getDConst()); - unsigned literal; - static_assert(sizeof(literal) == sizeof(floatValue), "sizeof(unsigned) != sizeof(float)"); - memcpy(&literal, &floatValue, sizeof(literal)); - operands.push_back({false, literal}); - } else if (constant->getBasicType() == glslang::EbtInt) { - unsigned literal = constant->getConstArray()[0].getIConst(); - operands.push_back({false, literal}); - } else if (constant->getBasicType() == glslang::EbtUint) { - unsigned literal = constant->getConstArray()[0].getUConst(); - operands.push_back({false, literal}); - } else if (constant->getBasicType() == glslang::EbtBool) { - unsigned literal = constant->getConstArray()[0].getBConst(); - operands.push_back({false, literal}); - } else if (constant->getBasicType() == glslang::EbtString) { - auto str = constant->getConstArray()[0].getSConst()->c_str(); - unsigned literal = 0; - char* literalPtr = reinterpret_cast(&literal); - unsigned charCount = 0; - char ch = 0; - do { - ch = *(str++); - *(literalPtr++) = ch; - ++charCount; - if (charCount == 4) { - operands.push_back({false, literal}); - literalPtr = reinterpret_cast(&literal); - charCount = 0; - } - } while (ch != 0); - - // Partial literal is padded with 0 - if (charCount > 0) { - for (; charCount < 4; ++charCount) - *(literalPtr++) = 0; - operands.push_back({false, literal}); - } - } else - assert(0); // Unexpected type - } else - operands.push_back({true, createSpvConstant(*constant)}); - } else { - // Type specifier - assert(typeParam.getAsType() != nullptr); - operands.push_back({true, convertGlslangToSpvType(*typeParam.getAsType())}); - } - } - - assert(spirvInst.set == ""); // Currently, couldn't be extended instructions. - spvType = builder.makeGenericType(static_cast(spirvInst.id), operands); - - break; - } - default: - assert(0); - break; - } - - if (type.isMatrix()) - spvType = builder.makeMatrixType(spvType, type.getMatrixCols(), type.getMatrixRows()); - else { - // If this variable has a vector element count greater than 1, create a SPIR-V vector - if (type.getVectorSize() > 1) - spvType = builder.makeVectorType(spvType, type.getVectorSize()); - } - - if (type.isCoopMatNV()) { - builder.addCapability(spv::CapabilityCooperativeMatrixNV); - builder.addExtension(spv::E_SPV_NV_cooperative_matrix); - - if (type.getBasicType() == glslang::EbtFloat16) - builder.addCapability(spv::CapabilityFloat16); - if (type.getBasicType() == glslang::EbtUint8 || - type.getBasicType() == glslang::EbtInt8) { - builder.addCapability(spv::CapabilityInt8); - } - - spv::Id scope = makeArraySizeId(*type.getTypeParameters()->arraySizes, 1); - spv::Id rows = makeArraySizeId(*type.getTypeParameters()->arraySizes, 2); - spv::Id cols = makeArraySizeId(*type.getTypeParameters()->arraySizes, 3); - - spvType = builder.makeCooperativeMatrixTypeNV(spvType, scope, rows, cols); - } - - if (type.isCoopMatKHR()) { - builder.addCapability(spv::CapabilityCooperativeMatrixKHR); - builder.addExtension(spv::E_SPV_KHR_cooperative_matrix); - - if (type.getBasicType() == glslang::EbtFloat16) - builder.addCapability(spv::CapabilityFloat16); - if (type.getBasicType() == glslang::EbtUint8 || type.getBasicType() == glslang::EbtInt8) { - builder.addCapability(spv::CapabilityInt8); - } - - spv::Id scope = makeArraySizeId(*type.getTypeParameters()->arraySizes, 0); - spv::Id rows = makeArraySizeId(*type.getTypeParameters()->arraySizes, 1); - spv::Id cols = makeArraySizeId(*type.getTypeParameters()->arraySizes, 2); - spv::Id use = builder.makeUintConstant(type.getCoopMatKHRuse()); - - spvType = builder.makeCooperativeMatrixTypeKHR(spvType, scope, rows, cols, use); - } - - if (type.isArray()) { - int stride = 0; // keep this 0 unless doing an explicit layout; 0 will mean no decoration, no stride - - // Do all but the outer dimension - if (type.getArraySizes()->getNumDims() > 1) { - // We need to decorate array strides for types needing explicit layout, except blocks. - if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock) { - // Use a dummy glslang type for querying internal strides of - // arrays of arrays, but using just a one-dimensional array. - glslang::TType simpleArrayType(type, 0); // deference type of the array - while (simpleArrayType.getArraySizes()->getNumDims() > 1) - simpleArrayType.getArraySizes()->dereference(); - - // Will compute the higher-order strides here, rather than making a whole - // pile of types and doing repetitive recursion on their contents. - stride = getArrayStride(simpleArrayType, explicitLayout, qualifier.layoutMatrix); - } - - // make the arrays - for (int dim = type.getArraySizes()->getNumDims() - 1; dim > 0; --dim) { - spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), dim), stride); - if (stride > 0) - builder.addDecoration(spvType, spv::DecorationArrayStride, stride); - stride *= type.getArraySizes()->getDimSize(dim); - } - } else { - // single-dimensional array, and don't yet have stride - - // We need to decorate array strides for types needing explicit layout, except blocks. - if (explicitLayout != glslang::ElpNone && type.getBasicType() != glslang::EbtBlock) - stride = getArrayStride(type, explicitLayout, qualifier.layoutMatrix); - } - - // Do the outer dimension, which might not be known for a runtime-sized array. - // (Unsized arrays that survive through linking will be runtime-sized arrays) - if (type.isSizedArray()) - spvType = builder.makeArrayType(spvType, makeArraySizeId(*type.getArraySizes(), 0), stride); - else { - if (!lastBufferBlockMember) { - builder.addIncorporatedExtension("SPV_EXT_descriptor_indexing", spv::Spv_1_5); - builder.addCapability(spv::CapabilityRuntimeDescriptorArrayEXT); - } - spvType = builder.makeRuntimeArray(spvType); - } - if (stride > 0) - builder.addDecoration(spvType, spv::DecorationArrayStride, stride); - } - - return spvType; -} - -// Apply SPIR-V decorations to the SPIR-V object (provided by SPIR-V ID). If member index is provided, the -// decorations are applied to this member. -void TGlslangToSpvTraverser::applySpirvDecorate(const glslang::TType& type, spv::Id id, std::optional member) -{ - assert(type.getQualifier().hasSpirvDecorate()); - - const glslang::TSpirvDecorate& spirvDecorate = type.getQualifier().getSpirvDecorate(); - - // Add spirv_decorate - for (auto& decorate : spirvDecorate.decorates) { - if (!decorate.second.empty()) { - std::vector literals; - TranslateLiterals(decorate.second, literals); - if (member.has_value()) - builder.addMemberDecoration(id, *member, static_cast(decorate.first), literals); - else - builder.addDecoration(id, static_cast(decorate.first), literals); - } else { - if (member.has_value()) - builder.addMemberDecoration(id, *member, static_cast(decorate.first)); - else - builder.addDecoration(id, static_cast(decorate.first)); - } - } - - // Add spirv_decorate_id - if (member.has_value()) { - // spirv_decorate_id not applied to members - assert(spirvDecorate.decorateIds.empty()); - } else { - for (auto& decorateId : spirvDecorate.decorateIds) { - std::vector operandIds; - assert(!decorateId.second.empty()); - for (auto extraOperand : decorateId.second) { - if (extraOperand->getQualifier().isFrontEndConstant()) - operandIds.push_back(createSpvConstant(*extraOperand)); - else - operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode())); - } - builder.addDecorationId(id, static_cast(decorateId.first), operandIds); - } - } - - // Add spirv_decorate_string - for (auto& decorateString : spirvDecorate.decorateStrings) { - std::vector strings; - assert(!decorateString.second.empty()); - for (auto extraOperand : decorateString.second) { - const char* string = extraOperand->getConstArray()[0].getSConst()->c_str(); - strings.push_back(string); - } - if (member.has_value()) - builder.addMemberDecoration(id, *member, static_cast(decorateString.first), strings); - else - builder.addDecoration(id, static_cast(decorateString.first), strings); - } -} - -// TODO: this functionality should exist at a higher level, in creating the AST -// -// Identify interface members that don't have their required extension turned on. -// -bool TGlslangToSpvTraverser::filterMember(const glslang::TType& member) -{ - auto& extensions = glslangIntermediate->getRequestedExtensions(); - - if (member.getFieldName() == "gl_SecondaryViewportMaskNV" && - extensions.find("GL_NV_stereo_view_rendering") == extensions.end()) - return true; - if (member.getFieldName() == "gl_SecondaryPositionNV" && - extensions.find("GL_NV_stereo_view_rendering") == extensions.end()) - return true; - - if (glslangIntermediate->getStage() == EShLangMesh) { - if (member.getFieldName() == "gl_PrimitiveShadingRateEXT" && - extensions.find("GL_EXT_fragment_shading_rate") == extensions.end()) - return true; - } - - if (glslangIntermediate->getStage() != EShLangMesh) { - if (member.getFieldName() == "gl_ViewportMask" && - extensions.find("GL_NV_viewport_array2") == extensions.end()) - return true; - if (member.getFieldName() == "gl_PositionPerViewNV" && - extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end()) - return true; - if (member.getFieldName() == "gl_ViewportMaskPerViewNV" && - extensions.find("GL_NVX_multiview_per_view_attributes") == extensions.end()) - return true; - } - - return false; -}; - -// Do full recursive conversion of a glslang structure (or block) type to a SPIR-V Id. -// explicitLayout can be kept the same throughout the hierarchical recursive walk. -// Mutually recursive with convertGlslangToSpvType(). -spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TType& type, - const glslang::TTypeList* glslangMembers, - glslang::TLayoutPacking explicitLayout, - const glslang::TQualifier& qualifier) -{ - // Create a vector of struct types for SPIR-V to consume - std::vector spvMembers; - int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, - // except sometimes for blocks - std::vector > deferredForwardPointers; - for (int i = 0; i < (int)glslangMembers->size(); i++) { - auto& glslangMember = (*glslangMembers)[i]; - if (glslangMember.type->hiddenMember()) { - ++memberDelta; - if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; - } else { - if (type.getBasicType() == glslang::EbtBlock) { - if (filterMember(*glslangMember.type)) { - memberDelta++; - memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = -1; - continue; - } - memberRemapper[glslangTypeToIdMap[glslangMembers]][i] = i - memberDelta; - } - // modify just this child's view of the qualifier - glslang::TQualifier memberQualifier = glslangMember.type->getQualifier(); - InheritQualifiers(memberQualifier, qualifier); - - // manually inherit location - if (! memberQualifier.hasLocation() && qualifier.hasLocation()) - memberQualifier.layoutLocation = qualifier.layoutLocation; - - // recurse - bool lastBufferBlockMember = qualifier.storage == glslang::EvqBuffer && - i == (int)glslangMembers->size() - 1; - - // Make forward pointers for any pointer members. - if (glslangMember.type->isReference() && - forwardPointers.find(glslangMember.type->getReferentType()) == forwardPointers.end()) { - deferredForwardPointers.push_back(std::make_pair(glslangMember.type, memberQualifier)); - } - - // Create the member type. - auto const spvMember = convertGlslangToSpvType(*glslangMember.type, explicitLayout, memberQualifier, lastBufferBlockMember, - glslangMember.type->isReference()); - spvMembers.push_back(spvMember); - - // Update the builder with the type's location so that we can create debug types for the structure members. - // There doesn't exist a "clean" entry point for this information to be passed along to the builder so, for now, - // it is stored in the builder and consumed during the construction of composite debug types. - // TODO: This probably warrants further investigation. This approach was decided to be the least ugly of the - // quick and dirty approaches that were tried. - // Advantages of this approach: - // + Relatively clean. No direct calls into debug type system. - // + Handles nested recursive structures. - // Disadvantages of this approach: - // + Not as clean as desired. Traverser queries/sets persistent state. This is fragile. - // + Table lookup during creation of composite debug types. This really shouldn't be necessary. - if(options.emitNonSemanticShaderDebugInfo) { - builder.debugTypeLocs[spvMember].name = glslangMember.type->getFieldName().c_str(); - builder.debugTypeLocs[spvMember].line = glslangMember.loc.line; - builder.debugTypeLocs[spvMember].column = glslangMember.loc.column; - } - } - } - - // Make the SPIR-V type - spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str(), false); - if (! HasNonLayoutQualifiers(type, qualifier)) - structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType; - - // Decorate it - decorateStructType(type, glslangMembers, explicitLayout, qualifier, spvType, spvMembers); - - for (int i = 0; i < (int)deferredForwardPointers.size(); ++i) { - auto it = deferredForwardPointers[i]; - convertGlslangToSpvType(*it.first, explicitLayout, it.second, false); - } - - return spvType; -} - -void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, - const glslang::TTypeList* glslangMembers, - glslang::TLayoutPacking explicitLayout, - const glslang::TQualifier& qualifier, - spv::Id spvType, - const std::vector& spvMembers) -{ - // Name and decorate the non-hidden members - int offset = -1; - bool memberLocationInvalid = type.isArrayOfArrays() || - (type.isArray() && (type.getQualifier().isArrayedIo(glslangIntermediate->getStage()) == false)); - for (int i = 0; i < (int)glslangMembers->size(); i++) { - glslang::TType& glslangMember = *(*glslangMembers)[i].type; - int member = i; - if (type.getBasicType() == glslang::EbtBlock) { - member = memberRemapper[glslangTypeToIdMap[glslangMembers]][i]; - if (filterMember(glslangMember)) - continue; - } - - // modify just this child's view of the qualifier - glslang::TQualifier memberQualifier = glslangMember.getQualifier(); - InheritQualifiers(memberQualifier, qualifier); - - // using -1 above to indicate a hidden member - if (member < 0) - continue; - - builder.addMemberName(spvType, member, glslangMember.getFieldName().c_str()); - builder.addMemberDecoration(spvType, member, - TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix)); - builder.addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember)); - // Add interpolation and auxiliary storage decorations only to - // top-level members of Input and Output storage classes - if (type.getQualifier().storage == glslang::EvqVaryingIn || - type.getQualifier().storage == glslang::EvqVaryingOut) { - if (type.getBasicType() == glslang::EbtBlock || - glslangIntermediate->getSource() == glslang::EShSourceHlsl) { - builder.addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier)); - builder.addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier)); - addMeshNVDecoration(spvType, member, memberQualifier); - } - } - builder.addMemberDecoration(spvType, member, TranslateInvariantDecoration(memberQualifier)); - - if (type.getBasicType() == glslang::EbtBlock && - qualifier.storage == glslang::EvqBuffer) { - // Add memory decorations only to top-level members of shader storage block - std::vector memory; - TranslateMemoryDecoration(memberQualifier, memory, glslangIntermediate->usingVulkanMemoryModel()); - for (unsigned int i = 0; i < memory.size(); ++i) - builder.addMemberDecoration(spvType, member, memory[i]); - } - - // Location assignment was already completed correctly by the front end, - // just track whether a member needs to be decorated. - // Ignore member locations if the container is an array, as that's - // ill-specified and decisions have been made to not allow this. - if (!memberLocationInvalid && memberQualifier.hasLocation()) - builder.addMemberDecoration(spvType, member, spv::DecorationLocation, memberQualifier.layoutLocation); - - // component, XFB, others - if (glslangMember.getQualifier().hasComponent()) - builder.addMemberDecoration(spvType, member, spv::DecorationComponent, - glslangMember.getQualifier().layoutComponent); - if (glslangMember.getQualifier().hasXfbOffset()) - builder.addMemberDecoration(spvType, member, spv::DecorationOffset, - glslangMember.getQualifier().layoutXfbOffset); - else if (explicitLayout != glslang::ElpNone) { - // figure out what to do with offset, which is accumulating - int nextOffset; - updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix); - if (offset >= 0) - builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset); - offset = nextOffset; - } - - if (glslangMember.isMatrix() && explicitLayout != glslang::ElpNone) - builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, - getMatrixStride(glslangMember, explicitLayout, memberQualifier.layoutMatrix)); - - // built-in variable decorations - spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true); - if (builtIn != spv::BuiltInMax) - builder.addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn); - - // nonuniform - builder.addMemberDecoration(spvType, member, TranslateNonUniformDecoration(glslangMember.getQualifier())); - - if (glslangIntermediate->getHlslFunctionality1() && memberQualifier.semanticName != nullptr) { - builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); - builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE, - memberQualifier.semanticName); - } - - if (builtIn == spv::BuiltInLayer) { - // SPV_NV_viewport_array2 extension - if (glslangMember.getQualifier().layoutViewportRelative){ - builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationViewportRelativeNV); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - builder.addExtension(spv::E_SPV_NV_viewport_array2); - } - if (glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset != -2048){ - builder.addMemberDecoration(spvType, member, - (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, - glslangMember.getQualifier().layoutSecondaryViewportRelativeOffset); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - } - } - if (glslangMember.getQualifier().layoutPassthrough) { - builder.addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationPassthroughNV); - builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV); - builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); - } - - // Add SPIR-V decorations (GL_EXT_spirv_intrinsics) - if (glslangMember.getQualifier().hasSpirvDecorate()) - applySpirvDecorate(glslangMember, spvType, member); - } - - // Decorate the structure - builder.addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix)); - const auto basicType = type.getBasicType(); - const auto typeStorageQualifier = type.getQualifier().storage; - if (basicType == glslang::EbtBlock) { - builder.addDecoration(spvType, TranslateBlockDecoration(typeStorageQualifier, glslangIntermediate->usingStorageBuffer())); - } else if (basicType == glslang::EbtStruct && glslangIntermediate->getSpv().vulkan > 0) { - const auto hasRuntimeArray = !spvMembers.empty() && builder.getOpCode(spvMembers.back()) == spv::OpTypeRuntimeArray; - if (hasRuntimeArray) { - builder.addDecoration(spvType, TranslateBlockDecoration(typeStorageQualifier, glslangIntermediate->usingStorageBuffer())); - } - } - - if (qualifier.hasHitObjectShaderRecordNV()) - builder.addDecoration(spvType, spv::DecorationHitObjectShaderRecordBufferNV); -} - -// Turn the expression forming the array size into an id. -// This is not quite trivial, because of specialization constants. -// Sometimes, a raw constant is turned into an Id, and sometimes -// a specialization constant expression is. -spv::Id TGlslangToSpvTraverser::makeArraySizeId(const glslang::TArraySizes& arraySizes, int dim, bool allowZero) -{ - // First, see if this is sized with a node, meaning a specialization constant: - glslang::TIntermTyped* specNode = arraySizes.getDimNode(dim); - if (specNode != nullptr) { - builder.clearAccessChain(); - SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder); - spec_constant_op_mode_setter.turnOnSpecConstantOpMode(); - specNode->traverse(this); - return accessChainLoad(specNode->getAsTyped()->getType()); - } - - // Otherwise, need a compile-time (front end) size, get it: - int size = arraySizes.getDimSize(dim); - - if (!allowZero) - assert(size > 0); - - return builder.makeUintConstant(size); -} - -// Wrap the builder's accessChainLoad to: -// - localize handling of RelaxedPrecision -// - use the SPIR-V inferred type instead of another conversion of the glslang type -// (avoids unnecessary work and possible type punning for structures) -// - do conversion of concrete to abstract type -spv::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type) -{ - spv::Id nominalTypeId = builder.accessChainGetInferredType(); - - spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags; - coherentFlags |= TranslateCoherent(type); - - spv::MemoryAccessMask accessMask = spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask); - // If the value being loaded is HelperInvocation, SPIR-V 1.6 is being generated (so that - // SPV_EXT_demote_to_helper_invocation is in core) and the memory model is in use, add - // the Volatile MemoryAccess semantic. - if (type.getQualifier().builtIn == glslang::EbvHelperInvocation && - glslangIntermediate->usingVulkanMemoryModel() && - glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) { - accessMask = spv::MemoryAccessMask(accessMask | spv::MemoryAccessVolatileMask); - } - - unsigned int alignment = builder.getAccessChain().alignment; - alignment |= type.getBufferReferenceAlignment(); - - spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type), - TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags), - TranslateNonUniformDecoration(type.getQualifier()), - nominalTypeId, - accessMask, - TranslateMemoryScope(coherentFlags), - alignment); - - // Need to convert to abstract types when necessary - if (type.getBasicType() == glslang::EbtBool) { - loadedId = convertLoadedBoolInUniformToUint(type, nominalTypeId, loadedId); - } - - return loadedId; -} - -// Wrap the builder's accessChainStore to: -// - do conversion of concrete to abstract type -// -// Implicitly uses the existing builder.accessChain as the storage target. -void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::Id rvalue) -{ - // Need to convert to abstract types when necessary - if (type.getBasicType() == glslang::EbtBool) { - spv::Id nominalTypeId = builder.accessChainGetInferredType(); - - if (builder.isScalarType(nominalTypeId)) { - // Conversion for bool - spv::Id boolType = builder.makeBoolType(); - if (nominalTypeId != boolType) { - // keep these outside arguments, for determinant order-of-evaluation - spv::Id one = builder.makeUintConstant(1); - spv::Id zero = builder.makeUintConstant(0); - rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero); - } else if (builder.getTypeId(rvalue) != boolType) - rvalue = builder.createBinOp(spv::OpINotEqual, boolType, rvalue, builder.makeUintConstant(0)); - } else if (builder.isVectorType(nominalTypeId)) { - // Conversion for bvec - int vecSize = builder.getNumTypeComponents(nominalTypeId); - spv::Id bvecType = builder.makeVectorType(builder.makeBoolType(), vecSize); - if (nominalTypeId != bvecType) { - // keep these outside arguments, for determinant order-of-evaluation - spv::Id one = makeSmearedConstant(builder.makeUintConstant(1), vecSize); - spv::Id zero = makeSmearedConstant(builder.makeUintConstant(0), vecSize); - rvalue = builder.createTriOp(spv::OpSelect, nominalTypeId, rvalue, one, zero); - } else if (builder.getTypeId(rvalue) != bvecType) - rvalue = builder.createBinOp(spv::OpINotEqual, bvecType, rvalue, - makeSmearedConstant(builder.makeUintConstant(0), vecSize)); - } - } - - spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags; - coherentFlags |= TranslateCoherent(type); - - unsigned int alignment = builder.getAccessChain().alignment; - alignment |= type.getBufferReferenceAlignment(); - - builder.accessChainStore(rvalue, TranslateNonUniformDecoration(builder.getAccessChain().coherentFlags), - spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & - ~spv::MemoryAccessMakePointerVisibleKHRMask), - TranslateMemoryScope(coherentFlags), alignment); -} - -// For storing when types match at the glslang level, but not might match at the -// SPIR-V level. -// -// This especially happens when a single glslang type expands to multiple -// SPIR-V types, like a struct that is used in a member-undecorated way as well -// as in a member-decorated way. -// -// NOTE: This function can handle any store request; if it's not special it -// simplifies to a simple OpStore. -// -// Implicitly uses the existing builder.accessChain as the storage target. -void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id rValue) -{ - // we only do the complex path here if it's an aggregate - if (! type.isStruct() && ! type.isArray()) { - accessChainStore(type, rValue); - return; - } - - // and, it has to be a case of type aliasing - spv::Id rType = builder.getTypeId(rValue); - spv::Id lValue = builder.accessChainGetLValue(); - spv::Id lType = builder.getContainedTypeId(builder.getTypeId(lValue)); - if (lType == rType) { - accessChainStore(type, rValue); - return; - } - - // Recursively (as needed) copy an aggregate type to a different aggregate type, - // where the two types were the same type in GLSL. This requires member - // by member copy, recursively. - - // SPIR-V 1.4 added an instruction to do help do this. - if (glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_4) { - // However, bool in uniform space is changed to int, so - // OpCopyLogical does not work for that. - // TODO: It would be more robust to do a full recursive verification of the types satisfying SPIR-V rules. - bool rBool = builder.containsType(builder.getTypeId(rValue), spv::OpTypeBool, 0); - bool lBool = builder.containsType(lType, spv::OpTypeBool, 0); - if (lBool == rBool) { - spv::Id logicalCopy = builder.createUnaryOp(spv::OpCopyLogical, lType, rValue); - accessChainStore(type, logicalCopy); - return; - } - } - - // If an array, copy element by element. - if (type.isArray()) { - glslang::TType glslangElementType(type, 0); - spv::Id elementRType = builder.getContainedTypeId(rType); - for (int index = 0; index < type.getOuterArraySize(); ++index) { - // get the source member - spv::Id elementRValue = builder.createCompositeExtract(rValue, elementRType, index); - - // set up the target storage - builder.clearAccessChain(); - builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type), - type.getBufferReferenceAlignment()); - - // store the member - multiTypeStore(glslangElementType, elementRValue); - } - } else { - assert(type.isStruct()); - - // loop over structure members - const glslang::TTypeList& members = *type.getStruct(); - for (int m = 0; m < (int)members.size(); ++m) { - const glslang::TType& glslangMemberType = *members[m].type; - - // get the source member - spv::Id memberRType = builder.getContainedTypeId(rType, m); - spv::Id memberRValue = builder.createCompositeExtract(rValue, memberRType, m); - - // set up the target storage - builder.clearAccessChain(); - builder.setAccessChainLValue(lValue); - builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type), - type.getBufferReferenceAlignment()); - - // store the member - multiTypeStore(glslangMemberType, memberRValue); - } - } -} - -// Decide whether or not this type should be -// decorated with offsets and strides, and if so -// whether std140 or std430 rules should be applied. -glslang::TLayoutPacking TGlslangToSpvTraverser::getExplicitLayout(const glslang::TType& type) const -{ - // has to be a block - if (type.getBasicType() != glslang::EbtBlock) - return glslang::ElpNone; - - // has to be a uniform or buffer block or task in/out blocks - if (type.getQualifier().storage != glslang::EvqUniform && - type.getQualifier().storage != glslang::EvqBuffer && - type.getQualifier().storage != glslang::EvqShared && - !type.getQualifier().isTaskMemory()) - return glslang::ElpNone; - - // return the layout to use - switch (type.getQualifier().layoutPacking) { - case glslang::ElpStd140: - case glslang::ElpStd430: - case glslang::ElpScalar: - return type.getQualifier().layoutPacking; - default: - return glslang::ElpNone; - } -} - -// Given an array type, returns the integer stride required for that array -int TGlslangToSpvTraverser::getArrayStride(const glslang::TType& arrayType, glslang::TLayoutPacking explicitLayout, - glslang::TLayoutMatrix matrixLayout) -{ - int size; - int stride; - glslangIntermediate->getMemberAlignment(arrayType, size, stride, explicitLayout, - matrixLayout == glslang::ElmRowMajor); - - return stride; -} - -// Given a matrix type, or array (of array) of matrixes type, returns the integer stride required for that matrix -// when used as a member of an interface block -int TGlslangToSpvTraverser::getMatrixStride(const glslang::TType& matrixType, glslang::TLayoutPacking explicitLayout, - glslang::TLayoutMatrix matrixLayout) -{ - glslang::TType elementType; - elementType.shallowCopy(matrixType); - elementType.clearArraySizes(); - - int size; - int stride; - glslangIntermediate->getMemberAlignment(elementType, size, stride, explicitLayout, - matrixLayout == glslang::ElmRowMajor); - - return stride; -} - -// Given a member type of a struct, realign the current offset for it, and compute -// the next (not yet aligned) offset for the next member, which will get aligned -// on the next call. -// 'currentOffset' should be passed in already initialized, ready to modify, and reflecting -// the migration of data from nextOffset -> currentOffset. It should be -1 on the first call. -// -1 means a non-forced member offset (no decoration needed). -void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, - int& currentOffset, int& nextOffset, glslang::TLayoutPacking explicitLayout, glslang::TLayoutMatrix matrixLayout) -{ - // this will get a positive value when deemed necessary - nextOffset = -1; - - // override anything in currentOffset with user-set offset - if (memberType.getQualifier().hasOffset()) - currentOffset = memberType.getQualifier().layoutOffset; - - // It could be that current linker usage in glslang updated all the layoutOffset, - // in which case the following code does not matter. But, that's not quite right - // once cross-compilation unit GLSL validation is done, as the original user - // settings are needed in layoutOffset, and then the following will come into play. - - if (explicitLayout == glslang::ElpNone) { - if (! memberType.getQualifier().hasOffset()) - currentOffset = -1; - - return; - } - - // Getting this far means we need explicit offsets - if (currentOffset < 0) - currentOffset = 0; - - // Now, currentOffset is valid (either 0, or from a previous nextOffset), - // but possibly not yet correctly aligned. - - int memberSize; - int dummyStride; - int memberAlignment = glslangIntermediate->getMemberAlignment(memberType, memberSize, dummyStride, explicitLayout, - matrixLayout == glslang::ElmRowMajor); - - // Adjust alignment for HLSL rules - // TODO: make this consistent in early phases of code: - // adjusting this late means inconsistencies with earlier code, which for reflection is an issue - // Until reflection is brought in sync with these adjustments, don't apply to $Global, - // which is the most likely to rely on reflection, and least likely to rely implicit layouts - if (glslangIntermediate->usingHlslOffsets() && - ! memberType.isArray() && memberType.isVector() && structType.getTypeName().compare("$Global") != 0) { - int dummySize; - int componentAlignment = glslangIntermediate->getBaseAlignmentScalar(memberType, dummySize); - if (componentAlignment <= 4) - memberAlignment = componentAlignment; - } - - // Bump up to member alignment - glslang::RoundToPow2(currentOffset, memberAlignment); - - // Bump up to vec4 if there is a bad straddle - if (explicitLayout != glslang::ElpScalar && glslangIntermediate->improperStraddle(memberType, memberSize, - currentOffset)) - glslang::RoundToPow2(currentOffset, 16); - - nextOffset = currentOffset + memberSize; -} - -void TGlslangToSpvTraverser::declareUseOfStructMember(const glslang::TTypeList& members, int glslangMember) -{ - const glslang::TBuiltInVariable glslangBuiltIn = members[glslangMember].type->getQualifier().builtIn; - switch (glslangBuiltIn) - { - case glslang::EbvPointSize: - case glslang::EbvClipDistance: - case glslang::EbvCullDistance: - case glslang::EbvViewportMaskNV: - case glslang::EbvSecondaryPositionNV: - case glslang::EbvSecondaryViewportMaskNV: - case glslang::EbvPositionPerViewNV: - case glslang::EbvViewportMaskPerViewNV: - case glslang::EbvTaskCountNV: - case glslang::EbvPrimitiveCountNV: - case glslang::EbvPrimitiveIndicesNV: - case glslang::EbvClipDistancePerViewNV: - case glslang::EbvCullDistancePerViewNV: - case glslang::EbvLayerPerViewNV: - case glslang::EbvMeshViewCountNV: - case glslang::EbvMeshViewIndicesNV: - // Generate the associated capability. Delegate to TranslateBuiltInDecoration. - // Alternately, we could just call this for any glslang built-in, since the - // capability already guards against duplicates. - TranslateBuiltInDecoration(glslangBuiltIn, false); - break; - default: - // Capabilities were already generated when the struct was declared. - break; - } -} - -bool TGlslangToSpvTraverser::isShaderEntryPoint(const glslang::TIntermAggregate* node) -{ - return node->getName().compare(glslangIntermediate->getEntryPointMangledName().c_str()) == 0; -} - -// Does parameter need a place to keep writes, separate from the original? -// Assumes called after originalParam(), which filters out block/buffer/opaque-based -// qualifiers such that we should have only in/out/inout/constreadonly here. -bool TGlslangToSpvTraverser::writableParam(glslang::TStorageQualifier qualifier) const -{ - assert(qualifier == glslang::EvqIn || - qualifier == glslang::EvqOut || - qualifier == glslang::EvqInOut || - qualifier == glslang::EvqUniform || - qualifier == glslang::EvqConstReadOnly); - return qualifier != glslang::EvqConstReadOnly && - qualifier != glslang::EvqUniform; -} - -// Is parameter pass-by-original? -bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier, const glslang::TType& paramType, - bool implicitThisParam) -{ - if (implicitThisParam) // implicit this - return true; - if (glslangIntermediate->getSource() == glslang::EShSourceHlsl) - return paramType.getBasicType() == glslang::EbtBlock; - return (paramType.containsOpaque() && !glslangIntermediate->getBindlessMode()) || // sampler, etc. - paramType.getQualifier().isSpirvByReference() || // spirv_by_reference - (paramType.getBasicType() == glslang::EbtBlock && qualifier == glslang::EvqBuffer); // SSBO -} - -// Make all the functions, skeletally, without actually visiting their bodies. -void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions) -{ - const auto getParamDecorations = [&](std::vector& decorations, const glslang::TType& type, - bool useVulkanMemoryModel) { - spv::Decoration paramPrecision = TranslatePrecisionDecoration(type); - if (paramPrecision != spv::NoPrecision) - decorations.push_back(paramPrecision); - TranslateMemoryDecoration(type.getQualifier(), decorations, useVulkanMemoryModel); - if (type.isReference()) { - // Original and non-writable params pass the pointer directly and - // use restrict/aliased, others are stored to a pointer in Function - // memory and use RestrictPointer/AliasedPointer. - if (originalParam(type.getQualifier().storage, type, false) || - !writableParam(type.getQualifier().storage)) { - decorations.push_back(type.getQualifier().isRestrict() ? spv::DecorationRestrict : - spv::DecorationAliased); - } else { - decorations.push_back(type.getQualifier().isRestrict() ? spv::DecorationRestrictPointerEXT : - spv::DecorationAliasedPointerEXT); - } - } - }; - - for (int f = 0; f < (int)glslFunctions.size(); ++f) { - glslang::TIntermAggregate* glslFunction = glslFunctions[f]->getAsAggregate(); - if (! glslFunction || glslFunction->getOp() != glslang::EOpFunction) - continue; - if (isShaderEntryPoint(glslFunction)) { - if (glslangIntermediate->getSource() != glslang::EShSourceHlsl) { - builder.setupDebugFunctionEntry(shaderEntry, glslangIntermediate->getEntryPointMangledName().c_str(), - glslFunction->getLoc().line, - std::vector(), // main function has no param - std::vector()); - } - continue; - } - // We're on a user function. Set up the basic interface for the function now, - // so that it's available to call. Translating the body will happen later. - // - // Typically (except for a "const in" parameter), an address will be passed to the - // function. What it is an address of varies: - // - // - "in" parameters not marked as "const" can be written to without modifying the calling - // argument so that write needs to be to a copy, hence the address of a copy works. - // - // - "const in" parameters can just be the r-value, as no writes need occur. - // - // - "out" and "inout" arguments can't be done as pointers to the calling argument, because - // GLSL has copy-in/copy-out semantics. They can be handled though with a pointer to a copy. - - std::vector paramTypes; - std::vector paramNames; - std::vector> paramDecorations; // list of decorations per parameter - glslang::TIntermSequence& parameters = glslFunction->getSequence()[0]->getAsAggregate()->getSequence(); - -#ifdef ENABLE_HLSL - bool implicitThis = (int)parameters.size() > 0 && parameters[0]->getAsSymbolNode()->getName() == - glslangIntermediate->implicitThisName; -#else - bool implicitThis = false; -#endif - - paramDecorations.resize(parameters.size()); - for (int p = 0; p < (int)parameters.size(); ++p) { - const glslang::TType& paramType = parameters[p]->getAsTyped()->getType(); - spv::Id typeId = convertGlslangToSpvType(paramType); - if (originalParam(paramType.getQualifier().storage, paramType, implicitThis && p == 0)) - typeId = builder.makePointer(TranslateStorageClass(paramType), typeId); - else if (writableParam(paramType.getQualifier().storage)) - typeId = builder.makePointer(spv::StorageClassFunction, typeId); - else - rValueParameters.insert(parameters[p]->getAsSymbolNode()->getId()); - getParamDecorations(paramDecorations[p], paramType, glslangIntermediate->usingVulkanMemoryModel()); - paramTypes.push_back(typeId); - } - - for (auto const parameter:parameters) { - paramNames.push_back(parameter->getAsSymbolNode()->getName().c_str()); - } - - spv::Block* functionBlock; - spv::Function* function = builder.makeFunctionEntry( - TranslatePrecisionDecoration(glslFunction->getType()), convertGlslangToSpvType(glslFunction->getType()), - glslFunction->getName().c_str(), convertGlslangLinkageToSpv(glslFunction->getLinkType()), paramTypes, - paramDecorations, &functionBlock); - builder.setupDebugFunctionEntry(function, glslFunction->getName().c_str(), glslFunction->getLoc().line, - paramTypes, paramNames); - if (implicitThis) - function->setImplicitThis(); - - // Track function to emit/call later - functionMap[glslFunction->getName().c_str()] = function; - - // Set the parameter id's - for (int p = 0; p < (int)parameters.size(); ++p) { - symbolValues[parameters[p]->getAsSymbolNode()->getId()] = function->getParamId(p); - // give a name too - builder.addName(function->getParamId(p), parameters[p]->getAsSymbolNode()->getName().c_str()); - - const glslang::TType& paramType = parameters[p]->getAsTyped()->getType(); - if (paramType.contains8BitInt()) - builder.addCapability(spv::CapabilityInt8); - if (paramType.contains16BitInt()) - builder.addCapability(spv::CapabilityInt16); - if (paramType.contains16BitFloat()) - builder.addCapability(spv::CapabilityFloat16); - } - } -} - -// Process all the initializers, while skipping the functions and link objects -void TGlslangToSpvTraverser::makeGlobalInitializers(const glslang::TIntermSequence& initializers) -{ - builder.setBuildPoint(shaderEntry->getLastBlock()); - for (int i = 0; i < (int)initializers.size(); ++i) { - glslang::TIntermAggregate* initializer = initializers[i]->getAsAggregate(); - if (initializer && initializer->getOp() != glslang::EOpFunction && initializer->getOp() != - glslang::EOpLinkerObjects) { - - // We're on a top-level node that's not a function. Treat as an initializer, whose - // code goes into the beginning of the entry point. - initializer->traverse(this); - } - } -} -// Walk over all linker objects to create a map for payload and callable data linker objects -// and their location to be used during codegen for OpTraceKHR and OpExecuteCallableKHR -// This is done here since it is possible that these linker objects are not be referenced in the AST -void TGlslangToSpvTraverser::collectRayTracingLinkerObjects() -{ - glslang::TIntermAggregate* linkerObjects = glslangIntermediate->findLinkerObjects(); - for (auto& objSeq : linkerObjects->getSequence()) { - auto objNode = objSeq->getAsSymbolNode(); - if (objNode != nullptr) { - if (objNode->getQualifier().hasLocation()) { - unsigned int location = objNode->getQualifier().layoutLocation; - auto st = objNode->getQualifier().storage; - int set; - switch (st) - { - case glslang::EvqPayload: - case glslang::EvqPayloadIn: - set = 0; - break; - case glslang::EvqCallableData: - case glslang::EvqCallableDataIn: - set = 1; - break; - - case glslang::EvqHitObjectAttrNV: - set = 2; - break; - - default: - set = -1; - } - if (set != -1) - locationToSymbol[set].insert(std::make_pair(location, objNode)); - } - } - } -} -// Process all the functions, while skipping initializers. -void TGlslangToSpvTraverser::visitFunctions(const glslang::TIntermSequence& glslFunctions) -{ - for (int f = 0; f < (int)glslFunctions.size(); ++f) { - glslang::TIntermAggregate* node = glslFunctions[f]->getAsAggregate(); - if (node && (node->getOp() == glslang::EOpFunction || node->getOp() == glslang::EOpLinkerObjects)) - node->traverse(this); - } -} - -void TGlslangToSpvTraverser::handleFunctionEntry(const glslang::TIntermAggregate* node) -{ - // SPIR-V functions should already be in the functionMap from the prepass - // that called makeFunctions(). - currentFunction = functionMap[node->getName().c_str()]; - spv::Block* functionBlock = currentFunction->getEntryBlock(); - builder.setBuildPoint(functionBlock); - builder.enterFunction(currentFunction); -} - -void TGlslangToSpvTraverser::translateArguments(const glslang::TIntermAggregate& node, std::vector& arguments, - spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) -{ - const glslang::TIntermSequence& glslangArguments = node.getSequence(); - - glslang::TSampler sampler = {}; - bool cubeCompare = false; - bool f16ShadowCompare = false; - if (node.isTexture() || node.isImage()) { - sampler = glslangArguments[0]->getAsTyped()->getType().getSampler(); - cubeCompare = sampler.dim == glslang::EsdCube && sampler.arrayed && sampler.shadow; - f16ShadowCompare = sampler.shadow && - glslangArguments[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16; - } - - for (int i = 0; i < (int)glslangArguments.size(); ++i) { - builder.clearAccessChain(); - glslangArguments[i]->traverse(this); - - // Special case l-value operands - bool lvalue = false; - switch (node.getOp()) { - case glslang::EOpImageAtomicAdd: - case glslang::EOpImageAtomicMin: - case glslang::EOpImageAtomicMax: - case glslang::EOpImageAtomicAnd: - case glslang::EOpImageAtomicOr: - case glslang::EOpImageAtomicXor: - case glslang::EOpImageAtomicExchange: - case glslang::EOpImageAtomicCompSwap: - case glslang::EOpImageAtomicLoad: - case glslang::EOpImageAtomicStore: - if (i == 0) - lvalue = true; - break; - case glslang::EOpSparseImageLoad: - if ((sampler.ms && i == 3) || (! sampler.ms && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTexture: - if (((cubeCompare || f16ShadowCompare) && i == 3) || (! (cubeCompare || f16ShadowCompare) && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureClamp: - if (((cubeCompare || f16ShadowCompare) && i == 4) || (! (cubeCompare || f16ShadowCompare) && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureLod: - case glslang::EOpSparseTextureOffset: - if ((f16ShadowCompare && i == 4) || (! f16ShadowCompare && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureFetch: - if ((sampler.dim != glslang::EsdRect && i == 3) || (sampler.dim == glslang::EsdRect && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureFetchOffset: - if ((sampler.dim != glslang::EsdRect && i == 4) || (sampler.dim == glslang::EsdRect && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureLodOffset: - case glslang::EOpSparseTextureGrad: - case glslang::EOpSparseTextureOffsetClamp: - if ((f16ShadowCompare && i == 5) || (! f16ShadowCompare && i == 4)) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffset: - case glslang::EOpSparseTextureGradClamp: - if ((f16ShadowCompare && i == 6) || (! f16ShadowCompare && i == 5)) - lvalue = true; - break; - case glslang::EOpSparseTextureGradOffsetClamp: - if ((f16ShadowCompare && i == 7) || (! f16ShadowCompare && i == 6)) - lvalue = true; - break; - case glslang::EOpSparseTextureGather: - if ((sampler.shadow && i == 3) || (! sampler.shadow && i == 2)) - lvalue = true; - break; - case glslang::EOpSparseTextureGatherOffset: - case glslang::EOpSparseTextureGatherOffsets: - if ((sampler.shadow && i == 4) || (! sampler.shadow && i == 3)) - lvalue = true; - break; - case glslang::EOpSparseTextureGatherLod: - if (i == 3) - lvalue = true; - break; - case glslang::EOpSparseTextureGatherLodOffset: - case glslang::EOpSparseTextureGatherLodOffsets: - if (i == 4) - lvalue = true; - break; - case glslang::EOpSparseImageLoadLod: - if (i == 3) - lvalue = true; - break; - case glslang::EOpImageSampleFootprintNV: - if (i == 4) - lvalue = true; - break; - case glslang::EOpImageSampleFootprintClampNV: - case glslang::EOpImageSampleFootprintLodNV: - if (i == 5) - lvalue = true; - break; - case glslang::EOpImageSampleFootprintGradNV: - if (i == 6) - lvalue = true; - break; - case glslang::EOpImageSampleFootprintGradClampNV: - if (i == 7) - lvalue = true; - break; - case glslang::EOpRayQueryGetIntersectionTriangleVertexPositionsEXT: - if (i == 2) - lvalue = true; - break; - default: - break; - } - - if (lvalue) { - spv::Id lvalue_id = builder.accessChainGetLValue(); - arguments.push_back(lvalue_id); - lvalueCoherentFlags = builder.getAccessChain().coherentFlags; - builder.addDecoration(lvalue_id, TranslateNonUniformDecoration(lvalueCoherentFlags)); - lvalueCoherentFlags |= TranslateCoherent(glslangArguments[i]->getAsTyped()->getType()); - } else - arguments.push_back(accessChainLoad(glslangArguments[i]->getAsTyped()->getType())); - } -} - -void TGlslangToSpvTraverser::translateArguments(glslang::TIntermUnary& node, std::vector& arguments) -{ - builder.clearAccessChain(); - node.getOperand()->traverse(this); - arguments.push_back(accessChainLoad(node.getOperand()->getType())); -} - -spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermOperator* node) -{ - if (! node->isImage() && ! node->isTexture()) - return spv::NoResult; - - builder.setLine(node->getLoc().line, node->getLoc().getFilename()); - - // Process a GLSL texturing op (will be SPV image) - - const glslang::TType &imageType = node->getAsAggregate() - ? node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType() - : node->getAsUnaryNode()->getOperand()->getAsTyped()->getType(); - const glslang::TSampler sampler = imageType.getSampler(); - bool f16ShadowCompare = (sampler.shadow && node->getAsAggregate()) - ? node->getAsAggregate()->getSequence()[1]->getAsTyped()->getType().getBasicType() == glslang::EbtFloat16 - : false; - - const auto signExtensionMask = [&]() { - if (builder.getSpvVersion() >= spv::Spv_1_4) { - if (sampler.type == glslang::EbtUint) - return spv::ImageOperandsZeroExtendMask; - else if (sampler.type == glslang::EbtInt) - return spv::ImageOperandsSignExtendMask; - } - return spv::ImageOperandsMaskNone; - }; - - spv::Builder::AccessChain::CoherentFlags lvalueCoherentFlags; - - std::vector arguments; - if (node->getAsAggregate()) - translateArguments(*node->getAsAggregate(), arguments, lvalueCoherentFlags); - else - translateArguments(*node->getAsUnaryNode(), arguments); - spv::Decoration precision = TranslatePrecisionDecoration(node->getType()); - - spv::Builder::TextureParameters params = { }; - params.sampler = arguments[0]; - - glslang::TCrackedTextureOp cracked; - node->crackTexture(sampler, cracked); - - const bool isUnsignedResult = node->getType().getBasicType() == glslang::EbtUint; - - if (builder.isSampledImage(params.sampler) && - ((cracked.query && node->getOp() != glslang::EOpTextureQueryLod) || cracked.fragMask || cracked.fetch)) { - params.sampler = builder.createUnaryOp(spv::OpImage, builder.getImageType(params.sampler), params.sampler); - if (imageType.getQualifier().isNonUniform()) { - builder.addDecoration(params.sampler, spv::DecorationNonUniformEXT); - } - } - // Check for queries - if (cracked.query) { - switch (node->getOp()) { - case glslang::EOpImageQuerySize: - case glslang::EOpTextureQuerySize: - if (arguments.size() > 1) { - params.lod = arguments[1]; - return builder.createTextureQueryCall(spv::OpImageQuerySizeLod, params, isUnsignedResult); - } else - return builder.createTextureQueryCall(spv::OpImageQuerySize, params, isUnsignedResult); - case glslang::EOpImageQuerySamples: - case glslang::EOpTextureQuerySamples: - return builder.createTextureQueryCall(spv::OpImageQuerySamples, params, isUnsignedResult); - case glslang::EOpTextureQueryLod: - params.coords = arguments[1]; - return builder.createTextureQueryCall(spv::OpImageQueryLod, params, isUnsignedResult); - case glslang::EOpTextureQueryLevels: - return builder.createTextureQueryCall(spv::OpImageQueryLevels, params, isUnsignedResult); - case glslang::EOpSparseTexelsResident: - return builder.createUnaryOp(spv::OpImageSparseTexelsResident, builder.makeBoolType(), arguments[0]); - default: - assert(0); - break; - } - } - - int components = node->getType().getVectorSize(); - - if (node->getOp() == glslang::EOpImageLoad || - node->getOp() == glslang::EOpImageLoadLod || - node->getOp() == glslang::EOpTextureFetch || - node->getOp() == glslang::EOpTextureFetchOffset) { - // These must produce 4 components, per SPIR-V spec. We'll add a conversion constructor if needed. - // This will only happen through the HLSL path for operator[], so we do not have to handle e.g. - // the EOpTexture/Proj/Lod/etc family. It would be harmless to do so, but would need more logic - // here around e.g. which ones return scalars or other types. - components = 4; - } - - glslang::TType returnType(node->getType().getBasicType(), glslang::EvqTemporary, components); - - auto resultType = [&returnType,this]{ return convertGlslangToSpvType(returnType); }; - - // Check for image functions other than queries - if (node->isImage()) { - std::vector operands; - auto opIt = arguments.begin(); - spv::IdImmediate image = { true, *(opIt++) }; - operands.push_back(image); - - // Handle subpass operations - // TODO: GLSL should change to have the "MS" only on the type rather than the - // built-in function. - if (cracked.subpass) { - // add on the (0,0) coordinate - spv::Id zero = builder.makeIntConstant(0); - std::vector comps; - comps.push_back(zero); - comps.push_back(zero); - spv::IdImmediate coord = { true, - builder.makeCompositeConstant(builder.makeVectorType(builder.makeIntType(32), 2), comps) }; - operands.push_back(coord); - spv::IdImmediate imageOperands = { false, spv::ImageOperandsMaskNone }; - imageOperands.word = imageOperands.word | signExtensionMask(); - if (sampler.isMultiSample()) { - imageOperands.word = imageOperands.word | spv::ImageOperandsSampleMask; - } - if (imageOperands.word != spv::ImageOperandsMaskNone) { - operands.push_back(imageOperands); - if (sampler.isMultiSample()) { - spv::IdImmediate imageOperand = { true, *(opIt++) }; - operands.push_back(imageOperand); - } - } - spv::Id result = builder.createOp(spv::OpImageRead, resultType(), operands); - builder.setPrecision(result, precision); - return result; - } - - if (cracked.attachmentEXT) { - if (opIt != arguments.end()) { - spv::IdImmediate sample = { true, *opIt }; - operands.push_back(sample); - } - spv::Id result = builder.createOp(spv::OpColorAttachmentReadEXT, resultType(), operands); - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - builder.setPrecision(result, precision); - return result; - } - - spv::IdImmediate coord = { true, *(opIt++) }; - operands.push_back(coord); - if (node->getOp() == glslang::EOpImageLoad || node->getOp() == glslang::EOpImageLoadLod) { - spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; - if (sampler.isMultiSample()) { - mask = mask | spv::ImageOperandsSampleMask; - } - if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - mask = mask | spv::ImageOperandsLodMask; - } - mask = mask | TranslateImageOperands(TranslateCoherent(imageType)); - mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask); - mask = mask | signExtensionMask(); - if (mask != spv::ImageOperandsMaskNone) { - spv::IdImmediate imageOperands = { false, (unsigned int)mask }; - operands.push_back(imageOperands); - } - if (mask & spv::ImageOperandsSampleMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsLodMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) { - spv::IdImmediate imageOperand = { true, - builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) }; - operands.push_back(imageOperand); - } - - if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat); - - std::vector result(1, builder.createOp(spv::OpImageRead, resultType(), operands)); - builder.setPrecision(result[0], precision); - - // If needed, add a conversion constructor to the proper size. - if (components != node->getType().getVectorSize()) - result[0] = builder.createConstructor(precision, result, convertGlslangToSpvType(node->getType())); - - return result[0]; - } else if (node->getOp() == glslang::EOpImageStore || node->getOp() == glslang::EOpImageStoreLod) { - - // Push the texel value before the operands - if (sampler.isMultiSample() || cracked.lod) { - spv::IdImmediate texel = { true, *(opIt + 1) }; - operands.push_back(texel); - } else { - spv::IdImmediate texel = { true, *opIt }; - operands.push_back(texel); - } - - spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; - if (sampler.isMultiSample()) { - mask = mask | spv::ImageOperandsSampleMask; - } - if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - mask = mask | spv::ImageOperandsLodMask; - } - mask = mask | TranslateImageOperands(TranslateCoherent(imageType)); - mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelVisibleKHRMask); - mask = mask | signExtensionMask(); - if (mask != spv::ImageOperandsMaskNone) { - spv::IdImmediate imageOperands = { false, (unsigned int)mask }; - operands.push_back(imageOperands); - } - if (mask & spv::ImageOperandsSampleMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsLodMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsMakeTexelAvailableKHRMask) { - spv::IdImmediate imageOperand = { true, - builder.makeUintConstant(TranslateMemoryScope(TranslateCoherent(imageType))) }; - operands.push_back(imageOperand); - } - - builder.createNoResultOp(spv::OpImageWrite, operands); - if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageWriteWithoutFormat); - return spv::NoResult; - } else if (node->getOp() == glslang::EOpSparseImageLoad || - node->getOp() == glslang::EOpSparseImageLoadLod) { - builder.addCapability(spv::CapabilitySparseResidency); - if (builder.getImageTypeFormat(builder.getImageType(operands.front().word)) == spv::ImageFormatUnknown) - builder.addCapability(spv::CapabilityStorageImageReadWithoutFormat); - - spv::ImageOperandsMask mask = spv::ImageOperandsMaskNone; - if (sampler.isMultiSample()) { - mask = mask | spv::ImageOperandsSampleMask; - } - if (cracked.lod) { - builder.addExtension(spv::E_SPV_AMD_shader_image_load_store_lod); - builder.addCapability(spv::CapabilityImageReadWriteLodAMD); - - mask = mask | spv::ImageOperandsLodMask; - } - mask = mask | TranslateImageOperands(TranslateCoherent(imageType)); - mask = (spv::ImageOperandsMask)(mask & ~spv::ImageOperandsMakeTexelAvailableKHRMask); - mask = mask | signExtensionMask(); - if (mask != spv::ImageOperandsMaskNone) { - spv::IdImmediate imageOperands = { false, (unsigned int)mask }; - operands.push_back(imageOperands); - } - if (mask & spv::ImageOperandsSampleMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsLodMask) { - spv::IdImmediate imageOperand = { true, *opIt++ }; - operands.push_back(imageOperand); - } - if (mask & spv::ImageOperandsMakeTexelVisibleKHRMask) { - spv::IdImmediate imageOperand = { true, builder.makeUintConstant(TranslateMemoryScope( - TranslateCoherent(imageType))) }; - operands.push_back(imageOperand); - } - - // Create the return type that was a special structure - spv::Id texelOut = *opIt; - spv::Id typeId0 = resultType(); - spv::Id typeId1 = builder.getDerefTypeId(texelOut); - spv::Id resultTypeId = builder.makeStructResultType(typeId0, typeId1); - - spv::Id resultId = builder.createOp(spv::OpImageSparseRead, resultTypeId, operands); - - // Decode the return type - builder.createStore(builder.createCompositeExtract(resultId, typeId1, 1), texelOut); - return builder.createCompositeExtract(resultId, typeId0, 0); - } else { - // Process image atomic operations - - // GLSL "IMAGE_PARAMS" will involve in constructing an image texel pointer and this pointer, - // as the first source operand, is required by SPIR-V atomic operations. - // For non-MS, the sample value should be 0 - spv::IdImmediate sample = { true, sampler.isMultiSample() ? *(opIt++) : builder.makeUintConstant(0) }; - operands.push_back(sample); - - spv::Id resultTypeId; - glslang::TBasicType typeProxy = node->getBasicType(); - // imageAtomicStore has a void return type so base the pointer type on - // the type of the value operand. - if (node->getOp() == glslang::EOpImageAtomicStore) { - resultTypeId = builder.makePointer(spv::StorageClassImage, builder.getTypeId(*opIt)); - typeProxy = node->getAsAggregate()->getSequence()[0]->getAsTyped()->getType().getSampler().type; - } else { - resultTypeId = builder.makePointer(spv::StorageClassImage, resultType()); - } - spv::Id pointer = builder.createOp(spv::OpImageTexelPointer, resultTypeId, operands); - if (imageType.getQualifier().nonUniform) { - builder.addDecoration(pointer, spv::DecorationNonUniformEXT); - } - - std::vector operands; - operands.push_back(pointer); - for (; opIt != arguments.end(); ++opIt) - operands.push_back(*opIt); - - return createAtomicOperation(node->getOp(), precision, resultType(), operands, typeProxy, - lvalueCoherentFlags); - } - } - - // Check for fragment mask functions other than queries - if (cracked.fragMask) { - assert(sampler.ms); - - auto opIt = arguments.begin(); - std::vector operands; - - operands.push_back(params.sampler); - ++opIt; - - if (sampler.isSubpass()) { - // add on the (0,0) coordinate - spv::Id zero = builder.makeIntConstant(0); - std::vector comps; - comps.push_back(zero); - comps.push_back(zero); - operands.push_back(builder.makeCompositeConstant( - builder.makeVectorType(builder.makeIntType(32), 2), comps)); - } - - for (; opIt != arguments.end(); ++opIt) - operands.push_back(*opIt); - - spv::Op fragMaskOp = spv::OpNop; - if (node->getOp() == glslang::EOpFragmentMaskFetch) - fragMaskOp = spv::OpFragmentMaskFetchAMD; - else if (node->getOp() == glslang::EOpFragmentFetch) - fragMaskOp = spv::OpFragmentFetchAMD; - - builder.addExtension(spv::E_SPV_AMD_shader_fragment_mask); - builder.addCapability(spv::CapabilityFragmentMaskAMD); - return builder.createOp(fragMaskOp, resultType(), operands); - } - - // Check for texture functions other than queries - bool sparse = node->isSparseTexture(); - bool imageFootprint = node->isImageFootprint(); - bool cubeCompare = sampler.dim == glslang::EsdCube && sampler.isArrayed() && sampler.isShadow(); - - // check for bias argument - bool bias = false; - if (! cracked.lod && ! cracked.grad && ! cracked.fetch && ! cubeCompare) { - int nonBiasArgCount = 2; - if (cracked.gather) - ++nonBiasArgCount; // comp argument should be present when bias argument is present - - if (f16ShadowCompare) - ++nonBiasArgCount; - if (cracked.offset) - ++nonBiasArgCount; - else if (cracked.offsets) - ++nonBiasArgCount; - if (cracked.grad) - nonBiasArgCount += 2; - if (cracked.lodClamp) - ++nonBiasArgCount; - if (sparse) - ++nonBiasArgCount; - if (imageFootprint) - //Following three extra arguments - // int granularity, bool coarse, out gl_TextureFootprint2DNV footprint - nonBiasArgCount += 3; - if ((int)arguments.size() > nonBiasArgCount) - bias = true; - } - - if (cracked.gather) { - const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions(); - if (bias || cracked.lod || - sourceExtensions.find(glslang::E_GL_AMD_texture_gather_bias_lod) != sourceExtensions.end()) { - builder.addExtension(spv::E_SPV_AMD_texture_gather_bias_lod); - builder.addCapability(spv::CapabilityImageGatherBiasLodAMD); - } - } - - // set the rest of the arguments - - params.coords = arguments[1]; - int extraArgs = 0; - bool noImplicitLod = false; - - // sort out where Dref is coming from - if (cubeCompare || f16ShadowCompare) { - params.Dref = arguments[2]; - ++extraArgs; - } else if (sampler.shadow && cracked.gather) { - params.Dref = arguments[2]; - ++extraArgs; - } else if (sampler.shadow) { - std::vector indexes; - int dRefComp; - if (cracked.proj) - dRefComp = 2; // "The resulting 3rd component of P in the shadow forms is used as Dref" - else - dRefComp = builder.getNumComponents(params.coords) - 1; - indexes.push_back(dRefComp); - params.Dref = builder.createCompositeExtract(params.coords, - builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes); - } - - // lod - if (cracked.lod) { - params.lod = arguments[2 + extraArgs]; - ++extraArgs; - } else if (glslangIntermediate->getStage() != EShLangFragment && - !(glslangIntermediate->getStage() == EShLangCompute && - glslangIntermediate->hasLayoutDerivativeModeNone())) { - // we need to invent the default lod for an explicit lod instruction for a non-fragment stage - noImplicitLod = true; - } - - // multisample - if (sampler.isMultiSample()) { - params.sample = arguments[2 + extraArgs]; // For MS, "sample" should be specified - ++extraArgs; - } - - // gradient - if (cracked.grad) { - params.gradX = arguments[2 + extraArgs]; - params.gradY = arguments[3 + extraArgs]; - extraArgs += 2; - } - - // offset and offsets - if (cracked.offset) { - params.offset = arguments[2 + extraArgs]; - ++extraArgs; - } else if (cracked.offsets) { - params.offsets = arguments[2 + extraArgs]; - ++extraArgs; - } - - // lod clamp - if (cracked.lodClamp) { - params.lodClamp = arguments[2 + extraArgs]; - ++extraArgs; - } - // sparse - if (sparse) { - params.texelOut = arguments[2 + extraArgs]; - ++extraArgs; - } - // gather component - if (cracked.gather && ! sampler.shadow) { - // default component is 0, if missing, otherwise an argument - if (2 + extraArgs < (int)arguments.size()) { - params.component = arguments[2 + extraArgs]; - ++extraArgs; - } else - params.component = builder.makeIntConstant(0); - } - spv::Id resultStruct = spv::NoResult; - if (imageFootprint) { - //Following three extra arguments - // int granularity, bool coarse, out gl_TextureFootprint2DNV footprint - params.granularity = arguments[2 + extraArgs]; - params.coarse = arguments[3 + extraArgs]; - resultStruct = arguments[4 + extraArgs]; - extraArgs += 3; - } - - // bias - if (bias) { - params.bias = arguments[2 + extraArgs]; - ++extraArgs; - } - - if (imageFootprint) { - builder.addExtension(spv::E_SPV_NV_shader_image_footprint); - builder.addCapability(spv::CapabilityImageFootprintNV); - - - //resultStructType(OpenGL type) contains 5 elements: - //struct gl_TextureFootprint2DNV { - // uvec2 anchor; - // uvec2 offset; - // uvec2 mask; - // uint lod; - // uint granularity; - //}; - //or - //struct gl_TextureFootprint3DNV { - // uvec3 anchor; - // uvec3 offset; - // uvec2 mask; - // uint lod; - // uint granularity; - //}; - spv::Id resultStructType = builder.getContainedTypeId(builder.getTypeId(resultStruct)); - assert(builder.isStructType(resultStructType)); - - //resType (SPIR-V type) contains 6 elements: - //Member 0 must be a Boolean type scalar(LOD), - //Member 1 must be a vector of integer type, whose Signedness operand is 0(anchor), - //Member 2 must be a vector of integer type, whose Signedness operand is 0(offset), - //Member 3 must be a vector of integer type, whose Signedness operand is 0(mask), - //Member 4 must be a scalar of integer type, whose Signedness operand is 0(lod), - //Member 5 must be a scalar of integer type, whose Signedness operand is 0(granularity). - std::vector members; - members.push_back(resultType()); - for (int i = 0; i < 5; i++) { - members.push_back(builder.getContainedTypeId(resultStructType, i)); - } - spv::Id resType = builder.makeStructType(members, "ResType"); - - //call ImageFootprintNV - spv::Id res = builder.createTextureCall(precision, resType, sparse, cracked.fetch, cracked.proj, - cracked.gather, noImplicitLod, params, signExtensionMask()); - - //copy resType (SPIR-V type) to resultStructType(OpenGL type) - for (int i = 0; i < 5; i++) { - builder.clearAccessChain(); - builder.setAccessChainLValue(resultStruct); - - //Accessing to a struct we created, no coherent flag is set - spv::Builder::AccessChain::CoherentFlags flags; - flags.clear(); - - builder.accessChainPush(builder.makeIntConstant(i), flags, 0); - builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1), - i+1), TranslateNonUniformDecoration(imageType.getQualifier())); - } - return builder.createCompositeExtract(res, resultType(), 0); - } - - // projective component (might not to move) - // GLSL: "The texture coordinates consumed from P, not including the last component of P, - // are divided by the last component of P." - // SPIR-V: "... (u [, v] [, w], q)... It may be a vector larger than needed, but all - // unused components will appear after all used components." - if (cracked.proj) { - int projSourceComp = builder.getNumComponents(params.coords) - 1; - int projTargetComp; - switch (sampler.dim) { - case glslang::Esd1D: projTargetComp = 1; break; - case glslang::Esd2D: projTargetComp = 2; break; - case glslang::EsdRect: projTargetComp = 2; break; - default: projTargetComp = projSourceComp; break; - } - // copy the projective coordinate if we have to - if (projTargetComp != projSourceComp) { - spv::Id projComp = builder.createCompositeExtract(params.coords, - builder.getScalarTypeId(builder.getTypeId(params.coords)), projSourceComp); - params.coords = builder.createCompositeInsert(projComp, params.coords, - builder.getTypeId(params.coords), projTargetComp); - } - } - - // nonprivate - if (imageType.getQualifier().nonprivate) { - params.nonprivate = true; - } - - // volatile - if (imageType.getQualifier().volatil) { - params.volatil = true; - } - - std::vector result( 1, - builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather, - noImplicitLod, params, signExtensionMask()) - ); - - if (components != node->getType().getVectorSize()) - result[0] = builder.createConstructor(precision, result, convertGlslangToSpvType(node->getType())); - - return result[0]; -} - -spv::Id TGlslangToSpvTraverser::handleUserFunctionCall(const glslang::TIntermAggregate* node) -{ - // Grab the function's pointer from the previously created function - spv::Function* function = functionMap[node->getName().c_str()]; - if (! function) - return 0; - - const glslang::TIntermSequence& glslangArgs = node->getSequence(); - const glslang::TQualifierList& qualifiers = node->getQualifierList(); - - // See comments in makeFunctions() for details about the semantics for parameter passing. - // - // These imply we need a four step process: - // 1. Evaluate the arguments - // 2. Allocate and make copies of in, out, and inout arguments - // 3. Make the call - // 4. Copy back the results - - // 1. Evaluate the arguments and their types - std::vector lValues; - std::vector rValues; - std::vector argTypes; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - argTypes.push_back(&glslangArgs[a]->getAsTyped()->getType()); - // build l-value - builder.clearAccessChain(); - glslangArgs[a]->traverse(this); - // keep outputs and pass-by-originals as l-values, evaluate others as r-values - if (originalParam(qualifiers[a], *argTypes[a], function->hasImplicitThis() && a == 0) || - writableParam(qualifiers[a])) { - // save l-value - lValues.push_back(builder.getAccessChain()); - } else { - // process r-value - rValues.push_back(accessChainLoad(*argTypes.back())); - } - } - - // 2. Allocate space for anything needing a copy, and if it's "in" or "inout" - // copy the original into that space. - // - // Also, build up the list of actual arguments to pass in for the call - int lValueCount = 0; - int rValueCount = 0; - std::vector spvArgs; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - spv::Id arg; - if (originalParam(qualifiers[a], *argTypes[a], function->hasImplicitThis() && a == 0)) { - builder.setAccessChain(lValues[lValueCount]); - arg = builder.accessChainGetLValue(); - ++lValueCount; - } else if (writableParam(qualifiers[a])) { - // need space to hold the copy - arg = builder.createVariable(function->getParamPrecision(a), spv::StorageClassFunction, - builder.getContainedTypeId(function->getParamType(a)), "param"); - if (qualifiers[a] == glslang::EvqIn || qualifiers[a] == glslang::EvqInOut) { - // need to copy the input into output space - builder.setAccessChain(lValues[lValueCount]); - spv::Id copy = accessChainLoad(*argTypes[a]); - builder.clearAccessChain(); - builder.setAccessChainLValue(arg); - multiTypeStore(*argTypes[a], copy); - } - ++lValueCount; - } else { - // process r-value, which involves a copy for a type mismatch - if (function->getParamType(a) != builder.getTypeId(rValues[rValueCount]) || - TranslatePrecisionDecoration(*argTypes[a]) != function->getParamPrecision(a)) - { - spv::Id argCopy = builder.createVariable(function->getParamPrecision(a), spv::StorageClassFunction, function->getParamType(a), "arg"); - builder.clearAccessChain(); - builder.setAccessChainLValue(argCopy); - multiTypeStore(*argTypes[a], rValues[rValueCount]); - arg = builder.createLoad(argCopy, function->getParamPrecision(a)); - } else - arg = rValues[rValueCount]; - ++rValueCount; - } - spvArgs.push_back(arg); - } - - // 3. Make the call. - spv::Id result = builder.createFunctionCall(function, spvArgs); - builder.setPrecision(result, TranslatePrecisionDecoration(node->getType())); - builder.addDecoration(result, TranslateNonUniformDecoration(node->getType().getQualifier())); - - // 4. Copy back out an "out" arguments. - lValueCount = 0; - for (int a = 0; a < (int)glslangArgs.size(); ++a) { - if (originalParam(qualifiers[a], *argTypes[a], function->hasImplicitThis() && a == 0)) - ++lValueCount; - else if (writableParam(qualifiers[a])) { - if (qualifiers[a] == glslang::EvqOut || qualifiers[a] == glslang::EvqInOut) { - spv::Id copy = builder.createLoad(spvArgs[a], spv::NoPrecision); - builder.addDecoration(copy, TranslateNonUniformDecoration(argTypes[a]->getQualifier())); - builder.setAccessChain(lValues[lValueCount]); - multiTypeStore(*argTypes[a], copy); - } - ++lValueCount; - } - } - - return result; -} - -// Translate AST operation to SPV operation, already having SPV-based operands/types. -spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, OpDecorations& decorations, - spv::Id typeId, spv::Id left, spv::Id right, - glslang::TBasicType typeProxy, bool reduceComparison) -{ - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - bool isBool = typeProxy == glslang::EbtBool; - - spv::Op binOp = spv::OpNop; - bool needMatchingVectors = true; // for non-matrix ops, would a scalar need to smear to match a vector? - bool comparison = false; - - switch (op) { - case glslang::EOpAdd: - case glslang::EOpAddAssign: - if (isFloat) - binOp = spv::OpFAdd; - else - binOp = spv::OpIAdd; - break; - case glslang::EOpSub: - case glslang::EOpSubAssign: - if (isFloat) - binOp = spv::OpFSub; - else - binOp = spv::OpISub; - break; - case glslang::EOpMul: - case glslang::EOpMulAssign: - if (isFloat) - binOp = spv::OpFMul; - else - binOp = spv::OpIMul; - break; - case glslang::EOpVectorTimesScalar: - case glslang::EOpVectorTimesScalarAssign: - if (isFloat && (builder.isVector(left) || builder.isVector(right))) { - if (builder.isVector(right)) - std::swap(left, right); - assert(builder.isScalar(right)); - needMatchingVectors = false; - binOp = spv::OpVectorTimesScalar; - } else if (isFloat) - binOp = spv::OpFMul; - else - binOp = spv::OpIMul; - break; - case glslang::EOpVectorTimesMatrix: - case glslang::EOpVectorTimesMatrixAssign: - binOp = spv::OpVectorTimesMatrix; - break; - case glslang::EOpMatrixTimesVector: - binOp = spv::OpMatrixTimesVector; - break; - case glslang::EOpMatrixTimesScalar: - case glslang::EOpMatrixTimesScalarAssign: - binOp = spv::OpMatrixTimesScalar; - break; - case glslang::EOpMatrixTimesMatrix: - case glslang::EOpMatrixTimesMatrixAssign: - binOp = spv::OpMatrixTimesMatrix; - break; - case glslang::EOpOuterProduct: - binOp = spv::OpOuterProduct; - needMatchingVectors = false; - break; - - case glslang::EOpDiv: - case glslang::EOpDivAssign: - if (isFloat) - binOp = spv::OpFDiv; - else if (isUnsigned) - binOp = spv::OpUDiv; - else - binOp = spv::OpSDiv; - break; - case glslang::EOpMod: - case glslang::EOpModAssign: - if (isFloat) - binOp = spv::OpFMod; - else if (isUnsigned) - binOp = spv::OpUMod; - else - binOp = spv::OpSMod; - break; - case glslang::EOpRightShift: - case glslang::EOpRightShiftAssign: - if (isUnsigned) - binOp = spv::OpShiftRightLogical; - else - binOp = spv::OpShiftRightArithmetic; - break; - case glslang::EOpLeftShift: - case glslang::EOpLeftShiftAssign: - binOp = spv::OpShiftLeftLogical; - break; - case glslang::EOpAnd: - case glslang::EOpAndAssign: - binOp = spv::OpBitwiseAnd; - break; - case glslang::EOpLogicalAnd: - needMatchingVectors = false; - binOp = spv::OpLogicalAnd; - break; - case glslang::EOpInclusiveOr: - case glslang::EOpInclusiveOrAssign: - binOp = spv::OpBitwiseOr; - break; - case glslang::EOpLogicalOr: - needMatchingVectors = false; - binOp = spv::OpLogicalOr; - break; - case glslang::EOpExclusiveOr: - case glslang::EOpExclusiveOrAssign: - binOp = spv::OpBitwiseXor; - break; - case glslang::EOpLogicalXor: - needMatchingVectors = false; - binOp = spv::OpLogicalNotEqual; - break; - - case glslang::EOpAbsDifference: - binOp = isUnsigned ? spv::OpAbsUSubINTEL : spv::OpAbsISubINTEL; - break; - - case glslang::EOpAddSaturate: - binOp = isUnsigned ? spv::OpUAddSatINTEL : spv::OpIAddSatINTEL; - break; - - case glslang::EOpSubSaturate: - binOp = isUnsigned ? spv::OpUSubSatINTEL : spv::OpISubSatINTEL; - break; - - case glslang::EOpAverage: - binOp = isUnsigned ? spv::OpUAverageINTEL : spv::OpIAverageINTEL; - break; - - case glslang::EOpAverageRounded: - binOp = isUnsigned ? spv::OpUAverageRoundedINTEL : spv::OpIAverageRoundedINTEL; - break; - - case glslang::EOpMul32x16: - binOp = isUnsigned ? spv::OpUMul32x16INTEL : spv::OpIMul32x16INTEL; - break; - - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpEqual: - case glslang::EOpNotEqual: - case glslang::EOpVectorEqual: - case glslang::EOpVectorNotEqual: - comparison = true; - break; - default: - break; - } - - // handle mapped binary operations (should be non-comparison) - if (binOp != spv::OpNop) { - assert(comparison == false); - if (builder.isMatrix(left) || builder.isMatrix(right) || - builder.isCooperativeMatrix(left) || builder.isCooperativeMatrix(right)) - return createBinaryMatrixOperation(binOp, decorations, typeId, left, right); - - // No matrix involved; make both operands be the same number of components, if needed - if (needMatchingVectors) - builder.promoteScalar(decorations.precision, left, right); - - spv::Id result = builder.createBinOp(binOp, typeId, left, right); - decorations.addNoContraction(builder, result); - decorations.addNonUniform(builder, result); - return builder.setPrecision(result, decorations.precision); - } - - if (! comparison) - return 0; - - // Handle comparison instructions - - if (reduceComparison && (op == glslang::EOpEqual || op == glslang::EOpNotEqual) - && (builder.isVector(left) || builder.isMatrix(left) || builder.isAggregate(left))) { - spv::Id result = builder.createCompositeCompare(decorations.precision, left, right, op == glslang::EOpEqual); - decorations.addNonUniform(builder, result); - return result; - } - - switch (op) { - case glslang::EOpLessThan: - if (isFloat) - binOp = spv::OpFOrdLessThan; - else if (isUnsigned) - binOp = spv::OpULessThan; - else - binOp = spv::OpSLessThan; - break; - case glslang::EOpGreaterThan: - if (isFloat) - binOp = spv::OpFOrdGreaterThan; - else if (isUnsigned) - binOp = spv::OpUGreaterThan; - else - binOp = spv::OpSGreaterThan; - break; - case glslang::EOpLessThanEqual: - if (isFloat) - binOp = spv::OpFOrdLessThanEqual; - else if (isUnsigned) - binOp = spv::OpULessThanEqual; - else - binOp = spv::OpSLessThanEqual; - break; - case glslang::EOpGreaterThanEqual: - if (isFloat) - binOp = spv::OpFOrdGreaterThanEqual; - else if (isUnsigned) - binOp = spv::OpUGreaterThanEqual; - else - binOp = spv::OpSGreaterThanEqual; - break; - case glslang::EOpEqual: - case glslang::EOpVectorEqual: - if (isFloat) - binOp = spv::OpFOrdEqual; - else if (isBool) - binOp = spv::OpLogicalEqual; - else - binOp = spv::OpIEqual; - break; - case glslang::EOpNotEqual: - case glslang::EOpVectorNotEqual: - if (isFloat) - binOp = spv::OpFUnordNotEqual; - else if (isBool) - binOp = spv::OpLogicalNotEqual; - else - binOp = spv::OpINotEqual; - break; - default: - break; - } - - if (binOp != spv::OpNop) { - spv::Id result = builder.createBinOp(binOp, typeId, left, right); - decorations.addNoContraction(builder, result); - decorations.addNonUniform(builder, result); - return builder.setPrecision(result, decorations.precision); - } - - return 0; -} - -// -// Translate AST matrix operation to SPV operation, already having SPV-based operands/types. -// These can be any of: -// -// matrix * scalar -// scalar * matrix -// matrix * matrix linear algebraic -// matrix * vector -// vector * matrix -// matrix * matrix componentwise -// matrix op matrix op in {+, -, /} -// matrix op scalar op in {+, -, /} -// scalar op matrix op in {+, -, /} -// -spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, OpDecorations& decorations, spv::Id typeId, - spv::Id left, spv::Id right) -{ - bool firstClass = true; - - // First, handle first-class matrix operations (* and matrix/scalar) - switch (op) { - case spv::OpFDiv: - if (builder.isMatrix(left) && builder.isScalar(right)) { - // turn matrix / scalar into a multiply... - spv::Id resultType = builder.getTypeId(right); - right = builder.createBinOp(spv::OpFDiv, resultType, builder.makeFpConstant(resultType, 1.0), right); - op = spv::OpMatrixTimesScalar; - } else - firstClass = false; - break; - case spv::OpMatrixTimesScalar: - if (builder.isMatrix(right) || builder.isCooperativeMatrix(right)) - std::swap(left, right); - assert(builder.isScalar(right)); - break; - case spv::OpVectorTimesMatrix: - assert(builder.isVector(left)); - assert(builder.isMatrix(right)); - break; - case spv::OpMatrixTimesVector: - assert(builder.isMatrix(left)); - assert(builder.isVector(right)); - break; - case spv::OpMatrixTimesMatrix: - assert(builder.isMatrix(left)); - assert(builder.isMatrix(right)); - break; - default: - firstClass = false; - break; - } - - if (builder.isCooperativeMatrix(left) || builder.isCooperativeMatrix(right)) - firstClass = true; - - if (firstClass) { - spv::Id result = builder.createBinOp(op, typeId, left, right); - decorations.addNoContraction(builder, result); - decorations.addNonUniform(builder, result); - return builder.setPrecision(result, decorations.precision); - } - - // Handle component-wise +, -, *, %, and / for all combinations of type. - // The result type of all of them is the same type as the (a) matrix operand. - // The algorithm is to: - // - break the matrix(es) into vectors - // - smear any scalar to a vector - // - do vector operations - // - make a matrix out the vector results - switch (op) { - case spv::OpFAdd: - case spv::OpFSub: - case spv::OpFDiv: - case spv::OpFMod: - case spv::OpFMul: - { - // one time set up... - bool leftMat = builder.isMatrix(left); - bool rightMat = builder.isMatrix(right); - unsigned int numCols = leftMat ? builder.getNumColumns(left) : builder.getNumColumns(right); - int numRows = leftMat ? builder.getNumRows(left) : builder.getNumRows(right); - spv::Id scalarType = builder.getScalarTypeId(typeId); - spv::Id vecType = builder.makeVectorType(scalarType, numRows); - std::vector results; - spv::Id smearVec = spv::NoResult; - if (builder.isScalar(left)) - smearVec = builder.smearScalar(decorations.precision, left, vecType); - else if (builder.isScalar(right)) - smearVec = builder.smearScalar(decorations.precision, right, vecType); - - // do each vector op - for (unsigned int c = 0; c < numCols; ++c) { - std::vector indexes; - indexes.push_back(c); - spv::Id leftVec = leftMat ? builder.createCompositeExtract( left, vecType, indexes) : smearVec; - spv::Id rightVec = rightMat ? builder.createCompositeExtract(right, vecType, indexes) : smearVec; - spv::Id result = builder.createBinOp(op, vecType, leftVec, rightVec); - decorations.addNoContraction(builder, result); - decorations.addNonUniform(builder, result); - results.push_back(builder.setPrecision(result, decorations.precision)); - } - - // put the pieces together - spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision); - decorations.addNonUniform(builder, result); - return result; - } - default: - assert(0); - return spv::NoResult; - } -} - -spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDecorations& decorations, spv::Id typeId, - spv::Id operand, glslang::TBasicType typeProxy, const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) -{ - spv::Op unaryOp = spv::OpNop; - int extBuiltins = -1; - int libCall = -1; - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - - switch (op) { - case glslang::EOpNegative: - if (isFloat) { - unaryOp = spv::OpFNegate; - if (builder.isMatrixType(typeId)) - return createUnaryMatrixOperation(unaryOp, decorations, typeId, operand, typeProxy); - } else - unaryOp = spv::OpSNegate; - break; - - case glslang::EOpLogicalNot: - case glslang::EOpVectorLogicalNot: - unaryOp = spv::OpLogicalNot; - break; - case glslang::EOpBitwiseNot: - unaryOp = spv::OpNot; - break; - - case glslang::EOpDeterminant: - libCall = spv::GLSLstd450Determinant; - break; - case glslang::EOpMatrixInverse: - libCall = spv::GLSLstd450MatrixInverse; - break; - case glslang::EOpTranspose: - unaryOp = spv::OpTranspose; - break; - - case glslang::EOpRadians: - libCall = spv::GLSLstd450Radians; - break; - case glslang::EOpDegrees: - libCall = spv::GLSLstd450Degrees; - break; - case glslang::EOpSin: - libCall = spv::GLSLstd450Sin; - break; - case glslang::EOpCos: - libCall = spv::GLSLstd450Cos; - break; - case glslang::EOpTan: - libCall = spv::GLSLstd450Tan; - break; - case glslang::EOpAcos: - libCall = spv::GLSLstd450Acos; - break; - case glslang::EOpAsin: - libCall = spv::GLSLstd450Asin; - break; - case glslang::EOpAtan: - libCall = spv::GLSLstd450Atan; - break; - - case glslang::EOpAcosh: - libCall = spv::GLSLstd450Acosh; - break; - case glslang::EOpAsinh: - libCall = spv::GLSLstd450Asinh; - break; - case glslang::EOpAtanh: - libCall = spv::GLSLstd450Atanh; - break; - case glslang::EOpTanh: - libCall = spv::GLSLstd450Tanh; - break; - case glslang::EOpCosh: - libCall = spv::GLSLstd450Cosh; - break; - case glslang::EOpSinh: - libCall = spv::GLSLstd450Sinh; - break; - - case glslang::EOpLength: - libCall = spv::GLSLstd450Length; - break; - case glslang::EOpNormalize: - libCall = spv::GLSLstd450Normalize; - break; - - case glslang::EOpExp: - libCall = spv::GLSLstd450Exp; - break; - case glslang::EOpLog: - libCall = spv::GLSLstd450Log; - break; - case glslang::EOpExp2: - libCall = spv::GLSLstd450Exp2; - break; - case glslang::EOpLog2: - libCall = spv::GLSLstd450Log2; - break; - case glslang::EOpSqrt: - libCall = spv::GLSLstd450Sqrt; - break; - case glslang::EOpInverseSqrt: - libCall = spv::GLSLstd450InverseSqrt; - break; - - case glslang::EOpFloor: - libCall = spv::GLSLstd450Floor; - break; - case glslang::EOpTrunc: - libCall = spv::GLSLstd450Trunc; - break; - case glslang::EOpRound: - libCall = spv::GLSLstd450Round; - break; - case glslang::EOpRoundEven: - libCall = spv::GLSLstd450RoundEven; - break; - case glslang::EOpCeil: - libCall = spv::GLSLstd450Ceil; - break; - case glslang::EOpFract: - libCall = spv::GLSLstd450Fract; - break; - - case glslang::EOpIsNan: - unaryOp = spv::OpIsNan; - break; - case glslang::EOpIsInf: - unaryOp = spv::OpIsInf; - break; - case glslang::EOpIsFinite: - unaryOp = spv::OpIsFinite; - break; - - case glslang::EOpFloatBitsToInt: - case glslang::EOpFloatBitsToUint: - case glslang::EOpIntBitsToFloat: - case glslang::EOpUintBitsToFloat: - case glslang::EOpDoubleBitsToInt64: - case glslang::EOpDoubleBitsToUint64: - case glslang::EOpInt64BitsToDouble: - case glslang::EOpUint64BitsToDouble: - case glslang::EOpFloat16BitsToInt16: - case glslang::EOpFloat16BitsToUint16: - case glslang::EOpInt16BitsToFloat16: - case glslang::EOpUint16BitsToFloat16: - unaryOp = spv::OpBitcast; - break; - - case glslang::EOpPackSnorm2x16: - libCall = spv::GLSLstd450PackSnorm2x16; - break; - case glslang::EOpUnpackSnorm2x16: - libCall = spv::GLSLstd450UnpackSnorm2x16; - break; - case glslang::EOpPackUnorm2x16: - libCall = spv::GLSLstd450PackUnorm2x16; - break; - case glslang::EOpUnpackUnorm2x16: - libCall = spv::GLSLstd450UnpackUnorm2x16; - break; - case glslang::EOpPackHalf2x16: - libCall = spv::GLSLstd450PackHalf2x16; - break; - case glslang::EOpUnpackHalf2x16: - libCall = spv::GLSLstd450UnpackHalf2x16; - break; - case glslang::EOpPackSnorm4x8: - libCall = spv::GLSLstd450PackSnorm4x8; - break; - case glslang::EOpUnpackSnorm4x8: - libCall = spv::GLSLstd450UnpackSnorm4x8; - break; - case glslang::EOpPackUnorm4x8: - libCall = spv::GLSLstd450PackUnorm4x8; - break; - case glslang::EOpUnpackUnorm4x8: - libCall = spv::GLSLstd450UnpackUnorm4x8; - break; - case glslang::EOpPackDouble2x32: - libCall = spv::GLSLstd450PackDouble2x32; - break; - case glslang::EOpUnpackDouble2x32: - libCall = spv::GLSLstd450UnpackDouble2x32; - break; - - case glslang::EOpPackInt2x32: - case glslang::EOpUnpackInt2x32: - case glslang::EOpPackUint2x32: - case glslang::EOpUnpackUint2x32: - case glslang::EOpPack16: - case glslang::EOpPack32: - case glslang::EOpPack64: - case glslang::EOpUnpack32: - case glslang::EOpUnpack16: - case glslang::EOpUnpack8: - case glslang::EOpPackInt2x16: - case glslang::EOpUnpackInt2x16: - case glslang::EOpPackUint2x16: - case glslang::EOpUnpackUint2x16: - case glslang::EOpPackInt4x16: - case glslang::EOpUnpackInt4x16: - case glslang::EOpPackUint4x16: - case glslang::EOpUnpackUint4x16: - case glslang::EOpPackFloat2x16: - case glslang::EOpUnpackFloat2x16: - unaryOp = spv::OpBitcast; - break; - - case glslang::EOpDPdx: - unaryOp = spv::OpDPdx; - break; - case glslang::EOpDPdy: - unaryOp = spv::OpDPdy; - break; - case glslang::EOpFwidth: - unaryOp = spv::OpFwidth; - break; - - case glslang::EOpAny: - unaryOp = spv::OpAny; - break; - case glslang::EOpAll: - unaryOp = spv::OpAll; - break; - - case glslang::EOpAbs: - if (isFloat) - libCall = spv::GLSLstd450FAbs; - else - libCall = spv::GLSLstd450SAbs; - break; - case glslang::EOpSign: - if (isFloat) - libCall = spv::GLSLstd450FSign; - else - libCall = spv::GLSLstd450SSign; - break; - - case glslang::EOpDPdxFine: - unaryOp = spv::OpDPdxFine; - break; - case glslang::EOpDPdyFine: - unaryOp = spv::OpDPdyFine; - break; - case glslang::EOpFwidthFine: - unaryOp = spv::OpFwidthFine; - break; - case glslang::EOpDPdxCoarse: - unaryOp = spv::OpDPdxCoarse; - break; - case glslang::EOpDPdyCoarse: - unaryOp = spv::OpDPdyCoarse; - break; - case glslang::EOpFwidthCoarse: - unaryOp = spv::OpFwidthCoarse; - break; - case glslang::EOpRayQueryProceed: - unaryOp = spv::OpRayQueryProceedKHR; - break; - case glslang::EOpRayQueryGetRayTMin: - unaryOp = spv::OpRayQueryGetRayTMinKHR; - break; - case glslang::EOpRayQueryGetRayFlags: - unaryOp = spv::OpRayQueryGetRayFlagsKHR; - break; - case glslang::EOpRayQueryGetWorldRayOrigin: - unaryOp = spv::OpRayQueryGetWorldRayOriginKHR; - break; - case glslang::EOpRayQueryGetWorldRayDirection: - unaryOp = spv::OpRayQueryGetWorldRayDirectionKHR; - break; - case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: - unaryOp = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR; - break; - case glslang::EOpInterpolateAtCentroid: - if (typeProxy == glslang::EbtFloat16) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - libCall = spv::GLSLstd450InterpolateAtCentroid; - break; - case glslang::EOpAtomicCounterIncrement: - case glslang::EOpAtomicCounterDecrement: - case glslang::EOpAtomicCounter: - { - // Handle all of the atomics in one place, in createAtomicOperation() - std::vector operands; - operands.push_back(operand); - return createAtomicOperation(op, decorations.precision, typeId, operands, typeProxy, lvalueCoherentFlags); - } - - case glslang::EOpBitFieldReverse: - unaryOp = spv::OpBitReverse; - break; - case glslang::EOpBitCount: - unaryOp = spv::OpBitCount; - break; - case glslang::EOpFindLSB: - libCall = spv::GLSLstd450FindILsb; - break; - case glslang::EOpFindMSB: - if (isUnsigned) - libCall = spv::GLSLstd450FindUMsb; - else - libCall = spv::GLSLstd450FindSMsb; - break; - - case glslang::EOpCountLeadingZeros: - builder.addCapability(spv::CapabilityIntegerFunctions2INTEL); - builder.addExtension("SPV_INTEL_shader_integer_functions2"); - unaryOp = spv::OpUCountLeadingZerosINTEL; - break; - - case glslang::EOpCountTrailingZeros: - builder.addCapability(spv::CapabilityIntegerFunctions2INTEL); - builder.addExtension("SPV_INTEL_shader_integer_functions2"); - unaryOp = spv::OpUCountTrailingZerosINTEL; - break; - - case glslang::EOpBallot: - case glslang::EOpReadFirstInvocation: - case glslang::EOpAnyInvocation: - case glslang::EOpAllInvocations: - case glslang::EOpAllInvocationsEqual: - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: - { - std::vector operands; - operands.push_back(operand); - return createInvocationsOperation(op, typeId, operands, typeProxy); - } - case glslang::EOpSubgroupAll: - case glslang::EOpSubgroupAny: - case glslang::EOpSubgroupAllEqual: - case glslang::EOpSubgroupBroadcastFirst: - case glslang::EOpSubgroupBallot: - case glslang::EOpSubgroupInverseBallot: - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupBallotExclusiveBitCount: - case glslang::EOpSubgroupBallotFindLSB: - case glslang::EOpSubgroupBallotFindMSB: - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupXor: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupInclusiveXor: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupExclusiveXor: - case glslang::EOpSubgroupQuadSwapHorizontal: - case glslang::EOpSubgroupQuadSwapVertical: - case glslang::EOpSubgroupQuadSwapDiagonal: { - std::vector operands; - operands.push_back(operand); - return createSubgroupOperation(op, typeId, operands, typeProxy); - } - case glslang::EOpMbcnt: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::MbcntAMD; - break; - - case glslang::EOpCubeFaceIndex: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader); - libCall = spv::CubeFaceIndexAMD; - break; - - case glslang::EOpCubeFaceCoord: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader); - libCall = spv::CubeFaceCoordAMD; - break; - case glslang::EOpSubgroupPartition: - unaryOp = spv::OpGroupNonUniformPartitionNV; - break; - case glslang::EOpConstructReference: - unaryOp = spv::OpBitcast; - break; - - case glslang::EOpConvUint64ToAccStruct: - case glslang::EOpConvUvec2ToAccStruct: - unaryOp = spv::OpConvertUToAccelerationStructureKHR; - break; - - case glslang::EOpHitObjectIsEmptyNV: - unaryOp = spv::OpHitObjectIsEmptyNV; - break; - - case glslang::EOpHitObjectIsMissNV: - unaryOp = spv::OpHitObjectIsMissNV; - break; - - case glslang::EOpHitObjectIsHitNV: - unaryOp = spv::OpHitObjectIsHitNV; - break; - - case glslang::EOpHitObjectGetObjectRayOriginNV: - unaryOp = spv::OpHitObjectGetObjectRayOriginNV; - break; - - case glslang::EOpHitObjectGetObjectRayDirectionNV: - unaryOp = spv::OpHitObjectGetObjectRayDirectionNV; - break; - - case glslang::EOpHitObjectGetWorldRayOriginNV: - unaryOp = spv::OpHitObjectGetWorldRayOriginNV; - break; - - case glslang::EOpHitObjectGetWorldRayDirectionNV: - unaryOp = spv::OpHitObjectGetWorldRayDirectionNV; - break; - - case glslang::EOpHitObjectGetObjectToWorldNV: - unaryOp = spv::OpHitObjectGetObjectToWorldNV; - break; - - case glslang::EOpHitObjectGetWorldToObjectNV: - unaryOp = spv::OpHitObjectGetWorldToObjectNV; - break; - - case glslang::EOpHitObjectGetRayTMinNV: - unaryOp = spv::OpHitObjectGetRayTMinNV; - break; - - case glslang::EOpHitObjectGetRayTMaxNV: - unaryOp = spv::OpHitObjectGetRayTMaxNV; - break; - - case glslang::EOpHitObjectGetPrimitiveIndexNV: - unaryOp = spv::OpHitObjectGetPrimitiveIndexNV; - break; - - case glslang::EOpHitObjectGetInstanceIdNV: - unaryOp = spv::OpHitObjectGetInstanceIdNV; - break; - - case glslang::EOpHitObjectGetInstanceCustomIndexNV: - unaryOp = spv::OpHitObjectGetInstanceCustomIndexNV; - break; - - case glslang::EOpHitObjectGetGeometryIndexNV: - unaryOp = spv::OpHitObjectGetGeometryIndexNV; - break; - - case glslang::EOpHitObjectGetHitKindNV: - unaryOp = spv::OpHitObjectGetHitKindNV; - break; - - case glslang::EOpHitObjectGetCurrentTimeNV: - unaryOp = spv::OpHitObjectGetCurrentTimeNV; - break; - - case glslang::EOpHitObjectGetShaderBindingTableRecordIndexNV: - unaryOp = spv::OpHitObjectGetShaderBindingTableRecordIndexNV; - break; - - case glslang::EOpHitObjectGetShaderRecordBufferHandleNV: - unaryOp = spv::OpHitObjectGetShaderRecordBufferHandleNV; - break; - - case glslang::EOpFetchMicroTriangleVertexPositionNV: - unaryOp = spv::OpFetchMicroTriangleVertexPositionNV; - break; - - case glslang::EOpFetchMicroTriangleVertexBarycentricNV: - unaryOp = spv::OpFetchMicroTriangleVertexBarycentricNV; - break; - - case glslang::EOpCopyObject: - unaryOp = spv::OpCopyObject; - break; - - case glslang::EOpDepthAttachmentReadEXT: - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - builder.addCapability(spv::CapabilityTileImageDepthReadAccessEXT); - unaryOp = spv::OpDepthAttachmentReadEXT; - decorations.precision = spv::NoPrecision; - break; - case glslang::EOpStencilAttachmentReadEXT: - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - builder.addCapability(spv::CapabilityTileImageStencilReadAccessEXT); - unaryOp = spv::OpStencilAttachmentReadEXT; - decorations.precision = spv::DecorationRelaxedPrecision; - break; - - default: - return 0; - } - - spv::Id id; - if (libCall >= 0) { - std::vector args; - args.push_back(operand); - id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, args); - } else { - id = builder.createUnaryOp(unaryOp, typeId, operand); - } - - decorations.addNoContraction(builder, id); - decorations.addNonUniform(builder, id); - return builder.setPrecision(id, decorations.precision); -} - -// Create a unary operation on a matrix -spv::Id TGlslangToSpvTraverser::createUnaryMatrixOperation(spv::Op op, OpDecorations& decorations, spv::Id typeId, - spv::Id operand, glslang::TBasicType /* typeProxy */) -{ - // Handle unary operations vector by vector. - // The result type is the same type as the original type. - // The algorithm is to: - // - break the matrix into vectors - // - apply the operation to each vector - // - make a matrix out the vector results - - // get the types sorted out - int numCols = builder.getNumColumns(operand); - int numRows = builder.getNumRows(operand); - spv::Id srcVecType = builder.makeVectorType(builder.getScalarTypeId(builder.getTypeId(operand)), numRows); - spv::Id destVecType = builder.makeVectorType(builder.getScalarTypeId(typeId), numRows); - std::vector results; - - // do each vector op - for (int c = 0; c < numCols; ++c) { - std::vector indexes; - indexes.push_back(c); - spv::Id srcVec = builder.createCompositeExtract(operand, srcVecType, indexes); - spv::Id destVec = builder.createUnaryOp(op, destVecType, srcVec); - decorations.addNoContraction(builder, destVec); - decorations.addNonUniform(builder, destVec); - results.push_back(builder.setPrecision(destVec, decorations.precision)); - } - - // put the pieces together - spv::Id result = builder.setPrecision(builder.createCompositeConstruct(typeId, results), decorations.precision); - decorations.addNonUniform(builder, result); - return result; -} - -// For converting integers where both the bitwidth and the signedness could -// change, but only do the width change here. The caller is still responsible -// for the signedness conversion. -// destType is the final type that will be converted to, but this function -// may only be doing part of that conversion. -spv::Id TGlslangToSpvTraverser::createIntWidthConversion(glslang::TOperator op, spv::Id operand, int vectorSize, spv::Id destType) -{ - // Get the result type width, based on the type to convert to. - int width = 32; - switch(op) { - case glslang::EOpConvInt16ToUint8: - case glslang::EOpConvIntToUint8: - case glslang::EOpConvInt64ToUint8: - case glslang::EOpConvUint16ToInt8: - case glslang::EOpConvUintToInt8: - case glslang::EOpConvUint64ToInt8: - width = 8; - break; - case glslang::EOpConvInt8ToUint16: - case glslang::EOpConvIntToUint16: - case glslang::EOpConvInt64ToUint16: - case glslang::EOpConvUint8ToInt16: - case glslang::EOpConvUintToInt16: - case glslang::EOpConvUint64ToInt16: - width = 16; - break; - case glslang::EOpConvInt8ToUint: - case glslang::EOpConvInt16ToUint: - case glslang::EOpConvInt64ToUint: - case glslang::EOpConvUint8ToInt: - case glslang::EOpConvUint16ToInt: - case glslang::EOpConvUint64ToInt: - width = 32; - break; - case glslang::EOpConvInt8ToUint64: - case glslang::EOpConvInt16ToUint64: - case glslang::EOpConvIntToUint64: - case glslang::EOpConvUint8ToInt64: - case glslang::EOpConvUint16ToInt64: - case glslang::EOpConvUintToInt64: - width = 64; - break; - - default: - assert(false && "Default missing"); - break; - } - - // Get the conversion operation and result type, - // based on the target width, but the source type. - spv::Id type = spv::NoType; - spv::Op convOp = spv::OpNop; - switch(op) { - case glslang::EOpConvInt8ToUint16: - case glslang::EOpConvInt8ToUint: - case glslang::EOpConvInt8ToUint64: - case glslang::EOpConvInt16ToUint8: - case glslang::EOpConvInt16ToUint: - case glslang::EOpConvInt16ToUint64: - case glslang::EOpConvIntToUint8: - case glslang::EOpConvIntToUint16: - case glslang::EOpConvIntToUint64: - case glslang::EOpConvInt64ToUint8: - case glslang::EOpConvInt64ToUint16: - case glslang::EOpConvInt64ToUint: - convOp = spv::OpSConvert; - type = builder.makeIntType(width); - break; - default: - convOp = spv::OpUConvert; - type = builder.makeUintType(width); - break; - } - - if (vectorSize > 0) - type = builder.makeVectorType(type, vectorSize); - else if (builder.getOpCode(destType) == spv::OpTypeCooperativeMatrixKHR || - builder.getOpCode(destType) == spv::OpTypeCooperativeMatrixNV) { - - type = builder.makeCooperativeMatrixTypeWithSameShape(type, destType); - } - - return builder.createUnaryOp(convOp, type, operand); -} - -spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecorations& decorations, spv::Id destType, - spv::Id operand, glslang::TBasicType typeProxy) -{ - spv::Op convOp = spv::OpNop; - spv::Id zero = 0; - spv::Id one = 0; - - int vectorSize = builder.isVectorType(destType) ? builder.getNumTypeComponents(destType) : 0; - - switch (op) { - case glslang::EOpConvIntToBool: - case glslang::EOpConvUintToBool: - zero = builder.makeUintConstant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - case glslang::EOpConvFloatToBool: - zero = builder.makeFloatConstant(0.0F); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFUnordNotEqual, destType, operand, zero); - case glslang::EOpConvBoolToFloat: - convOp = spv::OpSelect; - zero = builder.makeFloatConstant(0.0F); - one = builder.makeFloatConstant(1.0F); - break; - - case glslang::EOpConvBoolToInt: - case glslang::EOpConvBoolToInt64: - if (op == glslang::EOpConvBoolToInt64) { - zero = builder.makeInt64Constant(0); - one = builder.makeInt64Constant(1); - } else { - zero = builder.makeIntConstant(0); - one = builder.makeIntConstant(1); - } - - convOp = spv::OpSelect; - break; - - case glslang::EOpConvBoolToUint: - case glslang::EOpConvBoolToUint64: - if (op == glslang::EOpConvBoolToUint64) { - zero = builder.makeUint64Constant(0); - one = builder.makeUint64Constant(1); - } else { - zero = builder.makeUintConstant(0); - one = builder.makeUintConstant(1); - } - - convOp = spv::OpSelect; - break; - - case glslang::EOpConvInt8ToFloat16: - case glslang::EOpConvInt8ToFloat: - case glslang::EOpConvInt8ToDouble: - case glslang::EOpConvInt16ToFloat16: - case glslang::EOpConvInt16ToFloat: - case glslang::EOpConvInt16ToDouble: - case glslang::EOpConvIntToFloat16: - case glslang::EOpConvIntToFloat: - case glslang::EOpConvIntToDouble: - case glslang::EOpConvInt64ToFloat: - case glslang::EOpConvInt64ToDouble: - case glslang::EOpConvInt64ToFloat16: - convOp = spv::OpConvertSToF; - break; - - case glslang::EOpConvUint8ToFloat16: - case glslang::EOpConvUint8ToFloat: - case glslang::EOpConvUint8ToDouble: - case glslang::EOpConvUint16ToFloat16: - case glslang::EOpConvUint16ToFloat: - case glslang::EOpConvUint16ToDouble: - case glslang::EOpConvUintToFloat16: - case glslang::EOpConvUintToFloat: - case glslang::EOpConvUintToDouble: - case glslang::EOpConvUint64ToFloat: - case glslang::EOpConvUint64ToDouble: - case glslang::EOpConvUint64ToFloat16: - convOp = spv::OpConvertUToF; - break; - - case glslang::EOpConvFloat16ToInt8: - case glslang::EOpConvFloatToInt8: - case glslang::EOpConvDoubleToInt8: - case glslang::EOpConvFloat16ToInt16: - case glslang::EOpConvFloatToInt16: - case glslang::EOpConvDoubleToInt16: - case glslang::EOpConvFloat16ToInt: - case glslang::EOpConvFloatToInt: - case glslang::EOpConvDoubleToInt: - case glslang::EOpConvFloat16ToInt64: - case glslang::EOpConvFloatToInt64: - case glslang::EOpConvDoubleToInt64: - convOp = spv::OpConvertFToS; - break; - - case glslang::EOpConvUint8ToInt8: - case glslang::EOpConvInt8ToUint8: - case glslang::EOpConvUint16ToInt16: - case glslang::EOpConvInt16ToUint16: - case glslang::EOpConvUintToInt: - case glslang::EOpConvIntToUint: - case glslang::EOpConvUint64ToInt64: - case glslang::EOpConvInt64ToUint64: - if (builder.isInSpecConstCodeGenMode()) { - // Build zero scalar or vector for OpIAdd. - if(op == glslang::EOpConvUint8ToInt8 || op == glslang::EOpConvInt8ToUint8) { - zero = builder.makeUint8Constant(0); - } else if (op == glslang::EOpConvUint16ToInt16 || op == glslang::EOpConvInt16ToUint16) { - zero = builder.makeUint16Constant(0); - } else if (op == glslang::EOpConvUint64ToInt64 || op == glslang::EOpConvInt64ToUint64) { - zero = builder.makeUint64Constant(0); - } else { - zero = builder.makeUintConstant(0); - } - zero = makeSmearedConstant(zero, vectorSize); - // Use OpIAdd, instead of OpBitcast to do the conversion when - // generating for OpSpecConstantOp instruction. - return builder.createBinOp(spv::OpIAdd, destType, operand, zero); - } - // For normal run-time conversion instruction, use OpBitcast. - convOp = spv::OpBitcast; - break; - - case glslang::EOpConvFloat16ToUint8: - case glslang::EOpConvFloatToUint8: - case glslang::EOpConvDoubleToUint8: - case glslang::EOpConvFloat16ToUint16: - case glslang::EOpConvFloatToUint16: - case glslang::EOpConvDoubleToUint16: - case glslang::EOpConvFloat16ToUint: - case glslang::EOpConvFloatToUint: - case glslang::EOpConvDoubleToUint: - case glslang::EOpConvFloatToUint64: - case glslang::EOpConvDoubleToUint64: - case glslang::EOpConvFloat16ToUint64: - convOp = spv::OpConvertFToU; - break; - - case glslang::EOpConvInt8ToBool: - case glslang::EOpConvUint8ToBool: - zero = builder.makeUint8Constant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - case glslang::EOpConvInt16ToBool: - case glslang::EOpConvUint16ToBool: - zero = builder.makeUint16Constant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - case glslang::EOpConvInt64ToBool: - case glslang::EOpConvUint64ToBool: - zero = builder.makeUint64Constant(0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpINotEqual, destType, operand, zero); - case glslang::EOpConvDoubleToBool: - zero = builder.makeDoubleConstant(0.0); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFUnordNotEqual, destType, operand, zero); - case glslang::EOpConvFloat16ToBool: - zero = builder.makeFloat16Constant(0.0F); - zero = makeSmearedConstant(zero, vectorSize); - return builder.createBinOp(spv::OpFUnordNotEqual, destType, operand, zero); - case glslang::EOpConvBoolToDouble: - convOp = spv::OpSelect; - zero = builder.makeDoubleConstant(0.0); - one = builder.makeDoubleConstant(1.0); - break; - case glslang::EOpConvBoolToFloat16: - convOp = spv::OpSelect; - zero = builder.makeFloat16Constant(0.0F); - one = builder.makeFloat16Constant(1.0F); - break; - case glslang::EOpConvBoolToInt8: - zero = builder.makeInt8Constant(0); - one = builder.makeInt8Constant(1); - convOp = spv::OpSelect; - break; - case glslang::EOpConvBoolToUint8: - zero = builder.makeUint8Constant(0); - one = builder.makeUint8Constant(1); - convOp = spv::OpSelect; - break; - case glslang::EOpConvBoolToInt16: - zero = builder.makeInt16Constant(0); - one = builder.makeInt16Constant(1); - convOp = spv::OpSelect; - break; - case glslang::EOpConvBoolToUint16: - zero = builder.makeUint16Constant(0); - one = builder.makeUint16Constant(1); - convOp = spv::OpSelect; - break; - case glslang::EOpConvDoubleToFloat: - case glslang::EOpConvFloatToDouble: - case glslang::EOpConvDoubleToFloat16: - case glslang::EOpConvFloat16ToDouble: - case glslang::EOpConvFloatToFloat16: - case glslang::EOpConvFloat16ToFloat: - convOp = spv::OpFConvert; - if (builder.isMatrixType(destType)) - return createUnaryMatrixOperation(convOp, decorations, destType, operand, typeProxy); - break; - - case glslang::EOpConvInt8ToInt16: - case glslang::EOpConvInt8ToInt: - case glslang::EOpConvInt8ToInt64: - case glslang::EOpConvInt16ToInt8: - case glslang::EOpConvInt16ToInt: - case glslang::EOpConvInt16ToInt64: - case glslang::EOpConvIntToInt8: - case glslang::EOpConvIntToInt16: - case glslang::EOpConvIntToInt64: - case glslang::EOpConvInt64ToInt8: - case glslang::EOpConvInt64ToInt16: - case glslang::EOpConvInt64ToInt: - convOp = spv::OpSConvert; - break; - - case glslang::EOpConvUint8ToUint16: - case glslang::EOpConvUint8ToUint: - case glslang::EOpConvUint8ToUint64: - case glslang::EOpConvUint16ToUint8: - case glslang::EOpConvUint16ToUint: - case glslang::EOpConvUint16ToUint64: - case glslang::EOpConvUintToUint8: - case glslang::EOpConvUintToUint16: - case glslang::EOpConvUintToUint64: - case glslang::EOpConvUint64ToUint8: - case glslang::EOpConvUint64ToUint16: - case glslang::EOpConvUint64ToUint: - convOp = spv::OpUConvert; - break; - - case glslang::EOpConvInt8ToUint16: - case glslang::EOpConvInt8ToUint: - case glslang::EOpConvInt8ToUint64: - case glslang::EOpConvInt16ToUint8: - case glslang::EOpConvInt16ToUint: - case glslang::EOpConvInt16ToUint64: - case glslang::EOpConvIntToUint8: - case glslang::EOpConvIntToUint16: - case glslang::EOpConvIntToUint64: - case glslang::EOpConvInt64ToUint8: - case glslang::EOpConvInt64ToUint16: - case glslang::EOpConvInt64ToUint: - case glslang::EOpConvUint8ToInt16: - case glslang::EOpConvUint8ToInt: - case glslang::EOpConvUint8ToInt64: - case glslang::EOpConvUint16ToInt8: - case glslang::EOpConvUint16ToInt: - case glslang::EOpConvUint16ToInt64: - case glslang::EOpConvUintToInt8: - case glslang::EOpConvUintToInt16: - case glslang::EOpConvUintToInt64: - case glslang::EOpConvUint64ToInt8: - case glslang::EOpConvUint64ToInt16: - case glslang::EOpConvUint64ToInt: - // OpSConvert/OpUConvert + OpBitCast - operand = createIntWidthConversion(op, operand, vectorSize, destType); - - if (builder.isInSpecConstCodeGenMode()) { - // Build zero scalar or vector for OpIAdd. - switch(op) { - case glslang::EOpConvInt16ToUint8: - case glslang::EOpConvIntToUint8: - case glslang::EOpConvInt64ToUint8: - case glslang::EOpConvUint16ToInt8: - case glslang::EOpConvUintToInt8: - case glslang::EOpConvUint64ToInt8: - zero = builder.makeUint8Constant(0); - break; - case glslang::EOpConvInt8ToUint16: - case glslang::EOpConvIntToUint16: - case glslang::EOpConvInt64ToUint16: - case glslang::EOpConvUint8ToInt16: - case glslang::EOpConvUintToInt16: - case glslang::EOpConvUint64ToInt16: - zero = builder.makeUint16Constant(0); - break; - case glslang::EOpConvInt8ToUint: - case glslang::EOpConvInt16ToUint: - case glslang::EOpConvInt64ToUint: - case glslang::EOpConvUint8ToInt: - case glslang::EOpConvUint16ToInt: - case glslang::EOpConvUint64ToInt: - zero = builder.makeUintConstant(0); - break; - case glslang::EOpConvInt8ToUint64: - case glslang::EOpConvInt16ToUint64: - case glslang::EOpConvIntToUint64: - case glslang::EOpConvUint8ToInt64: - case glslang::EOpConvUint16ToInt64: - case glslang::EOpConvUintToInt64: - zero = builder.makeUint64Constant(0); - break; - default: - assert(false && "Default missing"); - break; - } - zero = makeSmearedConstant(zero, vectorSize); - // Use OpIAdd, instead of OpBitcast to do the conversion when - // generating for OpSpecConstantOp instruction. - return builder.createBinOp(spv::OpIAdd, destType, operand, zero); - } - // For normal run-time conversion instruction, use OpBitcast. - convOp = spv::OpBitcast; - break; - case glslang::EOpConvUint64ToPtr: - convOp = spv::OpConvertUToPtr; - break; - case glslang::EOpConvPtrToUint64: - convOp = spv::OpConvertPtrToU; - break; - case glslang::EOpConvPtrToUvec2: - case glslang::EOpConvUvec2ToPtr: - convOp = spv::OpBitcast; - break; - - default: - break; - } - - spv::Id result = 0; - if (convOp == spv::OpNop) - return result; - - if (convOp == spv::OpSelect) { - zero = makeSmearedConstant(zero, vectorSize); - one = makeSmearedConstant(one, vectorSize); - result = builder.createTriOp(convOp, destType, operand, one, zero); - } else - result = builder.createUnaryOp(convOp, destType, operand); - - result = builder.setPrecision(result, decorations.precision); - decorations.addNonUniform(builder, result); - return result; -} - -spv::Id TGlslangToSpvTraverser::makeSmearedConstant(spv::Id constant, int vectorSize) -{ - if (vectorSize == 0) - return constant; - - spv::Id vectorTypeId = builder.makeVectorType(builder.getTypeId(constant), vectorSize); - std::vector components; - for (int c = 0; c < vectorSize; ++c) - components.push_back(constant); - return builder.makeCompositeConstant(vectorTypeId, components); -} - -// For glslang ops that map to SPV atomic opCodes -spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv::Decoration /*precision*/, - spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy, - const spv::Builder::AccessChain::CoherentFlags &lvalueCoherentFlags) -{ - spv::Op opCode = spv::OpNop; - - switch (op) { - case glslang::EOpAtomicAdd: - case glslang::EOpImageAtomicAdd: - case glslang::EOpAtomicCounterAdd: - opCode = spv::OpAtomicIAdd; - if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) { - opCode = spv::OpAtomicFAddEXT; - builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_add); - if (typeProxy == glslang::EbtFloat16) { - builder.addExtension(spv::E_SPV_EXT_shader_atomic_float16_add); - builder.addCapability(spv::CapabilityAtomicFloat16AddEXT); - } else if (typeProxy == glslang::EbtFloat) { - builder.addCapability(spv::CapabilityAtomicFloat32AddEXT); - } else { - builder.addCapability(spv::CapabilityAtomicFloat64AddEXT); - } - } - break; - case glslang::EOpAtomicSubtract: - case glslang::EOpAtomicCounterSubtract: - opCode = spv::OpAtomicISub; - break; - case glslang::EOpAtomicMin: - case glslang::EOpImageAtomicMin: - case glslang::EOpAtomicCounterMin: - if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) { - opCode = spv::OpAtomicFMinEXT; - builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_min_max); - if (typeProxy == glslang::EbtFloat16) - builder.addCapability(spv::CapabilityAtomicFloat16MinMaxEXT); - else if (typeProxy == glslang::EbtFloat) - builder.addCapability(spv::CapabilityAtomicFloat32MinMaxEXT); - else - builder.addCapability(spv::CapabilityAtomicFloat64MinMaxEXT); - } else if (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) { - opCode = spv::OpAtomicUMin; - } else { - opCode = spv::OpAtomicSMin; - } - break; - case glslang::EOpAtomicMax: - case glslang::EOpImageAtomicMax: - case glslang::EOpAtomicCounterMax: - if (typeProxy == glslang::EbtFloat16 || typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble) { - opCode = spv::OpAtomicFMaxEXT; - builder.addExtension(spv::E_SPV_EXT_shader_atomic_float_min_max); - if (typeProxy == glslang::EbtFloat16) - builder.addCapability(spv::CapabilityAtomicFloat16MinMaxEXT); - else if (typeProxy == glslang::EbtFloat) - builder.addCapability(spv::CapabilityAtomicFloat32MinMaxEXT); - else - builder.addCapability(spv::CapabilityAtomicFloat64MinMaxEXT); - } else if (typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64) { - opCode = spv::OpAtomicUMax; - } else { - opCode = spv::OpAtomicSMax; - } - break; - case glslang::EOpAtomicAnd: - case glslang::EOpImageAtomicAnd: - case glslang::EOpAtomicCounterAnd: - opCode = spv::OpAtomicAnd; - break; - case glslang::EOpAtomicOr: - case glslang::EOpImageAtomicOr: - case glslang::EOpAtomicCounterOr: - opCode = spv::OpAtomicOr; - break; - case glslang::EOpAtomicXor: - case glslang::EOpImageAtomicXor: - case glslang::EOpAtomicCounterXor: - opCode = spv::OpAtomicXor; - break; - case glslang::EOpAtomicExchange: - case glslang::EOpImageAtomicExchange: - case glslang::EOpAtomicCounterExchange: - opCode = spv::OpAtomicExchange; - break; - case glslang::EOpAtomicCompSwap: - case glslang::EOpImageAtomicCompSwap: - case glslang::EOpAtomicCounterCompSwap: - opCode = spv::OpAtomicCompareExchange; - break; - case glslang::EOpAtomicCounterIncrement: - opCode = spv::OpAtomicIIncrement; - break; - case glslang::EOpAtomicCounterDecrement: - opCode = spv::OpAtomicIDecrement; - break; - case glslang::EOpAtomicCounter: - case glslang::EOpImageAtomicLoad: - case glslang::EOpAtomicLoad: - opCode = spv::OpAtomicLoad; - break; - case glslang::EOpAtomicStore: - case glslang::EOpImageAtomicStore: - opCode = spv::OpAtomicStore; - break; - default: - assert(0); - break; - } - - if (typeProxy == glslang::EbtInt64 || typeProxy == glslang::EbtUint64) - builder.addCapability(spv::CapabilityInt64Atomics); - - // Sort out the operands - // - mapping from glslang -> SPV - // - there are extra SPV operands that are optional in glslang - // - compare-exchange swaps the value and comparator - // - compare-exchange has an extra memory semantics - // - EOpAtomicCounterDecrement needs a post decrement - spv::Id pointerId = 0, compareId = 0, valueId = 0; - // scope defaults to Device in the old model, QueueFamilyKHR in the new model - spv::Id scopeId; - if (glslangIntermediate->usingVulkanMemoryModel()) { - scopeId = builder.makeUintConstant(spv::ScopeQueueFamilyKHR); - } else { - scopeId = builder.makeUintConstant(spv::ScopeDevice); - } - // semantics default to relaxed - spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && - glslangIntermediate->usingVulkanMemoryModel() ? - spv::MemorySemanticsVolatileMask : - spv::MemorySemanticsMaskNone); - spv::Id semanticsId2 = semanticsId; - - pointerId = operands[0]; - if (opCode == spv::OpAtomicIIncrement || opCode == spv::OpAtomicIDecrement) { - // no additional operands - } else if (opCode == spv::OpAtomicCompareExchange) { - compareId = operands[1]; - valueId = operands[2]; - if (operands.size() > 3) { - scopeId = operands[3]; - semanticsId = builder.makeUintConstant( - builder.getConstantScalar(operands[4]) | builder.getConstantScalar(operands[5])); - semanticsId2 = builder.makeUintConstant( - builder.getConstantScalar(operands[6]) | builder.getConstantScalar(operands[7])); - } - } else if (opCode == spv::OpAtomicLoad) { - if (operands.size() > 1) { - scopeId = operands[1]; - semanticsId = builder.makeUintConstant( - builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3])); - } - } else { - // atomic store or RMW - valueId = operands[1]; - if (operands.size() > 2) { - scopeId = operands[2]; - semanticsId = builder.makeUintConstant - (builder.getConstantScalar(operands[3]) | builder.getConstantScalar(operands[4])); - } - } - - // Check for capabilities - unsigned semanticsImmediate = builder.getConstantScalar(semanticsId) | builder.getConstantScalar(semanticsId2); - if (semanticsImmediate & (spv::MemorySemanticsMakeAvailableKHRMask | - spv::MemorySemanticsMakeVisibleKHRMask | - spv::MemorySemanticsOutputMemoryKHRMask | - spv::MemorySemanticsVolatileMask)) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - - if (builder.getConstantScalar(scopeId) == spv::ScopeQueueFamily) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - - if (glslangIntermediate->usingVulkanMemoryModel() && builder.getConstantScalar(scopeId) == spv::ScopeDevice) { - builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); - } - - std::vector spvAtomicOperands; // hold the spv operands - spvAtomicOperands.push_back(pointerId); - spvAtomicOperands.push_back(scopeId); - spvAtomicOperands.push_back(semanticsId); - if (opCode == spv::OpAtomicCompareExchange) { - spvAtomicOperands.push_back(semanticsId2); - spvAtomicOperands.push_back(valueId); - spvAtomicOperands.push_back(compareId); - } else if (opCode != spv::OpAtomicLoad && opCode != spv::OpAtomicIIncrement && opCode != spv::OpAtomicIDecrement) { - spvAtomicOperands.push_back(valueId); - } - - if (opCode == spv::OpAtomicStore) { - builder.createNoResultOp(opCode, spvAtomicOperands); - return 0; - } else { - spv::Id resultId = builder.createOp(opCode, typeId, spvAtomicOperands); - - // GLSL and HLSL atomic-counter decrement return post-decrement value, - // while SPIR-V returns pre-decrement value. Translate between these semantics. - if (op == glslang::EOpAtomicCounterDecrement) - resultId = builder.createBinOp(spv::OpISub, typeId, resultId, builder.makeIntConstant(1)); - - return resultId; - } -} - -// Create group invocation operations. -spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, - std::vector& operands, glslang::TBasicType typeProxy) -{ - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - - spv::Op opCode = spv::OpNop; - std::vector spvGroupOperands; - spv::GroupOperation groupOperation = spv::GroupOperationMax; - - if (op == glslang::EOpBallot || op == glslang::EOpReadFirstInvocation || - op == glslang::EOpReadInvocation) { - builder.addExtension(spv::E_SPV_KHR_shader_ballot); - builder.addCapability(spv::CapabilitySubgroupBallotKHR); - } else if (op == glslang::EOpAnyInvocation || - op == glslang::EOpAllInvocations || - op == glslang::EOpAllInvocationsEqual) { - builder.addExtension(spv::E_SPV_KHR_subgroup_vote); - builder.addCapability(spv::CapabilitySubgroupVoteKHR); - } else { - builder.addCapability(spv::CapabilityGroups); - if (op == glslang::EOpMinInvocationsNonUniform || - op == glslang::EOpMaxInvocationsNonUniform || - op == glslang::EOpAddInvocationsNonUniform || - op == glslang::EOpMinInvocationsInclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsInclusiveScanNonUniform || - op == glslang::EOpAddInvocationsInclusiveScanNonUniform || - op == glslang::EOpMinInvocationsExclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsExclusiveScanNonUniform || - op == glslang::EOpAddInvocationsExclusiveScanNonUniform) - builder.addExtension(spv::E_SPV_AMD_shader_ballot); - - switch (op) { - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - groupOperation = spv::GroupOperationReduce; - break; - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - groupOperation = spv::GroupOperationInclusiveScan; - break; - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: - groupOperation = spv::GroupOperationExclusiveScan; - break; - default: - break; - } - spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) }; - spvGroupOperands.push_back(scope); - if (groupOperation != spv::GroupOperationMax) { - spv::IdImmediate groupOp = { false, (unsigned)groupOperation }; - spvGroupOperands.push_back(groupOp); - } - } - - for (auto opIt = operands.begin(); opIt != operands.end(); ++opIt) { - spv::IdImmediate op = { true, *opIt }; - spvGroupOperands.push_back(op); - } - - switch (op) { - case glslang::EOpAnyInvocation: - opCode = spv::OpSubgroupAnyKHR; - break; - case glslang::EOpAllInvocations: - opCode = spv::OpSubgroupAllKHR; - break; - case glslang::EOpAllInvocationsEqual: - opCode = spv::OpSubgroupAllEqualKHR; - break; - case glslang::EOpReadInvocation: - opCode = spv::OpSubgroupReadInvocationKHR; - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - break; - case glslang::EOpReadFirstInvocation: - opCode = spv::OpSubgroupFirstInvocationKHR; - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - break; - case glslang::EOpBallot: - { - // NOTE: According to the spec, the result type of "OpSubgroupBallotKHR" must be a 4 component vector of 32 - // bit integer types. The GLSL built-in function "ballotARB()" assumes the maximum number of invocations in - // a subgroup is 64. Thus, we have to convert uvec4.xy to uint64_t as follow: - // - // result = Bitcast(SubgroupBallotKHR(Predicate).xy) - // - spv::Id uintType = builder.makeUintType(32); - spv::Id uvec4Type = builder.makeVectorType(uintType, 4); - spv::Id result = builder.createOp(spv::OpSubgroupBallotKHR, uvec4Type, spvGroupOperands); - - std::vector components; - components.push_back(builder.createCompositeExtract(result, uintType, 0)); - components.push_back(builder.createCompositeExtract(result, uintType, 1)); - - spv::Id uvec2Type = builder.makeVectorType(uintType, 2); - return builder.createUnaryOp(spv::OpBitcast, typeId, - builder.createCompositeConstruct(uvec2Type, components)); - } - - case glslang::EOpMinInvocations: - case glslang::EOpMaxInvocations: - case glslang::EOpAddInvocations: - case glslang::EOpMinInvocationsInclusiveScan: - case glslang::EOpMaxInvocationsInclusiveScan: - case glslang::EOpAddInvocationsInclusiveScan: - case glslang::EOpMinInvocationsExclusiveScan: - case glslang::EOpMaxInvocationsExclusiveScan: - case glslang::EOpAddInvocationsExclusiveScan: - if (op == glslang::EOpMinInvocations || - op == glslang::EOpMinInvocationsInclusiveScan || - op == glslang::EOpMinInvocationsExclusiveScan) { - if (isFloat) - opCode = spv::OpGroupFMin; - else { - if (isUnsigned) - opCode = spv::OpGroupUMin; - else - opCode = spv::OpGroupSMin; - } - } else if (op == glslang::EOpMaxInvocations || - op == glslang::EOpMaxInvocationsInclusiveScan || - op == glslang::EOpMaxInvocationsExclusiveScan) { - if (isFloat) - opCode = spv::OpGroupFMax; - else { - if (isUnsigned) - opCode = spv::OpGroupUMax; - else - opCode = spv::OpGroupSMax; - } - } else { - if (isFloat) - opCode = spv::OpGroupFAdd; - else - opCode = spv::OpGroupIAdd; - } - - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - - break; - case glslang::EOpMinInvocationsNonUniform: - case glslang::EOpMaxInvocationsNonUniform: - case glslang::EOpAddInvocationsNonUniform: - case glslang::EOpMinInvocationsInclusiveScanNonUniform: - case glslang::EOpMaxInvocationsInclusiveScanNonUniform: - case glslang::EOpAddInvocationsInclusiveScanNonUniform: - case glslang::EOpMinInvocationsExclusiveScanNonUniform: - case glslang::EOpMaxInvocationsExclusiveScanNonUniform: - case glslang::EOpAddInvocationsExclusiveScanNonUniform: - if (op == glslang::EOpMinInvocationsNonUniform || - op == glslang::EOpMinInvocationsInclusiveScanNonUniform || - op == glslang::EOpMinInvocationsExclusiveScanNonUniform) { - if (isFloat) - opCode = spv::OpGroupFMinNonUniformAMD; - else { - if (isUnsigned) - opCode = spv::OpGroupUMinNonUniformAMD; - else - opCode = spv::OpGroupSMinNonUniformAMD; - } - } - else if (op == glslang::EOpMaxInvocationsNonUniform || - op == glslang::EOpMaxInvocationsInclusiveScanNonUniform || - op == glslang::EOpMaxInvocationsExclusiveScanNonUniform) { - if (isFloat) - opCode = spv::OpGroupFMaxNonUniformAMD; - else { - if (isUnsigned) - opCode = spv::OpGroupUMaxNonUniformAMD; - else - opCode = spv::OpGroupSMaxNonUniformAMD; - } - } - else { - if (isFloat) - opCode = spv::OpGroupFAddNonUniformAMD; - else - opCode = spv::OpGroupIAddNonUniformAMD; - } - - if (builder.isVectorType(typeId)) - return CreateInvocationsVectorOperation(opCode, groupOperation, typeId, operands); - - break; - default: - logger->missingFunctionality("invocation operation"); - return spv::NoResult; - } - - assert(opCode != spv::OpNop); - return builder.createOp(opCode, typeId, spvGroupOperands); -} - -// Create group invocation operations on a vector -spv::Id TGlslangToSpvTraverser::CreateInvocationsVectorOperation(spv::Op op, spv::GroupOperation groupOperation, - spv::Id typeId, std::vector& operands) -{ - assert(op == spv::OpGroupFMin || op == spv::OpGroupUMin || op == spv::OpGroupSMin || - op == spv::OpGroupFMax || op == spv::OpGroupUMax || op == spv::OpGroupSMax || - op == spv::OpGroupFAdd || op == spv::OpGroupIAdd || op == spv::OpGroupBroadcast || - op == spv::OpSubgroupReadInvocationKHR || op == spv::OpSubgroupFirstInvocationKHR || - op == spv::OpGroupFMinNonUniformAMD || op == spv::OpGroupUMinNonUniformAMD || - op == spv::OpGroupSMinNonUniformAMD || - op == spv::OpGroupFMaxNonUniformAMD || op == spv::OpGroupUMaxNonUniformAMD || - op == spv::OpGroupSMaxNonUniformAMD || - op == spv::OpGroupFAddNonUniformAMD || op == spv::OpGroupIAddNonUniformAMD); - - // Handle group invocation operations scalar by scalar. - // The result type is the same type as the original type. - // The algorithm is to: - // - break the vector into scalars - // - apply the operation to each scalar - // - make a vector out the scalar results - - // get the types sorted out - int numComponents = builder.getNumComponents(operands[0]); - spv::Id scalarType = builder.getScalarTypeId(builder.getTypeId(operands[0])); - std::vector results; - - // do each scalar op - for (int comp = 0; comp < numComponents; ++comp) { - std::vector indexes; - indexes.push_back(comp); - spv::IdImmediate scalar = { true, builder.createCompositeExtract(operands[0], scalarType, indexes) }; - std::vector spvGroupOperands; - if (op == spv::OpSubgroupReadInvocationKHR) { - spvGroupOperands.push_back(scalar); - spv::IdImmediate operand = { true, operands[1] }; - spvGroupOperands.push_back(operand); - } else if (op == spv::OpSubgroupFirstInvocationKHR) { - spvGroupOperands.push_back(scalar); - } else if (op == spv::OpGroupBroadcast) { - spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) }; - spvGroupOperands.push_back(scope); - spvGroupOperands.push_back(scalar); - spv::IdImmediate operand = { true, operands[1] }; - spvGroupOperands.push_back(operand); - } else { - spv::IdImmediate scope = { true, builder.makeUintConstant(spv::ScopeSubgroup) }; - spvGroupOperands.push_back(scope); - spv::IdImmediate groupOp = { false, (unsigned)groupOperation }; - spvGroupOperands.push_back(groupOp); - spvGroupOperands.push_back(scalar); - } - - results.push_back(builder.createOp(op, scalarType, spvGroupOperands)); - } - - // put the pieces together - return builder.createCompositeConstruct(typeId, results); -} - -// Create subgroup invocation operations. -spv::Id TGlslangToSpvTraverser::createSubgroupOperation(glslang::TOperator op, spv::Id typeId, - std::vector& operands, glslang::TBasicType typeProxy) -{ - // Add the required capabilities. - switch (op) { - case glslang::EOpSubgroupElect: - builder.addCapability(spv::CapabilityGroupNonUniform); - break; - case glslang::EOpSubgroupAll: - case glslang::EOpSubgroupAny: - case glslang::EOpSubgroupAllEqual: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformVote); - break; - case glslang::EOpSubgroupBroadcast: - case glslang::EOpSubgroupBroadcastFirst: - case glslang::EOpSubgroupBallot: - case glslang::EOpSubgroupInverseBallot: - case glslang::EOpSubgroupBallotBitExtract: - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupBallotExclusiveBitCount: - case glslang::EOpSubgroupBallotFindLSB: - case glslang::EOpSubgroupBallotFindMSB: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformBallot); - break; - case glslang::EOpSubgroupShuffle: - case glslang::EOpSubgroupShuffleXor: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformShuffle); - break; - case glslang::EOpSubgroupShuffleUp: - case glslang::EOpSubgroupShuffleDown: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformShuffleRelative); - break; - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupXor: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupInclusiveXor: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupExclusiveXor: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformArithmetic); - break; - case glslang::EOpSubgroupClusteredAdd: - case glslang::EOpSubgroupClusteredMul: - case glslang::EOpSubgroupClusteredMin: - case glslang::EOpSubgroupClusteredMax: - case glslang::EOpSubgroupClusteredAnd: - case glslang::EOpSubgroupClusteredOr: - case glslang::EOpSubgroupClusteredXor: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformClustered); - break; - case glslang::EOpSubgroupQuadBroadcast: - case glslang::EOpSubgroupQuadSwapHorizontal: - case glslang::EOpSubgroupQuadSwapVertical: - case glslang::EOpSubgroupQuadSwapDiagonal: - builder.addCapability(spv::CapabilityGroupNonUniform); - builder.addCapability(spv::CapabilityGroupNonUniformQuad); - break; - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedXor: - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedInclusiveXor: - case glslang::EOpSubgroupPartitionedExclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveXor: - builder.addExtension(spv::E_SPV_NV_shader_subgroup_partitioned); - builder.addCapability(spv::CapabilityGroupNonUniformPartitionedNV); - break; - default: assert(0 && "Unhandled subgroup operation!"); - } - - - const bool isUnsigned = isTypeUnsignedInt(typeProxy); - const bool isFloat = isTypeFloat(typeProxy); - const bool isBool = typeProxy == glslang::EbtBool; - - spv::Op opCode = spv::OpNop; - - // Figure out which opcode to use. - switch (op) { - case glslang::EOpSubgroupElect: opCode = spv::OpGroupNonUniformElect; break; - case glslang::EOpSubgroupAll: opCode = spv::OpGroupNonUniformAll; break; - case glslang::EOpSubgroupAny: opCode = spv::OpGroupNonUniformAny; break; - case glslang::EOpSubgroupAllEqual: opCode = spv::OpGroupNonUniformAllEqual; break; - case glslang::EOpSubgroupBroadcast: opCode = spv::OpGroupNonUniformBroadcast; break; - case glslang::EOpSubgroupBroadcastFirst: opCode = spv::OpGroupNonUniformBroadcastFirst; break; - case glslang::EOpSubgroupBallot: opCode = spv::OpGroupNonUniformBallot; break; - case glslang::EOpSubgroupInverseBallot: opCode = spv::OpGroupNonUniformInverseBallot; break; - case glslang::EOpSubgroupBallotBitExtract: opCode = spv::OpGroupNonUniformBallotBitExtract; break; - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupBallotExclusiveBitCount: opCode = spv::OpGroupNonUniformBallotBitCount; break; - case glslang::EOpSubgroupBallotFindLSB: opCode = spv::OpGroupNonUniformBallotFindLSB; break; - case glslang::EOpSubgroupBallotFindMSB: opCode = spv::OpGroupNonUniformBallotFindMSB; break; - case glslang::EOpSubgroupShuffle: opCode = spv::OpGroupNonUniformShuffle; break; - case glslang::EOpSubgroupShuffleXor: opCode = spv::OpGroupNonUniformShuffleXor; break; - case glslang::EOpSubgroupShuffleUp: opCode = spv::OpGroupNonUniformShuffleUp; break; - case glslang::EOpSubgroupShuffleDown: opCode = spv::OpGroupNonUniformShuffleDown; break; - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupClusteredAdd: - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveAdd: - if (isFloat) { - opCode = spv::OpGroupNonUniformFAdd; - } else { - opCode = spv::OpGroupNonUniformIAdd; - } - break; - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupClusteredMul: - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMul: - if (isFloat) { - opCode = spv::OpGroupNonUniformFMul; - } else { - opCode = spv::OpGroupNonUniformIMul; - } - break; - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupClusteredMin: - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMin: - if (isFloat) { - opCode = spv::OpGroupNonUniformFMin; - } else if (isUnsigned) { - opCode = spv::OpGroupNonUniformUMin; - } else { - opCode = spv::OpGroupNonUniformSMin; - } - break; - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupClusteredMax: - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveMax: - if (isFloat) { - opCode = spv::OpGroupNonUniformFMax; - } else if (isUnsigned) { - opCode = spv::OpGroupNonUniformUMax; - } else { - opCode = spv::OpGroupNonUniformSMax; - } - break; - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupClusteredAnd: - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveAnd: - if (isBool) { - opCode = spv::OpGroupNonUniformLogicalAnd; - } else { - opCode = spv::OpGroupNonUniformBitwiseAnd; - } - break; - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupClusteredOr: - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveOr: - if (isBool) { - opCode = spv::OpGroupNonUniformLogicalOr; - } else { - opCode = spv::OpGroupNonUniformBitwiseOr; - } - break; - case glslang::EOpSubgroupXor: - case glslang::EOpSubgroupInclusiveXor: - case glslang::EOpSubgroupExclusiveXor: - case glslang::EOpSubgroupClusteredXor: - case glslang::EOpSubgroupPartitionedXor: - case glslang::EOpSubgroupPartitionedInclusiveXor: - case glslang::EOpSubgroupPartitionedExclusiveXor: - if (isBool) { - opCode = spv::OpGroupNonUniformLogicalXor; - } else { - opCode = spv::OpGroupNonUniformBitwiseXor; - } - break; - case glslang::EOpSubgroupQuadBroadcast: opCode = spv::OpGroupNonUniformQuadBroadcast; break; - case glslang::EOpSubgroupQuadSwapHorizontal: - case glslang::EOpSubgroupQuadSwapVertical: - case glslang::EOpSubgroupQuadSwapDiagonal: opCode = spv::OpGroupNonUniformQuadSwap; break; - default: assert(0 && "Unhandled subgroup operation!"); - } - - // get the right Group Operation - spv::GroupOperation groupOperation = spv::GroupOperationMax; - switch (op) { - default: - break; - case glslang::EOpSubgroupBallotBitCount: - case glslang::EOpSubgroupAdd: - case glslang::EOpSubgroupMul: - case glslang::EOpSubgroupMin: - case glslang::EOpSubgroupMax: - case glslang::EOpSubgroupAnd: - case glslang::EOpSubgroupOr: - case glslang::EOpSubgroupXor: - groupOperation = spv::GroupOperationReduce; - break; - case glslang::EOpSubgroupBallotInclusiveBitCount: - case glslang::EOpSubgroupInclusiveAdd: - case glslang::EOpSubgroupInclusiveMul: - case glslang::EOpSubgroupInclusiveMin: - case glslang::EOpSubgroupInclusiveMax: - case glslang::EOpSubgroupInclusiveAnd: - case glslang::EOpSubgroupInclusiveOr: - case glslang::EOpSubgroupInclusiveXor: - groupOperation = spv::GroupOperationInclusiveScan; - break; - case glslang::EOpSubgroupBallotExclusiveBitCount: - case glslang::EOpSubgroupExclusiveAdd: - case glslang::EOpSubgroupExclusiveMul: - case glslang::EOpSubgroupExclusiveMin: - case glslang::EOpSubgroupExclusiveMax: - case glslang::EOpSubgroupExclusiveAnd: - case glslang::EOpSubgroupExclusiveOr: - case glslang::EOpSubgroupExclusiveXor: - groupOperation = spv::GroupOperationExclusiveScan; - break; - case glslang::EOpSubgroupClusteredAdd: - case glslang::EOpSubgroupClusteredMul: - case glslang::EOpSubgroupClusteredMin: - case glslang::EOpSubgroupClusteredMax: - case glslang::EOpSubgroupClusteredAnd: - case glslang::EOpSubgroupClusteredOr: - case glslang::EOpSubgroupClusteredXor: - groupOperation = spv::GroupOperationClusteredReduce; - break; - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedXor: - groupOperation = spv::GroupOperationPartitionedReduceNV; - break; - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedInclusiveXor: - groupOperation = spv::GroupOperationPartitionedInclusiveScanNV; - break; - case glslang::EOpSubgroupPartitionedExclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveXor: - groupOperation = spv::GroupOperationPartitionedExclusiveScanNV; - break; - } - - // build the instruction - std::vector spvGroupOperands; - - // Every operation begins with the Execution Scope operand. - spv::IdImmediate executionScope = { true, builder.makeUintConstant(spv::ScopeSubgroup) }; - spvGroupOperands.push_back(executionScope); - - // Next, for all operations that use a Group Operation, push that as an operand. - if (groupOperation != spv::GroupOperationMax) { - spv::IdImmediate groupOperand = { false, (unsigned)groupOperation }; - spvGroupOperands.push_back(groupOperand); - } - - // Push back the operands next. - for (auto opIt = operands.cbegin(); opIt != operands.cend(); ++opIt) { - spv::IdImmediate operand = { true, *opIt }; - spvGroupOperands.push_back(operand); - } - - // Some opcodes have additional operands. - spv::Id directionId = spv::NoResult; - switch (op) { - default: break; - case glslang::EOpSubgroupQuadSwapHorizontal: directionId = builder.makeUintConstant(0); break; - case glslang::EOpSubgroupQuadSwapVertical: directionId = builder.makeUintConstant(1); break; - case glslang::EOpSubgroupQuadSwapDiagonal: directionId = builder.makeUintConstant(2); break; - } - if (directionId != spv::NoResult) { - spv::IdImmediate direction = { true, directionId }; - spvGroupOperands.push_back(direction); - } - - return builder.createOp(opCode, typeId, spvGroupOperands); -} - -spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, - spv::Id typeId, std::vector& operands, glslang::TBasicType typeProxy) -{ - bool isUnsigned = isTypeUnsignedInt(typeProxy); - bool isFloat = isTypeFloat(typeProxy); - - spv::Op opCode = spv::OpNop; - int extBuiltins = -1; - int libCall = -1; - size_t consumedOperands = operands.size(); - spv::Id typeId0 = 0; - if (consumedOperands > 0) - typeId0 = builder.getTypeId(operands[0]); - spv::Id typeId1 = 0; - if (consumedOperands > 1) - typeId1 = builder.getTypeId(operands[1]); - spv::Id frexpIntType = 0; - - switch (op) { - case glslang::EOpMin: - if (isFloat) - libCall = nanMinMaxClamp ? spv::GLSLstd450NMin : spv::GLSLstd450FMin; - else if (isUnsigned) - libCall = spv::GLSLstd450UMin; - else - libCall = spv::GLSLstd450SMin; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpModf: - libCall = spv::GLSLstd450Modf; - break; - case glslang::EOpMax: - if (isFloat) - libCall = nanMinMaxClamp ? spv::GLSLstd450NMax : spv::GLSLstd450FMax; - else if (isUnsigned) - libCall = spv::GLSLstd450UMax; - else - libCall = spv::GLSLstd450SMax; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpPow: - libCall = spv::GLSLstd450Pow; - break; - case glslang::EOpDot: - opCode = spv::OpDot; - break; - case glslang::EOpAtan: - libCall = spv::GLSLstd450Atan2; - break; - - case glslang::EOpClamp: - if (isFloat) - libCall = nanMinMaxClamp ? spv::GLSLstd450NClamp : spv::GLSLstd450FClamp; - else if (isUnsigned) - libCall = spv::GLSLstd450UClamp; - else - libCall = spv::GLSLstd450SClamp; - builder.promoteScalar(precision, operands.front(), operands[1]); - builder.promoteScalar(precision, operands.front(), operands[2]); - break; - case glslang::EOpMix: - if (! builder.isBoolType(builder.getScalarTypeId(builder.getTypeId(operands.back())))) { - assert(isFloat); - libCall = spv::GLSLstd450FMix; - } else { - opCode = spv::OpSelect; - std::swap(operands.front(), operands.back()); - } - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpStep: - libCall = spv::GLSLstd450Step; - builder.promoteScalar(precision, operands.front(), operands.back()); - break; - case glslang::EOpSmoothStep: - libCall = spv::GLSLstd450SmoothStep; - builder.promoteScalar(precision, operands[0], operands[2]); - builder.promoteScalar(precision, operands[1], operands[2]); - break; - - case glslang::EOpDistance: - libCall = spv::GLSLstd450Distance; - break; - case glslang::EOpCross: - libCall = spv::GLSLstd450Cross; - break; - case glslang::EOpFaceForward: - libCall = spv::GLSLstd450FaceForward; - break; - case glslang::EOpReflect: - libCall = spv::GLSLstd450Reflect; - break; - case glslang::EOpRefract: - libCall = spv::GLSLstd450Refract; - break; - case glslang::EOpBarrier: - { - // This is for the extended controlBarrier function, with four operands. - // The unextended barrier() goes through createNoArgOperation. - assert(operands.size() == 4); - unsigned int executionScope = builder.getConstantScalar(operands[0]); - unsigned int memoryScope = builder.getConstantScalar(operands[1]); - unsigned int semantics = builder.getConstantScalar(operands[2]) | builder.getConstantScalar(operands[3]); - builder.createControlBarrier((spv::Scope)executionScope, (spv::Scope)memoryScope, - (spv::MemorySemanticsMask)semantics); - if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | - spv::MemorySemanticsMakeVisibleKHRMask | - spv::MemorySemanticsOutputMemoryKHRMask | - spv::MemorySemanticsVolatileMask)) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - if (glslangIntermediate->usingVulkanMemoryModel() && (executionScope == spv::ScopeDevice || - memoryScope == spv::ScopeDevice)) { - builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); - } - return 0; - } - break; - case glslang::EOpMemoryBarrier: - { - // This is for the extended memoryBarrier function, with three operands. - // The unextended memoryBarrier() goes through createNoArgOperation. - assert(operands.size() == 3); - unsigned int memoryScope = builder.getConstantScalar(operands[0]); - unsigned int semantics = builder.getConstantScalar(operands[1]) | builder.getConstantScalar(operands[2]); - builder.createMemoryBarrier((spv::Scope)memoryScope, (spv::MemorySemanticsMask)semantics); - if (semantics & (spv::MemorySemanticsMakeAvailableKHRMask | - spv::MemorySemanticsMakeVisibleKHRMask | - spv::MemorySemanticsOutputMemoryKHRMask | - spv::MemorySemanticsVolatileMask)) { - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } - if (glslangIntermediate->usingVulkanMemoryModel() && memoryScope == spv::ScopeDevice) { - builder.addCapability(spv::CapabilityVulkanMemoryModelDeviceScopeKHR); - } - return 0; - } - break; - - case glslang::EOpInterpolateAtSample: - if (typeProxy == glslang::EbtFloat16) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - libCall = spv::GLSLstd450InterpolateAtSample; - break; - case glslang::EOpInterpolateAtOffset: - if (typeProxy == glslang::EbtFloat16) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - libCall = spv::GLSLstd450InterpolateAtOffset; - break; - case glslang::EOpAddCarry: - opCode = spv::OpIAddCarry; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpSubBorrow: - opCode = spv::OpISubBorrow; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpUMulExtended: - opCode = spv::OpUMulExtended; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpIMulExtended: - opCode = spv::OpSMulExtended; - typeId = builder.makeStructResultType(typeId0, typeId0); - consumedOperands = 2; - break; - case glslang::EOpBitfieldExtract: - if (isUnsigned) - opCode = spv::OpBitFieldUExtract; - else - opCode = spv::OpBitFieldSExtract; - break; - case glslang::EOpBitfieldInsert: - opCode = spv::OpBitFieldInsert; - break; - - case glslang::EOpFma: - libCall = spv::GLSLstd450Fma; - break; - case glslang::EOpFrexp: - { - libCall = spv::GLSLstd450FrexpStruct; - assert(builder.isPointerType(typeId1)); - typeId1 = builder.getContainedTypeId(typeId1); - int width = builder.getScalarTypeWidth(typeId1); - if (width == 16) - // Using 16-bit exp operand, enable extension SPV_AMD_gpu_shader_int16 - builder.addExtension(spv::E_SPV_AMD_gpu_shader_int16); - if (builder.getNumComponents(operands[0]) == 1) - frexpIntType = builder.makeIntegerType(width, true); - else - frexpIntType = builder.makeVectorType(builder.makeIntegerType(width, true), - builder.getNumComponents(operands[0])); - typeId = builder.makeStructResultType(typeId0, frexpIntType); - consumedOperands = 1; - } - break; - case glslang::EOpLdexp: - libCall = spv::GLSLstd450Ldexp; - break; - - case glslang::EOpReadInvocation: - return createInvocationsOperation(op, typeId, operands, typeProxy); - - case glslang::EOpSubgroupBroadcast: - case glslang::EOpSubgroupBallotBitExtract: - case glslang::EOpSubgroupShuffle: - case glslang::EOpSubgroupShuffleXor: - case glslang::EOpSubgroupShuffleUp: - case glslang::EOpSubgroupShuffleDown: - case glslang::EOpSubgroupClusteredAdd: - case glslang::EOpSubgroupClusteredMul: - case glslang::EOpSubgroupClusteredMin: - case glslang::EOpSubgroupClusteredMax: - case glslang::EOpSubgroupClusteredAnd: - case glslang::EOpSubgroupClusteredOr: - case glslang::EOpSubgroupClusteredXor: - case glslang::EOpSubgroupQuadBroadcast: - case glslang::EOpSubgroupPartitionedAdd: - case glslang::EOpSubgroupPartitionedMul: - case glslang::EOpSubgroupPartitionedMin: - case glslang::EOpSubgroupPartitionedMax: - case glslang::EOpSubgroupPartitionedAnd: - case glslang::EOpSubgroupPartitionedOr: - case glslang::EOpSubgroupPartitionedXor: - case glslang::EOpSubgroupPartitionedInclusiveAdd: - case glslang::EOpSubgroupPartitionedInclusiveMul: - case glslang::EOpSubgroupPartitionedInclusiveMin: - case glslang::EOpSubgroupPartitionedInclusiveMax: - case glslang::EOpSubgroupPartitionedInclusiveAnd: - case glslang::EOpSubgroupPartitionedInclusiveOr: - case glslang::EOpSubgroupPartitionedInclusiveXor: - case glslang::EOpSubgroupPartitionedExclusiveAdd: - case glslang::EOpSubgroupPartitionedExclusiveMul: - case glslang::EOpSubgroupPartitionedExclusiveMin: - case glslang::EOpSubgroupPartitionedExclusiveMax: - case glslang::EOpSubgroupPartitionedExclusiveAnd: - case glslang::EOpSubgroupPartitionedExclusiveOr: - case glslang::EOpSubgroupPartitionedExclusiveXor: - return createSubgroupOperation(op, typeId, operands, typeProxy); - - case glslang::EOpSwizzleInvocations: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::SwizzleInvocationsAMD; - break; - case glslang::EOpSwizzleInvocationsMasked: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::SwizzleInvocationsMaskedAMD; - break; - case glslang::EOpWriteInvocation: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot); - libCall = spv::WriteInvocationAMD; - break; - - case glslang::EOpMin3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMin3AMD; - else { - if (isUnsigned) - libCall = spv::UMin3AMD; - else - libCall = spv::SMin3AMD; - } - break; - case glslang::EOpMax3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMax3AMD; - else { - if (isUnsigned) - libCall = spv::UMax3AMD; - else - libCall = spv::SMax3AMD; - } - break; - case glslang::EOpMid3: - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax); - if (isFloat) - libCall = spv::FMid3AMD; - else { - if (isUnsigned) - libCall = spv::UMid3AMD; - else - libCall = spv::SMid3AMD; - } - break; - - case glslang::EOpInterpolateAtVertex: - if (typeProxy == glslang::EbtFloat16) - builder.addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_explicit_vertex_parameter); - libCall = spv::InterpolateAtVertexAMD; - break; - - case glslang::EOpReportIntersection: - typeId = builder.makeBoolType(); - opCode = spv::OpReportIntersectionKHR; - break; - case glslang::EOpTraceNV: - builder.createNoResultOp(spv::OpTraceNV, operands); - return 0; - case glslang::EOpTraceRayMotionNV: - builder.addExtension(spv::E_SPV_NV_ray_tracing_motion_blur); - builder.addCapability(spv::CapabilityRayTracingMotionBlurNV); - builder.createNoResultOp(spv::OpTraceRayMotionNV, operands); - return 0; - case glslang::EOpTraceKHR: - builder.createNoResultOp(spv::OpTraceRayKHR, operands); - return 0; - case glslang::EOpExecuteCallableNV: - builder.createNoResultOp(spv::OpExecuteCallableNV, operands); - return 0; - case glslang::EOpExecuteCallableKHR: - builder.createNoResultOp(spv::OpExecuteCallableKHR, operands); - return 0; - - case glslang::EOpRayQueryInitialize: - builder.createNoResultOp(spv::OpRayQueryInitializeKHR, operands); - return 0; - case glslang::EOpRayQueryTerminate: - builder.createNoResultOp(spv::OpRayQueryTerminateKHR, operands); - return 0; - case glslang::EOpRayQueryGenerateIntersection: - builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR, operands); - return 0; - case glslang::EOpRayQueryConfirmIntersection: - builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR, operands); - return 0; - case glslang::EOpRayQueryProceed: - typeId = builder.makeBoolType(); - opCode = spv::OpRayQueryProceedKHR; - break; - case glslang::EOpRayQueryGetIntersectionType: - typeId = builder.makeUintType(32); - opCode = spv::OpRayQueryGetIntersectionTypeKHR; - break; - case glslang::EOpRayQueryGetRayTMin: - typeId = builder.makeFloatType(32); - opCode = spv::OpRayQueryGetRayTMinKHR; - break; - case glslang::EOpRayQueryGetRayFlags: - typeId = builder.makeIntType(32); - opCode = spv::OpRayQueryGetRayFlagsKHR; - break; - case glslang::EOpRayQueryGetIntersectionT: - typeId = builder.makeFloatType(32); - opCode = spv::OpRayQueryGetIntersectionTKHR; - break; - case glslang::EOpRayQueryGetIntersectionInstanceCustomIndex: - typeId = builder.makeIntType(32); - opCode = spv::OpRayQueryGetIntersectionInstanceCustomIndexKHR; - break; - case glslang::EOpRayQueryGetIntersectionInstanceId: - typeId = builder.makeIntType(32); - opCode = spv::OpRayQueryGetIntersectionInstanceIdKHR; - break; - case glslang::EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: - typeId = builder.makeUintType(32); - opCode = spv::OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR; - break; - case glslang::EOpRayQueryGetIntersectionGeometryIndex: - typeId = builder.makeIntType(32); - opCode = spv::OpRayQueryGetIntersectionGeometryIndexKHR; - break; - case glslang::EOpRayQueryGetIntersectionPrimitiveIndex: - typeId = builder.makeIntType(32); - opCode = spv::OpRayQueryGetIntersectionPrimitiveIndexKHR; - break; - case glslang::EOpRayQueryGetIntersectionBarycentrics: - typeId = builder.makeVectorType(builder.makeFloatType(32), 2); - opCode = spv::OpRayQueryGetIntersectionBarycentricsKHR; - break; - case glslang::EOpRayQueryGetIntersectionFrontFace: - typeId = builder.makeBoolType(); - opCode = spv::OpRayQueryGetIntersectionFrontFaceKHR; - break; - case glslang::EOpRayQueryGetIntersectionCandidateAABBOpaque: - typeId = builder.makeBoolType(); - opCode = spv::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR; - break; - case glslang::EOpRayQueryGetIntersectionObjectRayDirection: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpRayQueryGetIntersectionObjectRayDirectionKHR; - break; - case glslang::EOpRayQueryGetIntersectionObjectRayOrigin: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpRayQueryGetIntersectionObjectRayOriginKHR; - break; - case glslang::EOpRayQueryGetWorldRayDirection: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpRayQueryGetWorldRayDirectionKHR; - break; - case glslang::EOpRayQueryGetWorldRayOrigin: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpRayQueryGetWorldRayOriginKHR; - break; - case glslang::EOpRayQueryGetIntersectionObjectToWorld: - typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); - opCode = spv::OpRayQueryGetIntersectionObjectToWorldKHR; - break; - case glslang::EOpRayQueryGetIntersectionWorldToObject: - typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); - opCode = spv::OpRayQueryGetIntersectionWorldToObjectKHR; - break; - case glslang::EOpWritePackedPrimitiveIndices4x8NV: - builder.createNoResultOp(spv::OpWritePackedPrimitiveIndices4x8NV, operands); - return 0; - case glslang::EOpEmitMeshTasksEXT: - if (taskPayloadID) - operands.push_back(taskPayloadID); - // As per SPV_EXT_mesh_shader make it a terminating instruction in the current block - builder.makeStatementTerminator(spv::OpEmitMeshTasksEXT, operands, "post-OpEmitMeshTasksEXT"); - return 0; - case glslang::EOpSetMeshOutputsEXT: - builder.createNoResultOp(spv::OpSetMeshOutputsEXT, operands); - return 0; - case glslang::EOpCooperativeMatrixMulAddNV: - opCode = spv::OpCooperativeMatrixMulAddNV; - break; - case glslang::EOpHitObjectTraceRayNV: - builder.createNoResultOp(spv::OpHitObjectTraceRayNV, operands); - return 0; - case glslang::EOpHitObjectTraceRayMotionNV: - builder.createNoResultOp(spv::OpHitObjectTraceRayMotionNV, operands); - return 0; - case glslang::EOpHitObjectRecordHitNV: - builder.createNoResultOp(spv::OpHitObjectRecordHitNV, operands); - return 0; - case glslang::EOpHitObjectRecordHitMotionNV: - builder.createNoResultOp(spv::OpHitObjectRecordHitMotionNV, operands); - return 0; - case glslang::EOpHitObjectRecordHitWithIndexNV: - builder.createNoResultOp(spv::OpHitObjectRecordHitWithIndexNV, operands); - return 0; - case glslang::EOpHitObjectRecordHitWithIndexMotionNV: - builder.createNoResultOp(spv::OpHitObjectRecordHitWithIndexMotionNV, operands); - return 0; - case glslang::EOpHitObjectRecordMissNV: - builder.createNoResultOp(spv::OpHitObjectRecordMissNV, operands); - return 0; - case glslang::EOpHitObjectRecordMissMotionNV: - builder.createNoResultOp(spv::OpHitObjectRecordMissMotionNV, operands); - return 0; - case glslang::EOpHitObjectExecuteShaderNV: - builder.createNoResultOp(spv::OpHitObjectExecuteShaderNV, operands); - return 0; - case glslang::EOpHitObjectIsEmptyNV: - typeId = builder.makeBoolType(); - opCode = spv::OpHitObjectIsEmptyNV; - break; - case glslang::EOpHitObjectIsMissNV: - typeId = builder.makeBoolType(); - opCode = spv::OpHitObjectIsMissNV; - break; - case glslang::EOpHitObjectIsHitNV: - typeId = builder.makeBoolType(); - opCode = spv::OpHitObjectIsHitNV; - break; - case glslang::EOpHitObjectGetRayTMinNV: - typeId = builder.makeFloatType(32); - opCode = spv::OpHitObjectGetRayTMinNV; - break; - case glslang::EOpHitObjectGetRayTMaxNV: - typeId = builder.makeFloatType(32); - opCode = spv::OpHitObjectGetRayTMaxNV; - break; - case glslang::EOpHitObjectGetObjectRayOriginNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpHitObjectGetObjectRayOriginNV; - break; - case glslang::EOpHitObjectGetObjectRayDirectionNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpHitObjectGetObjectRayDirectionNV; - break; - case glslang::EOpHitObjectGetWorldRayOriginNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpHitObjectGetWorldRayOriginNV; - break; - case glslang::EOpHitObjectGetWorldRayDirectionNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpHitObjectGetWorldRayDirectionNV; - break; - case glslang::EOpHitObjectGetWorldToObjectNV: - typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); - opCode = spv::OpHitObjectGetWorldToObjectNV; - break; - case glslang::EOpHitObjectGetObjectToWorldNV: - typeId = builder.makeMatrixType(builder.makeFloatType(32), 4, 3); - opCode = spv::OpHitObjectGetObjectToWorldNV; - break; - case glslang::EOpHitObjectGetInstanceCustomIndexNV: - typeId = builder.makeIntegerType(32, 1); - opCode = spv::OpHitObjectGetInstanceCustomIndexNV; - break; - case glslang::EOpHitObjectGetInstanceIdNV: - typeId = builder.makeIntegerType(32, 1); - opCode = spv::OpHitObjectGetInstanceIdNV; - break; - case glslang::EOpHitObjectGetGeometryIndexNV: - typeId = builder.makeIntegerType(32, 1); - opCode = spv::OpHitObjectGetGeometryIndexNV; - break; - case glslang::EOpHitObjectGetPrimitiveIndexNV: - typeId = builder.makeIntegerType(32, 1); - opCode = spv::OpHitObjectGetPrimitiveIndexNV; - break; - case glslang::EOpHitObjectGetHitKindNV: - typeId = builder.makeIntegerType(32, 0); - opCode = spv::OpHitObjectGetHitKindNV; - break; - case glslang::EOpHitObjectGetCurrentTimeNV: - typeId = builder.makeFloatType(32); - opCode = spv::OpHitObjectGetCurrentTimeNV; - break; - case glslang::EOpHitObjectGetShaderBindingTableRecordIndexNV: - typeId = builder.makeIntegerType(32, 0); - opCode = spv::OpHitObjectGetShaderBindingTableRecordIndexNV; - return 0; - case glslang::EOpHitObjectGetAttributesNV: - builder.createNoResultOp(spv::OpHitObjectGetAttributesNV, operands); - return 0; - case glslang::EOpHitObjectGetShaderRecordBufferHandleNV: - typeId = builder.makeVectorType(builder.makeUintType(32), 2); - opCode = spv::OpHitObjectGetShaderRecordBufferHandleNV; - break; - case glslang::EOpReorderThreadNV: { - if (operands.size() == 2) { - builder.createNoResultOp(spv::OpReorderThreadWithHintNV, operands); - } else { - builder.createNoResultOp(spv::OpReorderThreadWithHitObjectNV, operands); - } - return 0; - - } - - case glslang::EOpImageSampleWeightedQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageSampleWeightedQCOM; - addImageProcessingQCOMDecoration(operands[2], spv::DecorationWeightTextureQCOM); - break; - case glslang::EOpImageBoxFilterQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageBoxFilterQCOM; - break; - case glslang::EOpImageBlockMatchSADQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageBlockMatchSADQCOM; - addImageProcessingQCOMDecoration(operands[0], spv::DecorationBlockMatchTextureQCOM); - addImageProcessingQCOMDecoration(operands[2], spv::DecorationBlockMatchTextureQCOM); - break; - case glslang::EOpImageBlockMatchSSDQCOM: - typeId = builder.makeVectorType(builder.makeFloatType(32), 4); - opCode = spv::OpImageBlockMatchSSDQCOM; - addImageProcessingQCOMDecoration(operands[0], spv::DecorationBlockMatchTextureQCOM); - addImageProcessingQCOMDecoration(operands[2], spv::DecorationBlockMatchTextureQCOM); - break; - - case glslang::EOpFetchMicroTriangleVertexBarycentricNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 2); - opCode = spv::OpFetchMicroTriangleVertexBarycentricNV; - break; - - case glslang::EOpFetchMicroTriangleVertexPositionNV: - typeId = builder.makeVectorType(builder.makeFloatType(32), 3); - opCode = spv::OpFetchMicroTriangleVertexPositionNV; - break; - - default: - return 0; - } - - spv::Id id = 0; - if (libCall >= 0) { - // Use an extended instruction from the standard library. - // Construct the call arguments, without modifying the original operands vector. - // We might need the remaining arguments, e.g. in the EOpFrexp case. - std::vector callArguments(operands.begin(), operands.begin() + consumedOperands); - id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, callArguments); - } else if (opCode == spv::OpDot && !isFloat) { - // int dot(int, int) - // NOTE: never called for scalar/vector1, this is turned into simple mul before this can be reached - const int componentCount = builder.getNumComponents(operands[0]); - spv::Id mulOp = builder.createBinOp(spv::OpIMul, builder.getTypeId(operands[0]), operands[0], operands[1]); - builder.setPrecision(mulOp, precision); - id = builder.createCompositeExtract(mulOp, typeId, 0); - for (int i = 1; i < componentCount; ++i) { - builder.setPrecision(id, precision); - id = builder.createBinOp(spv::OpIAdd, typeId, id, builder.createCompositeExtract(mulOp, typeId, i)); - } - } else { - switch (consumedOperands) { - case 0: - // should all be handled by visitAggregate and createNoArgOperation - assert(0); - return 0; - case 1: - // should all be handled by createUnaryOperation - assert(0); - return 0; - case 2: - id = builder.createBinOp(opCode, typeId, operands[0], operands[1]); - break; - default: - // anything 3 or over doesn't have l-value operands, so all should be consumed - assert(consumedOperands == operands.size()); - id = builder.createOp(opCode, typeId, operands); - break; - } - } - - // Decode the return types that were structures - switch (op) { - case glslang::EOpAddCarry: - case glslang::EOpSubBorrow: - builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]); - id = builder.createCompositeExtract(id, typeId0, 0); - break; - case glslang::EOpUMulExtended: - case glslang::EOpIMulExtended: - builder.createStore(builder.createCompositeExtract(id, typeId0, 0), operands[3]); - builder.createStore(builder.createCompositeExtract(id, typeId0, 1), operands[2]); - break; - case glslang::EOpFrexp: - { - assert(operands.size() == 2); - if (builder.isFloatType(builder.getScalarTypeId(typeId1))) { - // "exp" is floating-point type (from HLSL intrinsic) - spv::Id member1 = builder.createCompositeExtract(id, frexpIntType, 1); - member1 = builder.createUnaryOp(spv::OpConvertSToF, typeId1, member1); - builder.createStore(member1, operands[1]); - } else - // "exp" is integer type (from GLSL built-in function) - builder.createStore(builder.createCompositeExtract(id, frexpIntType, 1), operands[1]); - id = builder.createCompositeExtract(id, typeId0, 0); - } - break; - default: - break; - } - - return builder.setPrecision(id, precision); -} - -// Intrinsics with no arguments (or no return value, and no precision). -spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId) -{ - // GLSL memory barriers use queuefamily scope in new model, device scope in old model - spv::Scope memoryBarrierScope = glslangIntermediate->usingVulkanMemoryModel() ? - spv::ScopeQueueFamilyKHR : spv::ScopeDevice; - - switch (op) { - case glslang::EOpBarrier: - if (glslangIntermediate->getStage() == EShLangTessControl) { - if (glslangIntermediate->usingVulkanMemoryModel()) { - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, - spv::MemorySemanticsOutputMemoryKHRMask | - spv::MemorySemanticsAcquireReleaseMask); - builder.addCapability(spv::CapabilityVulkanMemoryModelKHR); - } else { - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeInvocation, spv::MemorySemanticsMaskNone); - } - } else { - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, - spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - } - return 0; - case glslang::EOpMemoryBarrier: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierBuffer: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierShared: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpGroupMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierAtomicCounter: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsAtomicCounterMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpMemoryBarrierImage: - builder.createMemoryBarrier(memoryBarrierScope, spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpAllMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice, - spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpDeviceMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpDeviceMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpWorkgroupMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeWorkgroup, spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpWorkgroupMemoryBarrierWithGroupSync: - builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, - spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return 0; - case glslang::EOpSubgroupBarrier: - builder.createControlBarrier(spv::ScopeSubgroup, spv::ScopeSubgroup, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrier: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsAllMemory | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrierBuffer: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsUniformMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrierImage: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsImageMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - case glslang::EOpSubgroupMemoryBarrierShared: - builder.createMemoryBarrier(spv::ScopeSubgroup, spv::MemorySemanticsWorkgroupMemoryMask | - spv::MemorySemanticsAcquireReleaseMask); - return spv::NoResult; - - case glslang::EOpEmitVertex: - builder.createNoResultOp(spv::OpEmitVertex); - return 0; - case glslang::EOpEndPrimitive: - builder.createNoResultOp(spv::OpEndPrimitive); - return 0; - - case glslang::EOpSubgroupElect: { - std::vector operands; - return createSubgroupOperation(op, typeId, operands, glslang::EbtVoid); - } - case glslang::EOpTime: - { - std::vector args; // Dummy arguments - spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args); - return builder.setPrecision(id, precision); - } - case glslang::EOpIgnoreIntersectionNV: - builder.createNoResultOp(spv::OpIgnoreIntersectionNV); - return 0; - case glslang::EOpTerminateRayNV: - builder.createNoResultOp(spv::OpTerminateRayNV); - return 0; - case glslang::EOpRayQueryInitialize: - builder.createNoResultOp(spv::OpRayQueryInitializeKHR); - return 0; - case glslang::EOpRayQueryTerminate: - builder.createNoResultOp(spv::OpRayQueryTerminateKHR); - return 0; - case glslang::EOpRayQueryGenerateIntersection: - builder.createNoResultOp(spv::OpRayQueryGenerateIntersectionKHR); - return 0; - case glslang::EOpRayQueryConfirmIntersection: - builder.createNoResultOp(spv::OpRayQueryConfirmIntersectionKHR); - return 0; - case glslang::EOpBeginInvocationInterlock: - builder.createNoResultOp(spv::OpBeginInvocationInterlockEXT); - return 0; - case glslang::EOpEndInvocationInterlock: - builder.createNoResultOp(spv::OpEndInvocationInterlockEXT); - return 0; - - case glslang::EOpIsHelperInvocation: - { - std::vector args; // Dummy arguments - builder.addExtension(spv::E_SPV_EXT_demote_to_helper_invocation); - builder.addCapability(spv::CapabilityDemoteToHelperInvocationEXT); - return builder.createOp(spv::OpIsHelperInvocationEXT, typeId, args); - } - - case glslang::EOpReadClockSubgroupKHR: { - std::vector args; - args.push_back(builder.makeUintConstant(spv::ScopeSubgroup)); - builder.addExtension(spv::E_SPV_KHR_shader_clock); - builder.addCapability(spv::CapabilityShaderClockKHR); - return builder.createOp(spv::OpReadClockKHR, typeId, args); - } - - case glslang::EOpReadClockDeviceKHR: { - std::vector args; - args.push_back(builder.makeUintConstant(spv::ScopeDevice)); - builder.addExtension(spv::E_SPV_KHR_shader_clock); - builder.addCapability(spv::CapabilityShaderClockKHR); - return builder.createOp(spv::OpReadClockKHR, typeId, args); - } - case glslang::EOpStencilAttachmentReadEXT: - case glslang::EOpDepthAttachmentReadEXT: - { - builder.addExtension(spv::E_SPV_EXT_shader_tile_image); - - spv::Decoration precision; - spv::Op spv_op; - if (op == glslang::EOpStencilAttachmentReadEXT) - { - precision = spv::DecorationRelaxedPrecision; - spv_op = spv::OpStencilAttachmentReadEXT; - builder.addCapability(spv::CapabilityTileImageStencilReadAccessEXT); - } - else - { - precision = spv::NoPrecision; - spv_op = spv::OpDepthAttachmentReadEXT; - builder.addCapability(spv::CapabilityTileImageDepthReadAccessEXT); - } - - std::vector args; // Dummy args - spv::Id result = builder.createOp(spv_op, typeId, args); - return builder.setPrecision(result, precision); - } - default: - break; - } - - logger->missingFunctionality("unknown operation with no arguments"); - - return 0; -} - -spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol) -{ - auto iter = symbolValues.find(symbol->getId()); - spv::Id id; - if (symbolValues.end() != iter) { - id = iter->second; - return id; - } - - // it was not found, create it - spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn, false); - auto forcedType = getForcedType(symbol->getQualifier().builtIn, symbol->getType()); - - // There are pairs of symbols that map to the same SPIR-V built-in: - // gl_ObjectToWorldEXT and gl_ObjectToWorld3x4EXT, and gl_WorldToObjectEXT - // and gl_WorldToObject3x4EXT. SPIR-V forbids having two OpVariables - // with the same BuiltIn in the same storage class, so we must re-use one. - const bool mayNeedToReuseBuiltIn = - builtIn == spv::BuiltInObjectToWorldKHR || - builtIn == spv::BuiltInWorldToObjectKHR; - - if (mayNeedToReuseBuiltIn) { - auto iter = builtInVariableIds.find(uint32_t(builtIn)); - if (builtInVariableIds.end() != iter) { - id = iter->second; - symbolValues[symbol->getId()] = id; - if (forcedType.second != spv::NoType) - forceType[id] = forcedType.second; - return id; - } - } - - id = createSpvVariable(symbol, forcedType.first); - - if (mayNeedToReuseBuiltIn) { - builtInVariableIds.insert({uint32_t(builtIn), id}); - } - - symbolValues[symbol->getId()] = id; - if (forcedType.second != spv::NoType) - forceType[id] = forcedType.second; - - if (symbol->getBasicType() != glslang::EbtBlock) { - builder.addDecoration(id, TranslatePrecisionDecoration(symbol->getType())); - builder.addDecoration(id, TranslateInterpolationDecoration(symbol->getType().getQualifier())); - builder.addDecoration(id, TranslateAuxiliaryStorageDecoration(symbol->getType().getQualifier())); - addMeshNVDecoration(id, /*member*/ -1, symbol->getType().getQualifier()); - if (symbol->getQualifier().hasComponent()) - builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent); - if (symbol->getQualifier().hasIndex()) - builder.addDecoration(id, spv::DecorationIndex, symbol->getQualifier().layoutIndex); - if (symbol->getType().getQualifier().hasSpecConstantId()) - builder.addDecoration(id, spv::DecorationSpecId, symbol->getType().getQualifier().layoutSpecConstantId); - // atomic counters use this: - if (symbol->getQualifier().hasOffset()) - builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutOffset); - } - - if (symbol->getQualifier().hasLocation()) { - if (!(glslangIntermediate->isRayTracingStage() && - (glslangIntermediate->IsRequestedExtension(glslang::E_GL_EXT_ray_tracing) || - glslangIntermediate->IsRequestedExtension(glslang::E_GL_NV_shader_invocation_reorder)) - && (builder.getStorageClass(id) == spv::StorageClassRayPayloadKHR || - builder.getStorageClass(id) == spv::StorageClassIncomingRayPayloadKHR || - builder.getStorageClass(id) == spv::StorageClassCallableDataKHR || - builder.getStorageClass(id) == spv::StorageClassIncomingCallableDataKHR || - builder.getStorageClass(id) == spv::StorageClassHitObjectAttributeNV))) { - // Location values are used to link TraceRayKHR/ExecuteCallableKHR/HitObjectGetAttributesNV - // to corresponding variables but are not valid in SPIRV since they are supported only - // for Input/Output Storage classes. - builder.addDecoration(id, spv::DecorationLocation, symbol->getQualifier().layoutLocation); - } - } - - builder.addDecoration(id, TranslateInvariantDecoration(symbol->getType().getQualifier())); - if (symbol->getQualifier().hasStream() && glslangIntermediate->isMultiStream()) { - builder.addCapability(spv::CapabilityGeometryStreams); - builder.addDecoration(id, spv::DecorationStream, symbol->getQualifier().layoutStream); - } - if (symbol->getQualifier().hasSet()) - builder.addDecoration(id, spv::DecorationDescriptorSet, symbol->getQualifier().layoutSet); - else if (IsDescriptorResource(symbol->getType())) { - // default to 0 - builder.addDecoration(id, spv::DecorationDescriptorSet, 0); - } - if (symbol->getQualifier().hasBinding()) - builder.addDecoration(id, spv::DecorationBinding, symbol->getQualifier().layoutBinding); - else if (IsDescriptorResource(symbol->getType())) { - // default to 0 - builder.addDecoration(id, spv::DecorationBinding, 0); - } - if (symbol->getQualifier().hasAttachment()) - builder.addDecoration(id, spv::DecorationInputAttachmentIndex, symbol->getQualifier().layoutAttachment); - if (glslangIntermediate->getXfbMode()) { - builder.addCapability(spv::CapabilityTransformFeedback); - if (symbol->getQualifier().hasXfbBuffer()) { - builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer); - unsigned stride = glslangIntermediate->getXfbStride(symbol->getQualifier().layoutXfbBuffer); - if (stride != glslang::TQualifier::layoutXfbStrideEnd) - builder.addDecoration(id, spv::DecorationXfbStride, stride); - } - if (symbol->getQualifier().hasXfbOffset()) - builder.addDecoration(id, spv::DecorationOffset, symbol->getQualifier().layoutXfbOffset); - } - - // add built-in variable decoration - if (builtIn != spv::BuiltInMax) { - // WorkgroupSize deprecated in spirv1.6 - if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_6 || - builtIn != spv::BuiltInWorkgroupSize) - builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn); - } - - // Add volatile decoration to HelperInvocation for spirv1.6 and beyond - if (builtIn == spv::BuiltInHelperInvocation && - !glslangIntermediate->usingVulkanMemoryModel() && - glslangIntermediate->getSpv().spv >= glslang::EShTargetSpv_1_6) { - builder.addDecoration(id, spv::DecorationVolatile); - } - - // Subgroup builtins which have input storage class are volatile for ray tracing stages. - if (symbol->getType().isImage() || symbol->getQualifier().isPipeInput()) { - std::vector memory; - TranslateMemoryDecoration(symbol->getType().getQualifier(), memory, - glslangIntermediate->usingVulkanMemoryModel()); - for (unsigned int i = 0; i < memory.size(); ++i) - builder.addDecoration(id, memory[i]); - } - - if (builtIn == spv::BuiltInSampleMask) { - spv::Decoration decoration; - // GL_NV_sample_mask_override_coverage extension - if (glslangIntermediate->getLayoutOverrideCoverage()) - decoration = (spv::Decoration)spv::DecorationOverrideCoverageNV; - else - decoration = (spv::Decoration)spv::DecorationMax; - builder.addDecoration(id, decoration); - if (decoration != spv::DecorationMax) { - builder.addCapability(spv::CapabilitySampleMaskOverrideCoverageNV); - builder.addExtension(spv::E_SPV_NV_sample_mask_override_coverage); - } - } - else if (builtIn == spv::BuiltInLayer) { - // SPV_NV_viewport_array2 extension - if (symbol->getQualifier().layoutViewportRelative) { - builder.addDecoration(id, (spv::Decoration)spv::DecorationViewportRelativeNV); - builder.addCapability(spv::CapabilityShaderViewportMaskNV); - builder.addExtension(spv::E_SPV_NV_viewport_array2); - } - if (symbol->getQualifier().layoutSecondaryViewportRelativeOffset != -2048) { - builder.addDecoration(id, (spv::Decoration)spv::DecorationSecondaryViewportRelativeNV, - symbol->getQualifier().layoutSecondaryViewportRelativeOffset); - builder.addCapability(spv::CapabilityShaderStereoViewNV); - builder.addExtension(spv::E_SPV_NV_stereo_view_rendering); - } - } - - if (symbol->getQualifier().layoutPassthrough) { - builder.addDecoration(id, spv::DecorationPassthroughNV); - builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV); - builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough); - } - if (symbol->getQualifier().pervertexNV) { - builder.addDecoration(id, spv::DecorationPerVertexNV); - builder.addCapability(spv::CapabilityFragmentBarycentricNV); - builder.addExtension(spv::E_SPV_NV_fragment_shader_barycentric); - } - - if (symbol->getQualifier().pervertexEXT) { - builder.addDecoration(id, spv::DecorationPerVertexKHR); - builder.addCapability(spv::CapabilityFragmentBarycentricKHR); - builder.addExtension(spv::E_SPV_KHR_fragment_shader_barycentric); - } - - if (glslangIntermediate->getHlslFunctionality1() && symbol->getType().getQualifier().semanticName != nullptr) { - builder.addExtension("SPV_GOOGLE_hlsl_functionality1"); - builder.addDecoration(id, (spv::Decoration)spv::DecorationHlslSemanticGOOGLE, - symbol->getType().getQualifier().semanticName); - } - - if (symbol->isReference()) { - builder.addDecoration(id, symbol->getType().getQualifier().restrict ? - spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT); - } - - // Add SPIR-V decorations (GL_EXT_spirv_intrinsics) - if (symbol->getType().getQualifier().hasSpirvDecorate()) - applySpirvDecorate(symbol->getType(), id, {}); - - return id; -} - -// add per-primitive, per-view. per-task decorations to a struct member (member >= 0) or an object -void TGlslangToSpvTraverser::addMeshNVDecoration(spv::Id id, int member, const glslang::TQualifier& qualifier) -{ - bool isMeshShaderExt = (glslangIntermediate->getRequestedExtensions().find(glslang::E_GL_EXT_mesh_shader) != - glslangIntermediate->getRequestedExtensions().end()); - - if (member >= 0) { - if (qualifier.perPrimitiveNV) { - // Need to add capability/extension for fragment shader. - // Mesh shader already adds this by default. - if (glslangIntermediate->getStage() == EShLangFragment) { - if(isMeshShaderExt) { - builder.addCapability(spv::CapabilityMeshShadingEXT); - builder.addExtension(spv::E_SPV_EXT_mesh_shader); - } else { - builder.addCapability(spv::CapabilityMeshShadingNV); - builder.addExtension(spv::E_SPV_NV_mesh_shader); - } - } - builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerPrimitiveNV); - } - if (qualifier.perViewNV) - builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerViewNV); - if (qualifier.perTaskNV) - builder.addMemberDecoration(id, (unsigned)member, spv::DecorationPerTaskNV); - } else { - if (qualifier.perPrimitiveNV) { - // Need to add capability/extension for fragment shader. - // Mesh shader already adds this by default. - if (glslangIntermediate->getStage() == EShLangFragment) { - if(isMeshShaderExt) { - builder.addCapability(spv::CapabilityMeshShadingEXT); - builder.addExtension(spv::E_SPV_EXT_mesh_shader); - } else { - builder.addCapability(spv::CapabilityMeshShadingNV); - builder.addExtension(spv::E_SPV_NV_mesh_shader); - } - } - builder.addDecoration(id, spv::DecorationPerPrimitiveNV); - } - if (qualifier.perViewNV) - builder.addDecoration(id, spv::DecorationPerViewNV); - if (qualifier.perTaskNV) - builder.addDecoration(id, spv::DecorationPerTaskNV); - } -} - -void TGlslangToSpvTraverser::addImageProcessingQCOMDecoration(spv::Id id, spv::Decoration decor) -{ - spv::Op opc = builder.getOpCode(id); - if (opc == spv::OpSampledImage) { - id = builder.getIdOperand(id, 0); - opc = builder.getOpCode(id); - } - - if (opc == spv::OpLoad) { - spv::Id texid = builder.getIdOperand(id, 0); - builder.addDecoration(texid, decor); - } -} - -// Make a full tree of instructions to build a SPIR-V specialization constant, -// or regular constant if possible. -// -// TBD: this is not yet done, nor verified to be the best design, it does do the leaf symbols though -// -// Recursively walk the nodes. The nodes form a tree whose leaves are -// regular constants, which themselves are trees that createSpvConstant() -// recursively walks. So, this function walks the "top" of the tree: -// - emit specialization constant-building instructions for specConstant -// - when running into a non-spec-constant, switch to createSpvConstant() -spv::Id TGlslangToSpvTraverser::createSpvConstant(const glslang::TIntermTyped& node) -{ - assert(node.getQualifier().isConstant()); - - // Handle front-end constants first (non-specialization constants). - if (! node.getQualifier().specConstant) { - // hand off to the non-spec-constant path - assert(node.getAsConstantUnion() != nullptr || node.getAsSymbolNode() != nullptr); - int nextConst = 0; - return createSpvConstantFromConstUnionArray(node.getType(), node.getAsConstantUnion() ? - node.getAsConstantUnion()->getConstArray() : node.getAsSymbolNode()->getConstArray(), - nextConst, false); - } - - // We now know we have a specialization constant to build - - // Extra capabilities may be needed. - if (node.getType().contains8BitInt()) - builder.addCapability(spv::CapabilityInt8); - if (node.getType().contains16BitFloat()) - builder.addCapability(spv::CapabilityFloat16); - if (node.getType().contains16BitInt()) - builder.addCapability(spv::CapabilityInt16); - if (node.getType().contains64BitInt()) - builder.addCapability(spv::CapabilityInt64); - if (node.getType().containsDouble()) - builder.addCapability(spv::CapabilityFloat64); - - // gl_WorkGroupSize is a special case until the front-end handles hierarchical specialization constants, - // even then, it's specialization ids are handled by special case syntax in GLSL: layout(local_size_x = ... - if (node.getType().getQualifier().builtIn == glslang::EbvWorkGroupSize) { - std::vector dimConstId; - for (int dim = 0; dim < 3; ++dim) { - bool specConst = (glslangIntermediate->getLocalSizeSpecId(dim) != glslang::TQualifier::layoutNotSet); - dimConstId.push_back(builder.makeUintConstant(glslangIntermediate->getLocalSize(dim), specConst)); - if (specConst) { - builder.addDecoration(dimConstId.back(), spv::DecorationSpecId, - glslangIntermediate->getLocalSizeSpecId(dim)); - } - } - return builder.makeCompositeConstant(builder.makeVectorType(builder.makeUintType(32), 3), dimConstId, true); - } - - // An AST node labelled as specialization constant should be a symbol node. - // Its initializer should either be a sub tree with constant nodes, or a constant union array. - if (auto* sn = node.getAsSymbolNode()) { - spv::Id result; - if (auto* sub_tree = sn->getConstSubtree()) { - // Traverse the constant constructor sub tree like generating normal run-time instructions. - // During the AST traversal, if the node is marked as 'specConstant', SpecConstantOpModeGuard - // will set the builder into spec constant op instruction generating mode. - sub_tree->traverse(this); - result = accessChainLoad(sub_tree->getType()); - } else if (auto* const_union_array = &sn->getConstArray()) { - int nextConst = 0; - result = createSpvConstantFromConstUnionArray(sn->getType(), *const_union_array, nextConst, true); - } else { - logger->missingFunctionality("Invalid initializer for spec onstant."); - return spv::NoResult; - } - builder.addName(result, sn->getName().c_str()); - return result; - } - - // Neither a front-end constant node, nor a specialization constant node with constant union array or - // constant sub tree as initializer. - logger->missingFunctionality("Neither a front-end constant nor a spec constant."); - return spv::NoResult; -} - -// Use 'consts' as the flattened glslang source of scalar constants to recursively -// build the aggregate SPIR-V constant. -// -// If there are not enough elements present in 'consts', 0 will be substituted; -// an empty 'consts' can be used to create a fully zeroed SPIR-V constant. -// -spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glslang::TType& glslangType, - const glslang::TConstUnionArray& consts, int& nextConst, bool specConstant) -{ - // vector of constants for SPIR-V - std::vector spvConsts; - - // Type is used for struct and array constants - spv::Id typeId = convertGlslangToSpvType(glslangType); - - if (glslangType.isArray()) { - glslang::TType elementType(glslangType, 0); - for (int i = 0; i < glslangType.getOuterArraySize(); ++i) - spvConsts.push_back(createSpvConstantFromConstUnionArray(elementType, consts, nextConst, false)); - } else if (glslangType.isMatrix()) { - glslang::TType vectorType(glslangType, 0); - for (int col = 0; col < glslangType.getMatrixCols(); ++col) - spvConsts.push_back(createSpvConstantFromConstUnionArray(vectorType, consts, nextConst, false)); - } else if (glslangType.isCoopMat()) { - glslang::TType componentType(glslangType.getBasicType()); - spvConsts.push_back(createSpvConstantFromConstUnionArray(componentType, consts, nextConst, false)); - } else if (glslangType.isStruct()) { - glslang::TVector::const_iterator iter; - for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter) - spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false)); - } else if (glslangType.getVectorSize() > 1) { - for (unsigned int i = 0; i < (unsigned int)glslangType.getVectorSize(); ++i) { - bool zero = nextConst >= consts.size(); - switch (glslangType.getBasicType()) { - case glslang::EbtInt: - spvConsts.push_back(builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst())); - break; - case glslang::EbtUint: - spvConsts.push_back(builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst())); - break; - case glslang::EbtFloat: - spvConsts.push_back(builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst())); - break; - case glslang::EbtBool: - spvConsts.push_back(builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst())); - break; - case glslang::EbtInt8: - builder.addCapability(spv::CapabilityInt8); - spvConsts.push_back(builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const())); - break; - case glslang::EbtUint8: - builder.addCapability(spv::CapabilityInt8); - spvConsts.push_back(builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const())); - break; - case glslang::EbtInt16: - builder.addCapability(spv::CapabilityInt16); - spvConsts.push_back(builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const())); - break; - case glslang::EbtUint16: - builder.addCapability(spv::CapabilityInt16); - spvConsts.push_back(builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const())); - break; - case glslang::EbtInt64: - spvConsts.push_back(builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const())); - break; - case glslang::EbtUint64: - spvConsts.push_back(builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const())); - break; - case glslang::EbtDouble: - spvConsts.push_back(builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst())); - break; - case glslang::EbtFloat16: - builder.addCapability(spv::CapabilityFloat16); - spvConsts.push_back(builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst())); - break; - default: - assert(0); - break; - } - ++nextConst; - } - } else { - // we have a non-aggregate (scalar) constant - bool zero = nextConst >= consts.size(); - spv::Id scalar = 0; - switch (glslangType.getBasicType()) { - case glslang::EbtInt: - scalar = builder.makeIntConstant(zero ? 0 : consts[nextConst].getIConst(), specConstant); - break; - case glslang::EbtUint: - scalar = builder.makeUintConstant(zero ? 0 : consts[nextConst].getUConst(), specConstant); - break; - case glslang::EbtFloat: - scalar = builder.makeFloatConstant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); - break; - case glslang::EbtBool: - scalar = builder.makeBoolConstant(zero ? false : consts[nextConst].getBConst(), specConstant); - break; - case glslang::EbtInt8: - builder.addCapability(spv::CapabilityInt8); - scalar = builder.makeInt8Constant(zero ? 0 : consts[nextConst].getI8Const(), specConstant); - break; - case glslang::EbtUint8: - builder.addCapability(spv::CapabilityInt8); - scalar = builder.makeUint8Constant(zero ? 0 : consts[nextConst].getU8Const(), specConstant); - break; - case glslang::EbtInt16: - builder.addCapability(spv::CapabilityInt16); - scalar = builder.makeInt16Constant(zero ? 0 : consts[nextConst].getI16Const(), specConstant); - break; - case glslang::EbtUint16: - builder.addCapability(spv::CapabilityInt16); - scalar = builder.makeUint16Constant(zero ? 0 : consts[nextConst].getU16Const(), specConstant); - break; - case glslang::EbtInt64: - scalar = builder.makeInt64Constant(zero ? 0 : consts[nextConst].getI64Const(), specConstant); - break; - case glslang::EbtUint64: - scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant); - break; - case glslang::EbtDouble: - scalar = builder.makeDoubleConstant(zero ? 0.0 : consts[nextConst].getDConst(), specConstant); - break; - case glslang::EbtFloat16: - builder.addCapability(spv::CapabilityFloat16); - scalar = builder.makeFloat16Constant(zero ? 0.0F : (float)consts[nextConst].getDConst(), specConstant); - break; - case glslang::EbtReference: - scalar = builder.makeUint64Constant(zero ? 0 : consts[nextConst].getU64Const(), specConstant); - scalar = builder.createUnaryOp(spv::OpBitcast, typeId, scalar); - break; - case glslang::EbtString: - scalar = builder.getStringId(consts[nextConst].getSConst()->c_str()); - break; - default: - assert(0); - break; - } - ++nextConst; - return scalar; - } - - return builder.makeCompositeConstant(typeId, spvConsts); -} - -// Return true if the node is a constant or symbol whose reading has no -// non-trivial observable cost or effect. -bool TGlslangToSpvTraverser::isTrivialLeaf(const glslang::TIntermTyped* node) -{ - // don't know what this is - if (node == nullptr) - return false; - - // a constant is safe - if (node->getAsConstantUnion() != nullptr) - return true; - - // not a symbol means non-trivial - if (node->getAsSymbolNode() == nullptr) - return false; - - // a symbol, depends on what's being read - switch (node->getType().getQualifier().storage) { - case glslang::EvqTemporary: - case glslang::EvqGlobal: - case glslang::EvqIn: - case glslang::EvqInOut: - case glslang::EvqConst: - case glslang::EvqConstReadOnly: - case glslang::EvqUniform: - return true; - default: - return false; - } -} - -// A node is trivial if it is a single operation with no side effects. -// HLSL (and/or vectors) are always trivial, as it does not short circuit. -// Otherwise, error on the side of saying non-trivial. -// Return true if trivial. -bool TGlslangToSpvTraverser::isTrivial(const glslang::TIntermTyped* node) -{ - if (node == nullptr) - return false; - - // count non scalars as trivial, as well as anything coming from HLSL - if (! node->getType().isScalarOrVec1() || glslangIntermediate->getSource() == glslang::EShSourceHlsl) - return true; - - // symbols and constants are trivial - if (isTrivialLeaf(node)) - return true; - - // otherwise, it needs to be a simple operation or one or two leaf nodes - - // not a simple operation - const glslang::TIntermBinary* binaryNode = node->getAsBinaryNode(); - const glslang::TIntermUnary* unaryNode = node->getAsUnaryNode(); - if (binaryNode == nullptr && unaryNode == nullptr) - return false; - - // not on leaf nodes - if (binaryNode && (! isTrivialLeaf(binaryNode->getLeft()) || ! isTrivialLeaf(binaryNode->getRight()))) - return false; - - if (unaryNode && ! isTrivialLeaf(unaryNode->getOperand())) { - return false; - } - - switch (node->getAsOperator()->getOp()) { - case glslang::EOpLogicalNot: - case glslang::EOpConvIntToBool: - case glslang::EOpConvUintToBool: - case glslang::EOpConvFloatToBool: - case glslang::EOpConvDoubleToBool: - case glslang::EOpEqual: - case glslang::EOpNotEqual: - case glslang::EOpLessThan: - case glslang::EOpGreaterThan: - case glslang::EOpLessThanEqual: - case glslang::EOpGreaterThanEqual: - case glslang::EOpIndexDirect: - case glslang::EOpIndexDirectStruct: - case glslang::EOpLogicalXor: - case glslang::EOpAny: - case glslang::EOpAll: - return true; - default: - return false; - } -} - -// Emit short-circuiting code, where 'right' is never evaluated unless -// the left side is true (for &&) or false (for ||). -spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslang::TIntermTyped& left, - glslang::TIntermTyped& right) -{ - spv::Id boolTypeId = builder.makeBoolType(); - - // emit left operand - builder.clearAccessChain(); - left.traverse(this); - spv::Id leftId = accessChainLoad(left.getType()); - - // Operands to accumulate OpPhi operands - std::vector phiOperands; - // accumulate left operand's phi information - phiOperands.push_back(leftId); - phiOperands.push_back(builder.getBuildPoint()->getId()); - - // Make the two kinds of operation symmetric with a "!" - // || => emit "if (! left) result = right" - // && => emit "if ( left) result = right" - // - // TODO: this runtime "not" for || could be avoided by adding functionality - // to 'builder' to have an "else" without an "then" - if (op == glslang::EOpLogicalOr) - leftId = builder.createUnaryOp(spv::OpLogicalNot, boolTypeId, leftId); - - // make an "if" based on the left value - spv::Builder::If ifBuilder(leftId, spv::SelectionControlMaskNone, builder); - - // emit right operand as the "then" part of the "if" - builder.clearAccessChain(); - right.traverse(this); - spv::Id rightId = accessChainLoad(right.getType()); - - // accumulate left operand's phi information - phiOperands.push_back(rightId); - phiOperands.push_back(builder.getBuildPoint()->getId()); - - // finish the "if" - ifBuilder.makeEndIf(); - - // phi together the two results - return builder.createOp(spv::OpPhi, boolTypeId, phiOperands); -} - -// Return type Id of the imported set of extended instructions corresponds to the name. -// Import this set if it has not been imported yet. -spv::Id TGlslangToSpvTraverser::getExtBuiltins(const char* name) -{ - if (extBuiltinMap.find(name) != extBuiltinMap.end()) - return extBuiltinMap[name]; - else { - builder.addExtension(name); - spv::Id extBuiltins = builder.import(name); - extBuiltinMap[name] = extBuiltins; - return extBuiltins; - } -} - -}; // end anonymous namespace - -namespace glslang { - -void GetSpirvVersion(std::string& version) -{ - const int bufSize = 100; - char buf[bufSize]; - snprintf(buf, bufSize, "0x%08x, Revision %d", spv::Version, spv::Revision); - version = buf; -} - -// For low-order part of the generator's magic number. Bump up -// when there is a change in the style (e.g., if SSA form changes, -// or a different instruction sequence to do something gets used). -int GetSpirvGeneratorVersion() -{ - // return 1; // start - // return 2; // EOpAtomicCounterDecrement gets a post decrement, to map between GLSL -> SPIR-V - // return 3; // change/correct barrier-instruction operands, to match memory model group decisions - // return 4; // some deeper access chains: for dynamic vector component, and local Boolean component - // return 5; // make OpArrayLength result type be an int with signedness of 0 - // return 6; // revert version 5 change, which makes a different (new) kind of incorrect code, - // versions 4 and 6 each generate OpArrayLength as it has long been done - // return 7; // GLSL volatile keyword maps to both SPIR-V decorations Volatile and Coherent - // return 8; // switch to new dead block eliminator; use OpUnreachable - // return 9; // don't include opaque function parameters in OpEntryPoint global's operand list - // return 10; // Generate OpFUnordNotEqual for != comparisons - return 11; // Make OpEmitMeshTasksEXT a terminal instruction -} - -// Write SPIR-V out to a binary file -bool OutputSpvBin(const std::vector& spirv, const char* baseName) -{ - std::ofstream out; - out.open(baseName, std::ios::binary | std::ios::out); - if (out.fail()) { - printf("ERROR: Failed to open file: %s\n", baseName); - return false; - } - for (int i = 0; i < (int)spirv.size(); ++i) { - unsigned int word = spirv[i]; - out.write((const char*)&word, 4); - } - out.close(); - return true; -} - -// Write SPIR-V out to a text file with 32-bit hexadecimal words -bool OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName) -{ - std::ofstream out; - out.open(baseName, std::ios::binary | std::ios::out); - if (out.fail()) { - printf("ERROR: Failed to open file: %s\n", baseName); - return false; - } - out << "\t// " << - GetSpirvGeneratorVersion() << - GLSLANG_VERSION_MAJOR << "." << GLSLANG_VERSION_MINOR << "." << GLSLANG_VERSION_PATCH << - GLSLANG_VERSION_FLAVOR << std::endl; - if (varName != nullptr) { - out << "\t #pragma once" << std::endl; - out << "const uint32_t " << varName << "[] = {" << std::endl; - } - const int WORDS_PER_LINE = 8; - for (int i = 0; i < (int)spirv.size(); i += WORDS_PER_LINE) { - out << "\t"; - for (int j = 0; j < WORDS_PER_LINE && i + j < (int)spirv.size(); ++j) { - const unsigned int word = spirv[i + j]; - out << "0x" << std::hex << std::setw(8) << std::setfill('0') << word; - if (i + j + 1 < (int)spirv.size()) { - out << ","; - } - } - out << std::endl; - } - if (varName != nullptr) { - out << "};"; - out << std::endl; - } - out.close(); - return true; -} - -// -// Set up the glslang traversal -// -void GlslangToSpv(const TIntermediate& intermediate, std::vector& spirv, SpvOptions* options) -{ - spv::SpvBuildLogger logger; - GlslangToSpv(intermediate, spirv, &logger, options); -} - -void GlslangToSpv(const TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger* logger, SpvOptions* options) -{ - TIntermNode* root = intermediate.getTreeRoot(); - - if (root == nullptr) - return; - - SpvOptions defaultOptions; - if (options == nullptr) - options = &defaultOptions; - - GetThreadPoolAllocator().push(); - - TGlslangToSpvTraverser it(intermediate.getSpv().spv, &intermediate, logger, *options); - root->traverse(&it); - it.finishSpv(options->compileOnly); - it.dumpSpv(spirv); - -#if ENABLE_OPT - // If from HLSL, run spirv-opt to "legalize" the SPIR-V for Vulkan - // eg. forward and remove memory writes of opaque types. - bool prelegalization = intermediate.getSource() == EShSourceHlsl; - if ((prelegalization || options->optimizeSize) && !options->disableOptimizer) { - SpirvToolsTransform(intermediate, spirv, logger, options); - prelegalization = false; - } - else if (options->stripDebugInfo) { - // Strip debug info even if optimization is disabled. - SpirvToolsStripDebugInfo(intermediate, spirv, logger); - } - - if (options->validate) - SpirvToolsValidate(intermediate, spirv, logger, prelegalization); - - if (options->disassemble) - SpirvToolsDisassemble(std::cout, spirv); - -#endif - - GetThreadPoolAllocator().pop(); -} - -}; // end namespace glslang diff --git a/3rdparty/glslang/SPIRV/GlslangToSpv.h b/3rdparty/glslang/SPIRV/GlslangToSpv.h deleted file mode 100644 index 1b9ef3c5..00000000 --- a/3rdparty/glslang/SPIRV/GlslangToSpv.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (C) 2014 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#pragma once - -#include -#include - -#include "Logger.h" - -namespace glslang { -class TIntermediate; - -struct SpvOptions { - bool generateDebugInfo {false}; - bool stripDebugInfo {false}; - bool disableOptimizer {true}; - bool optimizeSize {false}; - bool disassemble {false}; - bool validate {false}; - bool emitNonSemanticShaderDebugInfo {false}; - bool emitNonSemanticShaderDebugSource{ false }; - bool compileOnly{false}; -}; - -void GetSpirvVersion(std::string&); -int GetSpirvGeneratorVersion(); -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, - SpvOptions* options = nullptr); -void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger* logger, SpvOptions* options = nullptr); -bool OutputSpvBin(const std::vector& spirv, const char* baseName); -bool OutputSpvHex(const std::vector& spirv, const char* baseName, const char* varName); - -} diff --git a/3rdparty/glslang/SPIRV/InReadableOrder.cpp b/3rdparty/glslang/SPIRV/InReadableOrder.cpp deleted file mode 100644 index 9d9410be..00000000 --- a/3rdparty/glslang/SPIRV/InReadableOrder.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// The SPIR-V spec requires code blocks to appear in an order satisfying the -// dominator-tree direction (ie, dominator before the dominated). This is, -// actually, easy to achieve: any pre-order CFG traversal algorithm will do it. -// Because such algorithms visit a block only after traversing some path to it -// from the root, they necessarily visit the block's idom first. -// -// But not every graph-traversal algorithm outputs blocks in an order that -// appears logical to human readers. The problem is that unrelated branches may -// be interspersed with each other, and merge blocks may come before some of the -// branches being merged. -// -// A good, human-readable order of blocks may be achieved by performing -// depth-first search but delaying merge nodes until after all their branches -// have been visited. This is implemented below by the inReadableOrder() -// function. - -#include "spvIR.h" - -#include -#include - -using spv::Block; -using spv::Id; - -namespace { -// Traverses CFG in a readable order, invoking a pre-set callback on each block. -// Use by calling visit() on the root block. -class ReadableOrderTraverser { -public: - ReadableOrderTraverser(std::function callback) - : callback_(callback) {} - // Visits the block if it hasn't been visited already and isn't currently - // being delayed. Invokes callback(block, why, header), then descends into its - // successors. Delays merge-block and continue-block processing until all - // the branches have been completed. If |block| is an unreachable merge block or - // an unreachable continue target, then |header| is the corresponding header block. - void visit(Block* block, spv::ReachReason why, Block* header) - { - assert(block); - if (why == spv::ReachViaControlFlow) { - reachableViaControlFlow_.insert(block); - } - if (visited_.count(block) || delayed_.count(block)) - return; - callback_(block, why, header); - visited_.insert(block); - Block* mergeBlock = nullptr; - Block* continueBlock = nullptr; - auto mergeInst = block->getMergeInstruction(); - if (mergeInst) { - Id mergeId = mergeInst->getIdOperand(0); - mergeBlock = block->getParent().getParent().getInstruction(mergeId)->getBlock(); - delayed_.insert(mergeBlock); - if (mergeInst->getOpCode() == spv::OpLoopMerge) { - Id continueId = mergeInst->getIdOperand(1); - continueBlock = - block->getParent().getParent().getInstruction(continueId)->getBlock(); - delayed_.insert(continueBlock); - } - } - if (why == spv::ReachViaControlFlow) { - const auto& successors = block->getSuccessors(); - for (auto it = successors.cbegin(); it != successors.cend(); ++it) - visit(*it, why, nullptr); - } - if (continueBlock) { - const spv::ReachReason continueWhy = - (reachableViaControlFlow_.count(continueBlock) > 0) - ? spv::ReachViaControlFlow - : spv::ReachDeadContinue; - delayed_.erase(continueBlock); - visit(continueBlock, continueWhy, block); - } - if (mergeBlock) { - const spv::ReachReason mergeWhy = - (reachableViaControlFlow_.count(mergeBlock) > 0) - ? spv::ReachViaControlFlow - : spv::ReachDeadMerge; - delayed_.erase(mergeBlock); - visit(mergeBlock, mergeWhy, block); - } - } - -private: - std::function callback_; - // Whether a block has already been visited or is being delayed. - std::unordered_set visited_, delayed_; - - // The set of blocks that actually are reached via control flow. - std::unordered_set reachableViaControlFlow_; -}; -} - -void spv::inReadableOrder(Block* root, std::function callback) -{ - ReadableOrderTraverser(callback).visit(root, spv::ReachViaControlFlow, nullptr); -} diff --git a/3rdparty/glslang/SPIRV/Logger.cpp b/3rdparty/glslang/SPIRV/Logger.cpp deleted file mode 100644 index 48bd4e3a..00000000 --- a/3rdparty/glslang/SPIRV/Logger.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include "Logger.h" - -#include -#include -#include - -namespace spv { - -void SpvBuildLogger::tbdFunctionality(const std::string& f) -{ - if (std::find(std::begin(tbdFeatures), std::end(tbdFeatures), f) == std::end(tbdFeatures)) - tbdFeatures.push_back(f); -} - -void SpvBuildLogger::missingFunctionality(const std::string& f) -{ - if (std::find(std::begin(missingFeatures), std::end(missingFeatures), f) == std::end(missingFeatures)) - missingFeatures.push_back(f); -} - -std::string SpvBuildLogger::getAllMessages() const { - std::ostringstream messages; - for (auto it = tbdFeatures.cbegin(); it != tbdFeatures.cend(); ++it) - messages << "TBD functionality: " << *it << "\n"; - for (auto it = missingFeatures.cbegin(); it != missingFeatures.cend(); ++it) - messages << "Missing functionality: " << *it << "\n"; - for (auto it = warnings.cbegin(); it != warnings.cend(); ++it) - messages << "warning: " << *it << "\n"; - for (auto it = errors.cbegin(); it != errors.cend(); ++it) - messages << "error: " << *it << "\n"; - return messages.str(); -} - -} // end spv namespace diff --git a/3rdparty/glslang/SPIRV/Logger.h b/3rdparty/glslang/SPIRV/Logger.h deleted file mode 100644 index 2e4ddaf5..00000000 --- a/3rdparty/glslang/SPIRV/Logger.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef GLSLANG_SPIRV_LOGGER_H -#define GLSLANG_SPIRV_LOGGER_H - -#include -#include - -namespace spv { - -// A class for holding all SPIR-V build status messages, including -// missing/TBD functionalities, warnings, and errors. -class SpvBuildLogger { -public: - SpvBuildLogger() {} - - // Registers a TBD functionality. - void tbdFunctionality(const std::string& f); - // Registers a missing functionality. - void missingFunctionality(const std::string& f); - - // Logs a warning. - void warning(const std::string& w) { warnings.push_back(w); } - // Logs an error. - void error(const std::string& e) { errors.push_back(e); } - - // Returns all messages accumulated in the order of: - // TBD functionalities, missing functionalities, warnings, errors. - std::string getAllMessages() const; - -private: - SpvBuildLogger(const SpvBuildLogger&); - - std::vector tbdFeatures; - std::vector missingFeatures; - std::vector warnings; - std::vector errors; -}; - -} // end spv namespace - -#endif // GLSLANG_SPIRV_LOGGER_H diff --git a/3rdparty/glslang/SPIRV/NonSemanticDebugPrintf.h b/3rdparty/glslang/SPIRV/NonSemanticDebugPrintf.h deleted file mode 100644 index 3ca7247f..00000000 --- a/3rdparty/glslang/SPIRV/NonSemanticDebugPrintf.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2020 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_UNIFIED1_NonSemanticDebugPrintf_H_ -#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - NonSemanticDebugPrintfRevision = 1, - NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff -}; - -enum NonSemanticDebugPrintfInstructions { - NonSemanticDebugPrintfDebugPrintf = 1, - NonSemanticDebugPrintfInstructionsMax = 0x7fffffff -}; - - -#ifdef __cplusplus -} -#endif - -#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_ diff --git a/3rdparty/glslang/SPIRV/NonSemanticShaderDebugInfo100.h b/3rdparty/glslang/SPIRV/NonSemanticShaderDebugInfo100.h deleted file mode 100644 index f74abcb6..00000000 --- a/3rdparty/glslang/SPIRV/NonSemanticShaderDebugInfo100.h +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) 2018 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_UNIFIED1_NonSemanticShaderDebugInfo100_H_ -#define SPIRV_UNIFIED1_NonSemanticShaderDebugInfo100_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - NonSemanticShaderDebugInfo100Version = 100, - NonSemanticShaderDebugInfo100Version_BitWidthPadding = 0x7fffffff -}; -enum { - NonSemanticShaderDebugInfo100Revision = 6, - NonSemanticShaderDebugInfo100Revision_BitWidthPadding = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100Instructions { - NonSemanticShaderDebugInfo100DebugInfoNone = 0, - NonSemanticShaderDebugInfo100DebugCompilationUnit = 1, - NonSemanticShaderDebugInfo100DebugTypeBasic = 2, - NonSemanticShaderDebugInfo100DebugTypePointer = 3, - NonSemanticShaderDebugInfo100DebugTypeQualifier = 4, - NonSemanticShaderDebugInfo100DebugTypeArray = 5, - NonSemanticShaderDebugInfo100DebugTypeVector = 6, - NonSemanticShaderDebugInfo100DebugTypedef = 7, - NonSemanticShaderDebugInfo100DebugTypeFunction = 8, - NonSemanticShaderDebugInfo100DebugTypeEnum = 9, - NonSemanticShaderDebugInfo100DebugTypeComposite = 10, - NonSemanticShaderDebugInfo100DebugTypeMember = 11, - NonSemanticShaderDebugInfo100DebugTypeInheritance = 12, - NonSemanticShaderDebugInfo100DebugTypePtrToMember = 13, - NonSemanticShaderDebugInfo100DebugTypeTemplate = 14, - NonSemanticShaderDebugInfo100DebugTypeTemplateParameter = 15, - NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter = 16, - NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack = 17, - NonSemanticShaderDebugInfo100DebugGlobalVariable = 18, - NonSemanticShaderDebugInfo100DebugFunctionDeclaration = 19, - NonSemanticShaderDebugInfo100DebugFunction = 20, - NonSemanticShaderDebugInfo100DebugLexicalBlock = 21, - NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator = 22, - NonSemanticShaderDebugInfo100DebugScope = 23, - NonSemanticShaderDebugInfo100DebugNoScope = 24, - NonSemanticShaderDebugInfo100DebugInlinedAt = 25, - NonSemanticShaderDebugInfo100DebugLocalVariable = 26, - NonSemanticShaderDebugInfo100DebugInlinedVariable = 27, - NonSemanticShaderDebugInfo100DebugDeclare = 28, - NonSemanticShaderDebugInfo100DebugValue = 29, - NonSemanticShaderDebugInfo100DebugOperation = 30, - NonSemanticShaderDebugInfo100DebugExpression = 31, - NonSemanticShaderDebugInfo100DebugMacroDef = 32, - NonSemanticShaderDebugInfo100DebugMacroUndef = 33, - NonSemanticShaderDebugInfo100DebugImportedEntity = 34, - NonSemanticShaderDebugInfo100DebugSource = 35, - NonSemanticShaderDebugInfo100DebugFunctionDefinition = 101, - NonSemanticShaderDebugInfo100DebugSourceContinued = 102, - NonSemanticShaderDebugInfo100DebugLine = 103, - NonSemanticShaderDebugInfo100DebugNoLine = 104, - NonSemanticShaderDebugInfo100DebugBuildIdentifier = 105, - NonSemanticShaderDebugInfo100DebugStoragePath = 106, - NonSemanticShaderDebugInfo100DebugEntryPoint = 107, - NonSemanticShaderDebugInfo100DebugTypeMatrix = 108, - NonSemanticShaderDebugInfo100InstructionsMax = 0x7fffffff -}; - - -enum NonSemanticShaderDebugInfo100DebugInfoFlags { - NonSemanticShaderDebugInfo100None = 0x0000, - NonSemanticShaderDebugInfo100FlagIsProtected = 0x01, - NonSemanticShaderDebugInfo100FlagIsPrivate = 0x02, - NonSemanticShaderDebugInfo100FlagIsPublic = 0x03, - NonSemanticShaderDebugInfo100FlagIsLocal = 0x04, - NonSemanticShaderDebugInfo100FlagIsDefinition = 0x08, - NonSemanticShaderDebugInfo100FlagFwdDecl = 0x10, - NonSemanticShaderDebugInfo100FlagArtificial = 0x20, - NonSemanticShaderDebugInfo100FlagExplicit = 0x40, - NonSemanticShaderDebugInfo100FlagPrototyped = 0x80, - NonSemanticShaderDebugInfo100FlagObjectPointer = 0x100, - NonSemanticShaderDebugInfo100FlagStaticMember = 0x200, - NonSemanticShaderDebugInfo100FlagIndirectVariable = 0x400, - NonSemanticShaderDebugInfo100FlagLValueReference = 0x800, - NonSemanticShaderDebugInfo100FlagRValueReference = 0x1000, - NonSemanticShaderDebugInfo100FlagIsOptimized = 0x2000, - NonSemanticShaderDebugInfo100FlagIsEnumClass = 0x4000, - NonSemanticShaderDebugInfo100FlagTypePassByValue = 0x8000, - NonSemanticShaderDebugInfo100FlagTypePassByReference = 0x10000, - NonSemanticShaderDebugInfo100FlagUnknownPhysicalLayout = 0x20000, - NonSemanticShaderDebugInfo100DebugInfoFlagsMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100BuildIdentifierFlags { - NonSemanticShaderDebugInfo100IdentifierPossibleDuplicates = 0x01, - NonSemanticShaderDebugInfo100BuildIdentifierFlagsMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100DebugBaseTypeAttributeEncoding { - NonSemanticShaderDebugInfo100Unspecified = 0, - NonSemanticShaderDebugInfo100Address = 1, - NonSemanticShaderDebugInfo100Boolean = 2, - NonSemanticShaderDebugInfo100Float = 3, - NonSemanticShaderDebugInfo100Signed = 4, - NonSemanticShaderDebugInfo100SignedChar = 5, - NonSemanticShaderDebugInfo100Unsigned = 6, - NonSemanticShaderDebugInfo100UnsignedChar = 7, - NonSemanticShaderDebugInfo100DebugBaseTypeAttributeEncodingMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100DebugCompositeType { - NonSemanticShaderDebugInfo100Class = 0, - NonSemanticShaderDebugInfo100Structure = 1, - NonSemanticShaderDebugInfo100Union = 2, - NonSemanticShaderDebugInfo100DebugCompositeTypeMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100DebugTypeQualifier { - NonSemanticShaderDebugInfo100ConstType = 0, - NonSemanticShaderDebugInfo100VolatileType = 1, - NonSemanticShaderDebugInfo100RestrictType = 2, - NonSemanticShaderDebugInfo100AtomicType = 3, - NonSemanticShaderDebugInfo100DebugTypeQualifierMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100DebugOperation { - NonSemanticShaderDebugInfo100Deref = 0, - NonSemanticShaderDebugInfo100Plus = 1, - NonSemanticShaderDebugInfo100Minus = 2, - NonSemanticShaderDebugInfo100PlusUconst = 3, - NonSemanticShaderDebugInfo100BitPiece = 4, - NonSemanticShaderDebugInfo100Swap = 5, - NonSemanticShaderDebugInfo100Xderef = 6, - NonSemanticShaderDebugInfo100StackValue = 7, - NonSemanticShaderDebugInfo100Constu = 8, - NonSemanticShaderDebugInfo100Fragment = 9, - NonSemanticShaderDebugInfo100DebugOperationMax = 0x7fffffff -}; - -enum NonSemanticShaderDebugInfo100DebugImportedEntity { - NonSemanticShaderDebugInfo100ImportedModule = 0, - NonSemanticShaderDebugInfo100ImportedDeclaration = 1, - NonSemanticShaderDebugInfo100DebugImportedEntityMax = 0x7fffffff -}; - - -#ifdef __cplusplus -} -#endif - -#endif // SPIRV_UNIFIED1_NonSemanticShaderDebugInfo100_H_ diff --git a/3rdparty/glslang/SPIRV/SPVRemapper.cpp b/3rdparty/glslang/SPIRV/SPVRemapper.cpp deleted file mode 100644 index f8f50a95..00000000 --- a/3rdparty/glslang/SPIRV/SPVRemapper.cpp +++ /dev/null @@ -1,1527 +0,0 @@ -// -// Copyright (C) 2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "SPVRemapper.h" -#include "doc.h" - -#include -#include -#include "../glslang/Include/Common.h" - -namespace spv { - - // By default, just abort on error. Can be overridden via RegisterErrorHandler - spirvbin_t::errorfn_t spirvbin_t::errorHandler = [](const std::string&) { exit(5); }; - // By default, eat log messages. Can be overridden via RegisterLogHandler - spirvbin_t::logfn_t spirvbin_t::logHandler = [](const std::string&) { }; - - // This can be overridden to provide other message behavior if needed - void spirvbin_t::msg(int minVerbosity, int indent, const std::string& txt) const - { - if (verbose >= minVerbosity) - logHandler(std::string(indent, ' ') + txt); - } - - // hash opcode, with special handling for OpExtInst - std::uint32_t spirvbin_t::asOpCodeHash(unsigned word) - { - const spv::Op opCode = asOpCode(word); - - std::uint32_t offset = 0; - - switch (opCode) { - case spv::OpExtInst: - offset += asId(word + 4); break; - default: - break; - } - - return opCode * 19 + offset; // 19 = small prime - } - - spirvbin_t::range_t spirvbin_t::literalRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - switch (opCode) { - case spv::OpTypeFloat: // fall through... - case spv::OpTypePointer: return range_t(2, 3); - case spv::OpTypeInt: return range_t(2, 4); - // TODO: case spv::OpTypeImage: - // TODO: case spv::OpTypeSampledImage: - case spv::OpTypeSampler: return range_t(3, 8); - case spv::OpTypeVector: // fall through - case spv::OpTypeMatrix: // ... - case spv::OpTypePipe: return range_t(3, 4); - case spv::OpConstant: return range_t(3, maxCount); - default: return range_t(0, 0); - } - } - - spirvbin_t::range_t spirvbin_t::typeRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - if (isConstOp(opCode)) - return range_t(1, 2); - - switch (opCode) { - case spv::OpTypeVector: // fall through - case spv::OpTypeMatrix: // ... - case spv::OpTypeSampler: // ... - case spv::OpTypeArray: // ... - case spv::OpTypeRuntimeArray: // ... - case spv::OpTypePipe: return range_t(2, 3); - case spv::OpTypeStruct: // fall through - case spv::OpTypeFunction: return range_t(2, maxCount); - case spv::OpTypePointer: return range_t(3, 4); - default: return range_t(0, 0); - } - } - - spirvbin_t::range_t spirvbin_t::constRange(spv::Op opCode) const - { - static const int maxCount = 1<<30; - - switch (opCode) { - case spv::OpTypeArray: // fall through... - case spv::OpTypeRuntimeArray: return range_t(3, 4); - case spv::OpConstantComposite: return range_t(3, maxCount); - default: return range_t(0, 0); - } - } - - // Return the size of a type in 32-bit words. This currently only - // handles ints and floats, and is only invoked by queries which must be - // integer types. If ever needed, it can be generalized. - unsigned spirvbin_t::typeSizeInWords(spv::Id id) const - { - const unsigned typeStart = idPos(id); - const spv::Op opCode = asOpCode(typeStart); - - if (errorLatch) - return 0; - - switch (opCode) { - case spv::OpTypeInt: // fall through... - case spv::OpTypeFloat: return (spv[typeStart+2]+31)/32; - default: - return 0; - } - } - - // Looks up the type of a given const or variable ID, and - // returns its size in 32-bit words. - unsigned spirvbin_t::idTypeSizeInWords(spv::Id id) const - { - const auto tid_it = idTypeSizeMap.find(id); - if (tid_it == idTypeSizeMap.end()) { - error("type size for ID not found"); - return 0; - } - - return tid_it->second; - } - - // Is this an opcode we should remove when using --strip? - bool spirvbin_t::isStripOp(spv::Op opCode, unsigned start) const - { - switch (opCode) { - case spv::OpSource: - case spv::OpSourceExtension: - case spv::OpName: - case spv::OpMemberName: - case spv::OpLine : - { - const std::string name = literalString(start + 2); - - std::vector::const_iterator it; - for (it = stripWhiteList.begin(); it < stripWhiteList.end(); it++) - { - if (name.find(*it) != std::string::npos) { - return false; - } - } - - return true; - } - default : - return false; - } - } - - // Return true if this opcode is flow control - bool spirvbin_t::isFlowCtrl(spv::Op opCode) const - { - switch (opCode) { - case spv::OpBranchConditional: - case spv::OpBranch: - case spv::OpSwitch: - case spv::OpLoopMerge: - case spv::OpSelectionMerge: - case spv::OpLabel: - case spv::OpFunction: - case spv::OpFunctionEnd: return true; - default: return false; - } - } - - // Return true if this opcode defines a type - bool spirvbin_t::isTypeOp(spv::Op opCode) const - { - switch (opCode) { - case spv::OpTypeVoid: - case spv::OpTypeBool: - case spv::OpTypeInt: - case spv::OpTypeFloat: - case spv::OpTypeVector: - case spv::OpTypeMatrix: - case spv::OpTypeImage: - case spv::OpTypeSampler: - case spv::OpTypeArray: - case spv::OpTypeRuntimeArray: - case spv::OpTypeStruct: - case spv::OpTypeOpaque: - case spv::OpTypePointer: - case spv::OpTypeFunction: - case spv::OpTypeEvent: - case spv::OpTypeDeviceEvent: - case spv::OpTypeReserveId: - case spv::OpTypeQueue: - case spv::OpTypeSampledImage: - case spv::OpTypePipe: return true; - default: return false; - } - } - - // Return true if this opcode defines a constant - bool spirvbin_t::isConstOp(spv::Op opCode) const - { - switch (opCode) { - case spv::OpConstantSampler: - error("unimplemented constant type"); - return true; - - case spv::OpConstantNull: - case spv::OpConstantTrue: - case spv::OpConstantFalse: - case spv::OpConstantComposite: - case spv::OpConstant: - return true; - - default: - return false; - } - } - - const auto inst_fn_nop = [](spv::Op, unsigned) { return false; }; - const auto op_fn_nop = [](spv::Id&) { }; - - // g++ doesn't like these defined in the class proper in an anonymous namespace. - // Dunno why. Also MSVC doesn't like the constexpr keyword. Also dunno why. - // Defining them externally seems to please both compilers, so, here they are. - const spv::Id spirvbin_t::unmapped = spv::Id(-10000); - const spv::Id spirvbin_t::unused = spv::Id(-10001); - const int spirvbin_t::header_size = 5; - - spv::Id spirvbin_t::nextUnusedId(spv::Id id) - { - while (isNewIdMapped(id)) // search for an unused ID - ++id; - - return id; - } - - spv::Id spirvbin_t::localId(spv::Id id, spv::Id newId) - { - //assert(id != spv::NoResult && newId != spv::NoResult); - - if (id > bound()) { - error(std::string("ID out of range: ") + std::to_string(id)); - return spirvbin_t::unused; - } - - if (id >= idMapL.size()) - idMapL.resize(id+1, unused); - - if (newId != unmapped && newId != unused) { - if (isOldIdUnused(id)) { - error(std::string("ID unused in module: ") + std::to_string(id)); - return spirvbin_t::unused; - } - - if (!isOldIdUnmapped(id)) { - error(std::string("ID already mapped: ") + std::to_string(id) + " -> " - + std::to_string(localId(id))); - - return spirvbin_t::unused; - } - - if (isNewIdMapped(newId)) { - error(std::string("ID already used in module: ") + std::to_string(newId)); - return spirvbin_t::unused; - } - - msg(4, 4, std::string("map: ") + std::to_string(id) + " -> " + std::to_string(newId)); - setMapped(newId); - largestNewId = std::max(largestNewId, newId); - } - - return idMapL[id] = newId; - } - - // Parse a literal string from the SPIR binary and return it as an std::string - // Due to C++11 RValue references, this doesn't copy the result string. - std::string spirvbin_t::literalString(unsigned word) const - { - std::string literal; - const spirword_t * pos = spv.data() + word; - - literal.reserve(16); - - do { - spirword_t word = *pos; - for (int i = 0; i < 4; i++) { - char c = word & 0xff; - if (c == '\0') - return literal; - literal += c; - word >>= 8; - } - pos++; - } while (true); - } - - void spirvbin_t::applyMap() - { - msg(3, 2, std::string("Applying map: ")); - - // Map local IDs through the ID map - process(inst_fn_nop, // ignore instructions - [this](spv::Id& id) { - id = localId(id); - - if (errorLatch) - return; - - assert(id != unused && id != unmapped); - } - ); - } - - // Find free IDs for anything we haven't mapped - void spirvbin_t::mapRemainder() - { - msg(3, 2, std::string("Remapping remainder: ")); - - spv::Id unusedId = 1; // can't use 0: that's NoResult - spirword_t maxBound = 0; - - for (spv::Id id = 0; id < idMapL.size(); ++id) { - if (isOldIdUnused(id)) - continue; - - // Find a new mapping for any used but unmapped IDs - if (isOldIdUnmapped(id)) { - localId(id, unusedId = nextUnusedId(unusedId)); - if (errorLatch) - return; - } - - if (isOldIdUnmapped(id)) { - error(std::string("old ID not mapped: ") + std::to_string(id)); - return; - } - - // Track max bound - maxBound = std::max(maxBound, localId(id) + 1); - - if (errorLatch) - return; - } - - bound(maxBound); // reset header ID bound to as big as it now needs to be - } - - // Mark debug instructions for stripping - void spirvbin_t::stripDebug() - { - // Strip instructions in the stripOp set: debug info. - process( - [&](spv::Op opCode, unsigned start) { - // remember opcodes we want to strip later - if (isStripOp(opCode, start)) - stripInst(start); - return true; - }, - op_fn_nop); - } - - // Mark instructions that refer to now-removed IDs for stripping - void spirvbin_t::stripDeadRefs() - { - process( - [&](spv::Op opCode, unsigned start) { - // strip opcodes pointing to removed data - switch (opCode) { - case spv::OpName: - case spv::OpMemberName: - case spv::OpDecorate: - case spv::OpMemberDecorate: - if (idPosR.find(asId(start+1)) == idPosR.end()) - stripInst(start); - break; - default: - break; // leave it alone - } - - return true; - }, - op_fn_nop); - - strip(); - } - - // Update local maps of ID, type, etc positions - void spirvbin_t::buildLocalMaps() - { - msg(2, 2, std::string("build local maps: ")); - - mapped.clear(); - idMapL.clear(); -// preserve nameMap, so we don't clear that. - fnPos.clear(); - fnCalls.clear(); - typeConstPos.clear(); - idPosR.clear(); - entryPoint = spv::NoResult; - largestNewId = 0; - - idMapL.resize(bound(), unused); - - int fnStart = 0; - spv::Id fnRes = spv::NoResult; - - // build local Id and name maps - process( - [&](spv::Op opCode, unsigned start) { - unsigned word = start+1; - spv::Id typeId = spv::NoResult; - - if (spv::InstructionDesc[opCode].hasType()) - typeId = asId(word++); - - // If there's a result ID, remember the size of its type - if (spv::InstructionDesc[opCode].hasResult()) { - const spv::Id resultId = asId(word++); - idPosR[resultId] = start; - - if (typeId != spv::NoResult) { - const unsigned idTypeSize = typeSizeInWords(typeId); - - if (errorLatch) - return false; - - if (idTypeSize != 0) - idTypeSizeMap[resultId] = idTypeSize; - } - } - - if (opCode == spv::Op::OpName) { - const spv::Id target = asId(start+1); - const std::string name = literalString(start+2); - nameMap[name] = target; - - } else if (opCode == spv::Op::OpFunctionCall) { - ++fnCalls[asId(start + 3)]; - } else if (opCode == spv::Op::OpEntryPoint) { - entryPoint = asId(start + 2); - } else if (opCode == spv::Op::OpFunction) { - if (fnStart != 0) { - error("nested function found"); - return false; - } - - fnStart = start; - fnRes = asId(start + 2); - } else if (opCode == spv::Op::OpFunctionEnd) { - assert(fnRes != spv::NoResult); - if (fnStart == 0) { - error("function end without function start"); - return false; - } - - fnPos[fnRes] = range_t(fnStart, start + asWordCount(start)); - fnStart = 0; - } else if (isConstOp(opCode)) { - if (errorLatch) - return false; - - assert(asId(start + 2) != spv::NoResult); - typeConstPos.insert(start); - } else if (isTypeOp(opCode)) { - assert(asId(start + 1) != spv::NoResult); - typeConstPos.insert(start); - } - - return false; - }, - - [this](spv::Id& id) { localId(id, unmapped); } - ); - } - - // Validate the SPIR header - void spirvbin_t::validate() const - { - msg(2, 2, std::string("validating: ")); - - if (spv.size() < header_size) { - error("file too short: "); - return; - } - - if (magic() != spv::MagicNumber) { - error("bad magic number"); - return; - } - - // field 1 = version - // field 2 = generator magic - // field 3 = result bound - - if (schemaNum() != 0) { - error("bad schema, must be 0"); - return; - } - } - - int spirvbin_t::processInstruction(unsigned word, instfn_t instFn, idfn_t idFn) - { - const auto instructionStart = word; - const unsigned wordCount = asWordCount(instructionStart); - const int nextInst = word++ + wordCount; - spv::Op opCode = asOpCode(instructionStart); - - if (nextInst > int(spv.size())) { - error("spir instruction terminated too early"); - return -1; - } - - // Base for computing number of operands; will be updated as more is learned - unsigned numOperands = wordCount - 1; - - if (instFn(opCode, instructionStart)) - return nextInst; - - // Read type and result ID from instruction desc table - if (spv::InstructionDesc[opCode].hasType()) { - idFn(asId(word++)); - --numOperands; - } - - if (spv::InstructionDesc[opCode].hasResult()) { - idFn(asId(word++)); - --numOperands; - } - - // Extended instructions: currently, assume everything is an ID. - // TODO: add whatever data we need for exceptions to that - if (opCode == spv::OpExtInst) { - - idFn(asId(word)); // Instruction set is an ID that also needs to be mapped - - word += 2; // instruction set, and instruction from set - numOperands -= 2; - - for (unsigned op=0; op < numOperands; ++op) - idFn(asId(word++)); // ID - - return nextInst; - } - - // Circular buffer so we can look back at previous unmapped values during the mapping pass. - static const unsigned idBufferSize = 4; - spv::Id idBuffer[idBufferSize]; - unsigned idBufferPos = 0; - - // Store IDs from instruction in our map - for (int op = 0; numOperands > 0; ++op, --numOperands) { - // SpecConstantOp is special: it includes the operands of another opcode which is - // given as a literal in the 3rd word. We will switch over to pretending that the - // opcode being processed is the literal opcode value of the SpecConstantOp. See the - // SPIRV spec for details. This way we will handle IDs and literals as appropriate for - // the embedded op. - if (opCode == spv::OpSpecConstantOp) { - if (op == 0) { - opCode = asOpCode(word++); // this is the opcode embedded in the SpecConstantOp. - --numOperands; - } - } - - switch (spv::InstructionDesc[opCode].operands.getClass(op)) { - case spv::OperandId: - case spv::OperandScope: - case spv::OperandMemorySemantics: - idBuffer[idBufferPos] = asId(word); - idBufferPos = (idBufferPos + 1) % idBufferSize; - idFn(asId(word++)); - break; - - case spv::OperandVariableIds: - for (unsigned i = 0; i < numOperands; ++i) - idFn(asId(word++)); - return nextInst; - - case spv::OperandVariableLiterals: - // for clarity - // if (opCode == spv::OpDecorate && asDecoration(word - 1) == spv::DecorationBuiltIn) { - // ++word; - // --numOperands; - // } - // word += numOperands; - return nextInst; - - case spv::OperandVariableLiteralId: { - if (opCode == OpSwitch) { - // word-2 is the position of the selector ID. OpSwitch Literals match its type. - // In case the IDs are currently being remapped, we get the word[-2] ID from - // the circular idBuffer. - const unsigned literalSizePos = (idBufferPos+idBufferSize-2) % idBufferSize; - const unsigned literalSize = idTypeSizeInWords(idBuffer[literalSizePos]); - const unsigned numLiteralIdPairs = (nextInst-word) / (1+literalSize); - - if (errorLatch) - return -1; - - for (unsigned arg=0; arg instPos; - instPos.reserve(unsigned(spv.size()) / 16); // initial estimate; can grow if needed. - - // Build local table of instruction start positions - process( - [&](spv::Op, unsigned start) { instPos.push_back(start); return true; }, - op_fn_nop); - - if (errorLatch) - return; - - // Window size for context-sensitive canonicalization values - // Empirical best size from a single data set. TODO: Would be a good tunable. - // We essentially perform a little convolution around each instruction, - // to capture the flavor of nearby code, to hopefully match to similar - // code in other modules. - static const unsigned windowSize = 2; - - for (unsigned entry = 0; entry < unsigned(instPos.size()); ++entry) { - const unsigned start = instPos[entry]; - const spv::Op opCode = asOpCode(start); - - if (opCode == spv::OpFunction) - fnId = asId(start + 2); - - if (opCode == spv::OpFunctionEnd) - fnId = spv::NoResult; - - if (fnId != spv::NoResult) { // if inside a function - if (spv::InstructionDesc[opCode].hasResult()) { - const unsigned word = start + (spv::InstructionDesc[opCode].hasType() ? 2 : 1); - const spv::Id resId = asId(word); - std::uint32_t hashval = fnId * 17; // small prime - - for (unsigned i = entry-1; i >= entry-windowSize; --i) { - if (asOpCode(instPos[i]) == spv::OpFunction) - break; - hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime - } - - for (unsigned i = entry; i <= entry + windowSize; ++i) { - if (asOpCode(instPos[i]) == spv::OpFunctionEnd) - break; - hashval = hashval * 30103 + asOpCodeHash(instPos[i]); // 30103 = semiarbitrary prime - } - - if (isOldIdUnmapped(resId)) { - localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - if (errorLatch) - return; - } - - } - } - } - - spv::Op thisOpCode(spv::OpNop); - std::unordered_map opCounter; - int idCounter(0); - fnId = spv::NoResult; - - process( - [&](spv::Op opCode, unsigned start) { - switch (opCode) { - case spv::OpFunction: - // Reset counters at each function - idCounter = 0; - opCounter.clear(); - fnId = asId(start + 2); - break; - - case spv::OpImageSampleImplicitLod: - case spv::OpImageSampleExplicitLod: - case spv::OpImageSampleDrefImplicitLod: - case spv::OpImageSampleDrefExplicitLod: - case spv::OpImageSampleProjImplicitLod: - case spv::OpImageSampleProjExplicitLod: - case spv::OpImageSampleProjDrefImplicitLod: - case spv::OpImageSampleProjDrefExplicitLod: - case spv::OpDot: - case spv::OpCompositeExtract: - case spv::OpCompositeInsert: - case spv::OpVectorShuffle: - case spv::OpLabel: - case spv::OpVariable: - - case spv::OpAccessChain: - case spv::OpLoad: - case spv::OpStore: - case spv::OpCompositeConstruct: - case spv::OpFunctionCall: - ++opCounter[opCode]; - idCounter = 0; - thisOpCode = opCode; - break; - default: - thisOpCode = spv::OpNop; - } - - return false; - }, - - [&](spv::Id& id) { - if (thisOpCode != spv::OpNop) { - ++idCounter; - const std::uint32_t hashval = - // Explicitly cast operands to unsigned int to avoid integer - // promotion to signed int followed by integer overflow, - // which would result in undefined behavior. - static_cast(opCounter[thisOpCode]) - * thisOpCode - * 50047 - + idCounter - + static_cast(fnId) * 117; - - if (isOldIdUnmapped(id)) - localId(id, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - } - }); - } - - // EXPERIMENTAL: forward IO and uniform load/stores into operands - // This produces invalid Schema-0 SPIRV - void spirvbin_t::forwardLoadStores() - { - idset_t fnLocalVars; // set of function local vars - idmap_t idMap; // Map of load result IDs to what they load - - // EXPERIMENTAL: Forward input and access chain loads into consumptions - process( - [&](spv::Op opCode, unsigned start) { - // Add inputs and uniforms to the map - if ((opCode == spv::OpVariable && asWordCount(start) == 4) && - (spv[start+3] == spv::StorageClassUniform || - spv[start+3] == spv::StorageClassUniformConstant || - spv[start+3] == spv::StorageClassInput)) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpAccessChain && fnLocalVars.count(asId(start+3)) > 0) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) { - idMap[asId(start+2)] = asId(start+3); - stripInst(start); - } - - return false; - }, - - [&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; } - ); - - if (errorLatch) - return; - - // EXPERIMENTAL: Implicit output stores - fnLocalVars.clear(); - idMap.clear(); - - process( - [&](spv::Op opCode, unsigned start) { - // Add inputs and uniforms to the map - if ((opCode == spv::OpVariable && asWordCount(start) == 4) && - (spv[start+3] == spv::StorageClassOutput)) - fnLocalVars.insert(asId(start+2)); - - if (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) { - idMap[asId(start+2)] = asId(start+1); - stripInst(start); - } - - return false; - }, - op_fn_nop); - - if (errorLatch) - return; - - process( - inst_fn_nop, - [&](spv::Id& id) { if (idMap.find(id) != idMap.end()) id = idMap[id]; } - ); - - if (errorLatch) - return; - - strip(); // strip out data we decided to eliminate - } - - // optimize loads and stores - void spirvbin_t::optLoadStore() - { - idset_t fnLocalVars; // candidates for removal (only locals) - idmap_t idMap; // Map of load result IDs to what they load - blockmap_t blockMap; // Map of IDs to blocks they first appear in - int blockNum = 0; // block count, to avoid crossing flow control - - // Find all the function local pointers stored at most once, and not via access chains - process( - [&](spv::Op opCode, unsigned start) { - const int wordCount = asWordCount(start); - - // Count blocks, so we can avoid crossing flow control - if (isFlowCtrl(opCode)) - ++blockNum; - - // Add local variables to the map - if ((opCode == spv::OpVariable && spv[start+3] == spv::StorageClassFunction && asWordCount(start) == 4)) { - fnLocalVars.insert(asId(start+2)); - return true; - } - - // Ignore process vars referenced via access chain - if ((opCode == spv::OpAccessChain || opCode == spv::OpInBoundsAccessChain) && fnLocalVars.count(asId(start+3)) > 0) { - fnLocalVars.erase(asId(start+3)); - idMap.erase(asId(start+3)); - return true; - } - - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) { - const spv::Id varId = asId(start+3); - - // Avoid loads before stores - if (idMap.find(varId) == idMap.end()) { - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // don't do for volatile references - if (wordCount > 4 && (spv[start+4] & spv::MemoryAccessVolatileMask)) { - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // Handle flow control - if (blockMap.find(varId) == blockMap.end()) { - blockMap[varId] = blockNum; // track block we found it in. - } else if (blockMap[varId] != blockNum) { - fnLocalVars.erase(varId); // Ignore if crosses flow control - idMap.erase(varId); - } - - return true; - } - - if (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) { - const spv::Id varId = asId(start+1); - - if (idMap.find(varId) == idMap.end()) { - idMap[varId] = asId(start+2); - } else { - // Remove if it has more than one store to the same pointer - fnLocalVars.erase(varId); - idMap.erase(varId); - } - - // don't do for volatile references - if (wordCount > 3 && (spv[start+3] & spv::MemoryAccessVolatileMask)) { - fnLocalVars.erase(asId(start+3)); - idMap.erase(asId(start+3)); - } - - // Handle flow control - if (blockMap.find(varId) == blockMap.end()) { - blockMap[varId] = blockNum; // track block we found it in. - } else if (blockMap[varId] != blockNum) { - fnLocalVars.erase(varId); // Ignore if crosses flow control - idMap.erase(varId); - } - - return true; - } - - return false; - }, - - // If local var id used anywhere else, don't eliminate - [&](spv::Id& id) { - if (fnLocalVars.count(id) > 0) { - fnLocalVars.erase(id); - idMap.erase(id); - } - } - ); - - if (errorLatch) - return; - - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) - idMap[asId(start+2)] = idMap[asId(start+3)]; - return false; - }, - op_fn_nop); - - if (errorLatch) - return; - - // Chase replacements to their origins, in case there is a chain such as: - // 2 = store 1 - // 3 = load 2 - // 4 = store 3 - // 5 = load 4 - // We want to replace uses of 5 with 1. - for (const auto& idPair : idMap) { - spv::Id id = idPair.first; - while (idMap.find(id) != idMap.end()) // Chase to end of chain - id = idMap[id]; - - idMap[idPair.first] = id; // replace with final result - } - - // Remove the load/store/variables for the ones we've discovered - process( - [&](spv::Op opCode, unsigned start) { - if ((opCode == spv::OpLoad && fnLocalVars.count(asId(start+3)) > 0) || - (opCode == spv::OpStore && fnLocalVars.count(asId(start+1)) > 0) || - (opCode == spv::OpVariable && fnLocalVars.count(asId(start+2)) > 0)) { - - stripInst(start); - return true; - } - - return false; - }, - - [&](spv::Id& id) { - if (idMap.find(id) != idMap.end()) id = idMap[id]; - } - ); - - if (errorLatch) - return; - - strip(); // strip out data we decided to eliminate - } - - // remove bodies of uncalled functions - void spirvbin_t::dceFuncs() - { - msg(3, 2, std::string("Removing Dead Functions: ")); - - // TODO: There are more efficient ways to do this. - bool changed = true; - - while (changed) { - changed = false; - - for (auto fn = fnPos.begin(); fn != fnPos.end(); ) { - if (fn->first == entryPoint) { // don't DCE away the entry point! - ++fn; - continue; - } - - const auto call_it = fnCalls.find(fn->first); - - if (call_it == fnCalls.end() || call_it->second == 0) { - changed = true; - stripRange.push_back(fn->second); - - // decrease counts of called functions - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::Op::OpFunctionCall) { - const auto call_it = fnCalls.find(asId(start + 3)); - if (call_it != fnCalls.end()) { - if (--call_it->second <= 0) - fnCalls.erase(call_it); - } - } - - return true; - }, - op_fn_nop, - fn->second.first, - fn->second.second); - - if (errorLatch) - return; - - fn = fnPos.erase(fn); - } else ++fn; - } - } - } - - // remove unused function variables + decorations - void spirvbin_t::dceVars() - { - msg(3, 2, std::string("DCE Vars: ")); - - std::unordered_map varUseCount; - - // Count function variable use - process( - [&](spv::Op opCode, unsigned start) { - if (opCode == spv::OpVariable) { - ++varUseCount[asId(start+2)]; - return true; - } else if (opCode == spv::OpEntryPoint) { - const int wordCount = asWordCount(start); - for (int i = 4; i < wordCount; i++) { - ++varUseCount[asId(start+i)]; - } - return true; - } else - return false; - }, - - [&](spv::Id& id) { if (varUseCount[id]) ++varUseCount[id]; } - ); - - if (errorLatch) - return; - - // Remove single-use function variables + associated decorations and names - process( - [&](spv::Op opCode, unsigned start) { - spv::Id id = spv::NoResult; - if (opCode == spv::OpVariable) - id = asId(start+2); - if (opCode == spv::OpDecorate || opCode == spv::OpName) - id = asId(start+1); - - if (id != spv::NoResult && varUseCount[id] == 1) - stripInst(start); - - return true; - }, - op_fn_nop); - } - - // remove unused types - void spirvbin_t::dceTypes() - { - std::vector isType(bound(), false); - - // for speed, make O(1) way to get to type query (map is log(n)) - for (const auto typeStart : typeConstPos) - isType[asTypeConstId(typeStart)] = true; - - std::unordered_map typeUseCount; - - // This is not the most efficient algorithm, but this is an offline tool, and - // it's easy to write this way. Can be improved opportunistically if needed. - bool changed = true; - while (changed) { - changed = false; - strip(); - typeUseCount.clear(); - - // Count total type usage - process(inst_fn_nop, - [&](spv::Id& id) { if (isType[id]) ++typeUseCount[id]; } - ); - - if (errorLatch) - return; - - // Remove single reference types - for (const auto typeStart : typeConstPos) { - const spv::Id typeId = asTypeConstId(typeStart); - if (typeUseCount[typeId] == 1) { - changed = true; - --typeUseCount[typeId]; - stripInst(typeStart); - } - } - - if (errorLatch) - return; - } - } - -#ifdef NOTDEF - bool spirvbin_t::matchType(const spirvbin_t::globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const - { - // Find the local type id "lt" and global type id "gt" - const auto lt_it = typeConstPosR.find(lt); - if (lt_it == typeConstPosR.end()) - return false; - - const auto typeStart = lt_it->second; - - // Search for entry in global table - const auto gtype = globalTypes.find(gt); - if (gtype == globalTypes.end()) - return false; - - const auto& gdata = gtype->second; - - // local wordcount and opcode - const int wordCount = asWordCount(typeStart); - const spv::Op opCode = asOpCode(typeStart); - - // no type match if opcodes don't match, or operand count doesn't match - if (opCode != opOpCode(gdata[0]) || wordCount != opWordCount(gdata[0])) - return false; - - const unsigned numOperands = wordCount - 2; // all types have a result - - const auto cmpIdRange = [&](range_t range) { - for (int x=range.first; xsecond; - } - - // Hash types to canonical values. This can return ID collisions (it's a bit - // inevitable): it's up to the caller to handle that gracefully. - std::uint32_t spirvbin_t::hashType(unsigned typeStart) const - { - const unsigned wordCount = asWordCount(typeStart); - const spv::Op opCode = asOpCode(typeStart); - - switch (opCode) { - case spv::OpTypeVoid: return 0; - case spv::OpTypeBool: return 1; - case spv::OpTypeInt: return 3 + (spv[typeStart+3]); - case spv::OpTypeFloat: return 5; - case spv::OpTypeVector: - return 6 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1); - case spv::OpTypeMatrix: - return 30 + hashType(idPos(spv[typeStart+2])) * (spv[typeStart+3] - 1); - case spv::OpTypeImage: - return 120 + hashType(idPos(spv[typeStart+2])) + - spv[typeStart+3] + // dimensionality - spv[typeStart+4] * 8 * 16 + // depth - spv[typeStart+5] * 4 * 16 + // arrayed - spv[typeStart+6] * 2 * 16 + // multisampled - spv[typeStart+7] * 1 * 16; // format - case spv::OpTypeSampler: - return 500; - case spv::OpTypeSampledImage: - return 502; - case spv::OpTypeArray: - return 501 + hashType(idPos(spv[typeStart+2])) * spv[typeStart+3]; - case spv::OpTypeRuntimeArray: - return 5000 + hashType(idPos(spv[typeStart+2])); - case spv::OpTypeStruct: - { - std::uint32_t hash = 10000; - for (unsigned w=2; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - - case spv::OpTypeOpaque: return 6000 + spv[typeStart+2]; - case spv::OpTypePointer: return 100000 + hashType(idPos(spv[typeStart+3])); - case spv::OpTypeFunction: - { - std::uint32_t hash = 200000; - for (unsigned w=2; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - - case spv::OpTypeEvent: return 300000; - case spv::OpTypeDeviceEvent: return 300001; - case spv::OpTypeReserveId: return 300002; - case spv::OpTypeQueue: return 300003; - case spv::OpTypePipe: return 300004; - case spv::OpConstantTrue: return 300007; - case spv::OpConstantFalse: return 300008; - case spv::OpConstantComposite: - { - std::uint32_t hash = 300011 + hashType(idPos(spv[typeStart+1])); - for (unsigned w=3; w < wordCount; ++w) - hash += w * hashType(idPos(spv[typeStart+w])); - return hash; - } - case spv::OpConstant: - { - std::uint32_t hash = 400011 + hashType(idPos(spv[typeStart+1])); - for (unsigned w=3; w < wordCount; ++w) - hash += w * spv[typeStart+w]; - return hash; - } - case spv::OpConstantNull: - { - std::uint32_t hash = 500009 + hashType(idPos(spv[typeStart+1])); - return hash; - } - case spv::OpConstantSampler: - { - std::uint32_t hash = 600011 + hashType(idPos(spv[typeStart+1])); - for (unsigned w=3; w < wordCount; ++w) - hash += w * spv[typeStart+w]; - return hash; - } - - default: - error("unknown type opcode"); - return 0; - } - } - - void spirvbin_t::mapTypeConst() - { - globaltypes_t globalTypeMap; - - msg(3, 2, std::string("Remapping Consts & Types: ")); - - static const std::uint32_t softTypeIdLimit = 3011; // small prime. TODO: get from options - static const std::uint32_t firstMappedID = 8; // offset into ID space - - for (auto& typeStart : typeConstPos) { - const spv::Id resId = asTypeConstId(typeStart); - const std::uint32_t hashval = hashType(typeStart); - - if (errorLatch) - return; - - if (isOldIdUnmapped(resId)) { - localId(resId, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); - if (errorLatch) - return; - } - } - } - - // Strip a single binary by removing ranges given in stripRange - void spirvbin_t::strip() - { - if (stripRange.empty()) // nothing to do - return; - - // Sort strip ranges in order of traversal - std::sort(stripRange.begin(), stripRange.end()); - - // Allocate a new binary big enough to hold old binary - // We'll step this iterator through the strip ranges as we go through the binary - auto strip_it = stripRange.begin(); - - int strippedPos = 0; - for (unsigned word = 0; word < unsigned(spv.size()); ++word) { - while (strip_it != stripRange.end() && word >= strip_it->second) - ++strip_it; - - if (strip_it == stripRange.end() || word < strip_it->first || word >= strip_it->second) - spv[strippedPos++] = spv[word]; - } - - spv.resize(strippedPos); - stripRange.clear(); - - buildLocalMaps(); - } - - // Strip a single binary by removing ranges given in stripRange - void spirvbin_t::remap(std::uint32_t opts) - { - options = opts; - - // Set up opcode tables from SpvDoc - spv::Parameterize(); - - validate(); // validate header - buildLocalMaps(); // build ID maps - - msg(3, 4, std::string("ID bound: ") + std::to_string(bound())); - - if (options & STRIP) stripDebug(); - if (errorLatch) return; - - strip(); // strip out data we decided to eliminate - if (errorLatch) return; - - if (options & OPT_LOADSTORE) optLoadStore(); - if (errorLatch) return; - - if (options & OPT_FWD_LS) forwardLoadStores(); - if (errorLatch) return; - - if (options & DCE_FUNCS) dceFuncs(); - if (errorLatch) return; - - if (options & DCE_VARS) dceVars(); - if (errorLatch) return; - - if (options & DCE_TYPES) dceTypes(); - if (errorLatch) return; - - strip(); // strip out data we decided to eliminate - if (errorLatch) return; - - stripDeadRefs(); // remove references to things we DCEed - if (errorLatch) return; - - // after the last strip, we must clean any debug info referring to now-deleted data - - if (options & MAP_TYPES) mapTypeConst(); - if (errorLatch) return; - - if (options & MAP_NAMES) mapNames(); - if (errorLatch) return; - - if (options & MAP_FUNCS) mapFnBodies(); - if (errorLatch) return; - - if (options & MAP_ALL) { - mapRemainder(); // map any unmapped IDs - if (errorLatch) return; - - applyMap(); // Now remap each shader to the new IDs we've come up with - if (errorLatch) return; - } - } - - // remap from a memory image - void spirvbin_t::remap(std::vector& in_spv, const std::vector& whiteListStrings, - std::uint32_t opts) - { - stripWhiteList = whiteListStrings; - spv.swap(in_spv); - remap(opts); - spv.swap(in_spv); - } - - // remap from a memory image - legacy interface without white list - void spirvbin_t::remap(std::vector& in_spv, std::uint32_t opts) - { - stripWhiteList.clear(); - spv.swap(in_spv); - remap(opts); - spv.swap(in_spv); - } - -} // namespace SPV - diff --git a/3rdparty/glslang/SPIRV/SPVRemapper.h b/3rdparty/glslang/SPIRV/SPVRemapper.h deleted file mode 100644 index 33efe331..00000000 --- a/3rdparty/glslang/SPIRV/SPVRemapper.h +++ /dev/null @@ -1,284 +0,0 @@ -// -// Copyright (C) 2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef SPIRVREMAPPER_H -#define SPIRVREMAPPER_H - -#include -#include -#include -#include - -namespace spv { - -class spirvbin_base_t -{ -public: - enum Options { - NONE = 0, - STRIP = (1<<0), - MAP_TYPES = (1<<1), - MAP_NAMES = (1<<2), - MAP_FUNCS = (1<<3), - DCE_FUNCS = (1<<4), - DCE_VARS = (1<<5), - DCE_TYPES = (1<<6), - OPT_LOADSTORE = (1<<7), - OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV - MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS), - DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES), - OPT_ALL = (OPT_LOADSTORE), - - ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL), - DO_EVERYTHING = (STRIP | ALL_BUT_STRIP) - }; -}; - -} // namespace SPV - -#include -#include -#include -#include -#include -#include -#include - -#include "spirv.hpp" - -namespace spv { -const Id NoResult = 0; - -// class to hold SPIR-V binary data for remapping, DCE, and debug stripping -class spirvbin_t : public spirvbin_base_t -{ -public: - spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false) - { } - - virtual ~spirvbin_t() { } - - // remap on an existing binary in memory - void remap(std::vector& spv, const std::vector& whiteListStrings, - std::uint32_t opts = DO_EVERYTHING); - - // remap on an existing binary in memory - legacy interface without white list - void remap(std::vector& spv, std::uint32_t opts = DO_EVERYTHING); - - // Type for error/log handler functions - typedef std::function errorfn_t; - typedef std::function logfn_t; - - // Register error/log handling functions (can be lambda fn / functor / etc) - static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; } - static void registerLogHandler(logfn_t handler) { logHandler = handler; } - -protected: - // This can be overridden to provide other message behavior if needed - virtual void msg(int minVerbosity, int indent, const std::string& txt) const; - -private: - // Local to global, or global to local ID map - typedef std::unordered_map idmap_t; - typedef std::unordered_set idset_t; - typedef std::unordered_map blockmap_t; - - void remap(std::uint32_t opts = DO_EVERYTHING); - - // Map of names to IDs - typedef std::unordered_map namemap_t; - - typedef std::uint32_t spirword_t; - - typedef std::pair range_t; - typedef std::function idfn_t; - typedef std::function instfn_t; - - // Special Values for ID map: - static const spv::Id unmapped; // unchanged from default value - static const spv::Id unused; // unused ID - static const int header_size; // SPIR header = 5 words - - class id_iterator_t; - - // For mapping type entries between different shaders - typedef std::vector typeentry_t; - typedef std::map globaltypes_t; - - // A set that preserves position order, and a reverse map - typedef std::set posmap_t; - typedef std::unordered_map posmap_rev_t; - - // Maps and ID to the size of its base type, if known. - typedef std::unordered_map typesize_map_t; - - // handle error - void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); } - - bool isConstOp(spv::Op opCode) const; - bool isTypeOp(spv::Op opCode) const; - bool isStripOp(spv::Op opCode) const; - bool isFlowCtrl(spv::Op opCode) const; - range_t literalRange(spv::Op opCode) const; - range_t typeRange(spv::Op opCode) const; - range_t constRange(spv::Op opCode) const; - unsigned typeSizeInWords(spv::Id id) const; - unsigned idTypeSizeInWords(spv::Id id) const; - - bool isStripOp(spv::Op opCode, unsigned start) const; - - spv::Id& asId(unsigned word) { return spv[word]; } - const spv::Id& asId(unsigned word) const { return spv[word]; } - spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); } - std::uint32_t asOpCodeHash(unsigned word); - spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); } - unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); } - spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); } - unsigned idPos(spv::Id id) const; - - static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; } - static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); } - - // Header access & set methods - spirword_t magic() const { return spv[0]; } // return magic number - spirword_t bound() const { return spv[3]; } // return Id bound from header - spirword_t bound(spirword_t b) { return spv[3] = b; } - spirword_t genmagic() const { return spv[2]; } // generator magic - spirword_t genmagic(spirword_t m) { return spv[2] = m; } - spirword_t schemaNum() const { return spv[4]; } // schema number from header - - // Mapping fns: get - spv::Id localId(spv::Id id) const { return idMapL[id]; } - - // Mapping fns: set - inline spv::Id localId(spv::Id id, spv::Id newId); - void countIds(spv::Id id); - - // Return next unused new local ID. - // NOTE: boost::dynamic_bitset would be more efficient due to find_next(), - // which std::vector doens't have. - inline spv::Id nextUnusedId(spv::Id id); - - void buildLocalMaps(); - std::string literalString(unsigned word) const; // Return literal as a std::string - int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; } - - bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); } - bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; } - bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; } - bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); } - bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); } - - // bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const; - // spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const; - std::uint32_t hashType(unsigned typeStart) const; - - spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0); - int processInstruction(unsigned word, instfn_t, idfn_t); - - void validate() const; - void mapTypeConst(); - void mapFnBodies(); - void optLoadStore(); - void dceFuncs(); - void dceVars(); - void dceTypes(); - void mapNames(); - void foldIds(); // fold IDs to smallest space - void forwardLoadStores(); // load store forwarding (EXPERIMENTAL) - void offsetIds(); // create relative offset IDs - - void applyMap(); // remap per local name map - void mapRemainder(); // map any IDs we haven't touched yet - void stripDebug(); // strip all debug info - void stripDeadRefs(); // strips debug info for now-dead references after DCE - void strip(); // remove debug symbols - - std::vector spv; // SPIR words - - std::vector stripWhiteList; - - namemap_t nameMap; // ID names from OpName - - // Since we want to also do binary ops, we can't use std::vector. we could use - // boost::dynamic_bitset, but we're trying to avoid a boost dependency. - typedef std::uint64_t bits_t; - std::vector mapped; // which new IDs have been mapped - static const int mBits = sizeof(bits_t) * 4; - - bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); } - void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); } - void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); } - size_t maxMappedId() const { return mapped.size() * mBits; } - - // Add a strip range for a given instruction starting at 'start' - // Note: avoiding brace initializers to please older versions os MSVC. - void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); } - - // Function start and end. use unordered_map because we'll have - // many fewer functions than IDs. - std::unordered_map fnPos; - - // Which functions are called, anywhere in the module, with a call count - std::unordered_map fnCalls; - - posmap_t typeConstPos; // word positions that define types & consts (ordered) - posmap_rev_t idPosR; // reverse map from IDs to positions - typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known. - - std::vector idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs - - spv::Id entryPoint; // module entry point - spv::Id largestNewId; // biggest new ID we have mapped anything to - - // Sections of the binary to strip, given as [begin,end) - std::vector stripRange; - - // processing options: - std::uint32_t options; - int verbose; // verbosity level - - // Error latch: this is set if the error handler is ever executed. It would be better to - // use a try/catch block and throw, but that's not desired for certain environments, so - // this is the alternative. - mutable bool errorLatch; - - static errorfn_t errorHandler; - static logfn_t logHandler; -}; - -} // namespace SPV - -#endif // SPIRVREMAPPER_H diff --git a/3rdparty/glslang/SPIRV/SpvBuilder.cpp b/3rdparty/glslang/SPIRV/SpvBuilder.cpp deleted file mode 100644 index c07f3b67..00000000 --- a/3rdparty/glslang/SPIRV/SpvBuilder.cpp +++ /dev/null @@ -1,4162 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Helper for making SPIR-V IR. Generally, this is documented in the header -// SpvBuilder.h. -// - -#include -#include - -#include -#include - -#include "SpvBuilder.h" -#include "hex_float.h" - -#ifndef _WIN32 - #include -#endif - -namespace spv { - -Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogger* buildLogger) : - spvVersion(spvVersion), - sourceLang(SourceLanguageUnknown), - sourceVersion(0), - sourceFileStringId(NoResult), - currentLine(0), - currentFile(nullptr), - currentFileId(NoResult), - lastDebugScopeId(NoResult), - emitOpLines(false), - emitNonSemanticShaderDebugInfo(false), - addressModel(AddressingModelLogical), - memoryModel(MemoryModelGLSL450), - builderNumber(magicNumber), - buildPoint(nullptr), - uniqueId(0), - entryPointFunction(nullptr), - generatingOpCodeForSpecConst(false), - logger(buildLogger) -{ - clearAccessChain(); -} - -Builder::~Builder() -{ -} - -Id Builder::import(const char* name) -{ - Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport); - import->addStringOperand(name); - module.mapInstruction(import); - - imports.push_back(std::unique_ptr(import)); - return import->getResultId(); -} - -// Emit instruction for non-filename-based #line directives (ie. no filename -// seen yet): emit an OpLine if we've been asked to emit OpLines and the line -// number has changed since the last time, and is a valid line number. -void Builder::setLine(int lineNum) -{ - if (lineNum != 0 && lineNum != currentLine) { - currentLine = lineNum; - if (emitOpLines) { - if (emitNonSemanticShaderDebugInfo) - addDebugScopeAndLine(currentFileId, currentLine, 0); - else - addLine(sourceFileStringId, currentLine, 0); - } - } -} - -// If no filename, do non-filename-based #line emit. Else do filename-based emit. -// Emit OpLine if we've been asked to emit OpLines and the line number or filename -// has changed since the last time, and line number is valid. -void Builder::setLine(int lineNum, const char* filename) -{ - if (filename == nullptr) { - setLine(lineNum); - return; - } - if ((lineNum != 0 && lineNum != currentLine) || currentFile == nullptr || - strncmp(filename, currentFile, strlen(currentFile) + 1) != 0) { - currentLine = lineNum; - currentFile = filename; - if (emitOpLines) { - spv::Id strId = getStringId(filename); - if (emitNonSemanticShaderDebugInfo) - addDebugScopeAndLine(strId, currentLine, 0); - else - addLine(strId, currentLine, 0); - } - } -} - -void Builder::addLine(Id fileName, int lineNum, int column) -{ - Instruction* line = new Instruction(OpLine); - line->addIdOperand(fileName); - line->addImmediateOperand(lineNum); - line->addImmediateOperand(column); - buildPoint->addInstruction(std::unique_ptr(line)); -} - -void Builder::addDebugScopeAndLine(Id fileName, int lineNum, int column) -{ - assert(!currentDebugScopeId.empty()); - if (currentDebugScopeId.top() != lastDebugScopeId) { - spv::Id resultId = getUniqueId(); - Instruction* scopeInst = new Instruction(resultId, makeVoidType(), OpExtInst); - scopeInst->addIdOperand(nonSemanticShaderDebugInfo); - scopeInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugScope); - scopeInst->addIdOperand(currentDebugScopeId.top()); - buildPoint->addInstruction(std::unique_ptr(scopeInst)); - lastDebugScopeId = currentDebugScopeId.top(); - } - spv::Id resultId = getUniqueId(); - Instruction* lineInst = new Instruction(resultId, makeVoidType(), OpExtInst); - lineInst->addIdOperand(nonSemanticShaderDebugInfo); - lineInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLine); - lineInst->addIdOperand(makeDebugSource(fileName)); - lineInst->addIdOperand(makeUintConstant(lineNum)); - lineInst->addIdOperand(makeUintConstant(lineNum)); - lineInst->addIdOperand(makeUintConstant(column)); - lineInst->addIdOperand(makeUintConstant(column)); - buildPoint->addInstruction(std::unique_ptr(lineInst)); -} - -// For creating new groupedTypes (will return old type if the requested one was already made). -Id Builder::makeVoidType() -{ - Instruction* type; - if (groupedTypes[OpTypeVoid].size() == 0) { - Id typeId = getUniqueId(); - type = new Instruction(typeId, NoType, OpTypeVoid); - groupedTypes[OpTypeVoid].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - // Core OpTypeVoid used for debug void type - if (emitNonSemanticShaderDebugInfo) - debugId[typeId] = typeId; - } else - type = groupedTypes[OpTypeVoid].back(); - - return type->getResultId(); -} - -Id Builder::makeBoolType() -{ - Instruction* type; - if (groupedTypes[OpTypeBool].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeBool); - groupedTypes[OpTypeBool].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) { - auto const debugResultId = makeBoolDebugType(32); - debugId[type->getResultId()] = debugResultId; - } - - } else - type = groupedTypes[OpTypeBool].back(); - - - return type->getResultId(); -} - -Id Builder::makeSamplerType() -{ - Instruction* type; - if (groupedTypes[OpTypeSampler].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeSampler); - groupedTypes[OpTypeSampler].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else - type = groupedTypes[OpTypeSampler].back(); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeCompositeDebugType({}, "type.sampler", NonSemanticShaderDebugInfo100Structure, true); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makePointer(StorageClass storageClass, Id pointee) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) { - type = groupedTypes[OpTypePointer][t]; - if (type->getImmediateOperand(0) == (unsigned)storageClass && - type->getIdOperand(1) == pointee) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypePointer); - type->addImmediateOperand(storageClass); - type->addIdOperand(pointee); - groupedTypes[OpTypePointer].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeForwardPointer(StorageClass storageClass) -{ - // Caching/uniquifying doesn't work here, because we don't know the - // pointee type and there can be multiple forward pointers of the same - // storage type. Somebody higher up in the stack must keep track. - Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeForwardPointer); - type->addImmediateOperand(storageClass); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardPointerType, Id pointee) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) { - type = groupedTypes[OpTypePointer][t]; - if (type->getImmediateOperand(0) == (unsigned)storageClass && - type->getIdOperand(1) == pointee) - return type->getResultId(); - } - - type = new Instruction(forwardPointerType, NoType, OpTypePointer); - type->addImmediateOperand(storageClass); - type->addIdOperand(pointee); - groupedTypes[OpTypePointer].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeIntegerType(int width, bool hasSign) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeInt].size(); ++t) { - type = groupedTypes[OpTypeInt][t]; - if (type->getImmediateOperand(0) == (unsigned)width && - type->getImmediateOperand(1) == (hasSign ? 1u : 0u)) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeInt); - type->addImmediateOperand(width); - type->addImmediateOperand(hasSign ? 1 : 0); - groupedTypes[OpTypeInt].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (width) { - case 8: - case 16: - // these are currently handled by storage-type declarations and post processing - break; - case 64: - addCapability(CapabilityInt64); - break; - default: - break; - } - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeIntegerDebugType(width, hasSign); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeFloatType(int width) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeFloat].size(); ++t) { - type = groupedTypes[OpTypeFloat][t]; - if (type->getImmediateOperand(0) == (unsigned)width) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeFloat); - type->addImmediateOperand(width); - groupedTypes[OpTypeFloat].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (width) { - case 16: - // currently handled by storage-type declarations and post processing - break; - case 64: - addCapability(CapabilityFloat64); - break; - default: - break; - } - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeFloatDebugType(width); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -// Make a struct without checking for duplication. -// See makeStructResultType() for non-decorated structs -// needed as the result of some instructions, which does -// check for duplicates. -Id Builder::makeStructType(const std::vector& members, const char* name, bool const compilerGenerated) -{ - // Don't look for previous one, because in the general case, - // structs can be duplicated except for decorations. - - // not found, make it - Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeStruct); - for (int op = 0; op < (int)members.size(); ++op) - type->addIdOperand(members[op]); - groupedTypes[OpTypeStruct].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - addName(type->getResultId(), name); - - if (emitNonSemanticShaderDebugInfo && !compilerGenerated) - { - auto const debugResultId = makeCompositeDebugType(members, name, NonSemanticShaderDebugInfo100Structure); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -// Make a struct for the simple results of several instructions, -// checking for duplication. -Id Builder::makeStructResultType(Id type0, Id type1) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeStruct].size(); ++t) { - type = groupedTypes[OpTypeStruct][t]; - if (type->getNumOperands() != 2) - continue; - if (type->getIdOperand(0) != type0 || - type->getIdOperand(1) != type1) - continue; - return type->getResultId(); - } - - // not found, make it - std::vector members; - members.push_back(type0); - members.push_back(type1); - - return makeStructType(members, "ResType"); -} - -Id Builder::makeVectorType(Id component, int size) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeVector].size(); ++t) { - type = groupedTypes[OpTypeVector][t]; - if (type->getIdOperand(0) == component && - type->getImmediateOperand(1) == (unsigned)size) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeVector); - type->addIdOperand(component); - type->addImmediateOperand(size); - groupedTypes[OpTypeVector].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeVectorDebugType(component, size); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeMatrixType(Id component, int cols, int rows) -{ - assert(cols <= maxMatrixSize && rows <= maxMatrixSize); - - Id column = makeVectorType(component, rows); - - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeMatrix].size(); ++t) { - type = groupedTypes[OpTypeMatrix][t]; - if (type->getIdOperand(0) == column && - type->getImmediateOperand(1) == (unsigned)cols) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeMatrix); - type->addIdOperand(column); - type->addImmediateOperand(cols); - groupedTypes[OpTypeMatrix].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeMatrixDebugType(column, cols); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeCooperativeMatrixTypeKHR(Id component, Id scope, Id rows, Id cols, Id use) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeCooperativeMatrixKHR].size(); ++t) { - type = groupedTypes[OpTypeCooperativeMatrixKHR][t]; - if (type->getIdOperand(0) == component && - type->getIdOperand(1) == scope && - type->getIdOperand(2) == rows && - type->getIdOperand(3) == cols && - type->getIdOperand(4) == use) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeCooperativeMatrixKHR); - type->addIdOperand(component); - type->addIdOperand(scope); - type->addIdOperand(rows); - type->addIdOperand(cols); - type->addIdOperand(use); - groupedTypes[OpTypeCooperativeMatrixKHR].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeCooperativeMatrixTypeNV(Id component, Id scope, Id rows, Id cols) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeCooperativeMatrixNV].size(); ++t) { - type = groupedTypes[OpTypeCooperativeMatrixNV][t]; - if (type->getIdOperand(0) == component && type->getIdOperand(1) == scope && type->getIdOperand(2) == rows && - type->getIdOperand(3) == cols) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeCooperativeMatrixNV); - type->addIdOperand(component); - type->addIdOperand(scope); - type->addIdOperand(rows); - type->addIdOperand(cols); - groupedTypes[OpTypeCooperativeMatrixNV].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeCooperativeMatrixTypeWithSameShape(Id component, Id otherType) -{ - Instruction* instr = module.getInstruction(otherType); - if (instr->getOpCode() == OpTypeCooperativeMatrixNV) { - return makeCooperativeMatrixTypeNV(component, instr->getIdOperand(1), instr->getIdOperand(2), instr->getIdOperand(3)); - } else { - assert(instr->getOpCode() == OpTypeCooperativeMatrixKHR); - return makeCooperativeMatrixTypeKHR(component, instr->getIdOperand(1), instr->getIdOperand(2), instr->getIdOperand(3), instr->getIdOperand(4)); - } -} - -Id Builder::makeGenericType(spv::Op opcode, std::vector& operands) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[opcode].size(); ++t) { - type = groupedTypes[opcode][t]; - if (static_cast(type->getNumOperands()) != operands.size()) - continue; // Number mismatch, find next - - bool match = true; - for (int op = 0; match && op < (int)operands.size(); ++op) { - match = (operands[op].isId ? type->getIdOperand(op) : type->getImmediateOperand(op)) == operands[op].word; - } - if (match) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, opcode); - for (size_t op = 0; op < operands.size(); ++op) { - if (operands[op].isId) - type->addIdOperand(operands[op].word); - else - type->addImmediateOperand(operands[op].word); - } - groupedTypes[opcode].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -// TODO: performance: track arrays per stride -// If a stride is supplied (non-zero) make an array. -// If no stride (0), reuse previous array types. -// 'size' is an Id of a constant or specialization constant of the array size -Id Builder::makeArrayType(Id element, Id sizeId, int stride) -{ - Instruction* type; - if (stride == 0) { - // try to find existing type - for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) { - type = groupedTypes[OpTypeArray][t]; - if (type->getIdOperand(0) == element && - type->getIdOperand(1) == sizeId) - return type->getResultId(); - } - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeArray); - type->addIdOperand(element); - type->addIdOperand(sizeId); - groupedTypes[OpTypeArray].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeArrayDebugType(element, sizeId); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeRuntimeArray(Id element) -{ - Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray); - type->addIdOperand(element); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeArrayDebugType(element, makeUintConstant(0)); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeFunctionType(Id returnType, const std::vector& paramTypes) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeFunction].size(); ++t) { - type = groupedTypes[OpTypeFunction][t]; - if (type->getIdOperand(0) != returnType || (int)paramTypes.size() != type->getNumOperands() - 1) - continue; - bool mismatch = false; - for (int p = 0; p < (int)paramTypes.size(); ++p) { - if (paramTypes[p] != type->getIdOperand(p + 1)) { - mismatch = true; - break; - } - } - if (! mismatch) - { - // If compiling HLSL, glslang will create a wrapper function around the entrypoint. Accordingly, a void(void) - // function type is created for the wrapper function. However, nonsemantic shader debug information is disabled - // while creating the HLSL wrapper. Consequently, if we encounter another void(void) function, we need to create - // the associated debug function type if it hasn't been created yet. - if(emitNonSemanticShaderDebugInfo && debugId[type->getResultId()] == 0) { - assert(sourceLang == spv::SourceLanguageHLSL); - assert(getTypeClass(returnType) == OpTypeVoid && paramTypes.size() == 0); - - Id debugTypeId = makeDebugFunctionType(returnType, {}); - debugId[type->getResultId()] = debugTypeId; - } - return type->getResultId(); - } - } - - // not found, make it - Id typeId = getUniqueId(); - type = new Instruction(typeId, NoType, OpTypeFunction); - type->addIdOperand(returnType); - for (int p = 0; p < (int)paramTypes.size(); ++p) - type->addIdOperand(paramTypes[p]); - groupedTypes[OpTypeFunction].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // make debug type and map it - if (emitNonSemanticShaderDebugInfo) { - Id debugTypeId = makeDebugFunctionType(returnType, paramTypes); - debugId[typeId] = debugTypeId; - } - - return type->getResultId(); -} - -Id Builder::makeDebugFunctionType(Id returnType, const std::vector& paramTypes) -{ - assert(debugId[returnType] != 0); - - Id typeId = getUniqueId(); - auto type = new Instruction(typeId, makeVoidType(), OpExtInst); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeFunction); - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); - type->addIdOperand(debugId[returnType]); - for (auto const paramType : paramTypes) { - if (isPointerType(paramType) || isArrayType(paramType)) { - type->addIdOperand(debugId[getContainedTypeId(paramType)]); - } - else { - type->addIdOperand(debugId[paramType]); - } - } - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - return typeId; -} - -Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, - ImageFormat format) -{ - assert(sampled == 1 || sampled == 2); - - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeImage].size(); ++t) { - type = groupedTypes[OpTypeImage][t]; - if (type->getIdOperand(0) == sampledType && - type->getImmediateOperand(1) == (unsigned int)dim && - type->getImmediateOperand(2) == ( depth ? 1u : 0u) && - type->getImmediateOperand(3) == (arrayed ? 1u : 0u) && - type->getImmediateOperand(4) == ( ms ? 1u : 0u) && - type->getImmediateOperand(5) == sampled && - type->getImmediateOperand(6) == (unsigned int)format) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeImage); - type->addIdOperand(sampledType); - type->addImmediateOperand( dim); - type->addImmediateOperand( depth ? 1 : 0); - type->addImmediateOperand(arrayed ? 1 : 0); - type->addImmediateOperand( ms ? 1 : 0); - type->addImmediateOperand(sampled); - type->addImmediateOperand((unsigned int)format); - - groupedTypes[OpTypeImage].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - // deal with capabilities - switch (dim) { - case DimBuffer: - if (sampled == 1) - addCapability(CapabilitySampledBuffer); - else - addCapability(CapabilityImageBuffer); - break; - case Dim1D: - if (sampled == 1) - addCapability(CapabilitySampled1D); - else - addCapability(CapabilityImage1D); - break; - case DimCube: - if (arrayed) { - if (sampled == 1) - addCapability(CapabilitySampledCubeArray); - else - addCapability(CapabilityImageCubeArray); - } - break; - case DimRect: - if (sampled == 1) - addCapability(CapabilitySampledRect); - else - addCapability(CapabilityImageRect); - break; - case DimSubpassData: - addCapability(CapabilityInputAttachment); - break; - default: - break; - } - - if (ms) { - if (sampled == 2) { - // Images used with subpass data are not storage - // images, so don't require the capability for them. - if (dim != Dim::DimSubpassData) - addCapability(CapabilityStorageImageMultisample); - if (arrayed) - addCapability(CapabilityImageMSArray); - } - } - - if (emitNonSemanticShaderDebugInfo) - { - auto TypeName = [&dim]() -> char const* { - switch (dim) { - case Dim1D: return "type.1d.image"; - case Dim2D: return "type.2d.image"; - case Dim3D: return "type.3d.image"; - case DimCube: return "type.cube.image"; - default: return "type.image"; - } - }; - - auto const debugResultId = makeCompositeDebugType({}, TypeName(), NonSemanticShaderDebugInfo100Class, true); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeSampledImageType(Id imageType) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedTypes[OpTypeSampledImage].size(); ++t) { - type = groupedTypes[OpTypeSampledImage][t]; - if (type->getIdOperand(0) == imageType) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), NoType, OpTypeSampledImage); - type->addIdOperand(imageType); - - groupedTypes[OpTypeSampledImage].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - if (emitNonSemanticShaderDebugInfo) - { - auto const debugResultId = makeCompositeDebugType({}, "type.sampled.image", NonSemanticShaderDebugInfo100Class, true); - debugId[type->getResultId()] = debugResultId; - } - - return type->getResultId(); -} - -Id Builder::makeDebugInfoNone() -{ - if (debugInfoNone != 0) - return debugInfoNone; - - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugInfoNone); - - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - - debugInfoNone = inst->getResultId(); - - return debugInfoNone; -} - -Id Builder::makeBoolDebugType(int const size) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) { - type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t]; - if (type->getIdOperand(0) == getStringId("bool") && - type->getIdOperand(1) == static_cast(size) && - type->getIdOperand(2) == NonSemanticShaderDebugInfo100Boolean) - return type->getResultId(); - } - - type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic); - - type->addIdOperand(getStringId("bool")); // name id - type->addIdOperand(makeUintConstant(size)); // size id - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Boolean)); // encoding id - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeIntegerDebugType(int const width, bool const hasSign) -{ - const char* typeName = nullptr; - switch (width) { - case 8: typeName = hasSign ? "int8_t" : "uint8_t"; break; - case 16: typeName = hasSign ? "int16_t" : "uint16_t"; break; - case 64: typeName = hasSign ? "int64_t" : "uint64_t"; break; - default: typeName = hasSign ? "int" : "uint"; - } - auto nameId = getStringId(typeName); - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) { - type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t]; - if (type->getIdOperand(0) == nameId && - type->getIdOperand(1) == static_cast(width) && - type->getIdOperand(2) == (hasSign ? NonSemanticShaderDebugInfo100Signed : NonSemanticShaderDebugInfo100Unsigned)) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic); - type->addIdOperand(nameId); // name id - type->addIdOperand(makeUintConstant(width)); // size id - if(hasSign == true) { - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Signed)); // encoding id - } else { - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Unsigned)); // encoding id - } - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeFloatDebugType(int const width) -{ - const char* typeName = nullptr; - switch (width) { - case 16: typeName = "float16_t"; break; - case 64: typeName = "double"; break; - default: typeName = "float"; break; - } - auto nameId = getStringId(typeName); - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].size(); ++t) { - type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic][t]; - if (type->getIdOperand(0) == nameId && - type->getIdOperand(1) == static_cast(width) && - type->getIdOperand(2) == NonSemanticShaderDebugInfo100Float) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeBasic); - type->addIdOperand(nameId); // name id - type->addIdOperand(makeUintConstant(width)); // size id - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100Float)); // encoding id - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100None)); // flags id - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeBasic].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeSequentialDebugType(Id const baseType, Id const componentCount, NonSemanticShaderDebugInfo100Instructions const sequenceType) -{ - assert(sequenceType == NonSemanticShaderDebugInfo100DebugTypeArray || - sequenceType == NonSemanticShaderDebugInfo100DebugTypeVector); - - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedDebugTypes[sequenceType].size(); ++t) { - type = groupedDebugTypes[sequenceType][t]; - if (type->getIdOperand(0) == baseType && - type->getIdOperand(1) == makeUintConstant(componentCount)) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(sequenceType); - type->addIdOperand(debugId[baseType]); // base type - type->addIdOperand(componentCount); // component count - - groupedDebugTypes[sequenceType].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeArrayDebugType(Id const baseType, Id const componentCount) -{ - return makeSequentialDebugType(baseType, componentCount, NonSemanticShaderDebugInfo100DebugTypeArray); -} - -Id Builder::makeVectorDebugType(Id const baseType, int const componentCount) -{ - return makeSequentialDebugType(baseType, makeUintConstant(componentCount), NonSemanticShaderDebugInfo100DebugTypeVector); -} - -Id Builder::makeMatrixDebugType(Id const vectorType, int const vectorCount, bool columnMajor) -{ - // try to find it - Instruction* type; - for (int t = 0; t < (int)groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix].size(); ++t) { - type = groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix][t]; - if (type->getIdOperand(0) == vectorType && - type->getIdOperand(1) == makeUintConstant(vectorCount)) - return type->getResultId(); - } - - // not found, make it - type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMatrix); - type->addIdOperand(debugId[vectorType]); // vector type id - type->addIdOperand(makeUintConstant(vectorCount)); // component count id - type->addIdOperand(makeBoolConstant(columnMajor)); // column-major id - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMatrix].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTypeLoc) -{ - assert(debugId[memberType] != 0); - - Instruction* type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeMember); - type->addIdOperand(getStringId(debugTypeLoc.name)); // name id - type->addIdOperand(debugId[memberType]); // type id - type->addIdOperand(makeDebugSource(sourceFileStringId)); // source id TODO: verify this works across include directives - type->addIdOperand(makeUintConstant(debugTypeLoc.line)); // line id TODO: currentLine is always zero - type->addIdOperand(makeUintConstant(debugTypeLoc.column)); // TODO: column id - type->addIdOperand(makeUintConstant(0)); // TODO: offset id - type->addIdOperand(makeUintConstant(0)); // TODO: size id - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); // flags id - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeMember].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -// Note: To represent a source language opaque type, this instruction must have no Members operands, Size operand must be -// DebugInfoNone, and Name must start with @ to avoid clashes with user defined names. -Id Builder::makeCompositeDebugType(std::vector const& memberTypes, char const*const name, - NonSemanticShaderDebugInfo100DebugCompositeType const tag, bool const isOpaqueType) -{ - // Create the debug member types. - std::vector memberDebugTypes; - for(auto const memberType : memberTypes) { - assert(debugTypeLocs.find(memberType) != debugTypeLocs.end()); - - // There _should_ be debug types for all the member types but currently buffer references - // do not have member debug info generated. - if (debugId[memberType]) - memberDebugTypes.emplace_back(makeMemberDebugType(memberType, debugTypeLocs[memberType])); - - // TODO: Need to rethink this method of passing location information. - // debugTypeLocs.erase(memberType); - } - - // Create The structure debug type. - Instruction* type = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugTypeComposite); - type->addIdOperand(getStringId(name)); // name id - type->addIdOperand(makeUintConstant(tag)); // tag id - type->addIdOperand(makeDebugSource(sourceFileStringId)); // source id TODO: verify this works across include directives - type->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero? - type->addIdOperand(makeUintConstant(0)); // TODO: column id - type->addIdOperand(makeDebugCompilationUnit()); // scope id - if(isOpaqueType == true) { - // Prepend '@' to opaque types. - type->addIdOperand(getStringId('@' + std::string(name))); // linkage name id - type->addIdOperand(makeDebugInfoNone()); // size id - } else { - type->addIdOperand(getStringId(name)); // linkage name id - type->addIdOperand(makeUintConstant(0)); // TODO: size id - } - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); // flags id - assert(isOpaqueType == false || (isOpaqueType == true && memberDebugTypes.empty())); - for(auto const memberDebugType : memberDebugTypes) { - type->addIdOperand(memberDebugType); - } - - groupedDebugTypes[NonSemanticShaderDebugInfo100DebugTypeComposite].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - - return type->getResultId(); -} - -Id Builder::makeDebugSource(const Id fileName) { - if (debugSourceId.find(fileName) != debugSourceId.end()) - return debugSourceId[fileName]; - spv::Id resultId = getUniqueId(); - Instruction* sourceInst = new Instruction(resultId, makeVoidType(), OpExtInst); - sourceInst->addIdOperand(nonSemanticShaderDebugInfo); - sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugSource); - sourceInst->addIdOperand(fileName); - if (emitNonSemanticShaderDebugSource) { - spv::Id sourceId = 0; - if (fileName == sourceFileStringId) { - sourceId = getStringId(sourceText); - } else { - auto incItr = includeFiles.find(fileName); - assert(incItr != includeFiles.end()); - sourceId = getStringId(*incItr->second); - } - sourceInst->addIdOperand(sourceId); - } - constantsTypesGlobals.push_back(std::unique_ptr(sourceInst)); - module.mapInstruction(sourceInst); - debugSourceId[fileName] = resultId; - return resultId; -} - -Id Builder::makeDebugCompilationUnit() { - if (nonSemanticShaderCompilationUnitId != 0) - return nonSemanticShaderCompilationUnitId; - spv::Id resultId = getUniqueId(); - Instruction* sourceInst = new Instruction(resultId, makeVoidType(), OpExtInst); - sourceInst->addIdOperand(nonSemanticShaderDebugInfo); - sourceInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugCompilationUnit); - sourceInst->addIdOperand(makeUintConstant(1)); // TODO(greg-lunarg): Get rid of magic number - sourceInst->addIdOperand(makeUintConstant(4)); // TODO(greg-lunarg): Get rid of magic number - sourceInst->addIdOperand(makeDebugSource(sourceFileStringId)); - sourceInst->addIdOperand(makeUintConstant(sourceLang)); - constantsTypesGlobals.push_back(std::unique_ptr(sourceInst)); - module.mapInstruction(sourceInst); - nonSemanticShaderCompilationUnitId = resultId; - - // We can reasonably assume that makeDebugCompilationUnit will be called before any of - // debug-scope stack. Function scopes and lexical scopes will occur afterward. - assert(currentDebugScopeId.empty()); - currentDebugScopeId.push(nonSemanticShaderCompilationUnitId); - - return resultId; -} - -Id Builder::createDebugGlobalVariable(Id const type, char const*const name, Id const variable) -{ - assert(type != 0); - - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugGlobalVariable); - inst->addIdOperand(getStringId(name)); // name id - inst->addIdOperand(type); // type id - inst->addIdOperand(makeDebugSource(sourceFileStringId)); // source id - inst->addIdOperand(makeUintConstant(currentLine)); // line id TODO: currentLine always zero? - inst->addIdOperand(makeUintConstant(0)); // TODO: column id - inst->addIdOperand(makeDebugCompilationUnit()); // scope id - inst->addIdOperand(getStringId(name)); // linkage name id - inst->addIdOperand(variable); // variable id - inst->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsDefinition)); // flags id - - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - - return inst->getResultId(); -} - -Id Builder::createDebugLocalVariable(Id type, char const*const name, size_t const argNumber) -{ - assert(name != nullptr); - assert(!currentDebugScopeId.empty()); - - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLocalVariable); - inst->addIdOperand(getStringId(name)); // name id - inst->addIdOperand(type); // type id - inst->addIdOperand(makeDebugSource(sourceFileStringId)); // source id - inst->addIdOperand(makeUintConstant(currentLine)); // line id - inst->addIdOperand(makeUintConstant(0)); // TODO: column id - inst->addIdOperand(currentDebugScopeId.top()); // scope id - inst->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsLocal)); // flags id - if(argNumber != 0) { - inst->addIdOperand(makeUintConstant(argNumber)); - } - - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - - return inst->getResultId(); -} - -Id Builder::makeDebugExpression() -{ - if (debugExpression != 0) - return debugExpression; - - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugExpression); - - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - - debugExpression = inst->getResultId(); - - return debugExpression; -} - -Id Builder::makeDebugDeclare(Id const debugLocalVariable, Id const pointer) -{ - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugDeclare); - inst->addIdOperand(debugLocalVariable); // debug local variable id - inst->addIdOperand(pointer); // pointer to local variable id - inst->addIdOperand(makeDebugExpression()); // expression id - buildPoint->addInstruction(std::unique_ptr(inst)); - - return inst->getResultId(); -} - -Id Builder::makeDebugValue(Id const debugLocalVariable, Id const value) -{ - Instruction* inst = new Instruction(getUniqueId(), makeVoidType(), OpExtInst); - inst->addIdOperand(nonSemanticShaderDebugInfo); - inst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugValue); - inst->addIdOperand(debugLocalVariable); // debug local variable id - inst->addIdOperand(value); // value of local variable id - inst->addIdOperand(makeDebugExpression()); // expression id - buildPoint->addInstruction(std::unique_ptr(inst)); - - return inst->getResultId(); -} - -Id Builder::makeAccelerationStructureType() -{ - Instruction *type; - if (groupedTypes[OpTypeAccelerationStructureKHR].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureKHR); - groupedTypes[OpTypeAccelerationStructureKHR].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else { - type = groupedTypes[OpTypeAccelerationStructureKHR].back(); - } - - return type->getResultId(); -} - -Id Builder::makeRayQueryType() -{ - Instruction *type; - if (groupedTypes[OpTypeRayQueryKHR].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeRayQueryKHR); - groupedTypes[OpTypeRayQueryKHR].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else { - type = groupedTypes[OpTypeRayQueryKHR].back(); - } - - return type->getResultId(); -} - -Id Builder::makeHitObjectNVType() -{ - Instruction *type; - if (groupedTypes[OpTypeHitObjectNV].size() == 0) { - type = new Instruction(getUniqueId(), NoType, OpTypeHitObjectNV); - groupedTypes[OpTypeHitObjectNV].push_back(type); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - } else { - type = groupedTypes[OpTypeHitObjectNV].back(); - } - - return type->getResultId(); -} - -Id Builder::getDerefTypeId(Id resultId) const -{ - Id typeId = getTypeId(resultId); - assert(isPointerType(typeId)); - - return module.getInstruction(typeId)->getIdOperand(1); -} - -Op Builder::getMostBasicTypeClass(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - return getMostBasicTypeClass(instr->getIdOperand(0)); - case OpTypePointer: - return getMostBasicTypeClass(instr->getIdOperand(1)); - default: - return typeClass; - } -} - -int Builder::getNumTypeConstituents(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - switch (instr->getOpCode()) - { - case OpTypeBool: - case OpTypeInt: - case OpTypeFloat: - case OpTypePointer: - return 1; - case OpTypeVector: - case OpTypeMatrix: - return instr->getImmediateOperand(1); - case OpTypeArray: - { - Id lengthId = instr->getIdOperand(1); - return module.getInstruction(lengthId)->getImmediateOperand(0); - } - case OpTypeStruct: - return instr->getNumOperands(); - case OpTypeCooperativeMatrixKHR: - case OpTypeCooperativeMatrixNV: - // has only one constituent when used with OpCompositeConstruct. - return 1; - default: - assert(0); - return 1; - } -} - -// Return the lowest-level type of scalar that an homogeneous composite is made out of. -// Typically, this is just to find out if something is made out of ints or floats. -// However, it includes returning a structure, if say, it is an array of structure. -Id Builder::getScalarTypeId(Id typeId) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVoid: - case OpTypeBool: - case OpTypeInt: - case OpTypeFloat: - case OpTypeStruct: - return instr->getResultId(); - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - case OpTypePointer: - return getScalarTypeId(getContainedTypeId(typeId)); - default: - assert(0); - return NoResult; - } -} - -// Return the type of 'member' of a composite. -Id Builder::getContainedTypeId(Id typeId, int member) const -{ - Instruction* instr = module.getInstruction(typeId); - - Op typeClass = instr->getOpCode(); - switch (typeClass) - { - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - case OpTypeCooperativeMatrixKHR: - case OpTypeCooperativeMatrixNV: - return instr->getIdOperand(0); - case OpTypePointer: - return instr->getIdOperand(1); - case OpTypeStruct: - return instr->getIdOperand(member); - default: - assert(0); - return NoResult; - } -} - -// Figure out the final resulting type of the access chain. -Id Builder::getResultingAccessChainType() const -{ - assert(accessChain.base != NoResult); - Id typeId = getTypeId(accessChain.base); - - assert(isPointerType(typeId)); - typeId = getContainedTypeId(typeId); - - for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) { - if (isStructType(typeId)) { - assert(isConstantScalar(accessChain.indexChain[i])); - typeId = getContainedTypeId(typeId, getConstantScalar(accessChain.indexChain[i])); - } else - typeId = getContainedTypeId(typeId, accessChain.indexChain[i]); - } - - return typeId; -} - -// Return the immediately contained type of a given composite type. -Id Builder::getContainedTypeId(Id typeId) const -{ - return getContainedTypeId(typeId, 0); -} - -// Returns true if 'typeId' is or contains a scalar type declared with 'typeOp' -// of width 'width'. The 'width' is only consumed for int and float types. -// Returns false otherwise. -bool Builder::containsType(Id typeId, spv::Op typeOp, unsigned int width) const -{ - const Instruction& instr = *module.getInstruction(typeId); - - Op typeClass = instr.getOpCode(); - switch (typeClass) - { - case OpTypeInt: - case OpTypeFloat: - return typeClass == typeOp && instr.getImmediateOperand(0) == width; - case OpTypeStruct: - for (int m = 0; m < instr.getNumOperands(); ++m) { - if (containsType(instr.getIdOperand(m), typeOp, width)) - return true; - } - return false; - case OpTypePointer: - return false; - case OpTypeVector: - case OpTypeMatrix: - case OpTypeArray: - case OpTypeRuntimeArray: - return containsType(getContainedTypeId(typeId), typeOp, width); - default: - return typeClass == typeOp; - } -} - -// return true if the type is a pointer to PhysicalStorageBufferEXT or an -// contains such a pointer. These require restrict/aliased decorations. -bool Builder::containsPhysicalStorageBufferOrArray(Id typeId) const -{ - const Instruction& instr = *module.getInstruction(typeId); - - Op typeClass = instr.getOpCode(); - switch (typeClass) - { - case OpTypePointer: - return getTypeStorageClass(typeId) == StorageClassPhysicalStorageBufferEXT; - case OpTypeArray: - return containsPhysicalStorageBufferOrArray(getContainedTypeId(typeId)); - case OpTypeStruct: - for (int m = 0; m < instr.getNumOperands(); ++m) { - if (containsPhysicalStorageBufferOrArray(instr.getIdOperand(m))) - return true; - } - return false; - default: - return false; - } -} - -// See if a scalar constant of this type has already been created, so it -// can be reused rather than duplicated. (Required by the specification). -Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) -{ - Instruction* constant; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - if (constant->getOpCode() == opcode && - constant->getTypeId() == typeId && - constant->getImmediateOperand(0) == value) - return constant->getResultId(); - } - - return 0; -} - -// Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double' or 'int64'). -Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) -{ - Instruction* constant; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - if (constant->getOpCode() == opcode && - constant->getTypeId() == typeId && - constant->getImmediateOperand(0) == v1 && - constant->getImmediateOperand(1) == v2) - return constant->getResultId(); - } - - return 0; -} - -// Return true if consuming 'opcode' means consuming a constant. -// "constant" here means after final transform to executable code, -// the value consumed will be a constant, so includes specialization. -bool Builder::isConstantOpCode(Op opcode) const -{ - switch (opcode) { - case OpUndef: - case OpConstantTrue: - case OpConstantFalse: - case OpConstant: - case OpConstantComposite: - case OpConstantSampler: - case OpConstantNull: - case OpSpecConstantTrue: - case OpSpecConstantFalse: - case OpSpecConstant: - case OpSpecConstantComposite: - case OpSpecConstantOp: - return true; - default: - return false; - } -} - -// Return true if consuming 'opcode' means consuming a specialization constant. -bool Builder::isSpecConstantOpCode(Op opcode) const -{ - switch (opcode) { - case OpSpecConstantTrue: - case OpSpecConstantFalse: - case OpSpecConstant: - case OpSpecConstantComposite: - case OpSpecConstantOp: - return true; - default: - return false; - } -} - -bool Builder::isRayTracingOpCode(Op opcode) const -{ - switch (opcode) { - case OpTypeAccelerationStructureKHR: - case OpTypeRayQueryKHR: - return true; - default: - return false; - } -} - -Id Builder::makeNullConstant(Id typeId) -{ - Instruction* constant; - - // See if we already made it. - Id existing = NoResult; - for (int i = 0; i < (int)nullConstants.size(); ++i) { - constant = nullConstants[i]; - if (constant->getTypeId() == typeId) - existing = constant->getResultId(); - } - - if (existing != NoResult) - return existing; - - // Make it - Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantNull); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - nullConstants.push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeBoolConstant(bool b, bool specConstant) -{ - Id typeId = makeBoolType(); - Instruction* constant; - Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse) : (b ? OpConstantTrue : OpConstantFalse); - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = 0; - for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) { - constant = groupedConstants[OpTypeBool][i]; - if (constant->getTypeId() == typeId && constant->getOpCode() == opcode) - existing = constant->getResultId(); - } - - if (existing) - return existing; - } - - // Make it - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeBool].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeInt, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeInt].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeInt64Constant(Id typeId, unsigned long long value, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - - unsigned op1 = value & 0xFFFFFFFF; - unsigned op2 = value >> 32; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeInt, opcode, typeId, op1, op2); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(op1); - c->addImmediateOperand(op2); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeInt].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeFloatConstant(float f, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(32); - union { float fl; unsigned int ui; } u; - u.fl = f; - unsigned value = u.ui; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeDoubleConstant(double d, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(64); - union { double db; unsigned long long ull; } u; - u.db = d; - unsigned long long value = u.ull; - unsigned op1 = value & 0xFFFFFFFF; - unsigned op2 = value >> 32; - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (! specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, op1, op2); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(op1); - c->addImmediateOperand(op2); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeFloat16Constant(float f16, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstant : OpConstant; - Id typeId = makeFloatType(16); - - spvutils::HexFloat> fVal(f16); - spvutils::HexFloat> f16Val(0); - fVal.castTo(f16Val, spvutils::kRoundToZero); - - unsigned value = f16Val.value().getAsFloat().get_value(); - - // See if we already made it. Applies only to regular constants, because specialization constants - // must remain distinct for the purpose of applying a SpecId decoration. - if (!specConstant) { - Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value); - if (existing) - return existing; - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - c->addImmediateOperand(value); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - groupedConstants[OpTypeFloat].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Id Builder::makeFpConstant(Id type, double d, bool specConstant) -{ - const int width = getScalarTypeWidth(type); - - assert(isFloatType(type)); - - switch (width) { - case 16: - return makeFloat16Constant((float)d, specConstant); - case 32: - return makeFloatConstant((float)d, specConstant); - case 64: - return makeDoubleConstant(d, specConstant); - default: - break; - } - - assert(false); - return NoResult; -} - -Id Builder::importNonSemanticShaderDebugInfoInstructions() -{ - assert(emitNonSemanticShaderDebugInfo == true); - - if(nonSemanticShaderDebugInfo == 0) - { - this->addExtension(spv::E_SPV_KHR_non_semantic_info); - nonSemanticShaderDebugInfo = this->import("NonSemantic.Shader.DebugInfo.100"); - } - - return nonSemanticShaderDebugInfo; -} - -Id Builder::findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps) -{ - Instruction* constant = nullptr; - bool found = false; - for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) { - constant = groupedConstants[typeClass][i]; - - if (constant->getTypeId() != typeId) - continue; - - // same contents? - bool mismatch = false; - for (int op = 0; op < constant->getNumOperands(); ++op) { - if (constant->getIdOperand(op) != comps[op]) { - mismatch = true; - break; - } - } - if (! mismatch) { - found = true; - break; - } - } - - return found ? constant->getResultId() : NoResult; -} - -Id Builder::findStructConstant(Id typeId, const std::vector& comps) -{ - Instruction* constant = nullptr; - bool found = false; - for (int i = 0; i < (int)groupedStructConstants[typeId].size(); ++i) { - constant = groupedStructConstants[typeId][i]; - - // same contents? - bool mismatch = false; - for (int op = 0; op < constant->getNumOperands(); ++op) { - if (constant->getIdOperand(op) != comps[op]) { - mismatch = true; - break; - } - } - if (! mismatch) { - found = true; - break; - } - } - - return found ? constant->getResultId() : NoResult; -} - -// Comments in header -Id Builder::makeCompositeConstant(Id typeId, const std::vector& members, bool specConstant) -{ - Op opcode = specConstant ? OpSpecConstantComposite : OpConstantComposite; - assert(typeId); - Op typeClass = getTypeClass(typeId); - - switch (typeClass) { - case OpTypeVector: - case OpTypeArray: - case OpTypeMatrix: - case OpTypeCooperativeMatrixKHR: - case OpTypeCooperativeMatrixNV: - if (! specConstant) { - Id existing = findCompositeConstant(typeClass, typeId, members); - if (existing) - return existing; - } - break; - case OpTypeStruct: - if (! specConstant) { - Id existing = findStructConstant(typeId, members); - if (existing) - return existing; - } - break; - default: - assert(0); - return makeFloatConstant(0.0); - } - - Instruction* c = new Instruction(getUniqueId(), typeId, opcode); - for (int op = 0; op < (int)members.size(); ++op) - c->addIdOperand(members[op]); - constantsTypesGlobals.push_back(std::unique_ptr(c)); - if (typeClass == OpTypeStruct) - groupedStructConstants[typeId].push_back(c); - else - groupedConstants[typeClass].push_back(c); - module.mapInstruction(c); - - return c->getResultId(); -} - -Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name) -{ - Instruction* entryPoint = new Instruction(OpEntryPoint); - entryPoint->addImmediateOperand(model); - entryPoint->addIdOperand(function->getId()); - entryPoint->addStringOperand(name); - - entryPoints.push_back(std::unique_ptr(entryPoint)); - - return entryPoint; -} - -// Currently relying on the fact that all 'value' of interest are small non-negative values. -void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2, int value3) -{ - // entryPoint can be null if we are in compile-only mode - if (!entryPoint) - return; - - Instruction* instr = new Instruction(OpExecutionMode); - instr->addIdOperand(entryPoint->getId()); - instr->addImmediateOperand(mode); - if (value1 >= 0) - instr->addImmediateOperand(value1); - if (value2 >= 0) - instr->addImmediateOperand(value2); - if (value3 >= 0) - instr->addImmediateOperand(value3); - - executionModes.push_back(std::unique_ptr(instr)); -} - -void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, const std::vector& literals) -{ - // entryPoint can be null if we are in compile-only mode - if (!entryPoint) - return; - - Instruction* instr = new Instruction(OpExecutionMode); - instr->addIdOperand(entryPoint->getId()); - instr->addImmediateOperand(mode); - for (auto literal : literals) - instr->addImmediateOperand(literal); - - executionModes.push_back(std::unique_ptr(instr)); -} - -void Builder::addExecutionModeId(Function* entryPoint, ExecutionMode mode, const std::vector& operandIds) -{ - // entryPoint can be null if we are in compile-only mode - if (!entryPoint) - return; - - Instruction* instr = new Instruction(OpExecutionModeId); - instr->addIdOperand(entryPoint->getId()); - instr->addImmediateOperand(mode); - for (auto operandId : operandIds) - instr->addIdOperand(operandId); - - executionModes.push_back(std::unique_ptr(instr)); -} - -void Builder::addName(Id id, const char* string) -{ - Instruction* name = new Instruction(OpName); - name->addIdOperand(id); - name->addStringOperand(string); - - names.push_back(std::unique_ptr(name)); -} - -void Builder::addMemberName(Id id, int memberNumber, const char* string) -{ - Instruction* name = new Instruction(OpMemberName); - name->addIdOperand(id); - name->addImmediateOperand(memberNumber); - name->addStringOperand(string); - - names.push_back(std::unique_ptr(name)); -} - -void Builder::addDecoration(Id id, Decoration decoration, int num) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorate); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - if (num >= 0) - dec->addImmediateOperand(num); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addDecoration(Id id, Decoration decoration, const char* s) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorateString); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - dec->addStringOperand(s); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addDecoration(Id id, Decoration decoration, const std::vector& literals) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorate); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - for (auto literal : literals) - dec->addImmediateOperand(literal); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addDecoration(Id id, Decoration decoration, const std::vector& strings) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorateString); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - for (auto string : strings) - dec->addStringOperand(string); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addLinkageDecoration(Id id, const char* name, spv::LinkageType linkType) { - Instruction* dec = new Instruction(OpDecorate); - dec->addIdOperand(id); - dec->addImmediateOperand(spv::DecorationLinkageAttributes); - dec->addStringOperand(name); - dec->addImmediateOperand(linkType); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorateId); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - dec->addIdOperand(idDecoration); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addDecorationId(Id id, Decoration decoration, const std::vector& operandIds) -{ - if(decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpDecorateId); - dec->addIdOperand(id); - dec->addImmediateOperand(decoration); - - for (auto operandId : operandIds) - dec->addIdOperand(operandId); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpMemberDecorate); - dec->addIdOperand(id); - dec->addImmediateOperand(member); - dec->addImmediateOperand(decoration); - if (num >= 0) - dec->addImmediateOperand(num); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const char *s) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpMemberDecorateStringGOOGLE); - dec->addIdOperand(id); - dec->addImmediateOperand(member); - dec->addImmediateOperand(decoration); - dec->addStringOperand(s); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector& literals) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpMemberDecorate); - dec->addIdOperand(id); - dec->addImmediateOperand(member); - dec->addImmediateOperand(decoration); - for (auto literal : literals) - dec->addImmediateOperand(literal); - - decorations.push_back(std::unique_ptr(dec)); -} - -void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector& strings) -{ - if (decoration == spv::DecorationMax) - return; - - Instruction* dec = new Instruction(OpMemberDecorateString); - dec->addIdOperand(id); - dec->addImmediateOperand(member); - dec->addImmediateOperand(decoration); - for (auto string : strings) - dec->addStringOperand(string); - - decorations.push_back(std::unique_ptr(dec)); -} - -// Comments in header -Function* Builder::makeEntryPoint(const char* entryPoint) -{ - assert(! entryPointFunction); - - auto const returnType = makeVoidType(); - - restoreNonSemanticShaderDebugInfo = emitNonSemanticShaderDebugInfo; - if(sourceLang == spv::SourceLanguageHLSL) { - emitNonSemanticShaderDebugInfo = false; - } - - Block* entry = nullptr; - entryPointFunction = makeFunctionEntry(NoPrecision, returnType, entryPoint, LinkageTypeMax, {}, {}, &entry); - - emitNonSemanticShaderDebugInfo = restoreNonSemanticShaderDebugInfo; - - return entryPointFunction; -} - -// Comments in header -Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, LinkageType linkType, - const std::vector& paramTypes, - const std::vector>& decorations, Block** entry) -{ - // Make the function and initial instructions in it - Id typeId = makeFunctionType(returnType, paramTypes); - Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size()); - Id funcId = getUniqueId(); - Function* function = new Function(funcId, returnType, typeId, firstParamId, linkType, name, module); - - // Set up the precisions - setPrecision(function->getId(), precision); - function->setReturnPrecision(precision); - for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) { - for (int d = 0; d < (int)decorations[p].size(); ++d) { - addDecoration(firstParamId + p, decorations[p][d]); - function->addParamPrecision(p, decorations[p][d]); - } - } - - // reset last debug scope - if (emitNonSemanticShaderDebugInfo) { - lastDebugScopeId = NoResult; - } - - // CFG - assert(entry != nullptr); - *entry = new Block(getUniqueId(), *function); - function->addBlock(*entry); - setBuildPoint(*entry); - - if (name) - addName(function->getId(), name); - - functions.push_back(std::unique_ptr(function)); - - return function; -} - -void Builder::setupDebugFunctionEntry(Function* function, const char* name, int line, const std::vector& paramTypes, - const std::vector& paramNames) -{ - - if (!emitNonSemanticShaderDebugInfo) - return; - - currentLine = line; - Id nameId = getStringId(unmangleFunctionName(name)); - Id funcTypeId = function->getFuncTypeId(); - assert(debugId[funcTypeId] != 0); - Id funcId = function->getId(); - - assert(funcId != 0); - - // Make the debug function instruction - Id debugFuncId = makeDebugFunction(function, nameId, funcTypeId); - debugId[funcId] = debugFuncId; - currentDebugScopeId.push(debugFuncId); - - // DebugScope and DebugLine for parameter DebugDeclares - assert(paramTypes.size() == paramNames.size()); - if ((int)paramTypes.size() > 0) { - addDebugScopeAndLine(currentFileId, currentLine, 0); - - Id firstParamId = function->getParamId(0); - - for (size_t p = 0; p < paramTypes.size(); ++p) { - bool passByRef = false; - Id paramTypeId = paramTypes[p]; - - // For pointer-typed parameters, they are actually passed by reference and we need unwrap the pointer to get the actual parameter type. - if (isPointerType(paramTypeId) || isArrayType(paramTypeId)) { - passByRef = true; - paramTypeId = getContainedTypeId(paramTypeId); - } - - auto const& paramName = paramNames[p]; - auto const debugLocalVariableId = createDebugLocalVariable(debugId[paramTypeId], paramName, p + 1); - auto const paramId = static_cast(firstParamId + p); - debugId[paramId] = debugLocalVariableId; - - if (passByRef) { - makeDebugDeclare(debugLocalVariableId, paramId); - } else { - makeDebugValue(debugLocalVariableId, paramId); - } - } - } - - // Clear debug scope stack - if (emitNonSemanticShaderDebugInfo) - currentDebugScopeId.pop(); -} - -Id Builder::makeDebugFunction([[maybe_unused]] Function* function, Id nameId, Id funcTypeId) -{ - assert(function != nullptr); - assert(nameId != 0); - assert(funcTypeId != 0); - assert(debugId[funcTypeId] != 0); - - Id funcId = getUniqueId(); - auto type = new Instruction(funcId, makeVoidType(), OpExtInst); - type->addIdOperand(nonSemanticShaderDebugInfo); - type->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunction); - type->addIdOperand(nameId); - type->addIdOperand(debugId[funcTypeId]); - type->addIdOperand(makeDebugSource(currentFileId)); // TODO: This points to file of definition instead of declaration - type->addIdOperand(makeUintConstant(currentLine)); // TODO: This points to line of definition instead of declaration - type->addIdOperand(makeUintConstant(0)); // column - type->addIdOperand(makeDebugCompilationUnit()); // scope - type->addIdOperand(nameId); // linkage name - type->addIdOperand(makeUintConstant(NonSemanticShaderDebugInfo100FlagIsPublic)); - type->addIdOperand(makeUintConstant(currentLine)); - constantsTypesGlobals.push_back(std::unique_ptr(type)); - module.mapInstruction(type); - return funcId; -} - -Id Builder::makeDebugLexicalBlock(uint32_t line) { - assert(!currentDebugScopeId.empty()); - - Id lexId = getUniqueId(); - auto lex = new Instruction(lexId, makeVoidType(), OpExtInst); - lex->addIdOperand(nonSemanticShaderDebugInfo); - lex->addImmediateOperand(NonSemanticShaderDebugInfo100DebugLexicalBlock); - lex->addIdOperand(makeDebugSource(currentFileId)); - lex->addIdOperand(makeUintConstant(line)); - lex->addIdOperand(makeUintConstant(0)); // column - lex->addIdOperand(currentDebugScopeId.top()); // scope - constantsTypesGlobals.push_back(std::unique_ptr(lex)); - module.mapInstruction(lex); - return lexId; -} - -std::string Builder::unmangleFunctionName(std::string const& name) const -{ - assert(name.length() > 0); - - if(name.rfind('(') != std::string::npos) { - return name.substr(0, name.rfind('(')); - } else { - return name; - } -} - -// Comments in header -void Builder::makeReturn(bool implicit, Id retVal) -{ - if (retVal) { - Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue); - inst->addIdOperand(retVal); - buildPoint->addInstruction(std::unique_ptr(inst)); - } else - buildPoint->addInstruction(std::unique_ptr(new Instruction(NoResult, NoType, OpReturn))); - - if (! implicit) - createAndSetNoPredecessorBlock("post-return"); -} - -// Comments in header -void Builder::enterScope(uint32_t line) -{ - // Generate new lexical scope debug instruction - Id lexId = makeDebugLexicalBlock(line); - currentDebugScopeId.push(lexId); - lastDebugScopeId = NoResult; -} - -// Comments in header -void Builder::leaveScope() -{ - // Pop current scope from stack and clear current scope - currentDebugScopeId.pop(); - lastDebugScopeId = NoResult; -} - -// Comments in header -void Builder::enterFunction(Function const* function) -{ - // Save and disable debugInfo for HLSL entry point function. It is a wrapper - // function with no user code in it. - restoreNonSemanticShaderDebugInfo = emitNonSemanticShaderDebugInfo; - if (sourceLang == spv::SourceLanguageHLSL && function == entryPointFunction) { - emitNonSemanticShaderDebugInfo = false; - } - - if (emitNonSemanticShaderDebugInfo) { - // Initialize scope state - Id funcId = function->getFuncId(); - currentDebugScopeId.push(debugId[funcId]); - // Create DebugFunctionDefinition - spv::Id resultId = getUniqueId(); - Instruction* defInst = new Instruction(resultId, makeVoidType(), OpExtInst); - defInst->addIdOperand(nonSemanticShaderDebugInfo); - defInst->addImmediateOperand(NonSemanticShaderDebugInfo100DebugFunctionDefinition); - defInst->addIdOperand(debugId[funcId]); - defInst->addIdOperand(funcId); - buildPoint->addInstruction(std::unique_ptr(defInst)); - } - - if (auto linkType = function->getLinkType(); linkType != LinkageTypeMax) { - Id funcId = function->getFuncId(); - addCapability(CapabilityLinkage); - addLinkageDecoration(funcId, function->getExportName(), linkType); - } -} - -// Comments in header -void Builder::leaveFunction() -{ - Block* block = buildPoint; - Function& function = buildPoint->getParent(); - assert(block); - - // If our function did not contain a return, add a return void now. - if (! block->isTerminated()) { - if (function.getReturnType() == makeVoidType()) - makeReturn(true); - else { - makeReturn(true, createUndefined(function.getReturnType())); - } - } - - // Clear function scope from debug scope stack - if (emitNonSemanticShaderDebugInfo) - currentDebugScopeId.pop(); - - emitNonSemanticShaderDebugInfo = restoreNonSemanticShaderDebugInfo; -} - -// Comments in header -void Builder::makeStatementTerminator(spv::Op opcode, const char *name) -{ - buildPoint->addInstruction(std::unique_ptr(new Instruction(opcode))); - createAndSetNoPredecessorBlock(name); -} - -// Comments in header -void Builder::makeStatementTerminator(spv::Op opcode, const std::vector& operands, const char* name) -{ - // It's assumed that the terminator instruction is always of void return type - // However in future if there is a need for non void return type, new helper - // methods can be created. - createNoResultOp(opcode, operands); - createAndSetNoPredecessorBlock(name); -} - -// Comments in header -Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer, - bool const compilerGenerated) -{ - Id pointerType = makePointer(storageClass, type); - Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable); - inst->addImmediateOperand(storageClass); - if (initializer != NoResult) - inst->addIdOperand(initializer); - - switch (storageClass) { - case StorageClassFunction: - // Validation rules require the declaration in the entry block - buildPoint->getParent().addLocalVariable(std::unique_ptr(inst)); - - if (emitNonSemanticShaderDebugInfo && !compilerGenerated) - { - auto const debugLocalVariableId = createDebugLocalVariable(debugId[type], name); - debugId[inst->getResultId()] = debugLocalVariableId; - - makeDebugDeclare(debugLocalVariableId, inst->getResultId()); - } - - break; - - default: - constantsTypesGlobals.push_back(std::unique_ptr(inst)); - module.mapInstruction(inst); - - if (emitNonSemanticShaderDebugInfo && !isRayTracingOpCode(getOpCode(type))) - { - auto const debugResultId = createDebugGlobalVariable(debugId[type], name, inst->getResultId()); - debugId[inst->getResultId()] = debugResultId; - } - break; - } - - if (name) - addName(inst->getResultId(), name); - setPrecision(inst->getResultId(), precision); - - return inst->getResultId(); -} - -// Comments in header -Id Builder::createUndefined(Id type) -{ - Instruction* inst = new Instruction(getUniqueId(), type, OpUndef); - buildPoint->addInstruction(std::unique_ptr(inst)); - return inst->getResultId(); -} - -// av/vis/nonprivate are unnecessary and illegal for some storage classes. -spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) - const -{ - switch (sc) { - case spv::StorageClassUniform: - case spv::StorageClassWorkgroup: - case spv::StorageClassStorageBuffer: - case spv::StorageClassPhysicalStorageBufferEXT: - break; - default: - memoryAccess = spv::MemoryAccessMask(memoryAccess & - ~(spv::MemoryAccessMakePointerAvailableKHRMask | - spv::MemoryAccessMakePointerVisibleKHRMask | - spv::MemoryAccessNonPrivatePointerKHRMask)); - break; - } - return memoryAccess; -} - -// Comments in header -void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, - unsigned int alignment) -{ - Instruction* store = new Instruction(OpStore); - store->addIdOperand(lValue); - store->addIdOperand(rValue); - - memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue)); - - if (memoryAccess != MemoryAccessMaskNone) { - store->addImmediateOperand(memoryAccess); - if (memoryAccess & spv::MemoryAccessAlignedMask) { - store->addImmediateOperand(alignment); - } - if (memoryAccess & spv::MemoryAccessMakePointerAvailableKHRMask) { - store->addIdOperand(makeUintConstant(scope)); - } - } - - buildPoint->addInstruction(std::unique_ptr(store)); -} - -// Comments in header -Id Builder::createLoad(Id lValue, spv::Decoration precision, spv::MemoryAccessMask memoryAccess, - spv::Scope scope, unsigned int alignment) -{ - Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad); - load->addIdOperand(lValue); - - memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue)); - - if (memoryAccess != MemoryAccessMaskNone) { - load->addImmediateOperand(memoryAccess); - if (memoryAccess & spv::MemoryAccessAlignedMask) { - load->addImmediateOperand(alignment); - } - if (memoryAccess & spv::MemoryAccessMakePointerVisibleKHRMask) { - load->addIdOperand(makeUintConstant(scope)); - } - } - - buildPoint->addInstruction(std::unique_ptr(load)); - setPrecision(load->getResultId(), precision); - - return load->getResultId(); -} - -// Comments in header -Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector& offsets) -{ - // Figure out the final resulting type. - Id typeId = getResultingAccessChainType(); - typeId = makePointer(storageClass, typeId); - - // Make the instruction - Instruction* chain = new Instruction(getUniqueId(), typeId, OpAccessChain); - chain->addIdOperand(base); - for (int i = 0; i < (int)offsets.size(); ++i) - chain->addIdOperand(offsets[i]); - buildPoint->addInstruction(std::unique_ptr(chain)); - - return chain->getResultId(); -} - -Id Builder::createArrayLength(Id base, unsigned int member) -{ - spv::Id intType = makeUintType(32); - Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength); - length->addIdOperand(base); - length->addImmediateOperand(member); - buildPoint->addInstruction(std::unique_ptr(length)); - - return length->getResultId(); -} - -Id Builder::createCooperativeMatrixLengthKHR(Id type) -{ - spv::Id intType = makeUintType(32); - - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCooperativeMatrixLengthKHR, intType, std::vector(1, type), std::vector()); - } - - Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthKHR); - length->addIdOperand(type); - buildPoint->addInstruction(std::unique_ptr(length)); - - return length->getResultId(); -} - -Id Builder::createCooperativeMatrixLengthNV(Id type) -{ - spv::Id intType = makeUintType(32); - - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCooperativeMatrixLengthNV, intType, std::vector(1, type), std::vector()); - } - - Instruction* length = new Instruction(getUniqueId(), intType, OpCooperativeMatrixLengthNV); - length->addIdOperand(type); - buildPoint->addInstruction(std::unique_ptr(length)); - - return length->getResultId(); -} - -Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), - std::vector(1, index)); - } - Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); - extract->addIdOperand(composite); - extract->addImmediateOperand(index); - buildPoint->addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createCompositeExtract(Id composite, Id typeId, const std::vector& indexes) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(OpCompositeExtract, typeId, std::vector(1, composite), indexes); - } - Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); - extract->addIdOperand(composite); - for (int i = 0; i < (int)indexes.size(); ++i) - extract->addImmediateOperand(indexes[i]); - buildPoint->addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned index) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert); - insert->addIdOperand(object); - insert->addIdOperand(composite); - insert->addImmediateOperand(index); - buildPoint->addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert); - insert->addIdOperand(object); - insert->addIdOperand(composite); - for (int i = 0; i < (int)indexes.size(); ++i) - insert->addImmediateOperand(indexes[i]); - buildPoint->addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex) -{ - Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic); - extract->addIdOperand(vector); - extract->addIdOperand(componentIndex); - buildPoint->addInstruction(std::unique_ptr(extract)); - - return extract->getResultId(); -} - -Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex) -{ - Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic); - insert->addIdOperand(vector); - insert->addIdOperand(component); - insert->addIdOperand(componentIndex); - buildPoint->addInstruction(std::unique_ptr(insert)); - - return insert->getResultId(); -} - -// An opcode that has no operands, no result id, and no type -void Builder::createNoResultOp(Op opCode) -{ - Instruction* op = new Instruction(opCode); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one id operand, no result id, and no type -void Builder::createNoResultOp(Op opCode, Id operand) -{ - Instruction* op = new Instruction(opCode); - op->addIdOperand(operand); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one or more operands, no result id, and no type -void Builder::createNoResultOp(Op opCode, const std::vector& operands) -{ - Instruction* op = new Instruction(opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) { - op->addIdOperand(*it); - } - buildPoint->addInstruction(std::unique_ptr(op)); -} - -// An opcode that has multiple operands, no result id, and no type -void Builder::createNoResultOp(Op opCode, const std::vector& operands) -{ - Instruction* op = new Instruction(opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) { - if (it->isId) - op->addIdOperand(it->word); - else - op->addImmediateOperand(it->word); - } - buildPoint->addInstruction(std::unique_ptr(op)); -} - -void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics) -{ - Instruction* op = new Instruction(OpControlBarrier); - op->addIdOperand(makeUintConstant(execution)); - op->addIdOperand(makeUintConstant(memory)); - op->addIdOperand(makeUintConstant(semantics)); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics) -{ - Instruction* op = new Instruction(OpMemoryBarrier); - op->addIdOperand(makeUintConstant(executionScope)); - op->addIdOperand(makeUintConstant(memorySemantics)); - buildPoint->addInstruction(std::unique_ptr(op)); -} - -// An opcode that has one operands, a result id, and a type -Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - return createSpecConstantOp(opCode, typeId, std::vector(1, operand), std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->addIdOperand(operand); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - std::vector operands(2); - operands[0] = left; operands[1] = right; - return createSpecConstantOp(opCode, typeId, operands, std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->addIdOperand(left); - op->addIdOperand(right); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3) -{ - // Generate code for spec constants if in spec constant operation - // generation mode. - if (generatingOpCodeForSpecConst) { - std::vector operands(3); - operands[0] = op1; - operands[1] = op2; - operands[2] = op3; - return createSpecConstantOp( - opCode, typeId, operands, std::vector()); - } - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - op->addIdOperand(op1); - op->addIdOperand(op2); - op->addIdOperand(op3); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createOp(Op opCode, Id typeId, const std::vector& operands) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) - op->addIdOperand(*it); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createOp(Op opCode, Id typeId, const std::vector& operands) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) { - if (it->isId) - op->addIdOperand(it->word); - else - op->addImmediateOperand(it->word); - } - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector& operands, - const std::vector& literals) -{ - Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); - op->addImmediateOperand((unsigned) opCode); - for (auto it = operands.cbegin(); it != operands.cend(); ++it) - op->addIdOperand(*it); - for (auto it = literals.cbegin(); it != literals.cend(); ++it) - op->addImmediateOperand(*it); - module.mapInstruction(op); - constantsTypesGlobals.push_back(std::unique_ptr(op)); - - return op->getResultId(); -} - -Id Builder::createFunctionCall(spv::Function* function, const std::vector& args) -{ - Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall); - op->addIdOperand(function->getId()); - for (int a = 0; a < (int)args.size(); ++a) - op->addIdOperand(args[a]); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -// Comments in header -Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels) -{ - if (channels.size() == 1) - return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision); - - if (generatingOpCodeForSpecConst) { - std::vector operands(2); - operands[0] = operands[1] = source; - return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, operands, channels), precision); - } - Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); - assert(isVector(source)); - swizzle->addIdOperand(source); - swizzle->addIdOperand(source); - for (int i = 0; i < (int)channels.size(); ++i) - swizzle->addImmediateOperand(channels[i]); - buildPoint->addInstruction(std::unique_ptr(swizzle)); - - return setPrecision(swizzle->getResultId(), precision); -} - -// Comments in header -Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels) -{ - if (channels.size() == 1 && getNumComponents(source) == 1) - return createCompositeInsert(source, target, typeId, channels.front()); - - Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle); - - assert(isVector(target)); - swizzle->addIdOperand(target); - - assert(getNumComponents(source) == (int)channels.size()); - assert(isVector(source)); - swizzle->addIdOperand(source); - - // Set up an identity shuffle from the base value to the result value - unsigned int components[4]; - int numTargetComponents = getNumComponents(target); - for (int i = 0; i < numTargetComponents; ++i) - components[i] = i; - - // Punch in the l-value swizzle - for (int i = 0; i < (int)channels.size(); ++i) - components[channels[i]] = numTargetComponents + i; - - // finish the instruction with these components selectors - for (int i = 0; i < numTargetComponents; ++i) - swizzle->addImmediateOperand(components[i]); - buildPoint->addInstruction(std::unique_ptr(swizzle)); - - return swizzle->getResultId(); -} - -// Comments in header -void Builder::promoteScalar(Decoration precision, Id& left, Id& right) -{ - int direction = getNumComponents(right) - getNumComponents(left); - - if (direction > 0) - left = smearScalar(precision, left, makeVectorType(getTypeId(left), getNumComponents(right))); - else if (direction < 0) - right = smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left))); - - return; -} - -// Comments in header -Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType) -{ - assert(getNumComponents(scalar) == 1); - assert(getTypeId(scalar) == getScalarTypeId(vectorType)); - - int numComponents = getNumTypeComponents(vectorType); - if (numComponents == 1) - return scalar; - - Instruction* smear = nullptr; - if (generatingOpCodeForSpecConst) { - auto members = std::vector(numComponents, scalar); - // Sometime even in spec-constant-op mode, the temporary vector created by - // promoting a scalar might not be a spec constant. This should depend on - // the scalar. - // e.g.: - // const vec2 spec_const_result = a_spec_const_vec2 + a_front_end_const_scalar; - // In such cases, the temporary vector created from a_front_end_const_scalar - // is not a spec constant vector, even though the binary operation node is marked - // as 'specConstant' and we are in spec-constant-op mode. - auto result_id = makeCompositeConstant(vectorType, members, isSpecConstant(scalar)); - smear = module.getInstruction(result_id); - } else { - smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct); - for (int c = 0; c < numComponents; ++c) - smear->addIdOperand(scalar); - buildPoint->addInstruction(std::unique_ptr(smear)); - } - - return setPrecision(smear->getResultId(), precision); -} - -// Comments in header -Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args) -{ - Instruction* inst = new Instruction(getUniqueId(), resultType, OpExtInst); - inst->addIdOperand(builtins); - inst->addImmediateOperand(entryPoint); - for (int arg = 0; arg < (int)args.size(); ++arg) - inst->addIdOperand(args[arg]); - - buildPoint->addInstruction(std::unique_ptr(inst)); - - return inst->getResultId(); -} - -// Accept all parameters needed to create a texture instruction. -// Create the correct instruction based on the inputs, and make the call. -Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, - bool noImplicitLod, const TextureParameters& parameters, ImageOperandsMask signExtensionMask) -{ - std::vector texArgs; - - // - // Set up the fixed arguments - // - bool explicitLod = false; - texArgs.push_back(parameters.sampler); - texArgs.push_back(parameters.coords); - if (parameters.Dref != NoResult) - texArgs.push_back(parameters.Dref); - if (parameters.component != NoResult) - texArgs.push_back(parameters.component); - - if (parameters.granularity != NoResult) - texArgs.push_back(parameters.granularity); - if (parameters.coarse != NoResult) - texArgs.push_back(parameters.coarse); - - // - // Set up the optional arguments - // - size_t optArgNum = texArgs.size(); // the position of the mask for the optional arguments, if any. - ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand - if (parameters.bias) { - mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask); - texArgs.push_back(parameters.bias); - } - if (parameters.lod) { - mask = (ImageOperandsMask)(mask | ImageOperandsLodMask); - texArgs.push_back(parameters.lod); - explicitLod = true; - } else if (parameters.gradX) { - mask = (ImageOperandsMask)(mask | ImageOperandsGradMask); - texArgs.push_back(parameters.gradX); - texArgs.push_back(parameters.gradY); - explicitLod = true; - } else if (noImplicitLod && ! fetch && ! gather) { - // have to explicitly use lod of 0 if not allowed to have them be implicit, and - // we would otherwise be about to issue an implicit instruction - mask = (ImageOperandsMask)(mask | ImageOperandsLodMask); - texArgs.push_back(makeFloatConstant(0.0)); - explicitLod = true; - } - if (parameters.offset) { - if (isConstant(parameters.offset)) - mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetMask); - else { - addCapability(CapabilityImageGatherExtended); - mask = (ImageOperandsMask)(mask | ImageOperandsOffsetMask); - } - texArgs.push_back(parameters.offset); - } - if (parameters.offsets) { - addCapability(CapabilityImageGatherExtended); - mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetsMask); - texArgs.push_back(parameters.offsets); - } - if (parameters.sample) { - mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask); - texArgs.push_back(parameters.sample); - } - if (parameters.lodClamp) { - // capability if this bit is used - addCapability(CapabilityMinLod); - - mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask); - texArgs.push_back(parameters.lodClamp); - } - if (parameters.nonprivate) { - mask = mask | ImageOperandsNonPrivateTexelKHRMask; - } - if (parameters.volatil) { - mask = mask | ImageOperandsVolatileTexelKHRMask; - } - mask = mask | signExtensionMask; - // insert the operand for the mask, if any bits were set. - if (mask != ImageOperandsMaskNone) - texArgs.insert(texArgs.begin() + optArgNum, mask); - - // - // Set up the instruction - // - Op opCode = OpNop; // All paths below need to set this - if (fetch) { - if (sparse) - opCode = OpImageSparseFetch; - else - opCode = OpImageFetch; - } else if (parameters.granularity && parameters.coarse) { - opCode = OpImageSampleFootprintNV; - } else if (gather) { - if (parameters.Dref) - if (sparse) - opCode = OpImageSparseDrefGather; - else - opCode = OpImageDrefGather; - else - if (sparse) - opCode = OpImageSparseGather; - else - opCode = OpImageGather; - } else if (explicitLod) { - if (parameters.Dref) { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjDrefExplicitLod; - else - opCode = OpImageSampleProjDrefExplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleDrefExplicitLod; - else - opCode = OpImageSampleDrefExplicitLod; - } else { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjExplicitLod; - else - opCode = OpImageSampleProjExplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleExplicitLod; - else - opCode = OpImageSampleExplicitLod; - } - } else { - if (parameters.Dref) { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjDrefImplicitLod; - else - opCode = OpImageSampleProjDrefImplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleDrefImplicitLod; - else - opCode = OpImageSampleDrefImplicitLod; - } else { - if (proj) - if (sparse) - opCode = OpImageSparseSampleProjImplicitLod; - else - opCode = OpImageSampleProjImplicitLod; - else - if (sparse) - opCode = OpImageSparseSampleImplicitLod; - else - opCode = OpImageSampleImplicitLod; - } - } - - // See if the result type is expecting a smeared result. - // This happens when a legacy shadow*() call is made, which - // gets a vec4 back instead of a float. - Id smearedType = resultType; - if (! isScalarType(resultType)) { - switch (opCode) { - case OpImageSampleDrefImplicitLod: - case OpImageSampleDrefExplicitLod: - case OpImageSampleProjDrefImplicitLod: - case OpImageSampleProjDrefExplicitLod: - resultType = getScalarTypeId(resultType); - break; - default: - break; - } - } - - Id typeId0 = 0; - Id typeId1 = 0; - - if (sparse) { - typeId0 = resultType; - typeId1 = getDerefTypeId(parameters.texelOut); - resultType = makeStructResultType(typeId0, typeId1); - } - - // Build the SPIR-V instruction - Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode); - for (size_t op = 0; op < optArgNum; ++op) - textureInst->addIdOperand(texArgs[op]); - if (optArgNum < texArgs.size()) - textureInst->addImmediateOperand(texArgs[optArgNum]); - for (size_t op = optArgNum + 1; op < texArgs.size(); ++op) - textureInst->addIdOperand(texArgs[op]); - setPrecision(textureInst->getResultId(), precision); - buildPoint->addInstruction(std::unique_ptr(textureInst)); - - Id resultId = textureInst->getResultId(); - - if (sparse) { - // set capability - addCapability(CapabilitySparseResidency); - - // Decode the return type that was a special structure - createStore(createCompositeExtract(resultId, typeId1, 1), parameters.texelOut); - resultId = createCompositeExtract(resultId, typeId0, 0); - setPrecision(resultId, precision); - } else { - // When a smear is needed, do it, as per what was computed - // above when resultType was changed to a scalar type. - if (resultType != smearedType) - resultId = smearScalar(precision, resultId, smearedType); - } - - return resultId; -} - -// Comments in header -Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters, bool isUnsignedResult) -{ - // Figure out the result type - Id resultType = 0; - switch (opCode) { - case OpImageQuerySize: - case OpImageQuerySizeLod: - { - int numComponents = 0; - switch (getTypeDimensionality(getImageType(parameters.sampler))) { - case Dim1D: - case DimBuffer: - numComponents = 1; - break; - case Dim2D: - case DimCube: - case DimRect: - case DimSubpassData: - numComponents = 2; - break; - case Dim3D: - numComponents = 3; - break; - - default: - assert(0); - break; - } - if (isArrayedImageType(getImageType(parameters.sampler))) - ++numComponents; - - Id intType = isUnsignedResult ? makeUintType(32) : makeIntType(32); - if (numComponents == 1) - resultType = intType; - else - resultType = makeVectorType(intType, numComponents); - - break; - } - case OpImageQueryLod: - resultType = makeVectorType(getScalarTypeId(getTypeId(parameters.coords)), 2); - break; - case OpImageQueryLevels: - case OpImageQuerySamples: - resultType = isUnsignedResult ? makeUintType(32) : makeIntType(32); - break; - default: - assert(0); - break; - } - - Instruction* query = new Instruction(getUniqueId(), resultType, opCode); - query->addIdOperand(parameters.sampler); - if (parameters.coords) - query->addIdOperand(parameters.coords); - if (parameters.lod) - query->addIdOperand(parameters.lod); - buildPoint->addInstruction(std::unique_ptr(query)); - addCapability(CapabilityImageQuery); - - return query->getResultId(); -} - -// External comments in header. -// Operates recursively to visit the composite's hierarchy. -Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, bool equal) -{ - Id boolType = makeBoolType(); - Id valueType = getTypeId(value1); - - Id resultId = NoResult; - - int numConstituents = getNumTypeConstituents(valueType); - - // Scalars and Vectors - - if (isScalarType(valueType) || isVectorType(valueType)) { - assert(valueType == getTypeId(value2)); - // These just need a single comparison, just have - // to figure out what it is. - Op op; - switch (getMostBasicTypeClass(valueType)) { - case OpTypeFloat: - op = equal ? OpFOrdEqual : OpFUnordNotEqual; - break; - case OpTypeInt: - default: - op = equal ? OpIEqual : OpINotEqual; - break; - case OpTypeBool: - op = equal ? OpLogicalEqual : OpLogicalNotEqual; - precision = NoPrecision; - break; - } - - if (isScalarType(valueType)) { - // scalar - resultId = createBinOp(op, boolType, value1, value2); - } else { - // vector - resultId = createBinOp(op, makeVectorType(boolType, numConstituents), value1, value2); - setPrecision(resultId, precision); - // reduce vector compares... - resultId = createUnaryOp(equal ? OpAll : OpAny, boolType, resultId); - } - - return setPrecision(resultId, precision); - } - - // Only structs, arrays, and matrices should be left. - // They share in common the reduction operation across their constituents. - assert(isAggregateType(valueType) || isMatrixType(valueType)); - - // Compare each pair of constituents - for (int constituent = 0; constituent < numConstituents; ++constituent) { - std::vector indexes(1, constituent); - Id constituentType1 = getContainedTypeId(getTypeId(value1), constituent); - Id constituentType2 = getContainedTypeId(getTypeId(value2), constituent); - Id constituent1 = createCompositeExtract(value1, constituentType1, indexes); - Id constituent2 = createCompositeExtract(value2, constituentType2, indexes); - - Id subResultId = createCompositeCompare(precision, constituent1, constituent2, equal); - - if (constituent == 0) - resultId = subResultId; - else - resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), - precision); - } - - return resultId; -} - -// OpCompositeConstruct -Id Builder::createCompositeConstruct(Id typeId, const std::vector& constituents) -{ - assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && - getNumTypeConstituents(typeId) == (int)constituents.size())); - - if (generatingOpCodeForSpecConst) { - // Sometime, even in spec-constant-op mode, the constant composite to be - // constructed may not be a specialization constant. - // e.g.: - // const mat2 m2 = mat2(a_spec_const, a_front_end_const, another_front_end_const, third_front_end_const); - // The first column vector should be a spec constant one, as a_spec_const is a spec constant. - // The second column vector should NOT be spec constant, as it does not contain any spec constants. - // To handle such cases, we check the constituents of the constant vector to determine whether this - // vector should be created as a spec constant. - return makeCompositeConstant(typeId, constituents, - std::any_of(constituents.begin(), constituents.end(), - [&](spv::Id id) { return isSpecConstant(id); })); - } - - Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct); - for (int c = 0; c < (int)constituents.size(); ++c) - op->addIdOperand(constituents[c]); - buildPoint->addInstruction(std::unique_ptr(op)); - - return op->getResultId(); -} - -// Vector or scalar constructor -Id Builder::createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId) -{ - Id result = NoResult; - unsigned int numTargetComponents = getNumTypeComponents(resultTypeId); - unsigned int targetComponent = 0; - - // Special case: when calling a vector constructor with a single scalar - // argument, smear the scalar - if (sources.size() == 1 && isScalar(sources[0]) && numTargetComponents > 1) - return smearScalar(precision, sources[0], resultTypeId); - - // accumulate the arguments for OpCompositeConstruct - std::vector constituents; - Id scalarTypeId = getScalarTypeId(resultTypeId); - - // lambda to store the result of visiting an argument component - const auto latchResult = [&](Id comp) { - if (numTargetComponents > 1) - constituents.push_back(comp); - else - result = comp; - ++targetComponent; - }; - - // lambda to visit a vector argument's components - const auto accumulateVectorConstituents = [&](Id sourceArg) { - unsigned int sourceSize = getNumComponents(sourceArg); - unsigned int sourcesToUse = sourceSize; - if (sourcesToUse + targetComponent > numTargetComponents) - sourcesToUse = numTargetComponents - targetComponent; - - for (unsigned int s = 0; s < sourcesToUse; ++s) { - std::vector swiz; - swiz.push_back(s); - latchResult(createRvalueSwizzle(precision, scalarTypeId, sourceArg, swiz)); - } - }; - - // lambda to visit a matrix argument's components - const auto accumulateMatrixConstituents = [&](Id sourceArg) { - unsigned int sourceSize = getNumColumns(sourceArg) * getNumRows(sourceArg); - unsigned int sourcesToUse = sourceSize; - if (sourcesToUse + targetComponent > numTargetComponents) - sourcesToUse = numTargetComponents - targetComponent; - - int col = 0; - int row = 0; - for (unsigned int s = 0; s < sourcesToUse; ++s) { - if (row >= getNumRows(sourceArg)) { - row = 0; - col++; - } - std::vector indexes; - indexes.push_back(col); - indexes.push_back(row); - latchResult(createCompositeExtract(sourceArg, scalarTypeId, indexes)); - row++; - } - }; - - // Go through the source arguments, each one could have either - // a single or multiple components to contribute. - for (unsigned int i = 0; i < sources.size(); ++i) { - - if (isScalar(sources[i]) || isPointer(sources[i])) - latchResult(sources[i]); - else if (isVector(sources[i])) - accumulateVectorConstituents(sources[i]); - else if (isMatrix(sources[i])) - accumulateMatrixConstituents(sources[i]); - else - assert(0); - - if (targetComponent >= numTargetComponents) - break; - } - - // If the result is a vector, make it from the gathered constituents. - if (constituents.size() > 0) - result = createCompositeConstruct(resultTypeId, constituents); - - return setPrecision(result, precision); -} - -// Comments in header -Id Builder::createMatrixConstructor(Decoration precision, const std::vector& sources, Id resultTypeId) -{ - Id componentTypeId = getScalarTypeId(resultTypeId); - int numCols = getTypeNumColumns(resultTypeId); - int numRows = getTypeNumRows(resultTypeId); - - Instruction* instr = module.getInstruction(componentTypeId); - const unsigned bitCount = instr->getImmediateOperand(0); - - // Optimize matrix constructed from a bigger matrix - if (isMatrix(sources[0]) && getNumColumns(sources[0]) >= numCols && getNumRows(sources[0]) >= numRows) { - // To truncate the matrix to a smaller number of rows/columns, we need to: - // 1. For each column, extract the column and truncate it to the required size using shuffle - // 2. Assemble the resulting matrix from all columns - Id matrix = sources[0]; - Id columnTypeId = getContainedTypeId(resultTypeId); - Id sourceColumnTypeId = getContainedTypeId(getTypeId(matrix)); - - std::vector channels; - for (int row = 0; row < numRows; ++row) - channels.push_back(row); - - std::vector matrixColumns; - for (int col = 0; col < numCols; ++col) { - std::vector indexes; - indexes.push_back(col); - Id colv = createCompositeExtract(matrix, sourceColumnTypeId, indexes); - setPrecision(colv, precision); - - if (numRows != getNumRows(matrix)) { - matrixColumns.push_back(createRvalueSwizzle(precision, columnTypeId, colv, channels)); - } else { - matrixColumns.push_back(colv); - } - } - - return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision); - } - - // Otherwise, will use a two step process - // 1. make a compile-time 2D array of values - // 2. construct a matrix from that array - - // Step 1. - - // initialize the array to the identity matrix - Id ids[maxMatrixSize][maxMatrixSize]; - Id one = (bitCount == 64 ? makeDoubleConstant(1.0) : makeFloatConstant(1.0)); - Id zero = (bitCount == 64 ? makeDoubleConstant(0.0) : makeFloatConstant(0.0)); - for (int col = 0; col < 4; ++col) { - for (int row = 0; row < 4; ++row) { - if (col == row) - ids[col][row] = one; - else - ids[col][row] = zero; - } - } - - // modify components as dictated by the arguments - if (sources.size() == 1 && isScalar(sources[0])) { - // a single scalar; resets the diagonals - for (int col = 0; col < 4; ++col) - ids[col][col] = sources[0]; - } else if (isMatrix(sources[0])) { - // constructing from another matrix; copy over the parts that exist in both the argument and constructee - Id matrix = sources[0]; - int minCols = std::min(numCols, getNumColumns(matrix)); - int minRows = std::min(numRows, getNumRows(matrix)); - for (int col = 0; col < minCols; ++col) { - std::vector indexes; - indexes.push_back(col); - for (int row = 0; row < minRows; ++row) { - indexes.push_back(row); - ids[col][row] = createCompositeExtract(matrix, componentTypeId, indexes); - indexes.pop_back(); - setPrecision(ids[col][row], precision); - } - } - } else { - // fill in the matrix in column-major order with whatever argument components are available - int row = 0; - int col = 0; - - for (int arg = 0; arg < (int)sources.size() && col < numCols; ++arg) { - Id argComp = sources[arg]; - for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) { - if (getNumComponents(sources[arg]) > 1) { - argComp = createCompositeExtract(sources[arg], componentTypeId, comp); - setPrecision(argComp, precision); - } - ids[col][row++] = argComp; - if (row == numRows) { - row = 0; - col++; - } - if (col == numCols) { - // If more components are provided than fit the matrix, discard the rest. - break; - } - } - } - } - - // Step 2: Construct a matrix from that array. - // First make the column vectors, then make the matrix. - - // make the column vectors - Id columnTypeId = getContainedTypeId(resultTypeId); - std::vector matrixColumns; - for (int col = 0; col < numCols; ++col) { - std::vector vectorComponents; - for (int row = 0; row < numRows; ++row) - vectorComponents.push_back(ids[col][row]); - Id column = createCompositeConstruct(columnTypeId, vectorComponents); - setPrecision(column, precision); - matrixColumns.push_back(column); - } - - // make the matrix - return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision); -} - -// Comments in header -Builder::If::If(Id cond, unsigned int ctrl, Builder& gb) : - builder(gb), - condition(cond), - control(ctrl), - elseBlock(nullptr) -{ - function = &builder.getBuildPoint()->getParent(); - - // make the blocks, but only put the then-block into the function, - // the else-block and merge-block will be added later, in order, after - // earlier code is emitted - thenBlock = new Block(builder.getUniqueId(), *function); - mergeBlock = new Block(builder.getUniqueId(), *function); - - // Save the current block, so that we can add in the flow control split when - // makeEndIf is called. - headerBlock = builder.getBuildPoint(); - - function->addBlock(thenBlock); - builder.setBuildPoint(thenBlock); -} - -// Comments in header -void Builder::If::makeBeginElse() -{ - // Close out the "then" by having it jump to the mergeBlock - builder.createBranch(mergeBlock); - - // Make the first else block and add it to the function - elseBlock = new Block(builder.getUniqueId(), *function); - function->addBlock(elseBlock); - - // Start building the else block - builder.setBuildPoint(elseBlock); -} - -// Comments in header -void Builder::If::makeEndIf() -{ - // jump to the merge block - builder.createBranch(mergeBlock); - - // Go back to the headerBlock and make the flow control split - builder.setBuildPoint(headerBlock); - builder.createSelectionMerge(mergeBlock, control); - if (elseBlock) - builder.createConditionalBranch(condition, thenBlock, elseBlock); - else - builder.createConditionalBranch(condition, thenBlock, mergeBlock); - - // add the merge block to the function - function->addBlock(mergeBlock); - builder.setBuildPoint(mergeBlock); -} - -// Comments in header -void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, const std::vector& caseValues, - const std::vector& valueIndexToSegment, int defaultSegment, - std::vector& segmentBlocks) -{ - Function& function = buildPoint->getParent(); - - // make all the blocks - for (int s = 0; s < numSegments; ++s) - segmentBlocks.push_back(new Block(getUniqueId(), function)); - - Block* mergeBlock = new Block(getUniqueId(), function); - - // make and insert the switch's selection-merge instruction - createSelectionMerge(mergeBlock, control); - - // make the switch instruction - Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch); - switchInst->addIdOperand(selector); - auto defaultOrMerge = (defaultSegment >= 0) ? segmentBlocks[defaultSegment] : mergeBlock; - switchInst->addIdOperand(defaultOrMerge->getId()); - defaultOrMerge->addPredecessor(buildPoint); - for (int i = 0; i < (int)caseValues.size(); ++i) { - switchInst->addImmediateOperand(caseValues[i]); - switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId()); - segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint); - } - buildPoint->addInstruction(std::unique_ptr(switchInst)); - - // push the merge block - switchMerges.push(mergeBlock); -} - -// Comments in header -void Builder::addSwitchBreak() -{ - // branch to the top of the merge block stack - createBranch(switchMerges.top()); - createAndSetNoPredecessorBlock("post-switch-break"); -} - -// Comments in header -void Builder::nextSwitchSegment(std::vector& segmentBlock, int nextSegment) -{ - int lastSegment = nextSegment - 1; - if (lastSegment >= 0) { - // Close out previous segment by jumping, if necessary, to next segment - if (! buildPoint->isTerminated()) - createBranch(segmentBlock[nextSegment]); - } - Block* block = segmentBlock[nextSegment]; - block->getParent().addBlock(block); - setBuildPoint(block); -} - -// Comments in header -void Builder::endSwitch(std::vector& /*segmentBlock*/) -{ - // Close out previous segment by jumping, if necessary, to next segment - if (! buildPoint->isTerminated()) - addSwitchBreak(); - - switchMerges.top()->getParent().addBlock(switchMerges.top()); - setBuildPoint(switchMerges.top()); - - switchMerges.pop(); -} - -Block& Builder::makeNewBlock() -{ - Function& function = buildPoint->getParent(); - auto block = new Block(getUniqueId(), function); - function.addBlock(block); - return *block; -} - -Builder::LoopBlocks& Builder::makeNewLoop() -{ - // This verbosity is needed to simultaneously get the same behavior - // everywhere (id's in the same order), have a syntax that works - // across lots of versions of C++, have no warnings from pedantic - // compilation modes, and leave the rest of the code alone. - Block& head = makeNewBlock(); - Block& body = makeNewBlock(); - Block& merge = makeNewBlock(); - Block& continue_target = makeNewBlock(); - LoopBlocks blocks(head, body, merge, continue_target); - loops.push(blocks); - return loops.top(); -} - -void Builder::createLoopContinue() -{ - createBranch(&loops.top().continue_target); - // Set up a block for dead code. - createAndSetNoPredecessorBlock("post-loop-continue"); -} - -void Builder::createLoopExit() -{ - createBranch(&loops.top().merge); - // Set up a block for dead code. - createAndSetNoPredecessorBlock("post-loop-break"); -} - -void Builder::closeLoop() -{ - loops.pop(); -} - -void Builder::clearAccessChain() -{ - accessChain.base = NoResult; - accessChain.indexChain.clear(); - accessChain.instr = NoResult; - accessChain.swizzle.clear(); - accessChain.component = NoResult; - accessChain.preSwizzleBaseType = NoType; - accessChain.isRValue = false; - accessChain.coherentFlags.clear(); - accessChain.alignment = 0; -} - -// Comments in header -void Builder::accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, - AccessChain::CoherentFlags coherentFlags, unsigned int alignment) -{ - accessChain.coherentFlags |= coherentFlags; - accessChain.alignment |= alignment; - - // swizzles can be stacked in GLSL, but simplified to a single - // one here; the base type doesn't change - if (accessChain.preSwizzleBaseType == NoType) - accessChain.preSwizzleBaseType = preSwizzleBaseType; - - // if needed, propagate the swizzle for the current access chain - if (accessChain.swizzle.size() > 0) { - std::vector oldSwizzle = accessChain.swizzle; - accessChain.swizzle.resize(0); - for (unsigned int i = 0; i < swizzle.size(); ++i) { - assert(swizzle[i] < oldSwizzle.size()); - accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]); - } - } else - accessChain.swizzle = swizzle; - - // determine if we need to track this swizzle anymore - simplifyAccessChainSwizzle(); -} - -// Comments in header -void Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) -{ - assert(accessChain.isRValue == false); - - transferAccessChainSwizzle(true); - - // If a swizzle exists and is not full and is not dynamic, then the swizzle will be broken into individual stores. - if (accessChain.swizzle.size() > 0 && - getNumTypeComponents(getResultingAccessChainType()) != (int)accessChain.swizzle.size() && - accessChain.component == NoResult) { - for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) { - accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle[i])); - accessChain.instr = NoResult; - - Id base = collapseAccessChain(); - addDecoration(base, nonUniform); - - accessChain.indexChain.pop_back(); - accessChain.instr = NoResult; - - // dynamic component should be gone - assert(accessChain.component == NoResult); - - Id source = createCompositeExtract(rvalue, getContainedTypeId(getTypeId(rvalue)), i); - - // take LSB of alignment - alignment = alignment & ~(alignment & (alignment-1)); - if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) { - memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); - } - - createStore(source, base, memoryAccess, scope, alignment); - } - } - else { - Id base = collapseAccessChain(); - addDecoration(base, nonUniform); - - Id source = rvalue; - - // dynamic component should be gone - assert(accessChain.component == NoResult); - - // If swizzle still exists, it may be out-of-order, we must load the target vector, - // extract and insert elements to perform writeMask and/or swizzle. - if (accessChain.swizzle.size() > 0) { - Id tempBaseId = createLoad(base, spv::NoPrecision); - source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle); - } - - // take LSB of alignment - alignment = alignment & ~(alignment & (alignment-1)); - if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) { - memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); - } - - createStore(source, base, memoryAccess, scope, alignment); - } -} - -// Comments in header -Id Builder::accessChainLoad(Decoration precision, Decoration l_nonUniform, - Decoration r_nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, - spv::Scope scope, unsigned int alignment) -{ - Id id; - - if (accessChain.isRValue) { - // transfer access chain, but try to stay in registers - transferAccessChainSwizzle(false); - if (accessChain.indexChain.size() > 0) { - Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType; - - // if all the accesses are constants, we can use OpCompositeExtract - std::vector indexes; - bool constant = true; - for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) { - if (isConstantScalar(accessChain.indexChain[i])) - indexes.push_back(getConstantScalar(accessChain.indexChain[i])); - else { - constant = false; - break; - } - } - - if (constant) { - id = createCompositeExtract(accessChain.base, swizzleBase, indexes); - setPrecision(id, precision); - } else { - Id lValue = NoResult; - if (spvVersion >= Spv_1_4 && isValidInitializer(accessChain.base)) { - // make a new function variable for this r-value, using an initializer, - // and mark it as NonWritable so that downstream it can be detected as a lookup - // table - lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base), - "indexable", accessChain.base); - addDecoration(lValue, DecorationNonWritable); - } else { - lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base), - "indexable"); - // store into it - createStore(accessChain.base, lValue); - } - // move base to the new variable - accessChain.base = lValue; - accessChain.isRValue = false; - - // load through the access chain - id = createLoad(collapseAccessChain(), precision); - } - } else - id = accessChain.base; // no precision, it was set when this was defined - } else { - transferAccessChainSwizzle(true); - - // take LSB of alignment - alignment = alignment & ~(alignment & (alignment-1)); - if (getStorageClass(accessChain.base) == StorageClassPhysicalStorageBufferEXT) { - memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); - } - - // load through the access chain - id = collapseAccessChain(); - // Apply nonuniform both to the access chain and the loaded value. - // Buffer accesses need the access chain decorated, and this is where - // loaded image types get decorated. TODO: This should maybe move to - // createImageTextureFunctionCall. - addDecoration(id, l_nonUniform); - id = createLoad(id, precision, memoryAccess, scope, alignment); - addDecoration(id, r_nonUniform); - } - - // Done, unless there are swizzles to do - if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult) - return id; - - // Do remaining swizzling - - // Do the basic swizzle - if (accessChain.swizzle.size() > 0) { - Id swizzledType = getScalarTypeId(getTypeId(id)); - if (accessChain.swizzle.size() > 1) - swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size()); - id = createRvalueSwizzle(precision, swizzledType, id, accessChain.swizzle); - } - - // Do the dynamic component - if (accessChain.component != NoResult) - id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision); - - addDecoration(id, r_nonUniform); - return id; -} - -Id Builder::accessChainGetLValue() -{ - assert(accessChain.isRValue == false); - - transferAccessChainSwizzle(true); - Id lvalue = collapseAccessChain(); - - // If swizzle exists, it is out-of-order or not full, we must load the target vector, - // extract and insert elements to perform writeMask and/or swizzle. This does not - // go with getting a direct l-value pointer. - assert(accessChain.swizzle.size() == 0); - assert(accessChain.component == NoResult); - - return lvalue; -} - -// comment in header -Id Builder::accessChainGetInferredType() -{ - // anything to operate on? - if (accessChain.base == NoResult) - return NoType; - Id type = getTypeId(accessChain.base); - - // do initial dereference - if (! accessChain.isRValue) - type = getContainedTypeId(type); - - // dereference each index - for (auto it = accessChain.indexChain.cbegin(); it != accessChain.indexChain.cend(); ++it) { - if (isStructType(type)) - type = getContainedTypeId(type, getConstantScalar(*it)); - else - type = getContainedTypeId(type); - } - - // dereference swizzle - if (accessChain.swizzle.size() == 1) - type = getContainedTypeId(type); - else if (accessChain.swizzle.size() > 1) - type = makeVectorType(getContainedTypeId(type), (int)accessChain.swizzle.size()); - - // dereference component selection - if (accessChain.component) - type = getContainedTypeId(type); - - return type; -} - -void Builder::dump(std::vector& out) const -{ - // Header, before first instructions: - out.push_back(MagicNumber); - out.push_back(spvVersion); - out.push_back(builderNumber); - out.push_back(uniqueId + 1); - out.push_back(0); - - // Capabilities - for (auto it = capabilities.cbegin(); it != capabilities.cend(); ++it) { - Instruction capInst(0, 0, OpCapability); - capInst.addImmediateOperand(*it); - capInst.dump(out); - } - - for (auto it = extensions.cbegin(); it != extensions.cend(); ++it) { - Instruction extInst(0, 0, OpExtension); - extInst.addStringOperand(it->c_str()); - extInst.dump(out); - } - - dumpInstructions(out, imports); - Instruction memInst(0, 0, OpMemoryModel); - memInst.addImmediateOperand(addressModel); - memInst.addImmediateOperand(memoryModel); - memInst.dump(out); - - // Instructions saved up while building: - dumpInstructions(out, entryPoints); - dumpInstructions(out, executionModes); - - // Debug instructions - dumpInstructions(out, strings); - dumpSourceInstructions(out); - for (int e = 0; e < (int)sourceExtensions.size(); ++e) { - Instruction sourceExtInst(0, 0, OpSourceExtension); - sourceExtInst.addStringOperand(sourceExtensions[e]); - sourceExtInst.dump(out); - } - dumpInstructions(out, names); - dumpModuleProcesses(out); - - // Annotation instructions - dumpInstructions(out, decorations); - - dumpInstructions(out, constantsTypesGlobals); - dumpInstructions(out, externals); - - // The functions - module.dump(out); -} - -// -// Protected methods. -// - -// Turn the described access chain in 'accessChain' into an instruction(s) -// computing its address. This *cannot* include complex swizzles, which must -// be handled after this is called. -// -// Can generate code. -Id Builder::collapseAccessChain() -{ - assert(accessChain.isRValue == false); - - // did we already emit an access chain for this? - if (accessChain.instr != NoResult) - return accessChain.instr; - - // If we have a dynamic component, we can still transfer - // that into a final operand to the access chain. We need to remap the - // dynamic component through the swizzle to get a new dynamic component to - // update. - // - // This was not done in transferAccessChainSwizzle() because it might - // generate code. - remapDynamicSwizzle(); - if (accessChain.component != NoResult) { - // transfer the dynamic component to the access chain - accessChain.indexChain.push_back(accessChain.component); - accessChain.component = NoResult; - } - - // note that non-trivial swizzling is left pending - - // do we have an access chain? - if (accessChain.indexChain.size() == 0) - return accessChain.base; - - // emit the access chain - StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base)); - accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain); - - return accessChain.instr; -} - -// For a dynamic component selection of a swizzle. -// -// Turn the swizzle and dynamic component into just a dynamic component. -// -// Generates code. -void Builder::remapDynamicSwizzle() -{ - // do we have a swizzle to remap a dynamic component through? - if (accessChain.component != NoResult && accessChain.swizzle.size() > 1) { - // build a vector of the swizzle for the component to map into - std::vector components; - for (int c = 0; c < (int)accessChain.swizzle.size(); ++c) - components.push_back(makeUintConstant(accessChain.swizzle[c])); - Id mapType = makeVectorType(makeUintType(32), (int)accessChain.swizzle.size()); - Id map = makeCompositeConstant(mapType, components); - - // use it - accessChain.component = createVectorExtractDynamic(map, makeUintType(32), accessChain.component); - accessChain.swizzle.clear(); - } -} - -// clear out swizzle if it is redundant, that is reselecting the same components -// that would be present without the swizzle. -void Builder::simplifyAccessChainSwizzle() -{ - // If the swizzle has fewer components than the vector, it is subsetting, and must stay - // to preserve that fact. - if (getNumTypeComponents(accessChain.preSwizzleBaseType) > (int)accessChain.swizzle.size()) - return; - - // if components are out of order, it is a swizzle - for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) { - if (i != accessChain.swizzle[i]) - return; - } - - // otherwise, there is no need to track this swizzle - accessChain.swizzle.clear(); - if (accessChain.component == NoResult) - accessChain.preSwizzleBaseType = NoType; -} - -// To the extent any swizzling can become part of the chain -// of accesses instead of a post operation, make it so. -// If 'dynamic' is true, include transferring the dynamic component, -// otherwise, leave it pending. -// -// Does not generate code. just updates the access chain. -void Builder::transferAccessChainSwizzle(bool dynamic) -{ - // non existent? - if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult) - return; - - // too complex? - // (this requires either a swizzle, or generating code for a dynamic component) - if (accessChain.swizzle.size() > 1) - return; - - // single component, either in the swizzle and/or dynamic component - if (accessChain.swizzle.size() == 1) { - assert(accessChain.component == NoResult); - // handle static component selection - accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front())); - accessChain.swizzle.clear(); - accessChain.preSwizzleBaseType = NoType; - } else if (dynamic && accessChain.component != NoResult) { - assert(accessChain.swizzle.size() == 0); - // handle dynamic component - accessChain.indexChain.push_back(accessChain.component); - accessChain.preSwizzleBaseType = NoType; - accessChain.component = NoResult; - } -} - -// Utility method for creating a new block and setting the insert point to -// be in it. This is useful for flow-control operations that need a "dummy" -// block proceeding them (e.g. instructions after a discard, etc). -void Builder::createAndSetNoPredecessorBlock(const char* /*name*/) -{ - Block* block = new Block(getUniqueId(), buildPoint->getParent()); - block->setUnreachable(); - buildPoint->getParent().addBlock(block); - setBuildPoint(block); - - // if (name) - // addName(block->getId(), name); -} - -// Comments in header -void Builder::createBranch(Block* block) -{ - Instruction* branch = new Instruction(OpBranch); - branch->addIdOperand(block->getId()); - buildPoint->addInstruction(std::unique_ptr(branch)); - block->addPredecessor(buildPoint); -} - -void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control) -{ - Instruction* merge = new Instruction(OpSelectionMerge); - merge->addIdOperand(mergeBlock->getId()); - merge->addImmediateOperand(control); - buildPoint->addInstruction(std::unique_ptr(merge)); -} - -void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, - const std::vector& operands) -{ - Instruction* merge = new Instruction(OpLoopMerge); - merge->addIdOperand(mergeBlock->getId()); - merge->addIdOperand(continueBlock->getId()); - merge->addImmediateOperand(control); - for (int op = 0; op < (int)operands.size(); ++op) - merge->addImmediateOperand(operands[op]); - buildPoint->addInstruction(std::unique_ptr(merge)); -} - -void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock) -{ - Instruction* branch = new Instruction(OpBranchConditional); - branch->addIdOperand(condition); - branch->addIdOperand(thenBlock->getId()); - branch->addIdOperand(elseBlock->getId()); - buildPoint->addInstruction(std::unique_ptr(branch)); - thenBlock->addPredecessor(buildPoint); - elseBlock->addPredecessor(buildPoint); -} - -// OpSource -// [OpSourceContinued] -// ... -void Builder::dumpSourceInstructions(const spv::Id fileId, const std::string& text, - std::vector& out) const -{ - const int maxWordCount = 0xFFFF; - const int opSourceWordCount = 4; - const int nonNullBytesPerInstruction = 4 * (maxWordCount - opSourceWordCount) - 1; - - if (sourceLang != SourceLanguageUnknown) { - // OpSource Language Version File Source - Instruction sourceInst(NoResult, NoType, OpSource); - sourceInst.addImmediateOperand(sourceLang); - sourceInst.addImmediateOperand(sourceVersion); - // File operand - if (fileId != NoResult) { - sourceInst.addIdOperand(fileId); - // Source operand - if (text.size() > 0) { - int nextByte = 0; - std::string subString; - while ((int)text.size() - nextByte > 0) { - subString = text.substr(nextByte, nonNullBytesPerInstruction); - if (nextByte == 0) { - // OpSource - sourceInst.addStringOperand(subString.c_str()); - sourceInst.dump(out); - } else { - // OpSourcContinued - Instruction sourceContinuedInst(OpSourceContinued); - sourceContinuedInst.addStringOperand(subString.c_str()); - sourceContinuedInst.dump(out); - } - nextByte += nonNullBytesPerInstruction; - } - } else - sourceInst.dump(out); - } else - sourceInst.dump(out); - } -} - -// Dump an OpSource[Continued] sequence for the source and every include file -void Builder::dumpSourceInstructions(std::vector& out) const -{ - if (emitNonSemanticShaderDebugInfo) return; - dumpSourceInstructions(sourceFileStringId, sourceText, out); - for (auto iItr = includeFiles.begin(); iItr != includeFiles.end(); ++iItr) - dumpSourceInstructions(iItr->first, *iItr->second, out); -} - -void Builder::dumpInstructions(std::vector& out, - const std::vector >& instructions) const -{ - for (int i = 0; i < (int)instructions.size(); ++i) { - instructions[i]->dump(out); - } -} - -void Builder::dumpModuleProcesses(std::vector& out) const -{ - for (int i = 0; i < (int)moduleProcesses.size(); ++i) { - Instruction moduleProcessed(OpModuleProcessed); - moduleProcessed.addStringOperand(moduleProcesses[i]); - moduleProcessed.dump(out); - } -} - -} // end spv namespace diff --git a/3rdparty/glslang/SPIRV/SpvBuilder.h b/3rdparty/glslang/SPIRV/SpvBuilder.h deleted file mode 100644 index b1ca6ce1..00000000 --- a/3rdparty/glslang/SPIRV/SpvBuilder.h +++ /dev/null @@ -1,961 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// Copyright (C) 2015-2020 Google, Inc. -// Copyright (C) 2017 ARM Limited. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// "Builder" is an interface to fully build SPIR-V IR. Allocate one of -// these to build (a thread safe) internal SPIR-V representation (IR), -// and then dump it as a binary stream according to the SPIR-V specification. -// -// A Builder has a 1:1 relationship with a SPIR-V module. -// - -#pragma once -#ifndef SpvBuilder_H -#define SpvBuilder_H - -#include "Logger.h" -#include "spirv.hpp" -#include "spvIR.h" -namespace spv { - #include "GLSL.ext.KHR.h" - #include "NonSemanticShaderDebugInfo100.h" -} - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace spv { - -typedef enum { - Spv_1_0 = (1 << 16), - Spv_1_1 = (1 << 16) | (1 << 8), - Spv_1_2 = (1 << 16) | (2 << 8), - Spv_1_3 = (1 << 16) | (3 << 8), - Spv_1_4 = (1 << 16) | (4 << 8), - Spv_1_5 = (1 << 16) | (5 << 8), -} SpvVersion; - -class Builder { -public: - Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger); - virtual ~Builder(); - - static const int maxMatrixSize = 4; - - unsigned int getSpvVersion() const { return spvVersion; } - - void setSource(spv::SourceLanguage lang, int version) - { - sourceLang = lang; - sourceVersion = version; - } - spv::Id getStringId(const std::string& str) - { - auto sItr = stringIds.find(str); - if (sItr != stringIds.end()) - return sItr->second; - spv::Id strId = getUniqueId(); - Instruction* fileString = new Instruction(strId, NoType, OpString); - const char* file_c_str = str.c_str(); - fileString->addStringOperand(file_c_str); - strings.push_back(std::unique_ptr(fileString)); - module.mapInstruction(fileString); - stringIds[file_c_str] = strId; - return strId; - } - spv::Id getSourceFile() const - { - return sourceFileStringId; - } - void setSourceFile(const std::string& file) - { - sourceFileStringId = getStringId(file); - currentFileId = sourceFileStringId; - } - void setSourceText(const std::string& text) { sourceText = text; } - void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } - void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } - void setEmitOpLines() { emitOpLines = true; } - void setEmitNonSemanticShaderDebugInfo(bool const emit) - { - emitNonSemanticShaderDebugInfo = emit; - - if(emit) - { - importNonSemanticShaderDebugInfoInstructions(); - } - } - void setEmitNonSemanticShaderDebugSource(bool const src) - { - emitNonSemanticShaderDebugSource = src; - } - void addExtension(const char* ext) { extensions.insert(ext); } - void removeExtension(const char* ext) - { - extensions.erase(ext); - } - void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion) - { - if (getSpvVersion() < static_cast(incorporatedVersion)) - addExtension(ext); - } - void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion) - { - removeExtension(baseExt); - addIncorporatedExtension(promoExt, incorporatedVersion); - } - void addInclude(const std::string& name, const std::string& text) - { - spv::Id incId = getStringId(name); - includeFiles[incId] = &text; - } - Id import(const char*); - void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) - { - addressModel = addr; - memoryModel = mem; - } - - void addCapability(spv::Capability cap) { capabilities.insert(cap); } - - // To get a new for anything needing a new one. - Id getUniqueId() { return ++uniqueId; } - - // To get a set of new s, e.g., for a set of function parameters - Id getUniqueIds(int numIds) - { - Id id = uniqueId + 1; - uniqueId += numIds; - return id; - } - - // Generate OpLine for non-filename-based #line directives (ie no filename - // seen yet): Log the current line, and if different than the last one, - // issue a new OpLine using the new line and current source file name. - void setLine(int line); - - // If filename null, generate OpLine for non-filename-based line directives, - // else do filename-based: Log the current line and file, and if different - // than the last one, issue a new OpLine using the new line and file - // name. - void setLine(int line, const char* filename); - // Low-level OpLine. See setLine() for a layered helper. - void addLine(Id fileName, int line, int column); - void addDebugScopeAndLine(Id fileName, int line, int column); - - // For creating new types (will return old type if the requested one was already made). - Id makeVoidType(); - Id makeBoolType(); - Id makePointer(StorageClass, Id pointee); - Id makeForwardPointer(StorageClass); - Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee); - Id makeIntegerType(int width, bool hasSign); // generic - Id makeIntType(int width) { return makeIntegerType(width, true); } - Id makeUintType(int width) { return makeIntegerType(width, false); } - Id makeFloatType(int width); - Id makeStructType(const std::vector& members, const char* name, bool const compilerGenerated = true); - Id makeStructResultType(Id type0, Id type1); - Id makeVectorType(Id component, int size); - Id makeMatrixType(Id component, int cols, int rows); - Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration - Id makeRuntimeArray(Id element); - Id makeFunctionType(Id returnType, const std::vector& paramTypes); - Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format); - Id makeSamplerType(); - Id makeSampledImageType(Id imageType); - Id makeCooperativeMatrixTypeKHR(Id component, Id scope, Id rows, Id cols, Id use); - Id makeCooperativeMatrixTypeNV(Id component, Id scope, Id rows, Id cols); - Id makeCooperativeMatrixTypeWithSameShape(Id component, Id otherType); - Id makeGenericType(spv::Op opcode, std::vector& operands); - - // SPIR-V NonSemantic Shader DebugInfo Instructions - struct DebugTypeLoc { - std::string name {}; - int line {0}; - int column {0}; - }; - std::unordered_map debugTypeLocs; - Id makeDebugInfoNone(); - Id makeBoolDebugType(int const size); - Id makeIntegerDebugType(int const width, bool const hasSign); - Id makeFloatDebugType(int const width); - Id makeSequentialDebugType(Id const baseType, Id const componentCount, NonSemanticShaderDebugInfo100Instructions const sequenceType); - Id makeArrayDebugType(Id const baseType, Id const componentCount); - Id makeVectorDebugType(Id const baseType, int const componentCount); - Id makeMatrixDebugType(Id const vectorType, int const vectorCount, bool columnMajor = true); - Id makeMemberDebugType(Id const memberType, DebugTypeLoc const& debugTypeLoc); - Id makeCompositeDebugType(std::vector const& memberTypes, char const*const name, - NonSemanticShaderDebugInfo100DebugCompositeType const tag, bool const isOpaqueType = false); - Id makeDebugSource(const Id fileName); - Id makeDebugCompilationUnit(); - Id createDebugGlobalVariable(Id const type, char const*const name, Id const variable); - Id createDebugLocalVariable(Id type, char const*const name, size_t const argNumber = 0); - Id makeDebugExpression(); - Id makeDebugDeclare(Id const debugLocalVariable, Id const pointer); - Id makeDebugValue(Id const debugLocalVariable, Id const value); - Id makeDebugFunctionType(Id returnType, const std::vector& paramTypes); - Id makeDebugFunction(Function* function, Id nameId, Id funcTypeId); - Id makeDebugLexicalBlock(uint32_t line); - std::string unmangleFunctionName(std::string const& name) const; - void setupDebugFunctionEntry(Function* function, const char* name, int line, - const std::vector& paramTypes, - const std::vector& paramNames); - - // accelerationStructureNV type - Id makeAccelerationStructureType(); - // rayQueryEXT type - Id makeRayQueryType(); - // hitObjectNV type - Id makeHitObjectNVType(); - - // For querying about types. - Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } - Id getDerefTypeId(Id resultId) const; - Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); } - Op getTypeClass(Id typeId) const { return getOpCode(typeId); } - Op getMostBasicTypeClass(Id typeId) const; - int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); } - int getNumTypeConstituents(Id typeId) const; - int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); } - Id getScalarTypeId(Id typeId) const; - Id getContainedTypeId(Id typeId) const; - Id getContainedTypeId(Id typeId, int) const; - StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } - ImageFormat getImageTypeFormat(Id typeId) const - { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } - Id getResultingAccessChainType() const; - Id getIdOperand(Id resultId, int idx) { return module.getInstruction(resultId)->getIdOperand(idx); } - - bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } - bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } - bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); } - bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); } - bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); } - bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } - bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); } - - bool isBoolType(Id typeId) - { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); } - bool isIntType(Id typeId) const - { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } - bool isUintType(Id typeId) const - { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } - bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; } - bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } - bool isScalarType(Id typeId) const - { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || - getTypeClass(typeId) == OpTypeBool; } - bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } - bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } - bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } - bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; } - bool isCooperativeMatrixType(Id typeId)const - { - return getTypeClass(typeId) == OpTypeCooperativeMatrixKHR || getTypeClass(typeId) == OpTypeCooperativeMatrixNV; - } - bool isAggregateType(Id typeId) const - { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } - bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } - bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } - bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } - bool containsType(Id typeId, Op typeOp, unsigned int width) const; - bool containsPhysicalStorageBufferOrArray(Id typeId) const; - - bool isConstantOpCode(Op opcode) const; - bool isSpecConstantOpCode(Op opcode) const; - bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } - bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } - bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } - unsigned int getConstantScalar(Id resultId) const - { return module.getInstruction(resultId)->getImmediateOperand(0); } - StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } - - bool isVariableOpCode(Op opcode) const { return opcode == OpVariable; } - bool isVariable(Id resultId) const { return isVariableOpCode(getOpCode(resultId)); } - bool isGlobalStorage(Id resultId) const { return getStorageClass(resultId) != StorageClassFunction; } - bool isGlobalVariable(Id resultId) const { return isVariable(resultId) && isGlobalStorage(resultId); } - // See if a resultId is valid for use as an initializer. - bool isValidInitializer(Id resultId) const { return isConstant(resultId) || isGlobalVariable(resultId); } - - bool isRayTracingOpCode(Op opcode) const; - - int getScalarTypeWidth(Id typeId) const - { - Id scalarTypeId = getScalarTypeId(typeId); - assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat); - return module.getInstruction(scalarTypeId)->getImmediateOperand(0); - } - - int getTypeNumColumns(Id typeId) const - { - assert(isMatrixType(typeId)); - return getNumTypeConstituents(typeId); - } - int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); } - int getTypeNumRows(Id typeId) const - { - assert(isMatrixType(typeId)); - return getNumTypeComponents(getContainedTypeId(typeId)); - } - int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); } - - Dim getTypeDimensionality(Id typeId) const - { - assert(isImageType(typeId)); - return (Dim)module.getInstruction(typeId)->getImmediateOperand(1); - } - Id getImageType(Id resultId) const - { - Id typeId = getTypeId(resultId); - assert(isImageType(typeId) || isSampledImageType(typeId)); - return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId; - } - bool isArrayedImageType(Id typeId) const - { - assert(isImageType(typeId)); - return module.getInstruction(typeId)->getImmediateOperand(3) != 0; - } - - // For making new constants (will return old constant if the requested one was already made). - Id makeNullConstant(Id typeId); - Id makeBoolConstant(bool b, bool specConstant = false); - Id makeInt8Constant(int i, bool specConstant = false) - { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } - Id makeUint8Constant(unsigned u, bool specConstant = false) - { return makeIntConstant(makeUintType(8), u, specConstant); } - Id makeInt16Constant(int i, bool specConstant = false) - { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } - Id makeUint16Constant(unsigned u, bool specConstant = false) - { return makeIntConstant(makeUintType(16), u, specConstant); } - Id makeIntConstant(int i, bool specConstant = false) - { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } - Id makeUintConstant(unsigned u, bool specConstant = false) - { return makeIntConstant(makeUintType(32), u, specConstant); } - Id makeInt64Constant(long long i, bool specConstant = false) - { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } - Id makeUint64Constant(unsigned long long u, bool specConstant = false) - { return makeInt64Constant(makeUintType(64), u, specConstant); } - Id makeFloatConstant(float f, bool specConstant = false); - Id makeDoubleConstant(double d, bool specConstant = false); - Id makeFloat16Constant(float f16, bool specConstant = false); - Id makeFpConstant(Id type, double d, bool specConstant = false); - - Id importNonSemanticShaderDebugInfoInstructions(); - - // Turn the array of constants into a proper spv constant of the requested type. - Id makeCompositeConstant(Id type, const std::vector& comps, bool specConst = false); - - // Methods for adding information outside the CFG. - Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); - void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1); - void addExecutionMode(Function*, ExecutionMode mode, const std::vector& literals); - void addExecutionModeId(Function*, ExecutionMode mode, const std::vector& operandIds); - void addName(Id, const char* name); - void addMemberName(Id, int member, const char* name); - void addDecoration(Id, Decoration, int num = -1); - void addDecoration(Id, Decoration, const char*); - void addDecoration(Id, Decoration, const std::vector& literals); - void addDecoration(Id, Decoration, const std::vector& strings); - void addLinkageDecoration(Id id, const char* name, spv::LinkageType linkType); - void addDecorationId(Id id, Decoration, Id idDecoration); - void addDecorationId(Id id, Decoration, const std::vector& operandIds); - void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); - void addMemberDecoration(Id, unsigned int member, Decoration, const char*); - void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector& literals); - void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector& strings); - - // At the end of what block do the next create*() instructions go? - // Also reset current last DebugScope and current source line to unknown - void setBuildPoint(Block* bp) { - buildPoint = bp; - lastDebugScopeId = NoResult; - currentLine = 0; - } - Block* getBuildPoint() const { return buildPoint; } - - // Make the entry-point function. The returned pointer is only valid - // for the lifetime of this builder. - Function* makeEntryPoint(const char*); - - // Make a shader-style function, and create its entry block if entry is non-zero. - // Return the function, pass back the entry. - // The returned pointer is only valid for the lifetime of this builder. - Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, LinkageType linkType, - const std::vector& paramTypes, - const std::vector>& precisions, Block** entry = nullptr); - - // Create a return. An 'implicit' return is one not appearing in the source - // code. In the case of an implicit return, no post-return block is inserted. - void makeReturn(bool implicit, Id retVal = 0); - - // Initialize state and generate instructions for new lexical scope - void enterScope(uint32_t line); - - // Set state and generate instructions to exit current lexical scope - void leaveScope(); - - // Prepare builder for generation of instructions for a function. - void enterFunction(Function const* function); - - // Generate all the code needed to finish up a function. - void leaveFunction(); - - // Create block terminator instruction for certain statements like - // discard, terminate-invocation, terminateRayEXT, or ignoreIntersectionEXT - void makeStatementTerminator(spv::Op opcode, const char *name); - - // Create block terminator instruction for statements that have input operands - // such as OpEmitMeshTasksEXT - void makeStatementTerminator(spv::Op opcode, const std::vector& operands, const char* name); - - // Create a global or function local or IO variable. - Id createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name = nullptr, - Id initializer = NoResult, bool const compilerGenerated = true); - - // Create an intermediate with an undefined value. - Id createUndefined(Id type); - - // Store into an Id and return the l-value - void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, - spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); - - // Load from an Id and return it - Id createLoad(Id lValue, spv::Decoration precision, - spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, - spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); - - // Create an OpAccessChain instruction - Id createAccessChain(StorageClass, Id base, const std::vector& offsets); - - // Create an OpArrayLength instruction - Id createArrayLength(Id base, unsigned int member); - - // Create an OpCooperativeMatrixLengthKHR instruction - Id createCooperativeMatrixLengthKHR(Id type); - // Create an OpCooperativeMatrixLengthNV instruction - Id createCooperativeMatrixLengthNV(Id type); - - // Create an OpCompositeExtract instruction - Id createCompositeExtract(Id composite, Id typeId, unsigned index); - Id createCompositeExtract(Id composite, Id typeId, const std::vector& indexes); - Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index); - Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector& indexes); - - Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex); - Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex); - - void createNoResultOp(Op); - void createNoResultOp(Op, Id operand); - void createNoResultOp(Op, const std::vector& operands); - void createNoResultOp(Op, const std::vector& operands); - void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); - void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); - Id createUnaryOp(Op, Id typeId, Id operand); - Id createBinOp(Op, Id typeId, Id operand1, Id operand2); - Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); - Id createOp(Op, Id typeId, const std::vector& operands); - Id createOp(Op, Id typeId, const std::vector& operands); - Id createFunctionCall(spv::Function*, const std::vector&); - Id createSpecConstantOp(Op, Id typeId, const std::vector& operands, const std::vector& literals); - - // Take an rvalue (source) and a set of channels to extract from it to - // make a new rvalue, which is returned. - Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector& channels); - - // Take a copy of an lvalue (target) and a source of components, and set the - // source components into the lvalue where the 'channels' say to put them. - // An updated version of the target is returned. - // (No true lvalue or stores are used.) - Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector& channels); - - // If both the id and precision are valid, the id - // gets tagged with the requested precision. - // The passed in id is always the returned id, to simplify use patterns. - Id setPrecision(Id id, Decoration precision) - { - if (precision != NoPrecision && id != NoResult) - addDecoration(id, precision); - - return id; - } - - // Can smear a scalar to a vector for the following forms: - // - promoteScalar(scalar, vector) // smear scalar to width of vector - // - promoteScalar(vector, scalar) // smear scalar to width of vector - // - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to - // - promoteScalar(scalar, scalar) // do nothing - // Other forms are not allowed. - // - // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'. - // The type of the created vector is a vector of components of the same type as the scalar. - // - // Note: One of the arguments will change, with the result coming back that way rather than - // through the return value. - void promoteScalar(Decoration precision, Id& left, Id& right); - - // Make a value by smearing the scalar to fill the type. - // vectorType should be the correct type for making a vector of scalarVal. - // (No conversions are done.) - Id smearScalar(Decoration precision, Id scalarVal, Id vectorType); - - // Create a call to a built-in function. - Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector& args); - - // List of parameters used to create a texture operation - struct TextureParameters { - Id sampler; - Id coords; - Id bias; - Id lod; - Id Dref; - Id offset; - Id offsets; - Id gradX; - Id gradY; - Id sample; - Id component; - Id texelOut; - Id lodClamp; - Id granularity; - Id coarse; - bool nonprivate; - bool volatil; - }; - - // Select the correct texture operation based on all inputs, and emit the correct instruction - Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, - bool noImplicit, const TextureParameters&, ImageOperandsMask); - - // Emit the OpTextureQuery* instruction that was passed in. - // Figure out the right return value and type, and return it. - Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult); - - Id createSamplePositionCall(Decoration precision, Id, Id); - - Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned); - Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id); - - // Reduction comparison for composites: For equal and not-equal resulting in a scalar. - Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */); - - // OpCompositeConstruct - Id createCompositeConstruct(Id typeId, const std::vector& constituents); - - // vector or scalar constructor - Id createConstructor(Decoration precision, const std::vector& sources, Id resultTypeId); - - // matrix constructor - Id createMatrixConstructor(Decoration precision, const std::vector& sources, Id constructee); - - // Helper to use for building nested control flow with if-then-else. - class If { - public: - If(Id condition, unsigned int ctrl, Builder& builder); - ~If() {} - - void makeBeginElse(); - void makeEndIf(); - - private: - If(const If&); - If& operator=(If&); - - Builder& builder; - Id condition; - unsigned int control; - Function* function; - Block* headerBlock; - Block* thenBlock; - Block* elseBlock; - Block* mergeBlock; - }; - - // Make a switch statement. A switch has 'numSegments' of pieces of code, not containing - // any case/default labels, all separated by one or more case/default labels. Each possible - // case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this - // number space. How to compute the value is given by 'condition', as in switch(condition). - // - // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches. - // - // Use a defaultSegment < 0 if there is no default segment (to branch to post switch). - // - // Returns the right set of basic blocks to start each code segment with, so that the caller's - // recursion stack can hold the memory for it. - // - void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector& caseValues, - const std::vector& valueToSegment, int defaultSegment, std::vector& segmentBB); - - // Add a branch to the innermost switch's merge block. - void addSwitchBreak(); - - // Move to the next code segment, passing in the return argument in makeSwitch() - void nextSwitchSegment(std::vector& segmentBB, int segment); - - // Finish off the innermost switch. - void endSwitch(std::vector& segmentBB); - - struct LoopBlocks { - LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) : - head(head), body(body), merge(merge), continue_target(continue_target) { } - Block &head, &body, &merge, &continue_target; - private: - LoopBlocks(); - LoopBlocks& operator=(const LoopBlocks&) = delete; - }; - - // Start a new loop and prepare the builder to generate code for it. Until - // closeLoop() is called for this loop, createLoopContinue() and - // createLoopExit() will target its corresponding blocks. - LoopBlocks& makeNewLoop(); - - // Create a new block in the function containing the build point. Memory is - // owned by the function object. - Block& makeNewBlock(); - - // Add a branch to the continue_target of the current (innermost) loop. - void createLoopContinue(); - - // Add an exit (e.g. "break") from the innermost loop that we're currently - // in. - void createLoopExit(); - - // Close the innermost loop that you're in - void closeLoop(); - - // - // Access chain design for an R-Value vs. L-Value: - // - // There is a single access chain the builder is building at - // any particular time. Such a chain can be used to either to a load or - // a store, when desired. - // - // Expressions can be r-values, l-values, or both, or only r-values: - // a[b.c].d = .... // l-value - // ... = a[b.c].d; // r-value, that also looks like an l-value - // ++a[b.c].d; // r-value and l-value - // (x + y)[2]; // r-value only, can't possibly be l-value - // - // Computing an r-value means generating code. Hence, - // r-values should only be computed when they are needed, not speculatively. - // - // Computing an l-value means saving away information for later use in the compiler, - // no code is generated until the l-value is later dereferenced. It is okay - // to speculatively generate an l-value, just not okay to speculatively dereference it. - // - // The base of the access chain (the left-most variable or expression - // from which everything is based) can be set either as an l-value - // or as an r-value. Most efficient would be to set an l-value if one - // is available. If an expression was evaluated, the resulting r-value - // can be set as the chain base. - // - // The users of this single access chain can save and restore if they - // want to nest or manage multiple chains. - // - - struct AccessChain { - Id base; // for l-values, pointer to the base object, for r-values, the base object - std::vector indexChain; - Id instr; // cache the instruction that generates this access chain - std::vector swizzle; // each std::vector element selects the next GLSL component number - Id component; // a dynamic component index, can coexist with a swizzle, - // done after the swizzle, NoResult if not present - Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; - // NoType unless a swizzle or component is present - bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value - unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. - // Only tracks base and (optional) component selection alignment. - - // Accumulate whether anything in the chain of structures has coherent decorations. - struct CoherentFlags { - CoherentFlags() { clear(); } - bool isVolatile() const { return volatil; } - bool isNonUniform() const { return nonUniform; } - bool anyCoherent() const { - return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent || - subgroupcoherent || shadercallcoherent; - } - - unsigned coherent : 1; - unsigned devicecoherent : 1; - unsigned queuefamilycoherent : 1; - unsigned workgroupcoherent : 1; - unsigned subgroupcoherent : 1; - unsigned shadercallcoherent : 1; - unsigned nonprivate : 1; - unsigned volatil : 1; - unsigned isImage : 1; - unsigned nonUniform : 1; - - void clear() { - coherent = 0; - devicecoherent = 0; - queuefamilycoherent = 0; - workgroupcoherent = 0; - subgroupcoherent = 0; - shadercallcoherent = 0; - nonprivate = 0; - volatil = 0; - isImage = 0; - nonUniform = 0; - } - - CoherentFlags operator |=(const CoherentFlags &other) { - coherent |= other.coherent; - devicecoherent |= other.devicecoherent; - queuefamilycoherent |= other.queuefamilycoherent; - workgroupcoherent |= other.workgroupcoherent; - subgroupcoherent |= other.subgroupcoherent; - shadercallcoherent |= other.shadercallcoherent; - nonprivate |= other.nonprivate; - volatil |= other.volatil; - isImage |= other.isImage; - nonUniform |= other.nonUniform; - return *this; - } - }; - CoherentFlags coherentFlags; - }; - - // - // the SPIR-V builder maintains a single active chain that - // the following methods operate on - // - - // for external save and restore - AccessChain getAccessChain() { return accessChain; } - void setAccessChain(AccessChain newChain) { accessChain = newChain; } - - // clear accessChain - void clearAccessChain(); - - // set new base as an l-value base - void setAccessChainLValue(Id lValue) - { - assert(isPointer(lValue)); - accessChain.base = lValue; - } - - // set new base value as an r-value - void setAccessChainRValue(Id rValue) - { - accessChain.isRValue = true; - accessChain.base = rValue; - } - - // push offset onto the end of the chain - void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) - { - accessChain.indexChain.push_back(offset); - accessChain.coherentFlags |= coherentFlags; - accessChain.alignment |= alignment; - } - - // push new swizzle onto the end of any existing swizzle, merging into a single swizzle - void accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType, - AccessChain::CoherentFlags coherentFlags, unsigned int alignment); - - // push a dynamic component selection onto the access chain, only applicable with a - // non-trivial swizzle or no swizzle - void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, - unsigned int alignment) - { - if (accessChain.swizzle.size() != 1) { - accessChain.component = component; - if (accessChain.preSwizzleBaseType == NoType) - accessChain.preSwizzleBaseType = preSwizzleBaseType; - } - accessChain.coherentFlags |= coherentFlags; - accessChain.alignment |= alignment; - } - - // use accessChain and swizzle to store value - void accessChainStore(Id rvalue, Decoration nonUniform, - spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, - spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); - - // use accessChain and swizzle to load an r-value - Id accessChainLoad(Decoration precision, Decoration l_nonUniform, Decoration r_nonUniform, Id ResultType, - spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, - unsigned int alignment = 0); - - // Return whether or not the access chain can be represented in SPIR-V - // as an l-value. - // E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be. - bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; } - - // get the direct pointer for an l-value - Id accessChainGetLValue(); - - // Get the inferred SPIR-V type of the result of the current access chain, - // based on the type of the base and the chain of dereferences. - Id accessChainGetInferredType(); - - // Add capabilities, extensions, remove unneeded decorations, etc., - // based on the resulting SPIR-V. - void postProcess(bool compileOnly); - - // Prune unreachable blocks in the CFG and remove unneeded decorations. - void postProcessCFG(); - - // Add capabilities, extensions based on instructions in the module. - void postProcessFeatures(); - // Hook to visit each instruction in a block in a function - void postProcess(Instruction&); - // Hook to visit each non-32-bit sized float/int operation in a block. - void postProcessType(const Instruction&, spv::Id typeId); - - void dump(std::vector&) const; - - void createBranch(Block* block); - void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); - void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, - const std::vector& operands); - - // Sets to generate opcode for specialization constants. - void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } - // Sets to generate opcode for non-specialization constants (normal mode). - void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; } - // Check if the builder is generating code for spec constants. - bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; } - - protected: - Id makeIntConstant(Id typeId, unsigned value, bool specConstant); - Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant); - Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value); - Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2); - Id findCompositeConstant(Op typeClass, Id typeId, const std::vector& comps); - Id findStructConstant(Id typeId, const std::vector& comps); - Id collapseAccessChain(); - void remapDynamicSwizzle(); - void transferAccessChainSwizzle(bool dynamic); - void simplifyAccessChainSwizzle(); - void createAndSetNoPredecessorBlock(const char*); - void createSelectionMerge(Block* mergeBlock, unsigned int control); - void dumpSourceInstructions(std::vector&) const; - void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; - void dumpInstructions(std::vector&, const std::vector >&) const; - void dumpModuleProcesses(std::vector&) const; - spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) - const; - - unsigned int spvVersion; // the version of SPIR-V to emit in the header - SourceLanguage sourceLang; - int sourceVersion; - spv::Id sourceFileStringId; - spv::Id nonSemanticShaderCompilationUnitId {0}; - spv::Id nonSemanticShaderDebugInfo {0}; - spv::Id debugInfoNone {0}; - spv::Id debugExpression {0}; // Debug expression with zero operations. - std::string sourceText; - int currentLine; - const char* currentFile; - spv::Id currentFileId; - std::stack currentDebugScopeId; - spv::Id lastDebugScopeId; - bool emitOpLines; - bool emitNonSemanticShaderDebugInfo; - bool restoreNonSemanticShaderDebugInfo; - bool emitNonSemanticShaderDebugSource; - std::set extensions; - std::vector sourceExtensions; - std::vector moduleProcesses; - AddressingModel addressModel; - MemoryModel memoryModel; - std::set capabilities; - int builderNumber; - Module module; - Block* buildPoint; - Id uniqueId; - Function* entryPointFunction; - bool generatingOpCodeForSpecConst; - AccessChain accessChain; - - // special blocks of instructions for output - std::vector > strings; - std::vector > imports; - std::vector > entryPoints; - std::vector > executionModes; - std::vector > names; - std::vector > decorations; - std::vector > constantsTypesGlobals; - std::vector > externals; - std::vector > functions; - - // not output, internally used for quick & dirty canonical (unique) creation - - // map type opcodes to constant inst. - std::unordered_map> groupedConstants; - // map struct-id to constant instructions - std::unordered_map> groupedStructConstants; - // map type opcodes to type instructions - std::unordered_map> groupedTypes; - // map type opcodes to debug type instructions - std::unordered_map> groupedDebugTypes; - // list of OpConstantNull instructions - std::vector nullConstants; - - // stack of switches - std::stack switchMerges; - - // Our loop stack. - std::stack loops; - - // map from strings to their string ids - std::unordered_map stringIds; - - // map from include file name ids to their contents - std::map includeFiles; - - // map from core id to debug id - std::map debugId; - - // map from file name string id to DebugSource id - std::unordered_map debugSourceId; - - // The stream for outputting warnings and errors. - SpvBuildLogger* logger; -}; // end Builder class - -}; // end spv namespace - -#endif // SpvBuilder_H diff --git a/3rdparty/glslang/SPIRV/SpvPostProcess.cpp b/3rdparty/glslang/SPIRV/SpvPostProcess.cpp deleted file mode 100644 index 13001a67..00000000 --- a/3rdparty/glslang/SPIRV/SpvPostProcess.cpp +++ /dev/null @@ -1,495 +0,0 @@ -// -// Copyright (C) 2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Post-processing for SPIR-V IR, in internal form, not standard binary form. -// - -#include -#include - -#include -#include -#include - -#include "SpvBuilder.h" -#include "spirv.hpp" - -namespace spv { - #include "GLSL.std.450.h" - #include "GLSL.ext.KHR.h" - #include "GLSL.ext.EXT.h" - #include "GLSL.ext.AMD.h" - #include "GLSL.ext.NV.h" - #include "GLSL.ext.ARM.h" - #include "GLSL.ext.QCOM.h" -} - -namespace spv { - -// Hook to visit each operand type and result type of an instruction. -// Will be called multiple times for one instruction, once for each typed -// operand and the result. -void Builder::postProcessType(const Instruction& inst, Id typeId) -{ - // Characterize the type being questioned - Id basicTypeOp = getMostBasicTypeClass(typeId); - int width = 0; - if (basicTypeOp == OpTypeFloat || basicTypeOp == OpTypeInt) - width = getScalarTypeWidth(typeId); - - // Do opcode-specific checks - switch (inst.getOpCode()) { - case OpLoad: - case OpStore: - if (basicTypeOp == OpTypeStruct) { - if (containsType(typeId, OpTypeInt, 8)) - addCapability(CapabilityInt8); - if (containsType(typeId, OpTypeInt, 16)) - addCapability(CapabilityInt16); - if (containsType(typeId, OpTypeFloat, 16)) - addCapability(CapabilityFloat16); - } else { - StorageClass storageClass = getStorageClass(inst.getIdOperand(0)); - if (width == 8) { - switch (storageClass) { - case StorageClassPhysicalStorageBufferEXT: - case StorageClassUniform: - case StorageClassStorageBuffer: - case StorageClassPushConstant: - break; - default: - addCapability(CapabilityInt8); - break; - } - } else if (width == 16) { - switch (storageClass) { - case StorageClassPhysicalStorageBufferEXT: - case StorageClassUniform: - case StorageClassStorageBuffer: - case StorageClassPushConstant: - case StorageClassInput: - case StorageClassOutput: - break; - default: - if (basicTypeOp == OpTypeInt) - addCapability(CapabilityInt16); - if (basicTypeOp == OpTypeFloat) - addCapability(CapabilityFloat16); - break; - } - } - } - break; - case OpCopyObject: - break; - case OpFConvert: - case OpSConvert: - case OpUConvert: - // Look for any 8/16-bit storage capabilities. If there are none, assume that - // the convert instruction requires the Float16/Int8/16 capability. - if (containsType(typeId, OpTypeFloat, 16) || containsType(typeId, OpTypeInt, 16)) { - bool foundStorage = false; - for (auto it = capabilities.begin(); it != capabilities.end(); ++it) { - spv::Capability cap = *it; - if (cap == spv::CapabilityStorageInputOutput16 || - cap == spv::CapabilityStoragePushConstant16 || - cap == spv::CapabilityStorageUniformBufferBlock16 || - cap == spv::CapabilityStorageUniform16) { - foundStorage = true; - break; - } - } - if (!foundStorage) { - if (containsType(typeId, OpTypeFloat, 16)) - addCapability(CapabilityFloat16); - if (containsType(typeId, OpTypeInt, 16)) - addCapability(CapabilityInt16); - } - } - if (containsType(typeId, OpTypeInt, 8)) { - bool foundStorage = false; - for (auto it = capabilities.begin(); it != capabilities.end(); ++it) { - spv::Capability cap = *it; - if (cap == spv::CapabilityStoragePushConstant8 || - cap == spv::CapabilityUniformAndStorageBuffer8BitAccess || - cap == spv::CapabilityStorageBuffer8BitAccess) { - foundStorage = true; - break; - } - } - if (!foundStorage) { - addCapability(CapabilityInt8); - } - } - break; - case OpExtInst: - switch (inst.getImmediateOperand(1)) { - case GLSLstd450Frexp: - case GLSLstd450FrexpStruct: - if (getSpvVersion() < spv::Spv_1_3 && containsType(typeId, OpTypeInt, 16)) - addExtension(spv::E_SPV_AMD_gpu_shader_int16); - break; - case GLSLstd450InterpolateAtCentroid: - case GLSLstd450InterpolateAtSample: - case GLSLstd450InterpolateAtOffset: - if (getSpvVersion() < spv::Spv_1_3 && containsType(typeId, OpTypeFloat, 16)) - addExtension(spv::E_SPV_AMD_gpu_shader_half_float); - break; - default: - break; - } - break; - case OpAccessChain: - case OpPtrAccessChain: - if (isPointerType(typeId)) - break; - if (basicTypeOp == OpTypeInt) { - if (width == 16) - addCapability(CapabilityInt16); - else if (width == 8) - addCapability(CapabilityInt8); - } - default: - if (basicTypeOp == OpTypeInt) { - if (width == 16) - addCapability(CapabilityInt16); - else if (width == 8) - addCapability(CapabilityInt8); - else if (width == 64) - addCapability(CapabilityInt64); - } else if (basicTypeOp == OpTypeFloat) { - if (width == 16) - addCapability(CapabilityFloat16); - else if (width == 64) - addCapability(CapabilityFloat64); - } - break; - } -} - -// Called for each instruction that resides in a block. -void Builder::postProcess(Instruction& inst) -{ - // Add capabilities based simply on the opcode. - switch (inst.getOpCode()) { - case OpExtInst: - switch (inst.getImmediateOperand(1)) { - case GLSLstd450InterpolateAtCentroid: - case GLSLstd450InterpolateAtSample: - case GLSLstd450InterpolateAtOffset: - addCapability(CapabilityInterpolationFunction); - break; - default: - break; - } - break; - case OpDPdxFine: - case OpDPdyFine: - case OpFwidthFine: - case OpDPdxCoarse: - case OpDPdyCoarse: - case OpFwidthCoarse: - addCapability(CapabilityDerivativeControl); - break; - - case OpImageQueryLod: - case OpImageQuerySize: - case OpImageQuerySizeLod: - case OpImageQuerySamples: - case OpImageQueryLevels: - addCapability(CapabilityImageQuery); - break; - - case OpGroupNonUniformPartitionNV: - addExtension(E_SPV_NV_shader_subgroup_partitioned); - addCapability(CapabilityGroupNonUniformPartitionedNV); - break; - - case OpLoad: - case OpStore: - { - // For any load/store to a PhysicalStorageBufferEXT, walk the accesschain - // index list to compute the misalignment. The pre-existing alignment value - // (set via Builder::AccessChain::alignment) only accounts for the base of - // the reference type and any scalar component selection in the accesschain, - // and this function computes the rest from the SPIR-V Offset decorations. - Instruction *accessChain = module.getInstruction(inst.getIdOperand(0)); - if (accessChain->getOpCode() == OpAccessChain) { - Instruction *base = module.getInstruction(accessChain->getIdOperand(0)); - // Get the type of the base of the access chain. It must be a pointer type. - Id typeId = base->getTypeId(); - Instruction *type = module.getInstruction(typeId); - assert(type->getOpCode() == OpTypePointer); - if (type->getImmediateOperand(0) != StorageClassPhysicalStorageBufferEXT) { - break; - } - // Get the pointee type. - typeId = type->getIdOperand(1); - type = module.getInstruction(typeId); - // Walk the index list for the access chain. For each index, find any - // misalignment that can apply when accessing the member/element via - // Offset/ArrayStride/MatrixStride decorations, and bitwise OR them all - // together. - int alignment = 0; - for (int i = 1; i < accessChain->getNumOperands(); ++i) { - Instruction *idx = module.getInstruction(accessChain->getIdOperand(i)); - if (type->getOpCode() == OpTypeStruct) { - assert(idx->getOpCode() == OpConstant); - unsigned int c = idx->getImmediateOperand(0); - - const auto function = [&](const std::unique_ptr& decoration) { - if (decoration.get()->getOpCode() == OpMemberDecorate && - decoration.get()->getIdOperand(0) == typeId && - decoration.get()->getImmediateOperand(1) == c && - (decoration.get()->getImmediateOperand(2) == DecorationOffset || - decoration.get()->getImmediateOperand(2) == DecorationMatrixStride)) { - alignment |= decoration.get()->getImmediateOperand(3); - } - }; - std::for_each(decorations.begin(), decorations.end(), function); - // get the next member type - typeId = type->getIdOperand(c); - type = module.getInstruction(typeId); - } else if (type->getOpCode() == OpTypeArray || - type->getOpCode() == OpTypeRuntimeArray) { - const auto function = [&](const std::unique_ptr& decoration) { - if (decoration.get()->getOpCode() == OpDecorate && - decoration.get()->getIdOperand(0) == typeId && - decoration.get()->getImmediateOperand(1) == DecorationArrayStride) { - alignment |= decoration.get()->getImmediateOperand(2); - } - }; - std::for_each(decorations.begin(), decorations.end(), function); - // Get the element type - typeId = type->getIdOperand(0); - type = module.getInstruction(typeId); - } else { - // Once we get to any non-aggregate type, we're done. - break; - } - } - assert(inst.getNumOperands() >= 3); - unsigned int memoryAccess = inst.getImmediateOperand((inst.getOpCode() == OpStore) ? 2 : 1); - assert(memoryAccess & MemoryAccessAlignedMask); - static_cast(memoryAccess); - // Compute the index of the alignment operand. - int alignmentIdx = 2; - if (inst.getOpCode() == OpStore) - alignmentIdx++; - // Merge new and old (mis)alignment - alignment |= inst.getImmediateOperand(alignmentIdx); - // Pick the LSB - alignment = alignment & ~(alignment & (alignment-1)); - // update the Aligned operand - inst.setImmediateOperand(alignmentIdx, alignment); - } - break; - } - - default: - break; - } - - // Checks based on type - if (inst.getTypeId() != NoType) - postProcessType(inst, inst.getTypeId()); - for (int op = 0; op < inst.getNumOperands(); ++op) { - if (inst.isIdOperand(op)) { - // In blocks, these are always result ids, but we are relying on - // getTypeId() to return NoType for things like OpLabel. - if (getTypeId(inst.getIdOperand(op)) != NoType) - postProcessType(inst, getTypeId(inst.getIdOperand(op))); - } - } -} - -// comment in header -void Builder::postProcessCFG() -{ - // reachableBlocks is the set of blockss reached via control flow, or which are - // unreachable continue targert or unreachable merge. - std::unordered_set reachableBlocks; - std::unordered_map headerForUnreachableContinue; - std::unordered_set unreachableMerges; - std::unordered_set unreachableDefinitions; - // Collect IDs defined in unreachable blocks. For each function, label the - // reachable blocks first. Then for each unreachable block, collect the - // result IDs of the instructions in it. - for (auto fi = module.getFunctions().cbegin(); fi != module.getFunctions().cend(); fi++) { - Function* f = *fi; - Block* entry = f->getEntryBlock(); - inReadableOrder(entry, - [&reachableBlocks, &unreachableMerges, &headerForUnreachableContinue] - (Block* b, ReachReason why, Block* header) { - reachableBlocks.insert(b); - if (why == ReachDeadContinue) headerForUnreachableContinue[b] = header; - if (why == ReachDeadMerge) unreachableMerges.insert(b); - }); - for (auto bi = f->getBlocks().cbegin(); bi != f->getBlocks().cend(); bi++) { - Block* b = *bi; - if (unreachableMerges.count(b) != 0 || headerForUnreachableContinue.count(b) != 0) { - auto ii = b->getInstructions().cbegin(); - ++ii; // Keep potential decorations on the label. - for (; ii != b->getInstructions().cend(); ++ii) - unreachableDefinitions.insert(ii->get()->getResultId()); - } else if (reachableBlocks.count(b) == 0) { - // The normal case for unreachable code. All definitions are considered dead. - for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ++ii) - unreachableDefinitions.insert(ii->get()->getResultId()); - } - } - } - - // Modify unreachable merge blocks and unreachable continue targets. - // Delete their contents. - for (auto mergeIter = unreachableMerges.begin(); mergeIter != unreachableMerges.end(); ++mergeIter) { - (*mergeIter)->rewriteAsCanonicalUnreachableMerge(); - } - for (auto continueIter = headerForUnreachableContinue.begin(); - continueIter != headerForUnreachableContinue.end(); - ++continueIter) { - Block* continue_target = continueIter->first; - Block* header = continueIter->second; - continue_target->rewriteAsCanonicalUnreachableContinue(header); - } - - // Remove unneeded decorations, for unreachable instructions - decorations.erase(std::remove_if(decorations.begin(), decorations.end(), - [&unreachableDefinitions](std::unique_ptr& I) -> bool { - Id decoration_id = I.get()->getIdOperand(0); - return unreachableDefinitions.count(decoration_id) != 0; - }), - decorations.end()); -} - -// comment in header -void Builder::postProcessFeatures() { - // Add per-instruction capabilities, extensions, etc., - - // Look for any 8/16 bit type in physical storage buffer class, and set the - // appropriate capability. This happens in createSpvVariable for other storage - // classes, but there isn't always a variable for physical storage buffer. - for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) { - Instruction* type = groupedTypes[OpTypePointer][t]; - if (type->getImmediateOperand(0) == (unsigned)StorageClassPhysicalStorageBufferEXT) { - if (containsType(type->getIdOperand(1), OpTypeInt, 8)) { - addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5); - addCapability(spv::CapabilityStorageBuffer8BitAccess); - } - if (containsType(type->getIdOperand(1), OpTypeInt, 16) || - containsType(type->getIdOperand(1), OpTypeFloat, 16)) { - addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3); - addCapability(spv::CapabilityStorageBuffer16BitAccess); - } - } - } - - // process all block-contained instructions - for (auto fi = module.getFunctions().cbegin(); fi != module.getFunctions().cend(); fi++) { - Function* f = *fi; - for (auto bi = f->getBlocks().cbegin(); bi != f->getBlocks().cend(); bi++) { - Block* b = *bi; - for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ii++) - postProcess(*ii->get()); - - // For all local variables that contain pointers to PhysicalStorageBufferEXT, check whether - // there is an existing restrict/aliased decoration. If we don't find one, add Aliased as the - // default. - for (auto vi = b->getLocalVariables().cbegin(); vi != b->getLocalVariables().cend(); vi++) { - const Instruction& inst = *vi->get(); - Id resultId = inst.getResultId(); - if (containsPhysicalStorageBufferOrArray(getDerefTypeId(resultId))) { - bool foundDecoration = false; - const auto function = [&](const std::unique_ptr& decoration) { - if (decoration.get()->getIdOperand(0) == resultId && - decoration.get()->getOpCode() == OpDecorate && - (decoration.get()->getImmediateOperand(1) == spv::DecorationAliasedPointerEXT || - decoration.get()->getImmediateOperand(1) == spv::DecorationRestrictPointerEXT)) { - foundDecoration = true; - } - }; - std::for_each(decorations.begin(), decorations.end(), function); - if (!foundDecoration) { - addDecoration(resultId, spv::DecorationAliasedPointerEXT); - } - } - } - } - } - - // If any Vulkan memory model-specific functionality is used, update the - // OpMemoryModel to match. - if (capabilities.find(spv::CapabilityVulkanMemoryModelKHR) != capabilities.end()) { - memoryModel = spv::MemoryModelVulkanKHR; - addIncorporatedExtension(spv::E_SPV_KHR_vulkan_memory_model, spv::Spv_1_5); - } - - // Add Aliased decoration if there's more than one Workgroup Block variable. - if (capabilities.find(spv::CapabilityWorkgroupMemoryExplicitLayoutKHR) != capabilities.end()) { - assert(entryPoints.size() == 1); - auto &ep = entryPoints[0]; - - std::vector workgroup_variables; - for (int i = 0; i < (int)ep->getNumOperands(); i++) { - if (!ep->isIdOperand(i)) - continue; - - const Id id = ep->getIdOperand(i); - const Instruction *instr = module.getInstruction(id); - if (instr->getOpCode() != spv::OpVariable) - continue; - - if (instr->getImmediateOperand(0) == spv::StorageClassWorkgroup) - workgroup_variables.push_back(id); - } - - if (workgroup_variables.size() > 1) { - for (size_t i = 0; i < workgroup_variables.size(); i++) - addDecoration(workgroup_variables[i], spv::DecorationAliased); - } - } -} - -// comment in header -void Builder::postProcess(bool compileOnly) -{ - // postProcessCFG needs an entrypoint to determine what is reachable, but if we are not creating an "executable" shader, we don't have an entrypoint - if (!compileOnly) - postProcessCFG(); - - postProcessFeatures(); -} - -}; // end spv namespace diff --git a/3rdparty/glslang/SPIRV/SpvTools.cpp b/3rdparty/glslang/SPIRV/SpvTools.cpp deleted file mode 100644 index ff04f4f9..00000000 --- a/3rdparty/glslang/SPIRV/SpvTools.cpp +++ /dev/null @@ -1,297 +0,0 @@ -// -// Copyright (C) 2014-2016 LunarG, Inc. -// Copyright (C) 2018-2020 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Call into SPIRV-Tools to disassemble, validate, and optimize. -// - -#if ENABLE_OPT - -#include -#include - -#include "SpvTools.h" -#include "spirv-tools/optimizer.hpp" - -namespace glslang { - -// Translate glslang's view of target versioning to what SPIRV-Tools uses. -spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLogger* logger) -{ - switch (spvVersion.vulkan) { - case glslang::EShTargetVulkan_1_0: - return spv_target_env::SPV_ENV_VULKAN_1_0; - case glslang::EShTargetVulkan_1_1: - switch (spvVersion.spv) { - case EShTargetSpv_1_0: - case EShTargetSpv_1_1: - case EShTargetSpv_1_2: - case EShTargetSpv_1_3: - return spv_target_env::SPV_ENV_VULKAN_1_1; - case EShTargetSpv_1_4: - return spv_target_env::SPV_ENV_VULKAN_1_1_SPIRV_1_4; - default: - logger->missingFunctionality("Target version for SPIRV-Tools validator"); - return spv_target_env::SPV_ENV_VULKAN_1_1; - } - case glslang::EShTargetVulkan_1_2: - return spv_target_env::SPV_ENV_VULKAN_1_2; - case glslang::EShTargetVulkan_1_3: - return spv_target_env::SPV_ENV_VULKAN_1_3; - default: - break; - } - - if (spvVersion.openGl > 0) - return spv_target_env::SPV_ENV_OPENGL_4_5; - - logger->missingFunctionality("Target version for SPIRV-Tools validator"); - return spv_target_env::SPV_ENV_UNIVERSAL_1_0; -} - -// Callback passed to spvtools::Optimizer::SetMessageConsumer -void OptimizerMesssageConsumer(spv_message_level_t level, const char *source, - const spv_position_t &position, const char *message) -{ - auto &out = std::cerr; - switch (level) - { - case SPV_MSG_FATAL: - case SPV_MSG_INTERNAL_ERROR: - case SPV_MSG_ERROR: - out << "error: "; - break; - case SPV_MSG_WARNING: - out << "warning: "; - break; - case SPV_MSG_INFO: - case SPV_MSG_DEBUG: - out << "info: "; - break; - default: - break; - } - if (source) - { - out << source << ":"; - } - out << position.line << ":" << position.column << ":" << position.index << ":"; - if (message) - { - out << " " << message; - } - out << std::endl; -} - -// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment. -void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv) -{ - SpirvToolsDisassemble(out, spirv, spv_target_env::SPV_ENV_UNIVERSAL_1_3); -} - -// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment. -void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv, - spv_target_env requested_context) -{ - // disassemble - spv_context context = spvContextCreate(requested_context); - spv_text text; - spv_diagnostic diagnostic = nullptr; - spvBinaryToText(context, spirv.data(), spirv.size(), - SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT, - &text, &diagnostic); - - // dump - if (diagnostic == nullptr) - out << text->str; - else - spvDiagnosticPrint(diagnostic); - - // teardown - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(context); -} - -// Apply the SPIRV-Tools validator to generated SPIR-V. -void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger* logger, bool prelegalization) -{ - // validate - spv_context context = spvContextCreate(MapToSpirvToolsEnv(intermediate.getSpv(), logger)); - spv_const_binary_t binary = { spirv.data(), spirv.size() }; - spv_diagnostic diagnostic = nullptr; - spv_validator_options options = spvValidatorOptionsCreate(); - spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets()); - spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization); - spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout()); - spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout()); - spvValidateWithOptions(context, options, &binary, &diagnostic); - - // report - if (diagnostic != nullptr) { - logger->error("SPIRV-Tools Validation Errors"); - logger->error(diagnostic->error); - } - - // tear down - spvValidatorOptionsDestroy(options); - spvDiagnosticDestroy(diagnostic); - spvContextDestroy(context); -} - -// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process. -void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger* logger, const SpvOptions* options) -{ - spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger); - - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer(OptimizerMesssageConsumer); - - // If debug (specifically source line info) is being generated, propagate - // line information into all SPIR-V instructions. This avoids loss of - // information when instructions are deleted or moved. Later, remove - // redundant information to minimize final SPRIR-V size. - if (options->stripDebugInfo) { - optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass()); - } - optimizer.RegisterPass(spvtools::CreateWrapOpKillPass()); - optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); - optimizer.RegisterPass(spvtools::CreateMergeReturnPass()); - optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass()); - optimizer.RegisterPass(spvtools::CreateEliminateDeadFunctionsPass()); - optimizer.RegisterPass(spvtools::CreateScalarReplacementPass()); - optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass()); - optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass()); - optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass()); - optimizer.RegisterPass(spvtools::CreateSimplificationPass()); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); - optimizer.RegisterPass(spvtools::CreateVectorDCEPass()); - optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); - optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); - optimizer.RegisterPass(spvtools::CreateBlockMergePass()); - optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass()); - optimizer.RegisterPass(spvtools::CreateIfConversionPass()); - optimizer.RegisterPass(spvtools::CreateSimplificationPass()); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); - optimizer.RegisterPass(spvtools::CreateVectorDCEPass()); - optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); - optimizer.RegisterPass(spvtools::CreateInterpolateFixupPass()); - if (options->optimizeSize) { - optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass()); - optimizer.RegisterPass(spvtools::CreateEliminateDeadInputComponentsSafePass()); - } - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); - optimizer.RegisterPass(spvtools::CreateCFGCleanupPass()); - - spvtools::OptimizerOptions spvOptOptions; - optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger)); - spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on - optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); -} - -bool SpirvToolsAnalyzeDeadOutputStores(spv_target_env target_env, std::vector& spirv, - std::unordered_set* live_locs, - std::unordered_set* live_builtins, - spv::SpvBuildLogger*) -{ - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer(OptimizerMesssageConsumer); - - optimizer.RegisterPass(spvtools::CreateAnalyzeLiveInputPass(live_locs, live_builtins)); - - spvtools::OptimizerOptions spvOptOptions; - optimizer.SetTargetEnv(target_env); - spvOptOptions.set_run_validator(false); - return optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); -} - -void SpirvToolsEliminateDeadOutputStores(spv_target_env target_env, std::vector& spirv, - std::unordered_set* live_locs, - std::unordered_set* live_builtins, - spv::SpvBuildLogger*) -{ - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer(OptimizerMesssageConsumer); - - optimizer.RegisterPass(spvtools::CreateEliminateDeadOutputStoresPass(live_locs, live_builtins)); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass(false, true)); - optimizer.RegisterPass(spvtools::CreateEliminateDeadOutputComponentsPass()); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass(false, true)); - - spvtools::OptimizerOptions spvOptOptions; - optimizer.SetTargetEnv(target_env); - spvOptOptions.set_run_validator(false); - optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); -} - -void SpirvToolsEliminateDeadInputComponents(spv_target_env target_env, std::vector& spirv, - spv::SpvBuildLogger*) -{ - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer(OptimizerMesssageConsumer); - - optimizer.RegisterPass(spvtools::CreateEliminateDeadInputComponentsPass()); - optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); - - spvtools::OptimizerOptions spvOptOptions; - optimizer.SetTargetEnv(target_env); - spvOptOptions.set_run_validator(false); - optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); -} - -// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by -// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if -// optimization is disabled. -void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate, - std::vector& spirv, spv::SpvBuildLogger* logger) -{ - spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger); - - spvtools::Optimizer optimizer(target_env); - optimizer.SetMessageConsumer(OptimizerMesssageConsumer); - - optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass()); - - spvtools::OptimizerOptions spvOptOptions; - optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger)); - spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on - optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions); -} - -}; // end namespace glslang - -#endif diff --git a/3rdparty/glslang/SPIRV/SpvTools.h b/3rdparty/glslang/SPIRV/SpvTools.h deleted file mode 100644 index eabde466..00000000 --- a/3rdparty/glslang/SPIRV/SpvTools.h +++ /dev/null @@ -1,102 +0,0 @@ -// -// Copyright (C) 2014-2016 LunarG, Inc. -// Copyright (C) 2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Call into SPIRV-Tools to disassemble, validate, and optimize. -// - -#pragma once -#ifndef GLSLANG_SPV_TOOLS_H -#define GLSLANG_SPV_TOOLS_H - -#if ENABLE_OPT -#include -#include -#include "spirv-tools/libspirv.h" -#endif - -#include "glslang/MachineIndependent/localintermediate.h" -#include "GlslangToSpv.h" -#include "Logger.h" - -namespace glslang { - -#if ENABLE_OPT - -// Translate glslang's view of target versioning to what SPIRV-Tools uses. -spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLogger* logger); - -// Use the SPIRV-Tools disassembler to print SPIR-V using a SPV_ENV_UNIVERSAL_1_3 environment. -void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv); - -// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment. -void SpirvToolsDisassemble(std::ostream& out, const std::vector& spirv, - spv_target_env requested_context); - -// Apply the SPIRV-Tools validator to generated SPIR-V. -void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger*, bool prelegalization); - -// Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process. -void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector& spirv, - spv::SpvBuildLogger*, const SpvOptions*); - -// Apply the SPIRV-Tools EliminateDeadInputComponents pass to generated SPIR-V. Put result in |spirv|. -void SpirvToolsEliminateDeadInputComponents(spv_target_env target_env, std::vector& spirv, - spv::SpvBuildLogger*); - -// Apply the SPIRV-Tools AnalyzeDeadOutputStores pass to generated SPIR-V. Put result in |live_locs|. -// Return true if the result is valid. -bool SpirvToolsAnalyzeDeadOutputStores(spv_target_env target_env, std::vector& spirv, - std::unordered_set* live_locs, - std::unordered_set* live_builtins, spv::SpvBuildLogger*); - -// Apply the SPIRV-Tools EliminateDeadOutputStores and AggressiveDeadCodeElimination passes to generated SPIR-V using -// |live_locs|. Put result in |spirv|. -void SpirvToolsEliminateDeadOutputStores(spv_target_env target_env, std::vector& spirv, - std::unordered_set* live_locs, - std::unordered_set* live_builtins, spv::SpvBuildLogger*); - -// Apply the SPIRV-Tools optimizer to strip debug info from SPIR-V. This is implicitly done by -// SpirvToolsTransform if spvOptions->stripDebugInfo is set, but can be called separately if -// optimization is disabled. -void SpirvToolsStripDebugInfo(const glslang::TIntermediate& intermediate, - std::vector& spirv, spv::SpvBuildLogger*); - -#endif - -} // end namespace glslang - -#endif // GLSLANG_SPV_TOOLS_H diff --git a/3rdparty/glslang/SPIRV/bitutils.h b/3rdparty/glslang/SPIRV/bitutils.h deleted file mode 100644 index 22e44cec..00000000 --- a/3rdparty/glslang/SPIRV/bitutils.h +++ /dev/null @@ -1,81 +0,0 @@ -// 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_UTIL_BITUTILS_H_ -#define LIBSPIRV_UTIL_BITUTILS_H_ - -#include -#include - -namespace spvutils { - -// Performs a bitwise copy of source to the destination type Dest. -template -Dest BitwiseCast(Src source) { - Dest dest; - static_assert(sizeof(source) == sizeof(dest), - "BitwiseCast: Source and destination must have the same size"); - std::memcpy(static_cast(&dest), &source, sizeof(dest)); - return dest; -} - -// SetBits returns an integer of type with bits set -// for position through , counting from the least -// significant bit. In particular when Num == 0, no positions are set to 1. -// A static assert will be triggered if First + Num > sizeof(T) * 8, that is, -// a bit that will not fit in the underlying type is set. -template -struct SetBits { - static_assert(First < sizeof(T) * 8, - "Tried to set a bit that is shifted too far."); - const static T get = (T(1) << First) | SetBits::get; -}; - -template -struct SetBits { - const static T get = T(0); -}; - -// This is all compile-time so we can put our tests right here. -static_assert(SetBits::get == uint32_t(0x00000000), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x00000001), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x80000000), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x00000006), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0xc0000000), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0x7FFFFFFF), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0xFFFFFFFF), - "SetBits failed"); -static_assert(SetBits::get == uint32_t(0xFFFF0000), - "SetBits failed"); - -static_assert(SetBits::get == uint64_t(0x0000000000000001LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0x8000000000000000LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0xc000000000000000LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0x0000000080000000LL), - "SetBits failed"); -static_assert(SetBits::get == uint64_t(0x00000000FFFF0000LL), - "SetBits failed"); - -} // namespace spvutils - -#endif // LIBSPIRV_UTIL_BITUTILS_H_ diff --git a/3rdparty/glslang/SPIRV/disassemble.cpp b/3rdparty/glslang/SPIRV/disassemble.cpp deleted file mode 100644 index c5e961cf..00000000 --- a/3rdparty/glslang/SPIRV/disassemble.cpp +++ /dev/null @@ -1,823 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Disassembler for SPIR-V. -// - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "disassemble.h" -#include "doc.h" - -namespace spv { - extern "C" { - // Include C-based headers that don't have a namespace - #include "GLSL.std.450.h" - #include "GLSL.ext.AMD.h" - #include "GLSL.ext.NV.h" - #include "GLSL.ext.ARM.h" - #include "NonSemanticShaderDebugInfo100.h" - #include "GLSL.ext.QCOM.h" - } -} -const char* GlslStd450DebugNames[spv::GLSLstd450Count]; - -namespace spv { - -static const char* GLSLextAMDGetDebugNames(const char*, unsigned); -static const char* GLSLextNVGetDebugNames(const char*, unsigned); -static const char* NonSemanticShaderDebugInfo100GetDebugNames(unsigned); - -static void Kill(std::ostream& out, const char* message) -{ - out << std::endl << "Disassembly failed: " << message << std::endl; - exit(1); -} - -// used to identify the extended instruction library imported when printing -enum ExtInstSet { - GLSL450Inst, - GLSLextAMDInst, - GLSLextNVInst, - OpenCLExtInst, - NonSemanticDebugPrintfExtInst, - NonSemanticShaderDebugInfo100 -}; - -// Container class for a single instance of a SPIR-V stream, with methods for disassembly. -class SpirvStream { -public: - SpirvStream(std::ostream& out, const std::vector& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { } - virtual ~SpirvStream() { } - - void validate(); - void processInstructions(); - -protected: - SpirvStream(const SpirvStream&); - SpirvStream& operator=(const SpirvStream&); - Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; } - - // Output methods - void outputIndent(); - void formatId(Id id, std::stringstream&); - void outputResultId(Id id); - void outputTypeId(Id id); - void outputId(Id id); - void outputMask(OperandClass operandClass, unsigned mask); - void disassembleImmediates(int numOperands); - void disassembleIds(int numOperands); - std::pair decodeString(); - int disassembleString(); - void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands); - - // Data - std::ostream& out; // where to write the disassembly - const std::vector& stream; // the actual word stream - int size; // the size of the word stream - int word; // the next word of the stream to read - - // map each to the instruction that created it - Id bound; - std::vector idInstruction; // the word offset into the stream where the instruction for result [id] starts; 0 if not yet seen (forward reference or function parameter) - - std::vector idDescriptor; // the best text string known for explaining the - - // schema - unsigned int schema; - - // stack of structured-merge points - std::stack nestedControl; - Id nextNestedControl; // need a slight delay for when we are nested -}; - -void SpirvStream::validate() -{ - size = (int)stream.size(); - if (size < 4) - Kill(out, "stream is too short"); - - // Magic number - if (stream[word++] != MagicNumber) { - out << "Bad magic number"; - return; - } - - // Version - out << "// Module Version " << std::hex << stream[word++] << std::endl; - - // Generator's magic number - out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl; - - // Result bound - bound = stream[word++]; - idInstruction.resize(bound); - idDescriptor.resize(bound); - out << "// Id's are bound by " << bound << std::endl; - out << std::endl; - - // Reserved schema, must be 0 for now - schema = stream[word++]; - if (schema != 0) - Kill(out, "bad schema, must be 0"); -} - -// Loop over all the instructions, in order, processing each. -// Boiler plate for each is handled here directly, the rest is dispatched. -void SpirvStream::processInstructions() -{ - // Instructions - while (word < size) { - int instructionStart = word; - - // Instruction wordCount and opcode - unsigned int firstWord = stream[word]; - unsigned wordCount = firstWord >> WordCountShift; - Op opCode = (Op)(firstWord & OpCodeMask); - int nextInst = word + wordCount; - ++word; - - // Presence of full instruction - if (nextInst > size) - Kill(out, "stream instruction terminated too early"); - - // Base for computing number of operands; will be updated as more is learned - unsigned numOperands = wordCount - 1; - - // Type - Id typeId = 0; - if (InstructionDesc[opCode].hasType()) { - typeId = stream[word++]; - --numOperands; - } - - // Result - Id resultId = 0; - if (InstructionDesc[opCode].hasResult()) { - resultId = stream[word++]; - --numOperands; - - // save instruction for future reference - idInstruction[resultId] = instructionStart; - } - - outputResultId(resultId); - outputTypeId(typeId); - outputIndent(); - - // Hand off the Op and all its operands - disassembleInstruction(resultId, typeId, opCode, numOperands); - if (word != nextInst) { - out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart; - word = nextInst; - } - out << std::endl; - } -} - -void SpirvStream::outputIndent() -{ - for (int i = 0; i < (int)nestedControl.size(); ++i) - out << " "; -} - -void SpirvStream::formatId(Id id, std::stringstream& idStream) -{ - if (id != 0) { - // On instructions with no IDs, this is called with "0", which does not - // have to be within ID bounds on null shaders. - if (id >= bound) - Kill(out, "Bad "); - - idStream << id; - if (idDescriptor[id].size() > 0) - idStream << "(" << idDescriptor[id] << ")"; - } -} - -void SpirvStream::outputResultId(Id id) -{ - const int width = 16; - std::stringstream idStream; - formatId(id, idStream); - out << std::setw(width) << std::right << idStream.str(); - if (id != 0) - out << ":"; - else - out << " "; - - if (nestedControl.size() && id == nestedControl.top()) - nestedControl.pop(); -} - -void SpirvStream::outputTypeId(Id id) -{ - const int width = 12; - std::stringstream idStream; - formatId(id, idStream); - out << std::setw(width) << std::right << idStream.str() << " "; -} - -void SpirvStream::outputId(Id id) -{ - if (id >= bound) - Kill(out, "Bad "); - - out << id; - if (idDescriptor[id].size() > 0) - out << "(" << idDescriptor[id] << ")"; -} - -void SpirvStream::outputMask(OperandClass operandClass, unsigned mask) -{ - if (mask == 0) - out << "None"; - else { - for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) { - if (mask & (1 << m)) - out << OperandClassParams[operandClass].getName(m) << " "; - } - } -} - -void SpirvStream::disassembleImmediates(int numOperands) -{ - for (int i = 0; i < numOperands; ++i) { - out << stream[word++]; - if (i < numOperands - 1) - out << " "; - } -} - -void SpirvStream::disassembleIds(int numOperands) -{ - for (int i = 0; i < numOperands; ++i) { - outputId(stream[word++]); - if (i < numOperands - 1) - out << " "; - } -} - -// decode string from words at current position (non-consuming) -std::pair SpirvStream::decodeString() -{ - std::string res; - int wordPos = word; - char c; - bool done = false; - - do { - unsigned int content = stream[wordPos]; - for (int charCount = 0; charCount < 4; ++charCount) { - c = content & 0xff; - content >>= 8; - if (c == '\0') { - done = true; - break; - } - res += c; - } - ++wordPos; - } while(! done); - - return std::make_pair(wordPos - word, res); -} - -// return the number of operands consumed by the string -int SpirvStream::disassembleString() -{ - out << " \""; - - std::pair decoderes = decodeString(); - - out << decoderes.second; - out << "\""; - - word += decoderes.first; - - return decoderes.first; -} - -void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands) -{ - // Process the opcode - - out << (OpcodeString(opCode) + 2); // leave out the "Op" - - if (opCode == OpLoopMerge || opCode == OpSelectionMerge) - nextNestedControl = stream[word]; - else if (opCode == OpBranchConditional || opCode == OpSwitch) { - if (nextNestedControl) { - nestedControl.push(nextNestedControl); - nextNestedControl = 0; - } - } else if (opCode == OpExtInstImport) { - idDescriptor[resultId] = decodeString().second; - } - else { - if (resultId != 0 && idDescriptor[resultId].size() == 0) { - switch (opCode) { - case OpTypeInt: - switch (stream[word]) { - case 8: idDescriptor[resultId] = "int8_t"; break; - case 16: idDescriptor[resultId] = "int16_t"; break; - default: assert(0); // fallthrough - case 32: idDescriptor[resultId] = "int"; break; - case 64: idDescriptor[resultId] = "int64_t"; break; - } - break; - case OpTypeFloat: - switch (stream[word]) { - case 16: idDescriptor[resultId] = "float16_t"; break; - default: assert(0); // fallthrough - case 32: idDescriptor[resultId] = "float"; break; - case 64: idDescriptor[resultId] = "float64_t"; break; - } - break; - case OpTypeBool: - idDescriptor[resultId] = "bool"; - break; - case OpTypeStruct: - idDescriptor[resultId] = "struct"; - break; - case OpTypePointer: - idDescriptor[resultId] = "ptr"; - break; - case OpTypeVector: - if (idDescriptor[stream[word]].size() > 0) { - idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1); - if (strstr(idDescriptor[stream[word]].c_str(), "8")) { - idDescriptor[resultId].append("8"); - } - if (strstr(idDescriptor[stream[word]].c_str(), "16")) { - idDescriptor[resultId].append("16"); - } - if (strstr(idDescriptor[stream[word]].c_str(), "64")) { - idDescriptor[resultId].append("64"); - } - } - idDescriptor[resultId].append("vec"); - switch (stream[word + 1]) { - case 2: idDescriptor[resultId].append("2"); break; - case 3: idDescriptor[resultId].append("3"); break; - case 4: idDescriptor[resultId].append("4"); break; - case 8: idDescriptor[resultId].append("8"); break; - case 16: idDescriptor[resultId].append("16"); break; - case 32: idDescriptor[resultId].append("32"); break; - default: break; - } - break; - default: - break; - } - } - } - - // Process the operands. Note, a new context-dependent set could be - // swapped in mid-traversal. - - // Handle images specially, so can put out helpful strings. - if (opCode == OpTypeImage) { - out << " "; - disassembleIds(1); - out << " " << DimensionString((Dim)stream[word++]); - out << (stream[word++] != 0 ? " depth" : ""); - out << (stream[word++] != 0 ? " array" : ""); - out << (stream[word++] != 0 ? " multi-sampled" : ""); - switch (stream[word++]) { - case 0: out << " runtime"; break; - case 1: out << " sampled"; break; - case 2: out << " nonsampled"; break; - } - out << " format:" << ImageFormatString((ImageFormat)stream[word++]); - - if (numOperands == 8) { - out << " " << AccessQualifierString(stream[word++]); - } - return; - } - - // Handle all the parameterized operands - for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) { - out << " "; - OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op); - switch (operandClass) { - case OperandId: - case OperandScope: - case OperandMemorySemantics: - disassembleIds(1); - --numOperands; - // Get names for printing "(XXX)" for readability, *after* this id - if (opCode == OpName) - idDescriptor[stream[word - 1]] = decodeString().second; - break; - case OperandVariableIds: - disassembleIds(numOperands); - return; - case OperandImageOperands: - outputMask(OperandImageOperands, stream[word++]); - --numOperands; - disassembleIds(numOperands); - return; - case OperandOptionalLiteral: - case OperandVariableLiterals: - if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) || - (opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) { - out << BuiltInString(stream[word++]); - --numOperands; - ++op; - } - disassembleImmediates(numOperands); - return; - case OperandVariableIdLiteral: - while (numOperands > 0) { - out << std::endl; - outputResultId(0); - outputTypeId(0); - outputIndent(); - out << " Type "; - disassembleIds(1); - out << ", member "; - disassembleImmediates(1); - numOperands -= 2; - } - return; - case OperandVariableLiteralId: - while (numOperands > 0) { - out << std::endl; - outputResultId(0); - outputTypeId(0); - outputIndent(); - out << " case "; - disassembleImmediates(1); - out << ": "; - disassembleIds(1); - numOperands -= 2; - } - return; - case OperandLiteralNumber: - disassembleImmediates(1); - --numOperands; - if (opCode == OpExtInst) { - ExtInstSet extInstSet = GLSL450Inst; - const char* name = idDescriptor[stream[word - 2]].c_str(); - if (strcmp("OpenCL.std", name) == 0) { - extInstSet = OpenCLExtInst; - } else if (strcmp("OpenCL.DebugInfo.100", name) == 0) { - extInstSet = OpenCLExtInst; - } else if (strcmp("NonSemantic.DebugPrintf", name) == 0) { - extInstSet = NonSemanticDebugPrintfExtInst; - } else if (strcmp("NonSemantic.Shader.DebugInfo.100", name) == 0) { - extInstSet = NonSemanticShaderDebugInfo100; - } else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 || - strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 || - strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 || - strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) { - extInstSet = GLSLextAMDInst; - } else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 || - strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 || - strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 || - strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 || - strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 || - strcmp(spv::E_SPV_NV_mesh_shader, name) == 0) { - extInstSet = GLSLextNVInst; - } - unsigned entrypoint = stream[word - 1]; - if (extInstSet == GLSL450Inst) { - if (entrypoint < GLSLstd450Count) { - out << "(" << GlslStd450DebugNames[entrypoint] << ")"; - } - } else if (extInstSet == GLSLextAMDInst) { - out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")"; - } - else if (extInstSet == GLSLextNVInst) { - out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")"; - } else if (extInstSet == NonSemanticDebugPrintfExtInst) { - out << "(DebugPrintf)"; - } else if (extInstSet == NonSemanticShaderDebugInfo100) { - out << "(" << NonSemanticShaderDebugInfo100GetDebugNames(entrypoint) << ")"; - } - } - break; - case OperandOptionalLiteralString: - case OperandLiteralString: - numOperands -= disassembleString(); - break; - case OperandVariableLiteralStrings: - while (numOperands > 0) - numOperands -= disassembleString(); - return; - case OperandMemoryAccess: - outputMask(OperandMemoryAccess, stream[word++]); - --numOperands; - // Aligned is the only memory access operand that uses an immediate - // value, and it is also the first operand that uses a value at all. - if (stream[word-1] & MemoryAccessAlignedMask) { - disassembleImmediates(1); - numOperands--; - if (numOperands) - out << " "; - } - disassembleIds(numOperands); - return; - default: - assert(operandClass >= OperandSource && operandClass < OperandOpcode); - - if (OperandClassParams[operandClass].bitmask) - outputMask(operandClass, stream[word++]); - else - out << OperandClassParams[operandClass].getName(stream[word++]); - --numOperands; - - break; - } - } - - return; -} - -static void GLSLstd450GetDebugNames(const char** names) -{ - for (int i = 0; i < GLSLstd450Count; ++i) - names[i] = "Unknown"; - - names[GLSLstd450Round] = "Round"; - names[GLSLstd450RoundEven] = "RoundEven"; - names[GLSLstd450Trunc] = "Trunc"; - names[GLSLstd450FAbs] = "FAbs"; - names[GLSLstd450SAbs] = "SAbs"; - names[GLSLstd450FSign] = "FSign"; - names[GLSLstd450SSign] = "SSign"; - names[GLSLstd450Floor] = "Floor"; - names[GLSLstd450Ceil] = "Ceil"; - names[GLSLstd450Fract] = "Fract"; - names[GLSLstd450Radians] = "Radians"; - names[GLSLstd450Degrees] = "Degrees"; - names[GLSLstd450Sin] = "Sin"; - names[GLSLstd450Cos] = "Cos"; - names[GLSLstd450Tan] = "Tan"; - names[GLSLstd450Asin] = "Asin"; - names[GLSLstd450Acos] = "Acos"; - names[GLSLstd450Atan] = "Atan"; - names[GLSLstd450Sinh] = "Sinh"; - names[GLSLstd450Cosh] = "Cosh"; - names[GLSLstd450Tanh] = "Tanh"; - names[GLSLstd450Asinh] = "Asinh"; - names[GLSLstd450Acosh] = "Acosh"; - names[GLSLstd450Atanh] = "Atanh"; - names[GLSLstd450Atan2] = "Atan2"; - names[GLSLstd450Pow] = "Pow"; - names[GLSLstd450Exp] = "Exp"; - names[GLSLstd450Log] = "Log"; - names[GLSLstd450Exp2] = "Exp2"; - names[GLSLstd450Log2] = "Log2"; - names[GLSLstd450Sqrt] = "Sqrt"; - names[GLSLstd450InverseSqrt] = "InverseSqrt"; - names[GLSLstd450Determinant] = "Determinant"; - names[GLSLstd450MatrixInverse] = "MatrixInverse"; - names[GLSLstd450Modf] = "Modf"; - names[GLSLstd450ModfStruct] = "ModfStruct"; - names[GLSLstd450FMin] = "FMin"; - names[GLSLstd450SMin] = "SMin"; - names[GLSLstd450UMin] = "UMin"; - names[GLSLstd450FMax] = "FMax"; - names[GLSLstd450SMax] = "SMax"; - names[GLSLstd450UMax] = "UMax"; - names[GLSLstd450FClamp] = "FClamp"; - names[GLSLstd450SClamp] = "SClamp"; - names[GLSLstd450UClamp] = "UClamp"; - names[GLSLstd450FMix] = "FMix"; - names[GLSLstd450Step] = "Step"; - names[GLSLstd450SmoothStep] = "SmoothStep"; - names[GLSLstd450Fma] = "Fma"; - names[GLSLstd450Frexp] = "Frexp"; - names[GLSLstd450FrexpStruct] = "FrexpStruct"; - names[GLSLstd450Ldexp] = "Ldexp"; - names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8"; - names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8"; - names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16"; - names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16"; - names[GLSLstd450PackHalf2x16] = "PackHalf2x16"; - names[GLSLstd450PackDouble2x32] = "PackDouble2x32"; - names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16"; - names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16"; - names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16"; - names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8"; - names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8"; - names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32"; - names[GLSLstd450Length] = "Length"; - names[GLSLstd450Distance] = "Distance"; - names[GLSLstd450Cross] = "Cross"; - names[GLSLstd450Normalize] = "Normalize"; - names[GLSLstd450FaceForward] = "FaceForward"; - names[GLSLstd450Reflect] = "Reflect"; - names[GLSLstd450Refract] = "Refract"; - names[GLSLstd450FindILsb] = "FindILsb"; - names[GLSLstd450FindSMsb] = "FindSMsb"; - names[GLSLstd450FindUMsb] = "FindUMsb"; - names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid"; - names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample"; - names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset"; - names[GLSLstd450NMin] = "NMin"; - names[GLSLstd450NMax] = "NMax"; - names[GLSLstd450NClamp] = "NClamp"; -} - -static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint) -{ - if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) { - switch (entrypoint) { - case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD"; - case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD"; - case WriteInvocationAMD: return "WriteInvocationAMD"; - case MbcntAMD: return "MbcntAMD"; - default: return "Bad"; - } - } else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) { - switch (entrypoint) { - case FMin3AMD: return "FMin3AMD"; - case UMin3AMD: return "UMin3AMD"; - case SMin3AMD: return "SMin3AMD"; - case FMax3AMD: return "FMax3AMD"; - case UMax3AMD: return "UMax3AMD"; - case SMax3AMD: return "SMax3AMD"; - case FMid3AMD: return "FMid3AMD"; - case UMid3AMD: return "UMid3AMD"; - case SMid3AMD: return "SMid3AMD"; - default: return "Bad"; - } - } else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) { - switch (entrypoint) { - case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD"; - default: return "Bad"; - } - } - else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) { - switch (entrypoint) { - case CubeFaceIndexAMD: return "CubeFaceIndexAMD"; - case CubeFaceCoordAMD: return "CubeFaceCoordAMD"; - case TimeAMD: return "TimeAMD"; - default: - break; - } - } - - return "Bad"; -} - -static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint) -{ - if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 || - strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 || - strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 || - strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 || - strcmp(name, spv::E_SPV_NVX_multiview_per_view_attributes) == 0 || - strcmp(name, spv::E_SPV_NV_fragment_shader_barycentric) == 0 || - strcmp(name, spv::E_SPV_NV_mesh_shader) == 0 || - strcmp(name, spv::E_SPV_NV_shader_image_footprint) == 0) { - switch (entrypoint) { - // NV builtins - case BuiltInViewportMaskNV: return "ViewportMaskNV"; - case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; - case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case BuiltInPositionPerViewNV: return "PositionPerViewNV"; - case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; - case BuiltInBaryCoordNV: return "BaryCoordNV"; - case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; - case BuiltInTaskCountNV: return "TaskCountNV"; - case BuiltInPrimitiveCountNV: return "PrimitiveCountNV"; - case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV"; - case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV"; - case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV"; - case BuiltInLayerPerViewNV: return "LayerPerViewNV"; - case BuiltInMeshViewCountNV: return "MeshViewCountNV"; - case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV"; - - // NV Capabilities - case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV"; - case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV"; - case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV"; - case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; - case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV"; - case CapabilityMeshShadingNV: return "MeshShadingNV"; - case CapabilityImageFootprintNV: return "ImageFootprintNV"; - case CapabilitySampleMaskOverrideCoverageNV:return "SampleMaskOverrideCoverageNV"; - - // NV Decorations - case DecorationOverrideCoverageNV: return "OverrideCoverageNV"; - case DecorationPassthroughNV: return "PassthroughNV"; - case DecorationViewportRelativeNV: return "ViewportRelativeNV"; - case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV"; - case DecorationPerVertexNV: return "PerVertexNV"; - case DecorationPerPrimitiveNV: return "PerPrimitiveNV"; - case DecorationPerViewNV: return "PerViewNV"; - case DecorationPerTaskNV: return "PerTaskNV"; - - default: return "Bad"; - } - } - return "Bad"; -} - -static const char* NonSemanticShaderDebugInfo100GetDebugNames(unsigned entrypoint) -{ - switch (entrypoint) { - case NonSemanticShaderDebugInfo100DebugInfoNone: return "DebugInfoNone"; - case NonSemanticShaderDebugInfo100DebugCompilationUnit: return "DebugCompilationUnit"; - case NonSemanticShaderDebugInfo100DebugTypeBasic: return "DebugTypeBasic"; - case NonSemanticShaderDebugInfo100DebugTypePointer: return "DebugTypePointer"; - case NonSemanticShaderDebugInfo100DebugTypeQualifier: return "DebugTypeQualifier"; - case NonSemanticShaderDebugInfo100DebugTypeArray: return "DebugTypeArray"; - case NonSemanticShaderDebugInfo100DebugTypeVector: return "DebugTypeVector"; - case NonSemanticShaderDebugInfo100DebugTypedef: return "DebugTypedef"; - case NonSemanticShaderDebugInfo100DebugTypeFunction: return "DebugTypeFunction"; - case NonSemanticShaderDebugInfo100DebugTypeEnum: return "DebugTypeEnum"; - case NonSemanticShaderDebugInfo100DebugTypeComposite: return "DebugTypeComposite"; - case NonSemanticShaderDebugInfo100DebugTypeMember: return "DebugTypeMember"; - case NonSemanticShaderDebugInfo100DebugTypeInheritance: return "DebugTypeInheritance"; - case NonSemanticShaderDebugInfo100DebugTypePtrToMember: return "DebugTypePtrToMember"; - case NonSemanticShaderDebugInfo100DebugTypeTemplate: return "DebugTypeTemplate"; - case NonSemanticShaderDebugInfo100DebugTypeTemplateParameter: return "DebugTypeTemplateParameter"; - case NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter: return "DebugTypeTemplateTemplateParameter"; - case NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack: return "DebugTypeTemplateParameterPack"; - case NonSemanticShaderDebugInfo100DebugGlobalVariable: return "DebugGlobalVariable"; - case NonSemanticShaderDebugInfo100DebugFunctionDeclaration: return "DebugFunctionDeclaration"; - case NonSemanticShaderDebugInfo100DebugFunction: return "DebugFunction"; - case NonSemanticShaderDebugInfo100DebugLexicalBlock: return "DebugLexicalBlock"; - case NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator: return "DebugLexicalBlockDiscriminator"; - case NonSemanticShaderDebugInfo100DebugScope: return "DebugScope"; - case NonSemanticShaderDebugInfo100DebugNoScope: return "DebugNoScope"; - case NonSemanticShaderDebugInfo100DebugInlinedAt: return "DebugInlinedAt"; - case NonSemanticShaderDebugInfo100DebugLocalVariable: return "DebugLocalVariable"; - case NonSemanticShaderDebugInfo100DebugInlinedVariable: return "DebugInlinedVariable"; - case NonSemanticShaderDebugInfo100DebugDeclare: return "DebugDeclare"; - case NonSemanticShaderDebugInfo100DebugValue: return "DebugValue"; - case NonSemanticShaderDebugInfo100DebugOperation: return "DebugOperation"; - case NonSemanticShaderDebugInfo100DebugExpression: return "DebugExpression"; - case NonSemanticShaderDebugInfo100DebugMacroDef: return "DebugMacroDef"; - case NonSemanticShaderDebugInfo100DebugMacroUndef: return "DebugMacroUndef"; - case NonSemanticShaderDebugInfo100DebugImportedEntity: return "DebugImportedEntity"; - case NonSemanticShaderDebugInfo100DebugSource: return "DebugSource"; - case NonSemanticShaderDebugInfo100DebugFunctionDefinition: return "DebugFunctionDefinition"; - case NonSemanticShaderDebugInfo100DebugSourceContinued: return "DebugSourceContinued"; - case NonSemanticShaderDebugInfo100DebugLine: return "DebugLine"; - case NonSemanticShaderDebugInfo100DebugNoLine: return "DebugNoLine"; - case NonSemanticShaderDebugInfo100DebugBuildIdentifier: return "DebugBuildIdentifier"; - case NonSemanticShaderDebugInfo100DebugStoragePath: return "DebugStoragePath"; - case NonSemanticShaderDebugInfo100DebugEntryPoint: return "DebugEntryPoint"; - case NonSemanticShaderDebugInfo100DebugTypeMatrix: return "DebugTypeMatrix"; - default: return "Bad"; - } - - return "Bad"; -} - -void Disassemble(std::ostream& out, const std::vector& stream) -{ - SpirvStream SpirvStream(out, stream); - spv::Parameterize(); - GLSLstd450GetDebugNames(GlslStd450DebugNames); - SpirvStream.validate(); - SpirvStream.processInstructions(); -} - -}; // end namespace spv diff --git a/3rdparty/glslang/SPIRV/disassemble.h b/3rdparty/glslang/SPIRV/disassemble.h deleted file mode 100644 index b6a46357..00000000 --- a/3rdparty/glslang/SPIRV/disassemble.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Disassembler for SPIR-V. -// - -#pragma once -#ifndef disassembler_H -#define disassembler_H - -#include -#include - -namespace spv { - - // disassemble with glslang custom disassembler - void Disassemble(std::ostream& out, const std::vector&); - -} // end namespace spv - -#endif // disassembler_H diff --git a/3rdparty/glslang/SPIRV/doc.cpp b/3rdparty/glslang/SPIRV/doc.cpp deleted file mode 100644 index 1a05c673..00000000 --- a/3rdparty/glslang/SPIRV/doc.cpp +++ /dev/null @@ -1,3409 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// 1) Programmatically fill in instruction/operand information. -// This can be used for disassembly, printing documentation, etc. -// -// 2) Print documentation from this parameterization. -// - -#include "doc.h" - -#include -#include -#include -#include - -namespace spv { - extern "C" { - // Include C-based headers that don't have a namespace - #include "GLSL.ext.KHR.h" - #include "GLSL.ext.EXT.h" - #include "GLSL.ext.AMD.h" - #include "GLSL.ext.NV.h" - #include "GLSL.ext.ARM.h" - #include "GLSL.ext.QCOM.h" - } -} - -namespace spv { - -// -// Whole set of functions that translate enumerants to their text strings for -// the specification (or their sanitized versions for auto-generating the -// spirv headers. -// -// Also, for masks the ceilings are declared next to these, to help keep them in sync. -// Ceilings should be -// - one more than the maximum value an enumerant takes on, for non-mask enumerants -// (for non-sparse enums, this is the number of enumerants) -// - the number of bits consumed by the set of masks -// (for non-sparse mask enums, this is the number of enumerants) -// - -const char* SourceString(int source) -{ - switch (source) { - case 0: return "Unknown"; - case 1: return "ESSL"; - case 2: return "GLSL"; - case 3: return "OpenCL_C"; - case 4: return "OpenCL_CPP"; - case 5: return "HLSL"; - - default: return "Bad"; - } -} - -const char* ExecutionModelString(int model) -{ - switch (model) { - case 0: return "Vertex"; - case 1: return "TessellationControl"; - case 2: return "TessellationEvaluation"; - case 3: return "Geometry"; - case 4: return "Fragment"; - case 5: return "GLCompute"; - case 6: return "Kernel"; - case ExecutionModelTaskNV: return "TaskNV"; - case ExecutionModelMeshNV: return "MeshNV"; - case ExecutionModelTaskEXT: return "TaskEXT"; - case ExecutionModelMeshEXT: return "MeshEXT"; - - default: return "Bad"; - - case ExecutionModelRayGenerationKHR: return "RayGenerationKHR"; - case ExecutionModelIntersectionKHR: return "IntersectionKHR"; - case ExecutionModelAnyHitKHR: return "AnyHitKHR"; - case ExecutionModelClosestHitKHR: return "ClosestHitKHR"; - case ExecutionModelMissKHR: return "MissKHR"; - case ExecutionModelCallableKHR: return "CallableKHR"; - } -} - -const char* AddressingString(int addr) -{ - switch (addr) { - case 0: return "Logical"; - case 1: return "Physical32"; - case 2: return "Physical64"; - - case AddressingModelPhysicalStorageBuffer64EXT: return "PhysicalStorageBuffer64EXT"; - - default: return "Bad"; - } -} - -const char* MemoryString(int mem) -{ - switch (mem) { - case MemoryModelSimple: return "Simple"; - case MemoryModelGLSL450: return "GLSL450"; - case MemoryModelOpenCL: return "OpenCL"; - case MemoryModelVulkanKHR: return "VulkanKHR"; - - default: return "Bad"; - } -} - -const int ExecutionModeCeiling = 40; - -const char* ExecutionModeString(int mode) -{ - switch (mode) { - case 0: return "Invocations"; - case 1: return "SpacingEqual"; - case 2: return "SpacingFractionalEven"; - case 3: return "SpacingFractionalOdd"; - case 4: return "VertexOrderCw"; - case 5: return "VertexOrderCcw"; - case 6: return "PixelCenterInteger"; - case 7: return "OriginUpperLeft"; - case 8: return "OriginLowerLeft"; - case 9: return "EarlyFragmentTests"; - case 10: return "PointMode"; - case 11: return "Xfb"; - case 12: return "DepthReplacing"; - case 13: return "Bad"; - case 14: return "DepthGreater"; - case 15: return "DepthLess"; - case 16: return "DepthUnchanged"; - case 17: return "LocalSize"; - case 18: return "LocalSizeHint"; - case 19: return "InputPoints"; - case 20: return "InputLines"; - case 21: return "InputLinesAdjacency"; - case 22: return "Triangles"; - case 23: return "InputTrianglesAdjacency"; - case 24: return "Quads"; - case 25: return "Isolines"; - case 26: return "OutputVertices"; - case 27: return "OutputPoints"; - case 28: return "OutputLineStrip"; - case 29: return "OutputTriangleStrip"; - case 30: return "VecTypeHint"; - case 31: return "ContractionOff"; - case 32: return "Bad"; - - case ExecutionModeInitializer: return "Initializer"; - case ExecutionModeFinalizer: return "Finalizer"; - case ExecutionModeSubgroupSize: return "SubgroupSize"; - case ExecutionModeSubgroupsPerWorkgroup: return "SubgroupsPerWorkgroup"; - case ExecutionModeSubgroupsPerWorkgroupId: return "SubgroupsPerWorkgroupId"; - case ExecutionModeLocalSizeId: return "LocalSizeId"; - case ExecutionModeLocalSizeHintId: return "LocalSizeHintId"; - - case ExecutionModePostDepthCoverage: return "PostDepthCoverage"; - case ExecutionModeDenormPreserve: return "DenormPreserve"; - case ExecutionModeDenormFlushToZero: return "DenormFlushToZero"; - case ExecutionModeSignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve"; - case ExecutionModeRoundingModeRTE: return "RoundingModeRTE"; - case ExecutionModeRoundingModeRTZ: return "RoundingModeRTZ"; - case ExecutionModeEarlyAndLateFragmentTestsAMD: return "EarlyAndLateFragmentTestsAMD"; - case ExecutionModeStencilRefUnchangedFrontAMD: return "StencilRefUnchangedFrontAMD"; - case ExecutionModeStencilRefLessFrontAMD: return "StencilRefLessFrontAMD"; - case ExecutionModeStencilRefGreaterBackAMD: return "StencilRefGreaterBackAMD"; - case ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT"; - case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow"; - - case ExecutionModeOutputLinesNV: return "OutputLinesNV"; - case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV"; - case ExecutionModeOutputTrianglesNV: return "OutputTrianglesNV"; - case ExecutionModeDerivativeGroupQuadsNV: return "DerivativeGroupQuadsNV"; - case ExecutionModeDerivativeGroupLinearNV: return "DerivativeGroupLinearNV"; - - case ExecutionModePixelInterlockOrderedEXT: return "PixelInterlockOrderedEXT"; - case ExecutionModePixelInterlockUnorderedEXT: return "PixelInterlockUnorderedEXT"; - case ExecutionModeSampleInterlockOrderedEXT: return "SampleInterlockOrderedEXT"; - case ExecutionModeSampleInterlockUnorderedEXT: return "SampleInterlockUnorderedEXT"; - case ExecutionModeShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT"; - case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT"; - - case ExecutionModeMaxWorkgroupSizeINTEL: return "MaxWorkgroupSizeINTEL"; - case ExecutionModeMaxWorkDimINTEL: return "MaxWorkDimINTEL"; - case ExecutionModeNoGlobalOffsetINTEL: return "NoGlobalOffsetINTEL"; - case ExecutionModeNumSIMDWorkitemsINTEL: return "NumSIMDWorkitemsINTEL"; - - case ExecutionModeNonCoherentColorAttachmentReadEXT: return "NonCoherentColorAttachmentReadEXT"; - case ExecutionModeNonCoherentDepthAttachmentReadEXT: return "NonCoherentDepthAttachmentReadEXT"; - case ExecutionModeNonCoherentStencilAttachmentReadEXT: return "NonCoherentStencilAttachmentReadEXT"; - - case ExecutionModeCeiling: - default: return "Bad"; - } -} - -const char* StorageClassString(int StorageClass) -{ - switch (StorageClass) { - case 0: return "UniformConstant"; - case 1: return "Input"; - case 2: return "Uniform"; - case 3: return "Output"; - case 4: return "Workgroup"; - case 5: return "CrossWorkgroup"; - case 6: return "Private"; - case 7: return "Function"; - case 8: return "Generic"; - case 9: return "PushConstant"; - case 10: return "AtomicCounter"; - case 11: return "Image"; - case 12: return "StorageBuffer"; - - case StorageClassRayPayloadKHR: return "RayPayloadKHR"; - case StorageClassHitAttributeKHR: return "HitAttributeKHR"; - case StorageClassIncomingRayPayloadKHR: return "IncomingRayPayloadKHR"; - case StorageClassShaderRecordBufferKHR: return "ShaderRecordBufferKHR"; - case StorageClassCallableDataKHR: return "CallableDataKHR"; - case StorageClassIncomingCallableDataKHR: return "IncomingCallableDataKHR"; - - case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT"; - case StorageClassTaskPayloadWorkgroupEXT: return "TaskPayloadWorkgroupEXT"; - case StorageClassHitObjectAttributeNV: return "HitObjectAttributeNV"; - case StorageClassTileImageEXT: return "TileImageEXT"; - default: return "Bad"; - } -} - -const int DecorationCeiling = 45; - -const char* DecorationString(int decoration) -{ - switch (decoration) { - case 0: return "RelaxedPrecision"; - case 1: return "SpecId"; - case 2: return "Block"; - case 3: return "BufferBlock"; - case 4: return "RowMajor"; - case 5: return "ColMajor"; - case 6: return "ArrayStride"; - case 7: return "MatrixStride"; - case 8: return "GLSLShared"; - case 9: return "GLSLPacked"; - case 10: return "CPacked"; - case 11: return "BuiltIn"; - case 12: return "Bad"; - case 13: return "NoPerspective"; - case 14: return "Flat"; - case 15: return "Patch"; - case 16: return "Centroid"; - case 17: return "Sample"; - case 18: return "Invariant"; - case 19: return "Restrict"; - case 20: return "Aliased"; - case 21: return "Volatile"; - case 22: return "Constant"; - case 23: return "Coherent"; - case 24: return "NonWritable"; - case 25: return "NonReadable"; - case 26: return "Uniform"; - case 27: return "Bad"; - case 28: return "SaturatedConversion"; - case 29: return "Stream"; - case 30: return "Location"; - case 31: return "Component"; - case 32: return "Index"; - case 33: return "Binding"; - case 34: return "DescriptorSet"; - case 35: return "Offset"; - case 36: return "XfbBuffer"; - case 37: return "XfbStride"; - case 38: return "FuncParamAttr"; - case 39: return "FP Rounding Mode"; - case 40: return "FP Fast Math Mode"; - case 41: return "Linkage Attributes"; - case 42: return "NoContraction"; - case 43: return "InputAttachmentIndex"; - case 44: return "Alignment"; - - case DecorationCeiling: - default: return "Bad"; - - case DecorationWeightTextureQCOM: return "DecorationWeightTextureQCOM"; - case DecorationBlockMatchTextureQCOM: return "DecorationBlockMatchTextureQCOM"; - case DecorationExplicitInterpAMD: return "ExplicitInterpAMD"; - case DecorationOverrideCoverageNV: return "OverrideCoverageNV"; - case DecorationPassthroughNV: return "PassthroughNV"; - case DecorationViewportRelativeNV: return "ViewportRelativeNV"; - case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV"; - case DecorationPerPrimitiveNV: return "PerPrimitiveNV"; - case DecorationPerViewNV: return "PerViewNV"; - case DecorationPerTaskNV: return "PerTaskNV"; - - case DecorationPerVertexKHR: return "PerVertexKHR"; - - case DecorationNonUniformEXT: return "DecorationNonUniformEXT"; - case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE"; - case DecorationHlslSemanticGOOGLE: return "DecorationHlslSemanticGOOGLE"; - case DecorationRestrictPointerEXT: return "DecorationRestrictPointerEXT"; - case DecorationAliasedPointerEXT: return "DecorationAliasedPointerEXT"; - - case DecorationHitObjectShaderRecordBufferNV: return "DecorationHitObjectShaderRecordBufferNV"; - } -} - -const char* BuiltInString(int builtIn) -{ - switch (builtIn) { - case 0: return "Position"; - case 1: return "PointSize"; - case 2: return "Bad"; - case 3: return "ClipDistance"; - case 4: return "CullDistance"; - case 5: return "VertexId"; - case 6: return "InstanceId"; - case 7: return "PrimitiveId"; - case 8: return "InvocationId"; - case 9: return "Layer"; - case 10: return "ViewportIndex"; - case 11: return "TessLevelOuter"; - case 12: return "TessLevelInner"; - case 13: return "TessCoord"; - case 14: return "PatchVertices"; - case 15: return "FragCoord"; - case 16: return "PointCoord"; - case 17: return "FrontFacing"; - case 18: return "SampleId"; - case 19: return "SamplePosition"; - case 20: return "SampleMask"; - case 21: return "Bad"; - case 22: return "FragDepth"; - case 23: return "HelperInvocation"; - case 24: return "NumWorkgroups"; - case 25: return "WorkgroupSize"; - case 26: return "WorkgroupId"; - case 27: return "LocalInvocationId"; - case 28: return "GlobalInvocationId"; - case 29: return "LocalInvocationIndex"; - case 30: return "WorkDim"; - case 31: return "GlobalSize"; - case 32: return "EnqueuedWorkgroupSize"; - case 33: return "GlobalOffset"; - case 34: return "GlobalLinearId"; - case 35: return "Bad"; - case 36: return "SubgroupSize"; - case 37: return "SubgroupMaxSize"; - case 38: return "NumSubgroups"; - case 39: return "NumEnqueuedSubgroups"; - case 40: return "SubgroupId"; - case 41: return "SubgroupLocalInvocationId"; - case 42: return "VertexIndex"; // TBD: put next to VertexId? - case 43: return "InstanceIndex"; // TBD: put next to InstanceId? - - case 4416: return "SubgroupEqMaskKHR"; - case 4417: return "SubgroupGeMaskKHR"; - case 4418: return "SubgroupGtMaskKHR"; - case 4419: return "SubgroupLeMaskKHR"; - case 4420: return "SubgroupLtMaskKHR"; - case 4438: return "DeviceIndex"; - case 4440: return "ViewIndex"; - case 4424: return "BaseVertex"; - case 4425: return "BaseInstance"; - case 4426: return "DrawIndex"; - case 4432: return "PrimitiveShadingRateKHR"; - case 4444: return "ShadingRateKHR"; - case 5014: return "FragStencilRefEXT"; - - case 4992: return "BaryCoordNoPerspAMD"; - case 4993: return "BaryCoordNoPerspCentroidAMD"; - case 4994: return "BaryCoordNoPerspSampleAMD"; - case 4995: return "BaryCoordSmoothAMD"; - case 4996: return "BaryCoordSmoothCentroidAMD"; - case 4997: return "BaryCoordSmoothSampleAMD"; - case 4998: return "BaryCoordPullModelAMD"; - case BuiltInLaunchIdKHR: return "LaunchIdKHR"; - case BuiltInLaunchSizeKHR: return "LaunchSizeKHR"; - case BuiltInWorldRayOriginKHR: return "WorldRayOriginKHR"; - case BuiltInWorldRayDirectionKHR: return "WorldRayDirectionKHR"; - case BuiltInObjectRayOriginKHR: return "ObjectRayOriginKHR"; - case BuiltInObjectRayDirectionKHR: return "ObjectRayDirectionKHR"; - case BuiltInRayTminKHR: return "RayTminKHR"; - case BuiltInRayTmaxKHR: return "RayTmaxKHR"; - case BuiltInCullMaskKHR: return "CullMaskKHR"; - case BuiltInHitTriangleVertexPositionsKHR: return "HitTriangleVertexPositionsKHR"; - case BuiltInHitMicroTriangleVertexPositionsNV: return "HitMicroTriangleVertexPositionsNV"; - case BuiltInHitMicroTriangleVertexBarycentricsNV: return "HitMicroTriangleVertexBarycentricsNV"; - case BuiltInHitKindFrontFacingMicroTriangleNV: return "HitKindFrontFacingMicroTriangleNV"; - case BuiltInHitKindBackFacingMicroTriangleNV: return "HitKindBackFacingMicroTriangleNV"; - case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR"; - case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR"; - case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR"; - case BuiltInWorldToObjectKHR: return "WorldToObjectKHR"; - case BuiltInHitTNV: return "HitTNV"; - case BuiltInHitKindKHR: return "HitKindKHR"; - case BuiltInIncomingRayFlagsKHR: return "IncomingRayFlagsKHR"; - case BuiltInViewportMaskNV: return "ViewportMaskNV"; - case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; - case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case BuiltInPositionPerViewNV: return "PositionPerViewNV"; - case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; -// case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT -// case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT - case BuiltInBaryCoordKHR: return "BaryCoordKHR"; - case BuiltInBaryCoordNoPerspKHR: return "BaryCoordNoPerspKHR"; - - case BuiltInFragSizeEXT: return "FragSizeEXT"; - case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT"; - - case 5264: return "FullyCoveredEXT"; - - case BuiltInTaskCountNV: return "TaskCountNV"; - case BuiltInPrimitiveCountNV: return "PrimitiveCountNV"; - case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV"; - case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV"; - case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV"; - case BuiltInLayerPerViewNV: return "LayerPerViewNV"; - case BuiltInMeshViewCountNV: return "MeshViewCountNV"; - case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV"; - case BuiltInWarpsPerSMNV: return "WarpsPerSMNV"; - case BuiltInSMCountNV: return "SMCountNV"; - case BuiltInWarpIDNV: return "WarpIDNV"; - case BuiltInSMIDNV: return "SMIDNV"; - case BuiltInCurrentRayTimeNV: return "CurrentRayTimeNV"; - case BuiltInPrimitivePointIndicesEXT: return "PrimitivePointIndicesEXT"; - case BuiltInPrimitiveLineIndicesEXT: return "PrimitiveLineIndicesEXT"; - case BuiltInPrimitiveTriangleIndicesEXT: return "PrimitiveTriangleIndicesEXT"; - case BuiltInCullPrimitiveEXT: return "CullPrimitiveEXT"; - case BuiltInCoreCountARM: return "CoreCountARM"; - case BuiltInCoreIDARM: return "CoreIDARM"; - case BuiltInCoreMaxIDARM: return "CoreMaxIDARM"; - case BuiltInWarpIDARM: return "WarpIDARM"; - case BuiltInWarpMaxIDARM: return "BuiltInWarpMaxIDARM"; - - default: return "Bad"; - } -} - -const char* DimensionString(int dim) -{ - switch (dim) { - case 0: return "1D"; - case 1: return "2D"; - case 2: return "3D"; - case 3: return "Cube"; - case 4: return "Rect"; - case 5: return "Buffer"; - case 6: return "SubpassData"; - case DimTileImageDataEXT: return "TileImageDataEXT"; - - default: return "Bad"; - } -} - -const char* SamplerAddressingModeString(int mode) -{ - switch (mode) { - case 0: return "None"; - case 1: return "ClampToEdge"; - case 2: return "Clamp"; - case 3: return "Repeat"; - case 4: return "RepeatMirrored"; - - default: return "Bad"; - } -} - -const char* SamplerFilterModeString(int mode) -{ - switch (mode) { - case 0: return "Nearest"; - case 1: return "Linear"; - - default: return "Bad"; - } -} - -const char* ImageFormatString(int format) -{ - switch (format) { - case 0: return "Unknown"; - - // ES/Desktop float - case 1: return "Rgba32f"; - case 2: return "Rgba16f"; - case 3: return "R32f"; - case 4: return "Rgba8"; - case 5: return "Rgba8Snorm"; - - // Desktop float - case 6: return "Rg32f"; - case 7: return "Rg16f"; - case 8: return "R11fG11fB10f"; - case 9: return "R16f"; - case 10: return "Rgba16"; - case 11: return "Rgb10A2"; - case 12: return "Rg16"; - case 13: return "Rg8"; - case 14: return "R16"; - case 15: return "R8"; - case 16: return "Rgba16Snorm"; - case 17: return "Rg16Snorm"; - case 18: return "Rg8Snorm"; - case 19: return "R16Snorm"; - case 20: return "R8Snorm"; - - // ES/Desktop int - case 21: return "Rgba32i"; - case 22: return "Rgba16i"; - case 23: return "Rgba8i"; - case 24: return "R32i"; - - // Desktop int - case 25: return "Rg32i"; - case 26: return "Rg16i"; - case 27: return "Rg8i"; - case 28: return "R16i"; - case 29: return "R8i"; - - // ES/Desktop uint - case 30: return "Rgba32ui"; - case 31: return "Rgba16ui"; - case 32: return "Rgba8ui"; - case 33: return "R32ui"; - - // Desktop uint - case 34: return "Rgb10a2ui"; - case 35: return "Rg32ui"; - case 36: return "Rg16ui"; - case 37: return "Rg8ui"; - case 38: return "R16ui"; - case 39: return "R8ui"; - case 40: return "R64ui"; - case 41: return "R64i"; - - default: - return "Bad"; - } -} - -const char* ImageChannelOrderString(int format) -{ - switch (format) { - case 0: return "R"; - case 1: return "A"; - case 2: return "RG"; - case 3: return "RA"; - case 4: return "RGB"; - case 5: return "RGBA"; - case 6: return "BGRA"; - case 7: return "ARGB"; - case 8: return "Intensity"; - case 9: return "Luminance"; - case 10: return "Rx"; - case 11: return "RGx"; - case 12: return "RGBx"; - case 13: return "Depth"; - case 14: return "DepthStencil"; - case 15: return "sRGB"; - case 16: return "sRGBx"; - case 17: return "sRGBA"; - case 18: return "sBGRA"; - - default: - return "Bad"; - } -} - -const char* ImageChannelDataTypeString(int type) -{ - switch (type) - { - case 0: return "SnormInt8"; - case 1: return "SnormInt16"; - case 2: return "UnormInt8"; - case 3: return "UnormInt16"; - case 4: return "UnormShort565"; - case 5: return "UnormShort555"; - case 6: return "UnormInt101010"; - case 7: return "SignedInt8"; - case 8: return "SignedInt16"; - case 9: return "SignedInt32"; - case 10: return "UnsignedInt8"; - case 11: return "UnsignedInt16"; - case 12: return "UnsignedInt32"; - case 13: return "HalfFloat"; - case 14: return "Float"; - case 15: return "UnormInt24"; - case 16: return "UnormInt101010_2"; - - default: - return "Bad"; - } -} - -const int ImageOperandsCeiling = 14; - -const char* ImageOperandsString(int format) -{ - switch (format) { - case ImageOperandsBiasShift: return "Bias"; - case ImageOperandsLodShift: return "Lod"; - case ImageOperandsGradShift: return "Grad"; - case ImageOperandsConstOffsetShift: return "ConstOffset"; - case ImageOperandsOffsetShift: return "Offset"; - case ImageOperandsConstOffsetsShift: return "ConstOffsets"; - case ImageOperandsSampleShift: return "Sample"; - case ImageOperandsMinLodShift: return "MinLod"; - case ImageOperandsMakeTexelAvailableKHRShift: return "MakeTexelAvailableKHR"; - case ImageOperandsMakeTexelVisibleKHRShift: return "MakeTexelVisibleKHR"; - case ImageOperandsNonPrivateTexelKHRShift: return "NonPrivateTexelKHR"; - case ImageOperandsVolatileTexelKHRShift: return "VolatileTexelKHR"; - case ImageOperandsSignExtendShift: return "SignExtend"; - case ImageOperandsZeroExtendShift: return "ZeroExtend"; - - case ImageOperandsCeiling: - default: - return "Bad"; - } -} - -const char* FPFastMathString(int mode) -{ - switch (mode) { - case 0: return "NotNaN"; - case 1: return "NotInf"; - case 2: return "NSZ"; - case 3: return "AllowRecip"; - case 4: return "Fast"; - - default: return "Bad"; - } -} - -const char* FPRoundingModeString(int mode) -{ - switch (mode) { - case 0: return "RTE"; - case 1: return "RTZ"; - case 2: return "RTP"; - case 3: return "RTN"; - - default: return "Bad"; - } -} - -const char* LinkageTypeString(int type) -{ - switch (type) { - case 0: return "Export"; - case 1: return "Import"; - - default: return "Bad"; - } -} - -const char* FuncParamAttrString(int attr) -{ - switch (attr) { - case 0: return "Zext"; - case 1: return "Sext"; - case 2: return "ByVal"; - case 3: return "Sret"; - case 4: return "NoAlias"; - case 5: return "NoCapture"; - case 6: return "NoWrite"; - case 7: return "NoReadWrite"; - - default: return "Bad"; - } -} - -const char* AccessQualifierString(int attr) -{ - switch (attr) { - case 0: return "ReadOnly"; - case 1: return "WriteOnly"; - case 2: return "ReadWrite"; - - default: return "Bad"; - } -} - -const int SelectControlCeiling = 2; - -const char* SelectControlString(int cont) -{ - switch (cont) { - case 0: return "Flatten"; - case 1: return "DontFlatten"; - - case SelectControlCeiling: - default: return "Bad"; - } -} - -const int LoopControlCeiling = LoopControlPartialCountShift + 1; - -const char* LoopControlString(int cont) -{ - switch (cont) { - case LoopControlUnrollShift: return "Unroll"; - case LoopControlDontUnrollShift: return "DontUnroll"; - case LoopControlDependencyInfiniteShift: return "DependencyInfinite"; - case LoopControlDependencyLengthShift: return "DependencyLength"; - case LoopControlMinIterationsShift: return "MinIterations"; - case LoopControlMaxIterationsShift: return "MaxIterations"; - case LoopControlIterationMultipleShift: return "IterationMultiple"; - case LoopControlPeelCountShift: return "PeelCount"; - case LoopControlPartialCountShift: return "PartialCount"; - - case LoopControlCeiling: - default: return "Bad"; - } -} - -const int FunctionControlCeiling = 4; - -const char* FunctionControlString(int cont) -{ - switch (cont) { - case 0: return "Inline"; - case 1: return "DontInline"; - case 2: return "Pure"; - case 3: return "Const"; - - case FunctionControlCeiling: - default: return "Bad"; - } -} - -const char* MemorySemanticsString(int mem) -{ - // Note: No bits set (None) means "Relaxed" - switch (mem) { - case 0: return "Bad"; // Note: this is a placeholder for 'Consume' - case 1: return "Acquire"; - case 2: return "Release"; - case 3: return "AcquireRelease"; - case 4: return "SequentiallyConsistent"; - case 5: return "Bad"; // Note: reserved for future expansion - case 6: return "UniformMemory"; - case 7: return "SubgroupMemory"; - case 8: return "WorkgroupMemory"; - case 9: return "CrossWorkgroupMemory"; - case 10: return "AtomicCounterMemory"; - case 11: return "ImageMemory"; - - default: return "Bad"; - } -} - -const int MemoryAccessCeiling = 6; - -const char* MemoryAccessString(int mem) -{ - switch (mem) { - case MemoryAccessVolatileShift: return "Volatile"; - case MemoryAccessAlignedShift: return "Aligned"; - case MemoryAccessNontemporalShift: return "Nontemporal"; - case MemoryAccessMakePointerAvailableKHRShift: return "MakePointerAvailableKHR"; - case MemoryAccessMakePointerVisibleKHRShift: return "MakePointerVisibleKHR"; - case MemoryAccessNonPrivatePointerKHRShift: return "NonPrivatePointerKHR"; - - default: return "Bad"; - } -} - -const int CooperativeMatrixOperandsCeiling = 6; - -const char* CooperativeMatrixOperandsString(int op) -{ - switch (op) { - case CooperativeMatrixOperandsMatrixASignedComponentsKHRShift: return "ASignedComponentsKHR"; - case CooperativeMatrixOperandsMatrixBSignedComponentsKHRShift: return "BSignedComponentsKHR"; - case CooperativeMatrixOperandsMatrixCSignedComponentsKHRShift: return "CSignedComponentsKHR"; - case CooperativeMatrixOperandsMatrixResultSignedComponentsKHRShift: return "ResultSignedComponentsKHR"; - case CooperativeMatrixOperandsSaturatingAccumulationKHRShift: return "SaturatingAccumulationKHR"; - - default: return "Bad"; - } -} - -const char* ScopeString(int mem) -{ - switch (mem) { - case 0: return "CrossDevice"; - case 1: return "Device"; - case 2: return "Workgroup"; - case 3: return "Subgroup"; - case 4: return "Invocation"; - - default: return "Bad"; - } -} - -const char* GroupOperationString(int gop) -{ - - switch (gop) - { - case GroupOperationReduce: return "Reduce"; - case GroupOperationInclusiveScan: return "InclusiveScan"; - case GroupOperationExclusiveScan: return "ExclusiveScan"; - case GroupOperationClusteredReduce: return "ClusteredReduce"; - case GroupOperationPartitionedReduceNV: return "PartitionedReduceNV"; - case GroupOperationPartitionedInclusiveScanNV: return "PartitionedInclusiveScanNV"; - case GroupOperationPartitionedExclusiveScanNV: return "PartitionedExclusiveScanNV"; - - default: return "Bad"; - } -} - -const char* KernelEnqueueFlagsString(int flag) -{ - switch (flag) - { - case 0: return "NoWait"; - case 1: return "WaitKernel"; - case 2: return "WaitWorkGroup"; - - default: return "Bad"; - } -} - -const char* KernelProfilingInfoString(int info) -{ - switch (info) - { - case 0: return "CmdExecTime"; - - default: return "Bad"; - } -} - -const char* CapabilityString(int info) -{ - switch (info) - { - case 0: return "Matrix"; - case 1: return "Shader"; - case 2: return "Geometry"; - case 3: return "Tessellation"; - case 4: return "Addresses"; - case 5: return "Linkage"; - case 6: return "Kernel"; - case 7: return "Vector16"; - case 8: return "Float16Buffer"; - case 9: return "Float16"; - case 10: return "Float64"; - case 11: return "Int64"; - case 12: return "Int64Atomics"; - case 13: return "ImageBasic"; - case 14: return "ImageReadWrite"; - case 15: return "ImageMipmap"; - case 16: return "Bad"; - case 17: return "Pipes"; - case 18: return "Groups"; - case 19: return "DeviceEnqueue"; - case 20: return "LiteralSampler"; - case 21: return "AtomicStorage"; - case 22: return "Int16"; - case 23: return "TessellationPointSize"; - case 24: return "GeometryPointSize"; - case 25: return "ImageGatherExtended"; - case 26: return "Bad"; - case 27: return "StorageImageMultisample"; - case 28: return "UniformBufferArrayDynamicIndexing"; - case 29: return "SampledImageArrayDynamicIndexing"; - case 30: return "StorageBufferArrayDynamicIndexing"; - case 31: return "StorageImageArrayDynamicIndexing"; - case 32: return "ClipDistance"; - case 33: return "CullDistance"; - case 34: return "ImageCubeArray"; - case 35: return "SampleRateShading"; - case 36: return "ImageRect"; - case 37: return "SampledRect"; - case 38: return "GenericPointer"; - case 39: return "Int8"; - case 40: return "InputAttachment"; - case 41: return "SparseResidency"; - case 42: return "MinLod"; - case 43: return "Sampled1D"; - case 44: return "Image1D"; - case 45: return "SampledCubeArray"; - case 46: return "SampledBuffer"; - case 47: return "ImageBuffer"; - case 48: return "ImageMSArray"; - case 49: return "StorageImageExtendedFormats"; - case 50: return "ImageQuery"; - case 51: return "DerivativeControl"; - case 52: return "InterpolationFunction"; - case 53: return "TransformFeedback"; - case 54: return "GeometryStreams"; - case 55: return "StorageImageReadWithoutFormat"; - case 56: return "StorageImageWriteWithoutFormat"; - case 57: return "MultiViewport"; - case 61: return "GroupNonUniform"; - case 62: return "GroupNonUniformVote"; - case 63: return "GroupNonUniformArithmetic"; - case 64: return "GroupNonUniformBallot"; - case 65: return "GroupNonUniformShuffle"; - case 66: return "GroupNonUniformShuffleRelative"; - case 67: return "GroupNonUniformClustered"; - case 68: return "GroupNonUniformQuad"; - - case CapabilitySubgroupBallotKHR: return "SubgroupBallotKHR"; - case CapabilityDrawParameters: return "DrawParameters"; - case CapabilitySubgroupVoteKHR: return "SubgroupVoteKHR"; - - case CapabilityStorageUniformBufferBlock16: return "StorageUniformBufferBlock16"; - case CapabilityStorageUniform16: return "StorageUniform16"; - case CapabilityStoragePushConstant16: return "StoragePushConstant16"; - case CapabilityStorageInputOutput16: return "StorageInputOutput16"; - - case CapabilityStorageBuffer8BitAccess: return "StorageBuffer8BitAccess"; - case CapabilityUniformAndStorageBuffer8BitAccess: return "UniformAndStorageBuffer8BitAccess"; - case CapabilityStoragePushConstant8: return "StoragePushConstant8"; - - case CapabilityDeviceGroup: return "DeviceGroup"; - case CapabilityMultiView: return "MultiView"; - - case CapabilityDenormPreserve: return "DenormPreserve"; - case CapabilityDenormFlushToZero: return "DenormFlushToZero"; - case CapabilitySignedZeroInfNanPreserve: return "SignedZeroInfNanPreserve"; - case CapabilityRoundingModeRTE: return "RoundingModeRTE"; - case CapabilityRoundingModeRTZ: return "RoundingModeRTZ"; - - case CapabilityStencilExportEXT: return "StencilExportEXT"; - - case CapabilityFloat16ImageAMD: return "Float16ImageAMD"; - case CapabilityImageGatherBiasLodAMD: return "ImageGatherBiasLodAMD"; - case CapabilityFragmentMaskAMD: return "FragmentMaskAMD"; - case CapabilityImageReadWriteLodAMD: return "ImageReadWriteLodAMD"; - - case CapabilityAtomicStorageOps: return "AtomicStorageOps"; - - case CapabilitySampleMaskPostDepthCoverage: return "SampleMaskPostDepthCoverage"; - case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV"; - case CapabilityShaderViewportIndexLayerNV: return "ShaderViewportIndexLayerNV"; - case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV"; - case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV"; - case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; - case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV"; - case CapabilityRayTracingNV: return "RayTracingNV"; - case CapabilityRayTracingMotionBlurNV: return "RayTracingMotionBlurNV"; - case CapabilityRayTracingKHR: return "RayTracingKHR"; - case CapabilityRayCullMaskKHR: return "RayCullMaskKHR"; - case CapabilityRayQueryKHR: return "RayQueryKHR"; - case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR"; - case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR"; - case CapabilityRayTracingPositionFetchKHR: return "RayTracingPositionFetchKHR"; - case CapabilityDisplacementMicromapNV: return "DisplacementMicromapNV"; - case CapabilityRayTracingDisplacementMicromapNV: return "CapabilityRayTracingDisplacementMicromapNV"; - case CapabilityRayQueryPositionFetchKHR: return "RayQueryPositionFetchKHR"; - case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV"; - case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV"; - case CapabilityFragmentBarycentricKHR: return "FragmentBarycentricKHR"; - case CapabilityMeshShadingNV: return "MeshShadingNV"; - case CapabilityImageFootprintNV: return "ImageFootprintNV"; - case CapabilityMeshShadingEXT: return "MeshShadingEXT"; -// case CapabilityShadingRateNV: return "ShadingRateNV"; // superseded by FragmentDensityEXT - case CapabilitySampleMaskOverrideCoverageNV: return "SampleMaskOverrideCoverageNV"; - case CapabilityFragmentDensityEXT: return "FragmentDensityEXT"; - - case CapabilityFragmentFullyCoveredEXT: return "FragmentFullyCoveredEXT"; - - case CapabilityShaderNonUniformEXT: return "ShaderNonUniformEXT"; - case CapabilityRuntimeDescriptorArrayEXT: return "RuntimeDescriptorArrayEXT"; - case CapabilityInputAttachmentArrayDynamicIndexingEXT: return "InputAttachmentArrayDynamicIndexingEXT"; - case CapabilityUniformTexelBufferArrayDynamicIndexingEXT: return "UniformTexelBufferArrayDynamicIndexingEXT"; - case CapabilityStorageTexelBufferArrayDynamicIndexingEXT: return "StorageTexelBufferArrayDynamicIndexingEXT"; - case CapabilityUniformBufferArrayNonUniformIndexingEXT: return "UniformBufferArrayNonUniformIndexingEXT"; - case CapabilitySampledImageArrayNonUniformIndexingEXT: return "SampledImageArrayNonUniformIndexingEXT"; - case CapabilityStorageBufferArrayNonUniformIndexingEXT: return "StorageBufferArrayNonUniformIndexingEXT"; - case CapabilityStorageImageArrayNonUniformIndexingEXT: return "StorageImageArrayNonUniformIndexingEXT"; - case CapabilityInputAttachmentArrayNonUniformIndexingEXT: return "InputAttachmentArrayNonUniformIndexingEXT"; - case CapabilityUniformTexelBufferArrayNonUniformIndexingEXT: return "UniformTexelBufferArrayNonUniformIndexingEXT"; - case CapabilityStorageTexelBufferArrayNonUniformIndexingEXT: return "StorageTexelBufferArrayNonUniformIndexingEXT"; - - case CapabilityVulkanMemoryModelKHR: return "VulkanMemoryModelKHR"; - case CapabilityVulkanMemoryModelDeviceScopeKHR: return "VulkanMemoryModelDeviceScopeKHR"; - - case CapabilityPhysicalStorageBufferAddressesEXT: return "PhysicalStorageBufferAddressesEXT"; - - case CapabilityVariablePointers: return "VariablePointers"; - - case CapabilityCooperativeMatrixNV: return "CooperativeMatrixNV"; - case CapabilityCooperativeMatrixKHR: return "CooperativeMatrixKHR"; - case CapabilityShaderSMBuiltinsNV: return "ShaderSMBuiltinsNV"; - - case CapabilityFragmentShaderSampleInterlockEXT: return "CapabilityFragmentShaderSampleInterlockEXT"; - case CapabilityFragmentShaderPixelInterlockEXT: return "CapabilityFragmentShaderPixelInterlockEXT"; - case CapabilityFragmentShaderShadingRateInterlockEXT: return "CapabilityFragmentShaderShadingRateInterlockEXT"; - - case CapabilityTileImageColorReadAccessEXT: return "TileImageColorReadAccessEXT"; - case CapabilityTileImageDepthReadAccessEXT: return "TileImageDepthReadAccessEXT"; - case CapabilityTileImageStencilReadAccessEXT: return "TileImageStencilReadAccessEXT"; - - case CapabilityFragmentShadingRateKHR: return "FragmentShadingRateKHR"; - - case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT"; - case CapabilityShaderClockKHR: return "ShaderClockKHR"; - case CapabilityInt64ImageEXT: return "Int64ImageEXT"; - - case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL"; - - case CapabilityAtomicFloat16AddEXT: return "AtomicFloat16AddEXT"; - case CapabilityAtomicFloat32AddEXT: return "AtomicFloat32AddEXT"; - case CapabilityAtomicFloat64AddEXT: return "AtomicFloat64AddEXT"; - case CapabilityAtomicFloat16MinMaxEXT: return "AtomicFloat16MinMaxEXT"; - case CapabilityAtomicFloat32MinMaxEXT: return "AtomicFloat32MinMaxEXT"; - case CapabilityAtomicFloat64MinMaxEXT: return "AtomicFloat64MinMaxEXT"; - - case CapabilityWorkgroupMemoryExplicitLayoutKHR: return "CapabilityWorkgroupMemoryExplicitLayoutKHR"; - case CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR"; - case CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR: return "CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR"; - case CapabilityCoreBuiltinsARM: return "CoreBuiltinsARM"; - - case CapabilityShaderInvocationReorderNV: return "ShaderInvocationReorderNV"; - - case CapabilityTextureSampleWeightedQCOM: return "TextureSampleWeightedQCOM"; - case CapabilityTextureBoxFilterQCOM: return "TextureBoxFilterQCOM"; - case CapabilityTextureBlockMatchQCOM: return "TextureBlockMatchQCOM"; - - default: return "Bad"; - } -} - -const char* OpcodeString(int op) -{ - switch (op) { - case 0: return "OpNop"; - case 1: return "OpUndef"; - case 2: return "OpSourceContinued"; - case 3: return "OpSource"; - case 4: return "OpSourceExtension"; - case 5: return "OpName"; - case 6: return "OpMemberName"; - case 7: return "OpString"; - case 8: return "OpLine"; - case 9: return "Bad"; - case 10: return "OpExtension"; - case 11: return "OpExtInstImport"; - case 12: return "OpExtInst"; - case 13: return "Bad"; - case 14: return "OpMemoryModel"; - case 15: return "OpEntryPoint"; - case 16: return "OpExecutionMode"; - case 17: return "OpCapability"; - case 18: return "Bad"; - case 19: return "OpTypeVoid"; - case 20: return "OpTypeBool"; - case 21: return "OpTypeInt"; - case 22: return "OpTypeFloat"; - case 23: return "OpTypeVector"; - case 24: return "OpTypeMatrix"; - case 25: return "OpTypeImage"; - case 26: return "OpTypeSampler"; - case 27: return "OpTypeSampledImage"; - case 28: return "OpTypeArray"; - case 29: return "OpTypeRuntimeArray"; - case 30: return "OpTypeStruct"; - case 31: return "OpTypeOpaque"; - case 32: return "OpTypePointer"; - case 33: return "OpTypeFunction"; - case 34: return "OpTypeEvent"; - case 35: return "OpTypeDeviceEvent"; - case 36: return "OpTypeReserveId"; - case 37: return "OpTypeQueue"; - case 38: return "OpTypePipe"; - case 39: return "OpTypeForwardPointer"; - case 40: return "Bad"; - case 41: return "OpConstantTrue"; - case 42: return "OpConstantFalse"; - case 43: return "OpConstant"; - case 44: return "OpConstantComposite"; - case 45: return "OpConstantSampler"; - case 46: return "OpConstantNull"; - case 47: return "Bad"; - case 48: return "OpSpecConstantTrue"; - case 49: return "OpSpecConstantFalse"; - case 50: return "OpSpecConstant"; - case 51: return "OpSpecConstantComposite"; - case 52: return "OpSpecConstantOp"; - case 53: return "Bad"; - case 54: return "OpFunction"; - case 55: return "OpFunctionParameter"; - case 56: return "OpFunctionEnd"; - case 57: return "OpFunctionCall"; - case 58: return "Bad"; - case 59: return "OpVariable"; - case 60: return "OpImageTexelPointer"; - case 61: return "OpLoad"; - case 62: return "OpStore"; - case 63: return "OpCopyMemory"; - case 64: return "OpCopyMemorySized"; - case 65: return "OpAccessChain"; - case 66: return "OpInBoundsAccessChain"; - case 67: return "OpPtrAccessChain"; - case 68: return "OpArrayLength"; - case 69: return "OpGenericPtrMemSemantics"; - case 70: return "OpInBoundsPtrAccessChain"; - case 71: return "OpDecorate"; - case 72: return "OpMemberDecorate"; - case 73: return "OpDecorationGroup"; - case 74: return "OpGroupDecorate"; - case 75: return "OpGroupMemberDecorate"; - case 76: return "Bad"; - case 77: return "OpVectorExtractDynamic"; - case 78: return "OpVectorInsertDynamic"; - case 79: return "OpVectorShuffle"; - case 80: return "OpCompositeConstruct"; - case 81: return "OpCompositeExtract"; - case 82: return "OpCompositeInsert"; - case 83: return "OpCopyObject"; - case 84: return "OpTranspose"; - case OpCopyLogical: return "OpCopyLogical"; - case 85: return "Bad"; - case 86: return "OpSampledImage"; - case 87: return "OpImageSampleImplicitLod"; - case 88: return "OpImageSampleExplicitLod"; - case 89: return "OpImageSampleDrefImplicitLod"; - case 90: return "OpImageSampleDrefExplicitLod"; - case 91: return "OpImageSampleProjImplicitLod"; - case 92: return "OpImageSampleProjExplicitLod"; - case 93: return "OpImageSampleProjDrefImplicitLod"; - case 94: return "OpImageSampleProjDrefExplicitLod"; - case 95: return "OpImageFetch"; - case 96: return "OpImageGather"; - case 97: return "OpImageDrefGather"; - case 98: return "OpImageRead"; - case 99: return "OpImageWrite"; - case 100: return "OpImage"; - case 101: return "OpImageQueryFormat"; - case 102: return "OpImageQueryOrder"; - case 103: return "OpImageQuerySizeLod"; - case 104: return "OpImageQuerySize"; - case 105: return "OpImageQueryLod"; - case 106: return "OpImageQueryLevels"; - case 107: return "OpImageQuerySamples"; - case 108: return "Bad"; - case 109: return "OpConvertFToU"; - case 110: return "OpConvertFToS"; - case 111: return "OpConvertSToF"; - case 112: return "OpConvertUToF"; - case 113: return "OpUConvert"; - case 114: return "OpSConvert"; - case 115: return "OpFConvert"; - case 116: return "OpQuantizeToF16"; - case 117: return "OpConvertPtrToU"; - case 118: return "OpSatConvertSToU"; - case 119: return "OpSatConvertUToS"; - case 120: return "OpConvertUToPtr"; - case 121: return "OpPtrCastToGeneric"; - case 122: return "OpGenericCastToPtr"; - case 123: return "OpGenericCastToPtrExplicit"; - case 124: return "OpBitcast"; - case 125: return "Bad"; - case 126: return "OpSNegate"; - case 127: return "OpFNegate"; - case 128: return "OpIAdd"; - case 129: return "OpFAdd"; - case 130: return "OpISub"; - case 131: return "OpFSub"; - case 132: return "OpIMul"; - case 133: return "OpFMul"; - case 134: return "OpUDiv"; - case 135: return "OpSDiv"; - case 136: return "OpFDiv"; - case 137: return "OpUMod"; - case 138: return "OpSRem"; - case 139: return "OpSMod"; - case 140: return "OpFRem"; - case 141: return "OpFMod"; - case 142: return "OpVectorTimesScalar"; - case 143: return "OpMatrixTimesScalar"; - case 144: return "OpVectorTimesMatrix"; - case 145: return "OpMatrixTimesVector"; - case 146: return "OpMatrixTimesMatrix"; - case 147: return "OpOuterProduct"; - case 148: return "OpDot"; - case 149: return "OpIAddCarry"; - case 150: return "OpISubBorrow"; - case 151: return "OpUMulExtended"; - case 152: return "OpSMulExtended"; - case 153: return "Bad"; - case 154: return "OpAny"; - case 155: return "OpAll"; - case 156: return "OpIsNan"; - case 157: return "OpIsInf"; - case 158: return "OpIsFinite"; - case 159: return "OpIsNormal"; - case 160: return "OpSignBitSet"; - case 161: return "OpLessOrGreater"; - case 162: return "OpOrdered"; - case 163: return "OpUnordered"; - case 164: return "OpLogicalEqual"; - case 165: return "OpLogicalNotEqual"; - case 166: return "OpLogicalOr"; - case 167: return "OpLogicalAnd"; - case 168: return "OpLogicalNot"; - case 169: return "OpSelect"; - case 170: return "OpIEqual"; - case 171: return "OpINotEqual"; - case 172: return "OpUGreaterThan"; - case 173: return "OpSGreaterThan"; - case 174: return "OpUGreaterThanEqual"; - case 175: return "OpSGreaterThanEqual"; - case 176: return "OpULessThan"; - case 177: return "OpSLessThan"; - case 178: return "OpULessThanEqual"; - case 179: return "OpSLessThanEqual"; - case 180: return "OpFOrdEqual"; - case 181: return "OpFUnordEqual"; - case 182: return "OpFOrdNotEqual"; - case 183: return "OpFUnordNotEqual"; - case 184: return "OpFOrdLessThan"; - case 185: return "OpFUnordLessThan"; - case 186: return "OpFOrdGreaterThan"; - case 187: return "OpFUnordGreaterThan"; - case 188: return "OpFOrdLessThanEqual"; - case 189: return "OpFUnordLessThanEqual"; - case 190: return "OpFOrdGreaterThanEqual"; - case 191: return "OpFUnordGreaterThanEqual"; - case 192: return "Bad"; - case 193: return "Bad"; - case 194: return "OpShiftRightLogical"; - case 195: return "OpShiftRightArithmetic"; - case 196: return "OpShiftLeftLogical"; - case 197: return "OpBitwiseOr"; - case 198: return "OpBitwiseXor"; - case 199: return "OpBitwiseAnd"; - case 200: return "OpNot"; - case 201: return "OpBitFieldInsert"; - case 202: return "OpBitFieldSExtract"; - case 203: return "OpBitFieldUExtract"; - case 204: return "OpBitReverse"; - case 205: return "OpBitCount"; - case 206: return "Bad"; - case 207: return "OpDPdx"; - case 208: return "OpDPdy"; - case 209: return "OpFwidth"; - case 210: return "OpDPdxFine"; - case 211: return "OpDPdyFine"; - case 212: return "OpFwidthFine"; - case 213: return "OpDPdxCoarse"; - case 214: return "OpDPdyCoarse"; - case 215: return "OpFwidthCoarse"; - case 216: return "Bad"; - case 217: return "Bad"; - case 218: return "OpEmitVertex"; - case 219: return "OpEndPrimitive"; - case 220: return "OpEmitStreamVertex"; - case 221: return "OpEndStreamPrimitive"; - case 222: return "Bad"; - case 223: return "Bad"; - case 224: return "OpControlBarrier"; - case 225: return "OpMemoryBarrier"; - case 226: return "Bad"; - case 227: return "OpAtomicLoad"; - case 228: return "OpAtomicStore"; - case 229: return "OpAtomicExchange"; - case 230: return "OpAtomicCompareExchange"; - case 231: return "OpAtomicCompareExchangeWeak"; - case 232: return "OpAtomicIIncrement"; - case 233: return "OpAtomicIDecrement"; - case 234: return "OpAtomicIAdd"; - case 235: return "OpAtomicISub"; - case 236: return "OpAtomicSMin"; - case 237: return "OpAtomicUMin"; - case 238: return "OpAtomicSMax"; - case 239: return "OpAtomicUMax"; - case 240: return "OpAtomicAnd"; - case 241: return "OpAtomicOr"; - case 242: return "OpAtomicXor"; - case 243: return "Bad"; - case 244: return "Bad"; - case 245: return "OpPhi"; - case 246: return "OpLoopMerge"; - case 247: return "OpSelectionMerge"; - case 248: return "OpLabel"; - case 249: return "OpBranch"; - case 250: return "OpBranchConditional"; - case 251: return "OpSwitch"; - case 252: return "OpKill"; - case 253: return "OpReturn"; - case 254: return "OpReturnValue"; - case 255: return "OpUnreachable"; - case 256: return "OpLifetimeStart"; - case 257: return "OpLifetimeStop"; - case 258: return "Bad"; - case 259: return "OpGroupAsyncCopy"; - case 260: return "OpGroupWaitEvents"; - case 261: return "OpGroupAll"; - case 262: return "OpGroupAny"; - case 263: return "OpGroupBroadcast"; - case 264: return "OpGroupIAdd"; - case 265: return "OpGroupFAdd"; - case 266: return "OpGroupFMin"; - case 267: return "OpGroupUMin"; - case 268: return "OpGroupSMin"; - case 269: return "OpGroupFMax"; - case 270: return "OpGroupUMax"; - case 271: return "OpGroupSMax"; - case 272: return "Bad"; - case 273: return "Bad"; - case 274: return "OpReadPipe"; - case 275: return "OpWritePipe"; - case 276: return "OpReservedReadPipe"; - case 277: return "OpReservedWritePipe"; - case 278: return "OpReserveReadPipePackets"; - case 279: return "OpReserveWritePipePackets"; - case 280: return "OpCommitReadPipe"; - case 281: return "OpCommitWritePipe"; - case 282: return "OpIsValidReserveId"; - case 283: return "OpGetNumPipePackets"; - case 284: return "OpGetMaxPipePackets"; - case 285: return "OpGroupReserveReadPipePackets"; - case 286: return "OpGroupReserveWritePipePackets"; - case 287: return "OpGroupCommitReadPipe"; - case 288: return "OpGroupCommitWritePipe"; - case 289: return "Bad"; - case 290: return "Bad"; - case 291: return "OpEnqueueMarker"; - case 292: return "OpEnqueueKernel"; - case 293: return "OpGetKernelNDrangeSubGroupCount"; - case 294: return "OpGetKernelNDrangeMaxSubGroupSize"; - case 295: return "OpGetKernelWorkGroupSize"; - case 296: return "OpGetKernelPreferredWorkGroupSizeMultiple"; - case 297: return "OpRetainEvent"; - case 298: return "OpReleaseEvent"; - case 299: return "OpCreateUserEvent"; - case 300: return "OpIsValidEvent"; - case 301: return "OpSetUserEventStatus"; - case 302: return "OpCaptureEventProfilingInfo"; - case 303: return "OpGetDefaultQueue"; - case 304: return "OpBuildNDRange"; - case 305: return "OpImageSparseSampleImplicitLod"; - case 306: return "OpImageSparseSampleExplicitLod"; - case 307: return "OpImageSparseSampleDrefImplicitLod"; - case 308: return "OpImageSparseSampleDrefExplicitLod"; - case 309: return "OpImageSparseSampleProjImplicitLod"; - case 310: return "OpImageSparseSampleProjExplicitLod"; - case 311: return "OpImageSparseSampleProjDrefImplicitLod"; - case 312: return "OpImageSparseSampleProjDrefExplicitLod"; - case 313: return "OpImageSparseFetch"; - case 314: return "OpImageSparseGather"; - case 315: return "OpImageSparseDrefGather"; - case 316: return "OpImageSparseTexelsResident"; - case 317: return "OpNoLine"; - case 318: return "OpAtomicFlagTestAndSet"; - case 319: return "OpAtomicFlagClear"; - case 320: return "OpImageSparseRead"; - - case OpModuleProcessed: return "OpModuleProcessed"; - case OpExecutionModeId: return "OpExecutionModeId"; - case OpDecorateId: return "OpDecorateId"; - - case 333: return "OpGroupNonUniformElect"; - case 334: return "OpGroupNonUniformAll"; - case 335: return "OpGroupNonUniformAny"; - case 336: return "OpGroupNonUniformAllEqual"; - case 337: return "OpGroupNonUniformBroadcast"; - case 338: return "OpGroupNonUniformBroadcastFirst"; - case 339: return "OpGroupNonUniformBallot"; - case 340: return "OpGroupNonUniformInverseBallot"; - case 341: return "OpGroupNonUniformBallotBitExtract"; - case 342: return "OpGroupNonUniformBallotBitCount"; - case 343: return "OpGroupNonUniformBallotFindLSB"; - case 344: return "OpGroupNonUniformBallotFindMSB"; - case 345: return "OpGroupNonUniformShuffle"; - case 346: return "OpGroupNonUniformShuffleXor"; - case 347: return "OpGroupNonUniformShuffleUp"; - case 348: return "OpGroupNonUniformShuffleDown"; - case 349: return "OpGroupNonUniformIAdd"; - case 350: return "OpGroupNonUniformFAdd"; - case 351: return "OpGroupNonUniformIMul"; - case 352: return "OpGroupNonUniformFMul"; - case 353: return "OpGroupNonUniformSMin"; - case 354: return "OpGroupNonUniformUMin"; - case 355: return "OpGroupNonUniformFMin"; - case 356: return "OpGroupNonUniformSMax"; - case 357: return "OpGroupNonUniformUMax"; - case 358: return "OpGroupNonUniformFMax"; - case 359: return "OpGroupNonUniformBitwiseAnd"; - case 360: return "OpGroupNonUniformBitwiseOr"; - case 361: return "OpGroupNonUniformBitwiseXor"; - case 362: return "OpGroupNonUniformLogicalAnd"; - case 363: return "OpGroupNonUniformLogicalOr"; - case 364: return "OpGroupNonUniformLogicalXor"; - case 365: return "OpGroupNonUniformQuadBroadcast"; - case 366: return "OpGroupNonUniformQuadSwap"; - - case OpTerminateInvocation: return "OpTerminateInvocation"; - - case 4421: return "OpSubgroupBallotKHR"; - case 4422: return "OpSubgroupFirstInvocationKHR"; - case 4428: return "OpSubgroupAllKHR"; - case 4429: return "OpSubgroupAnyKHR"; - case 4430: return "OpSubgroupAllEqualKHR"; - case 4432: return "OpSubgroupReadInvocationKHR"; - - case OpAtomicFAddEXT: return "OpAtomicFAddEXT"; - case OpAtomicFMinEXT: return "OpAtomicFMinEXT"; - case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT"; - - case 5000: return "OpGroupIAddNonUniformAMD"; - case 5001: return "OpGroupFAddNonUniformAMD"; - case 5002: return "OpGroupFMinNonUniformAMD"; - case 5003: return "OpGroupUMinNonUniformAMD"; - case 5004: return "OpGroupSMinNonUniformAMD"; - case 5005: return "OpGroupFMaxNonUniformAMD"; - case 5006: return "OpGroupUMaxNonUniformAMD"; - case 5007: return "OpGroupSMaxNonUniformAMD"; - - case 5011: return "OpFragmentMaskFetchAMD"; - case 5012: return "OpFragmentFetchAMD"; - - case OpReadClockKHR: return "OpReadClockKHR"; - - case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE"; - case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE"; - - case OpReportIntersectionKHR: return "OpReportIntersectionKHR"; - case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV"; - case OpIgnoreIntersectionKHR: return "OpIgnoreIntersectionKHR"; - case OpTerminateRayNV: return "OpTerminateRayNV"; - case OpTerminateRayKHR: return "OpTerminateRayKHR"; - case OpTraceNV: return "OpTraceNV"; - case OpTraceRayMotionNV: return "OpTraceRayMotionNV"; - case OpTraceRayKHR: return "OpTraceRayKHR"; - case OpTypeAccelerationStructureKHR: return "OpTypeAccelerationStructureKHR"; - case OpExecuteCallableNV: return "OpExecuteCallableNV"; - case OpExecuteCallableKHR: return "OpExecuteCallableKHR"; - case OpConvertUToAccelerationStructureKHR: return "OpConvertUToAccelerationStructureKHR"; - - case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV"; - case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV"; - case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV"; - case OpEmitMeshTasksEXT: return "OpEmitMeshTasksEXT"; - case OpSetMeshOutputsEXT: return "OpSetMeshOutputsEXT"; - - case OpTypeRayQueryKHR: return "OpTypeRayQueryKHR"; - case OpRayQueryInitializeKHR: return "OpRayQueryInitializeKHR"; - case OpRayQueryTerminateKHR: return "OpRayQueryTerminateKHR"; - case OpRayQueryGenerateIntersectionKHR: return "OpRayQueryGenerateIntersectionKHR"; - case OpRayQueryConfirmIntersectionKHR: return "OpRayQueryConfirmIntersectionKHR"; - case OpRayQueryProceedKHR: return "OpRayQueryProceedKHR"; - case OpRayQueryGetIntersectionTypeKHR: return "OpRayQueryGetIntersectionTypeKHR"; - case OpRayQueryGetRayTMinKHR: return "OpRayQueryGetRayTMinKHR"; - case OpRayQueryGetRayFlagsKHR: return "OpRayQueryGetRayFlagsKHR"; - case OpRayQueryGetIntersectionTKHR: return "OpRayQueryGetIntersectionTKHR"; - case OpRayQueryGetIntersectionInstanceCustomIndexKHR: return "OpRayQueryGetIntersectionInstanceCustomIndexKHR"; - case OpRayQueryGetIntersectionInstanceIdKHR: return "OpRayQueryGetIntersectionInstanceIdKHR"; - case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: return "OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR"; - case OpRayQueryGetIntersectionGeometryIndexKHR: return "OpRayQueryGetIntersectionGeometryIndexKHR"; - case OpRayQueryGetIntersectionPrimitiveIndexKHR: return "OpRayQueryGetIntersectionPrimitiveIndexKHR"; - case OpRayQueryGetIntersectionBarycentricsKHR: return "OpRayQueryGetIntersectionBarycentricsKHR"; - case OpRayQueryGetIntersectionFrontFaceKHR: return "OpRayQueryGetIntersectionFrontFaceKHR"; - case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: return "OpRayQueryGetIntersectionCandidateAABBOpaqueKHR"; - case OpRayQueryGetIntersectionObjectRayDirectionKHR: return "OpRayQueryGetIntersectionObjectRayDirectionKHR"; - case OpRayQueryGetIntersectionObjectRayOriginKHR: return "OpRayQueryGetIntersectionObjectRayOriginKHR"; - case OpRayQueryGetWorldRayDirectionKHR: return "OpRayQueryGetWorldRayDirectionKHR"; - case OpRayQueryGetWorldRayOriginKHR: return "OpRayQueryGetWorldRayOriginKHR"; - case OpRayQueryGetIntersectionObjectToWorldKHR: return "OpRayQueryGetIntersectionObjectToWorldKHR"; - case OpRayQueryGetIntersectionWorldToObjectKHR: return "OpRayQueryGetIntersectionWorldToObjectKHR"; - case OpRayQueryGetIntersectionTriangleVertexPositionsKHR: return "OpRayQueryGetIntersectionTriangleVertexPositionsKHR"; - - case OpTypeCooperativeMatrixNV: return "OpTypeCooperativeMatrixNV"; - case OpCooperativeMatrixLoadNV: return "OpCooperativeMatrixLoadNV"; - case OpCooperativeMatrixStoreNV: return "OpCooperativeMatrixStoreNV"; - case OpCooperativeMatrixMulAddNV: return "OpCooperativeMatrixMulAddNV"; - case OpCooperativeMatrixLengthNV: return "OpCooperativeMatrixLengthNV"; - case OpTypeCooperativeMatrixKHR: return "OpTypeCooperativeMatrixKHR"; - case OpCooperativeMatrixLoadKHR: return "OpCooperativeMatrixLoadKHR"; - case OpCooperativeMatrixStoreKHR: return "OpCooperativeMatrixStoreKHR"; - case OpCooperativeMatrixMulAddKHR: return "OpCooperativeMatrixMulAddKHR"; - case OpCooperativeMatrixLengthKHR: return "OpCooperativeMatrixLengthKHR"; - case OpDemoteToHelperInvocationEXT: return "OpDemoteToHelperInvocationEXT"; - case OpIsHelperInvocationEXT: return "OpIsHelperInvocationEXT"; - - case OpBeginInvocationInterlockEXT: return "OpBeginInvocationInterlockEXT"; - case OpEndInvocationInterlockEXT: return "OpEndInvocationInterlockEXT"; - - case OpTypeHitObjectNV: return "OpTypeHitObjectNV"; - case OpHitObjectTraceRayNV: return "OpHitObjectTraceRayNV"; - case OpHitObjectTraceRayMotionNV: return "OpHitObjectTraceRayMotionNV"; - case OpHitObjectRecordHitNV: return "OpHitObjectRecordHitNV"; - case OpHitObjectRecordHitMotionNV: return "OpHitObjectRecordHitMotionNV"; - case OpHitObjectRecordHitWithIndexNV: return "OpHitObjectRecordHitWithIndexNV"; - case OpHitObjectRecordHitWithIndexMotionNV: return "OpHitObjectRecordHitWithIndexMotionNV"; - case OpHitObjectRecordMissNV: return "OpHitObjectRecordMissNV"; - case OpHitObjectRecordMissMotionNV: return "OpHitObjectRecordMissMotionNV"; - case OpHitObjectRecordEmptyNV: return "OpHitObjectRecordEmptyNV"; - case OpHitObjectExecuteShaderNV: return "OpHitObjectExecuteShaderNV"; - case OpReorderThreadWithHintNV: return "OpReorderThreadWithHintNV"; - case OpReorderThreadWithHitObjectNV: return "OpReorderThreadWithHitObjectNV"; - case OpHitObjectGetCurrentTimeNV: return "OpHitObjectGetCurrentTimeNV"; - case OpHitObjectGetAttributesNV: return "OpHitObjectGetAttributesNV"; - case OpHitObjectGetHitKindNV: return "OpHitObjectGetFrontFaceNV"; - case OpHitObjectGetPrimitiveIndexNV: return "OpHitObjectGetPrimitiveIndexNV"; - case OpHitObjectGetGeometryIndexNV: return "OpHitObjectGetGeometryIndexNV"; - case OpHitObjectGetInstanceIdNV: return "OpHitObjectGetInstanceIdNV"; - case OpHitObjectGetInstanceCustomIndexNV: return "OpHitObjectGetInstanceCustomIndexNV"; - case OpHitObjectGetObjectRayDirectionNV: return "OpHitObjectGetObjectRayDirectionNV"; - case OpHitObjectGetObjectRayOriginNV: return "OpHitObjectGetObjectRayOriginNV"; - case OpHitObjectGetWorldRayDirectionNV: return "OpHitObjectGetWorldRayDirectionNV"; - case OpHitObjectGetWorldRayOriginNV: return "OpHitObjectGetWorldRayOriginNV"; - case OpHitObjectGetWorldToObjectNV: return "OpHitObjectGetWorldToObjectNV"; - case OpHitObjectGetObjectToWorldNV: return "OpHitObjectGetObjectToWorldNV"; - case OpHitObjectGetRayTMaxNV: return "OpHitObjectGetRayTMaxNV"; - case OpHitObjectGetRayTMinNV: return "OpHitObjectGetRayTMinNV"; - case OpHitObjectIsEmptyNV: return "OpHitObjectIsEmptyNV"; - case OpHitObjectIsHitNV: return "OpHitObjectIsHitNV"; - case OpHitObjectIsMissNV: return "OpHitObjectIsMissNV"; - case OpHitObjectGetShaderBindingTableRecordIndexNV: return "OpHitObjectGetShaderBindingTableRecordIndexNV"; - case OpHitObjectGetShaderRecordBufferHandleNV: return "OpHitObjectGetShaderRecordBufferHandleNV"; - - case OpFetchMicroTriangleVertexBarycentricNV: return "OpFetchMicroTriangleVertexBarycentricNV"; - case OpFetchMicroTriangleVertexPositionNV: return "OpFetchMicroTriangleVertexPositionNV"; - - case OpColorAttachmentReadEXT: return "OpColorAttachmentReadEXT"; - case OpDepthAttachmentReadEXT: return "OpDepthAttachmentReadEXT"; - case OpStencilAttachmentReadEXT: return "OpStencilAttachmentReadEXT"; - - case OpImageSampleWeightedQCOM: return "OpImageSampleWeightedQCOM"; - case OpImageBoxFilterQCOM: return "OpImageBoxFilterQCOM"; - case OpImageBlockMatchSADQCOM: return "OpImageBlockMatchSADQCOM"; - case OpImageBlockMatchSSDQCOM: return "OpImageBlockMatchSSDQCOM"; - - default: - return "Bad"; - } -} - -// The set of objects that hold all the instruction/operand -// parameterization information. -InstructionParameters InstructionDesc[OpCodeMask + 1]; -OperandParameters ExecutionModeOperands[ExecutionModeCeiling]; -OperandParameters DecorationOperands[DecorationCeiling]; - -EnumDefinition OperandClassParams[OperandCount]; -EnumParameters ExecutionModeParams[ExecutionModeCeiling]; -EnumParameters ImageOperandsParams[ImageOperandsCeiling]; -EnumParameters DecorationParams[DecorationCeiling]; -EnumParameters LoopControlParams[FunctionControlCeiling]; -EnumParameters SelectionControlParams[SelectControlCeiling]; -EnumParameters FunctionControlParams[FunctionControlCeiling]; -EnumParameters MemoryAccessParams[MemoryAccessCeiling]; -EnumParameters CooperativeMatrixOperandsParams[CooperativeMatrixOperandsCeiling]; - -// Set up all the parameterizing descriptions of the opcodes, operands, etc. -void Parameterize() -{ - // only do this once. - static std::once_flag initialized; - std::call_once(initialized, [](){ - - // Exceptions to having a result and a resulting type . - // (Everything is initialized to have both). - - InstructionDesc[OpNop].setResultAndType(false, false); - InstructionDesc[OpSource].setResultAndType(false, false); - InstructionDesc[OpSourceContinued].setResultAndType(false, false); - InstructionDesc[OpSourceExtension].setResultAndType(false, false); - InstructionDesc[OpExtension].setResultAndType(false, false); - InstructionDesc[OpExtInstImport].setResultAndType(true, false); - InstructionDesc[OpCapability].setResultAndType(false, false); - InstructionDesc[OpMemoryModel].setResultAndType(false, false); - InstructionDesc[OpEntryPoint].setResultAndType(false, false); - InstructionDesc[OpExecutionMode].setResultAndType(false, false); - InstructionDesc[OpExecutionModeId].setResultAndType(false, false); - InstructionDesc[OpTypeVoid].setResultAndType(true, false); - InstructionDesc[OpTypeBool].setResultAndType(true, false); - InstructionDesc[OpTypeInt].setResultAndType(true, false); - InstructionDesc[OpTypeFloat].setResultAndType(true, false); - InstructionDesc[OpTypeVector].setResultAndType(true, false); - InstructionDesc[OpTypeMatrix].setResultAndType(true, false); - InstructionDesc[OpTypeImage].setResultAndType(true, false); - InstructionDesc[OpTypeSampler].setResultAndType(true, false); - InstructionDesc[OpTypeSampledImage].setResultAndType(true, false); - InstructionDesc[OpTypeArray].setResultAndType(true, false); - InstructionDesc[OpTypeRuntimeArray].setResultAndType(true, false); - InstructionDesc[OpTypeStruct].setResultAndType(true, false); - InstructionDesc[OpTypeOpaque].setResultAndType(true, false); - InstructionDesc[OpTypePointer].setResultAndType(true, false); - InstructionDesc[OpTypeForwardPointer].setResultAndType(false, false); - InstructionDesc[OpTypeFunction].setResultAndType(true, false); - InstructionDesc[OpTypeEvent].setResultAndType(true, false); - InstructionDesc[OpTypeDeviceEvent].setResultAndType(true, false); - InstructionDesc[OpTypeReserveId].setResultAndType(true, false); - InstructionDesc[OpTypeQueue].setResultAndType(true, false); - InstructionDesc[OpTypePipe].setResultAndType(true, false); - InstructionDesc[OpFunctionEnd].setResultAndType(false, false); - InstructionDesc[OpStore].setResultAndType(false, false); - InstructionDesc[OpImageWrite].setResultAndType(false, false); - InstructionDesc[OpDecorationGroup].setResultAndType(true, false); - InstructionDesc[OpDecorate].setResultAndType(false, false); - InstructionDesc[OpDecorateId].setResultAndType(false, false); - InstructionDesc[OpDecorateStringGOOGLE].setResultAndType(false, false); - InstructionDesc[OpMemberDecorate].setResultAndType(false, false); - InstructionDesc[OpMemberDecorateStringGOOGLE].setResultAndType(false, false); - InstructionDesc[OpGroupDecorate].setResultAndType(false, false); - InstructionDesc[OpGroupMemberDecorate].setResultAndType(false, false); - InstructionDesc[OpName].setResultAndType(false, false); - InstructionDesc[OpMemberName].setResultAndType(false, false); - InstructionDesc[OpString].setResultAndType(true, false); - InstructionDesc[OpLine].setResultAndType(false, false); - InstructionDesc[OpNoLine].setResultAndType(false, false); - InstructionDesc[OpCopyMemory].setResultAndType(false, false); - InstructionDesc[OpCopyMemorySized].setResultAndType(false, false); - InstructionDesc[OpEmitVertex].setResultAndType(false, false); - InstructionDesc[OpEndPrimitive].setResultAndType(false, false); - InstructionDesc[OpEmitStreamVertex].setResultAndType(false, false); - InstructionDesc[OpEndStreamPrimitive].setResultAndType(false, false); - InstructionDesc[OpControlBarrier].setResultAndType(false, false); - InstructionDesc[OpMemoryBarrier].setResultAndType(false, false); - InstructionDesc[OpAtomicStore].setResultAndType(false, false); - InstructionDesc[OpLoopMerge].setResultAndType(false, false); - InstructionDesc[OpSelectionMerge].setResultAndType(false, false); - InstructionDesc[OpLabel].setResultAndType(true, false); - InstructionDesc[OpBranch].setResultAndType(false, false); - InstructionDesc[OpBranchConditional].setResultAndType(false, false); - InstructionDesc[OpSwitch].setResultAndType(false, false); - InstructionDesc[OpKill].setResultAndType(false, false); - InstructionDesc[OpTerminateInvocation].setResultAndType(false, false); - InstructionDesc[OpReturn].setResultAndType(false, false); - InstructionDesc[OpReturnValue].setResultAndType(false, false); - InstructionDesc[OpUnreachable].setResultAndType(false, false); - InstructionDesc[OpLifetimeStart].setResultAndType(false, false); - InstructionDesc[OpLifetimeStop].setResultAndType(false, false); - InstructionDesc[OpCommitReadPipe].setResultAndType(false, false); - InstructionDesc[OpCommitWritePipe].setResultAndType(false, false); - InstructionDesc[OpGroupCommitWritePipe].setResultAndType(false, false); - InstructionDesc[OpGroupCommitReadPipe].setResultAndType(false, false); - InstructionDesc[OpCaptureEventProfilingInfo].setResultAndType(false, false); - InstructionDesc[OpSetUserEventStatus].setResultAndType(false, false); - InstructionDesc[OpRetainEvent].setResultAndType(false, false); - InstructionDesc[OpReleaseEvent].setResultAndType(false, false); - InstructionDesc[OpGroupWaitEvents].setResultAndType(false, false); - InstructionDesc[OpAtomicFlagClear].setResultAndType(false, false); - InstructionDesc[OpModuleProcessed].setResultAndType(false, false); - InstructionDesc[OpTypeCooperativeMatrixNV].setResultAndType(true, false); - InstructionDesc[OpCooperativeMatrixStoreNV].setResultAndType(false, false); - InstructionDesc[OpTypeCooperativeMatrixKHR].setResultAndType(true, false); - InstructionDesc[OpCooperativeMatrixStoreKHR].setResultAndType(false, false); - InstructionDesc[OpBeginInvocationInterlockEXT].setResultAndType(false, false); - InstructionDesc[OpEndInvocationInterlockEXT].setResultAndType(false, false); - - // Specific additional context-dependent operands - - ExecutionModeOperands[ExecutionModeInvocations].push(OperandLiteralNumber, "'Number of <>'"); - - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'x size'"); - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'y size'"); - ExecutionModeOperands[ExecutionModeLocalSize].push(OperandLiteralNumber, "'z size'"); - - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'x size'"); - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'y size'"); - ExecutionModeOperands[ExecutionModeLocalSizeHint].push(OperandLiteralNumber, "'z size'"); - - ExecutionModeOperands[ExecutionModeOutputVertices].push(OperandLiteralNumber, "'Vertex count'"); - ExecutionModeOperands[ExecutionModeVecTypeHint].push(OperandLiteralNumber, "'Vector type'"); - - DecorationOperands[DecorationStream].push(OperandLiteralNumber, "'Stream Number'"); - DecorationOperands[DecorationLocation].push(OperandLiteralNumber, "'Location'"); - DecorationOperands[DecorationComponent].push(OperandLiteralNumber, "'Component'"); - DecorationOperands[DecorationIndex].push(OperandLiteralNumber, "'Index'"); - DecorationOperands[DecorationBinding].push(OperandLiteralNumber, "'Binding Point'"); - DecorationOperands[DecorationDescriptorSet].push(OperandLiteralNumber, "'Descriptor Set'"); - DecorationOperands[DecorationOffset].push(OperandLiteralNumber, "'Byte Offset'"); - DecorationOperands[DecorationXfbBuffer].push(OperandLiteralNumber, "'XFB Buffer Number'"); - DecorationOperands[DecorationXfbStride].push(OperandLiteralNumber, "'XFB Stride'"); - DecorationOperands[DecorationArrayStride].push(OperandLiteralNumber, "'Array Stride'"); - DecorationOperands[DecorationMatrixStride].push(OperandLiteralNumber, "'Matrix Stride'"); - DecorationOperands[DecorationBuiltIn].push(OperandLiteralNumber, "See <>"); - DecorationOperands[DecorationFPRoundingMode].push(OperandFPRoundingMode, "'Floating-Point Rounding Mode'"); - DecorationOperands[DecorationFPFastMathMode].push(OperandFPFastMath, "'Fast-Math Mode'"); - DecorationOperands[DecorationLinkageAttributes].push(OperandLiteralString, "'Name'"); - DecorationOperands[DecorationLinkageAttributes].push(OperandLinkageType, "'Linkage Type'"); - DecorationOperands[DecorationFuncParamAttr].push(OperandFuncParamAttr, "'Function Parameter Attribute'"); - DecorationOperands[DecorationSpecId].push(OperandLiteralNumber, "'Specialization Constant ID'"); - DecorationOperands[DecorationInputAttachmentIndex].push(OperandLiteralNumber, "'Attachment Index'"); - DecorationOperands[DecorationAlignment].push(OperandLiteralNumber, "'Alignment'"); - - OperandClassParams[OperandSource].set(0, SourceString, nullptr); - OperandClassParams[OperandExecutionModel].set(0, ExecutionModelString, nullptr); - OperandClassParams[OperandAddressing].set(0, AddressingString, nullptr); - OperandClassParams[OperandMemory].set(0, MemoryString, nullptr); - OperandClassParams[OperandExecutionMode].set(ExecutionModeCeiling, ExecutionModeString, ExecutionModeParams); - OperandClassParams[OperandExecutionMode].setOperands(ExecutionModeOperands); - OperandClassParams[OperandStorage].set(0, StorageClassString, nullptr); - OperandClassParams[OperandDimensionality].set(0, DimensionString, nullptr); - OperandClassParams[OperandSamplerAddressingMode].set(0, SamplerAddressingModeString, nullptr); - OperandClassParams[OperandSamplerFilterMode].set(0, SamplerFilterModeString, nullptr); - OperandClassParams[OperandSamplerImageFormat].set(0, ImageFormatString, nullptr); - OperandClassParams[OperandImageChannelOrder].set(0, ImageChannelOrderString, nullptr); - OperandClassParams[OperandImageChannelDataType].set(0, ImageChannelDataTypeString, nullptr); - OperandClassParams[OperandImageOperands].set(ImageOperandsCeiling, ImageOperandsString, ImageOperandsParams, true); - OperandClassParams[OperandFPFastMath].set(0, FPFastMathString, nullptr, true); - OperandClassParams[OperandFPRoundingMode].set(0, FPRoundingModeString, nullptr); - OperandClassParams[OperandLinkageType].set(0, LinkageTypeString, nullptr); - OperandClassParams[OperandFuncParamAttr].set(0, FuncParamAttrString, nullptr); - OperandClassParams[OperandAccessQualifier].set(0, AccessQualifierString, nullptr); - OperandClassParams[OperandDecoration].set(DecorationCeiling, DecorationString, DecorationParams); - OperandClassParams[OperandDecoration].setOperands(DecorationOperands); - OperandClassParams[OperandBuiltIn].set(0, BuiltInString, nullptr); - OperandClassParams[OperandSelect].set(SelectControlCeiling, SelectControlString, SelectionControlParams, true); - OperandClassParams[OperandLoop].set(LoopControlCeiling, LoopControlString, LoopControlParams, true); - OperandClassParams[OperandFunction].set(FunctionControlCeiling, FunctionControlString, FunctionControlParams, true); - OperandClassParams[OperandMemorySemantics].set(0, MemorySemanticsString, nullptr, true); - OperandClassParams[OperandMemoryAccess].set(MemoryAccessCeiling, MemoryAccessString, MemoryAccessParams, true); - OperandClassParams[OperandScope].set(0, ScopeString, nullptr); - OperandClassParams[OperandGroupOperation].set(0, GroupOperationString, nullptr); - OperandClassParams[OperandKernelEnqueueFlags].set(0, KernelEnqueueFlagsString, nullptr); - OperandClassParams[OperandKernelProfilingInfo].set(0, KernelProfilingInfoString, nullptr, true); - OperandClassParams[OperandCapability].set(0, CapabilityString, nullptr); - OperandClassParams[OperandCooperativeMatrixOperands].set(CooperativeMatrixOperandsCeiling, CooperativeMatrixOperandsString, CooperativeMatrixOperandsParams, true); - OperandClassParams[OperandOpcode].set(OpCodeMask + 1, OpcodeString, nullptr); - - // set name of operator, an initial set of style operands, and the description - - InstructionDesc[OpSource].operands.push(OperandSource, ""); - InstructionDesc[OpSource].operands.push(OperandLiteralNumber, "'Version'"); - InstructionDesc[OpSource].operands.push(OperandId, "'File'", true); - InstructionDesc[OpSource].operands.push(OperandLiteralString, "'Source'", true); - - InstructionDesc[OpSourceContinued].operands.push(OperandLiteralString, "'Continued Source'"); - - InstructionDesc[OpSourceExtension].operands.push(OperandLiteralString, "'Extension'"); - - InstructionDesc[OpName].operands.push(OperandId, "'Target'"); - InstructionDesc[OpName].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpMemberName].operands.push(OperandId, "'Type'"); - InstructionDesc[OpMemberName].operands.push(OperandLiteralNumber, "'Member'"); - InstructionDesc[OpMemberName].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpString].operands.push(OperandLiteralString, "'String'"); - - InstructionDesc[OpLine].operands.push(OperandId, "'File'"); - InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Line'"); - InstructionDesc[OpLine].operands.push(OperandLiteralNumber, "'Column'"); - - InstructionDesc[OpExtension].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpExtInstImport].operands.push(OperandLiteralString, "'Name'"); - - InstructionDesc[OpCapability].operands.push(OperandCapability, "'Capability'"); - - InstructionDesc[OpMemoryModel].operands.push(OperandAddressing, ""); - InstructionDesc[OpMemoryModel].operands.push(OperandMemory, ""); - - InstructionDesc[OpEntryPoint].operands.push(OperandExecutionModel, ""); - InstructionDesc[OpEntryPoint].operands.push(OperandId, "'Entry Point'"); - InstructionDesc[OpEntryPoint].operands.push(OperandLiteralString, "'Name'"); - InstructionDesc[OpEntryPoint].operands.push(OperandVariableIds, "'Interface'"); - - InstructionDesc[OpExecutionMode].operands.push(OperandId, "'Entry Point'"); - InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'"); - InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <>"); - - InstructionDesc[OpExecutionModeId].operands.push(OperandId, "'Entry Point'"); - InstructionDesc[OpExecutionModeId].operands.push(OperandExecutionMode, "'Mode'"); - InstructionDesc[OpExecutionModeId].operands.push(OperandVariableIds, "See <>"); - - InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'"); - InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'"); - - InstructionDesc[OpTypeFloat].operands.push(OperandLiteralNumber, "'Width'"); - - InstructionDesc[OpTypeVector].operands.push(OperandId, "'Component Type'"); - InstructionDesc[OpTypeVector].operands.push(OperandLiteralNumber, "'Component Count'"); - - InstructionDesc[OpTypeMatrix].operands.push(OperandId, "'Column Type'"); - InstructionDesc[OpTypeMatrix].operands.push(OperandLiteralNumber, "'Column Count'"); - - InstructionDesc[OpTypeImage].operands.push(OperandId, "'Sampled Type'"); - InstructionDesc[OpTypeImage].operands.push(OperandDimensionality, ""); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Depth'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Arrayed'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'MS'"); - InstructionDesc[OpTypeImage].operands.push(OperandLiteralNumber, "'Sampled'"); - InstructionDesc[OpTypeImage].operands.push(OperandSamplerImageFormat, ""); - InstructionDesc[OpTypeImage].operands.push(OperandAccessQualifier, "", true); - - InstructionDesc[OpTypeSampledImage].operands.push(OperandId, "'Image Type'"); - - InstructionDesc[OpTypeArray].operands.push(OperandId, "'Element Type'"); - InstructionDesc[OpTypeArray].operands.push(OperandId, "'Length'"); - - InstructionDesc[OpTypeRuntimeArray].operands.push(OperandId, "'Element Type'"); - - InstructionDesc[OpTypeStruct].operands.push(OperandVariableIds, "'Member 0 type', +\n'member 1 type', +\n..."); - - InstructionDesc[OpTypeOpaque].operands.push(OperandLiteralString, "The name of the opaque type."); - - InstructionDesc[OpTypePointer].operands.push(OperandStorage, ""); - InstructionDesc[OpTypePointer].operands.push(OperandId, "'Type'"); - - InstructionDesc[OpTypeForwardPointer].operands.push(OperandId, "'Pointer Type'"); - InstructionDesc[OpTypeForwardPointer].operands.push(OperandStorage, ""); - - InstructionDesc[OpTypePipe].operands.push(OperandAccessQualifier, "'Qualifier'"); - - InstructionDesc[OpTypeFunction].operands.push(OperandId, "'Return Type'"); - InstructionDesc[OpTypeFunction].operands.push(OperandVariableIds, "'Parameter 0 Type', +\n'Parameter 1 Type', +\n..."); - - InstructionDesc[OpConstant].operands.push(OperandVariableLiterals, "'Value'"); - - InstructionDesc[OpConstantComposite].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpConstantSampler].operands.push(OperandSamplerAddressingMode, ""); - InstructionDesc[OpConstantSampler].operands.push(OperandLiteralNumber, "'Param'"); - InstructionDesc[OpConstantSampler].operands.push(OperandSamplerFilterMode, ""); - - InstructionDesc[OpSpecConstant].operands.push(OperandVariableLiterals, "'Value'"); - - InstructionDesc[OpSpecConstantComposite].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpSpecConstantOp].operands.push(OperandLiteralNumber, "'Opcode'"); - InstructionDesc[OpSpecConstantOp].operands.push(OperandVariableIds, "'Operands'"); - - InstructionDesc[OpVariable].operands.push(OperandStorage, ""); - InstructionDesc[OpVariable].operands.push(OperandId, "'Initializer'", true); - - InstructionDesc[OpFunction].operands.push(OperandFunction, ""); - InstructionDesc[OpFunction].operands.push(OperandId, "'Function Type'"); - - InstructionDesc[OpFunctionCall].operands.push(OperandId, "'Function'"); - InstructionDesc[OpFunctionCall].operands.push(OperandVariableIds, "'Argument 0', +\n'Argument 1', +\n..."); - - InstructionDesc[OpExtInst].operands.push(OperandId, "'Set'"); - InstructionDesc[OpExtInst].operands.push(OperandLiteralNumber, "'Instruction'"); - InstructionDesc[OpExtInst].operands.push(OperandVariableIds, "'Operand 1', +\n'Operand 2', +\n..."); - - InstructionDesc[OpLoad].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLoad].operands.push(OperandMemoryAccess, "", true); - InstructionDesc[OpLoad].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpLoad].operands.push(OperandId, "", true); - - InstructionDesc[OpStore].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpStore].operands.push(OperandId, "'Object'"); - InstructionDesc[OpStore].operands.push(OperandMemoryAccess, "", true); - InstructionDesc[OpStore].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpStore].operands.push(OperandId, "", true); - - InstructionDesc[OpPhi].operands.push(OperandVariableIds, "'Variable, Parent, ...'"); - - InstructionDesc[OpDecorate].operands.push(OperandId, "'Target'"); - InstructionDesc[OpDecorate].operands.push(OperandDecoration, ""); - InstructionDesc[OpDecorate].operands.push(OperandVariableLiterals, "See <>."); - - InstructionDesc[OpDecorateId].operands.push(OperandId, "'Target'"); - InstructionDesc[OpDecorateId].operands.push(OperandDecoration, ""); - InstructionDesc[OpDecorateId].operands.push(OperandVariableIds, "See <>."); - - InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandId, "'Target'"); - InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandDecoration, ""); - InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'"); - - InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'"); - InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'"); - InstructionDesc[OpMemberDecorate].operands.push(OperandDecoration, ""); - InstructionDesc[OpMemberDecorate].operands.push(OperandVariableLiterals, "See <>."); - - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandId, "'Structure Type'"); - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralNumber, "'Member'"); - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandDecoration, ""); - InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'"); - - InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'"); - InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'"); - - InstructionDesc[OpGroupMemberDecorate].operands.push(OperandId, "'Decoration Group'"); - InstructionDesc[OpGroupMemberDecorate].operands.push(OperandVariableIdLiteral, "'Targets'"); - - InstructionDesc[OpVectorExtractDynamic].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorExtractDynamic].operands.push(OperandId, "'Index'"); - - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Component'"); - InstructionDesc[OpVectorInsertDynamic].operands.push(OperandId, "'Index'"); - - InstructionDesc[OpVectorShuffle].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpVectorShuffle].operands.push(OperandId, "'Vector 2'"); - InstructionDesc[OpVectorShuffle].operands.push(OperandVariableLiterals, "'Components'"); - - InstructionDesc[OpCompositeConstruct].operands.push(OperandVariableIds, "'Constituents'"); - - InstructionDesc[OpCompositeExtract].operands.push(OperandId, "'Composite'"); - InstructionDesc[OpCompositeExtract].operands.push(OperandVariableLiterals, "'Indexes'"); - - InstructionDesc[OpCompositeInsert].operands.push(OperandId, "'Object'"); - InstructionDesc[OpCompositeInsert].operands.push(OperandId, "'Composite'"); - InstructionDesc[OpCompositeInsert].operands.push(OperandVariableLiterals, "'Indexes'"); - - InstructionDesc[OpCopyObject].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Target'"); - InstructionDesc[OpCopyMemory].operands.push(OperandId, "'Source'"); - InstructionDesc[OpCopyMemory].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Target'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Source'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandId, "'Size'"); - InstructionDesc[OpCopyMemorySized].operands.push(OperandMemoryAccess, "", true); - - InstructionDesc[OpSampledImage].operands.push(OperandId, "'Image'"); - InstructionDesc[OpSampledImage].operands.push(OperandId, "'Sampler'"); - - InstructionDesc[OpImage].operands.push(OperandId, "'Sampled Image'"); - - InstructionDesc[OpImageRead].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageRead].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageRead].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageRead].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageWrite].operands.push(OperandId, "'Texel'"); - InstructionDesc[OpImageWrite].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageWrite].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageFetch].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageFetch].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageFetch].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageFetch].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageGather].operands.push(OperandId, "'Component'"); - InstructionDesc[OpImageGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageDrefGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageDrefGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjDrefImplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseSampleProjDrefExplicitLod].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageSparseFetch].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseFetch].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseFetch].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandId, "'Component'"); - InstructionDesc[OpImageSparseGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandId, "'D~ref~'"); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseDrefGather].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageSparseRead].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSparseRead].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSparseRead].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpImageSparseTexelsResident].operands.push(OperandId, "'Resident Code'"); - - InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQuerySizeLod].operands.push(OperandId, "'Level of Detail'"); - - InstructionDesc[OpImageQuerySize].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageQueryLod].operands.push(OperandId, "'Coordinate'"); - - InstructionDesc[OpImageQueryLevels].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQuerySamples].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQueryFormat].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpImageQueryOrder].operands.push(OperandId, "'Image'"); - - InstructionDesc[OpAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpInBoundsAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpInBoundsAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpPtrAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpPtrAccessChain].operands.push(OperandId, "'Element'"); - InstructionDesc[OpPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Base'"); - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandId, "'Element'"); - InstructionDesc[OpInBoundsPtrAccessChain].operands.push(OperandVariableIds, "'Indexes'"); - - InstructionDesc[OpSNegate].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpFNegate].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpNot].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpAny].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpAll].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpConvertFToU].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpConvertFToS].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpConvertSToF].operands.push(OperandId, "'Signed Value'"); - - InstructionDesc[OpConvertUToF].operands.push(OperandId, "'Unsigned Value'"); - - InstructionDesc[OpUConvert].operands.push(OperandId, "'Unsigned Value'"); - - InstructionDesc[OpSConvert].operands.push(OperandId, "'Signed Value'"); - - InstructionDesc[OpFConvert].operands.push(OperandId, "'Float Value'"); - - InstructionDesc[OpSatConvertSToU].operands.push(OperandId, "'Signed Value'"); - - InstructionDesc[OpSatConvertUToS].operands.push(OperandId, "'Unsigned Value'"); - - InstructionDesc[OpConvertPtrToU].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpConvertUToPtr].operands.push(OperandId, "'Integer Value'"); - - InstructionDesc[OpPtrCastToGeneric].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpGenericCastToPtr].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpGenericCastToPtrExplicit].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpGenericCastToPtrExplicit].operands.push(OperandStorage, "'Storage'"); - - InstructionDesc[OpGenericPtrMemSemantics].operands.push(OperandId, "'Pointer'"); - - InstructionDesc[OpBitcast].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpQuantizeToF16].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpTranspose].operands.push(OperandId, "'Matrix'"); - - InstructionDesc[OpCopyLogical].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpIsNan].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsInf].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsFinite].operands.push(OperandId, "'x'"); - - InstructionDesc[OpIsNormal].operands.push(OperandId, "'x'"); - - InstructionDesc[OpSignBitSet].operands.push(OperandId, "'x'"); - - InstructionDesc[OpLessOrGreater].operands.push(OperandId, "'x'"); - InstructionDesc[OpLessOrGreater].operands.push(OperandId, "'y'"); - - InstructionDesc[OpOrdered].operands.push(OperandId, "'x'"); - InstructionDesc[OpOrdered].operands.push(OperandId, "'y'"); - - InstructionDesc[OpUnordered].operands.push(OperandId, "'x'"); - InstructionDesc[OpUnordered].operands.push(OperandId, "'y'"); - - InstructionDesc[OpArrayLength].operands.push(OperandId, "'Structure'"); - InstructionDesc[OpArrayLength].operands.push(OperandLiteralNumber, "'Array member'"); - - InstructionDesc[OpIAdd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIAdd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFAdd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFAdd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpISub].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpISub].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFSub].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFSub].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpIMul].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIMul].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFMul].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFMul].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFDiv].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFDiv].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSRem].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSRem].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFRem].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFRem].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFMod].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFMod].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpVectorTimesScalar].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorTimesScalar].operands.push(OperandId, "'Scalar'"); - - InstructionDesc[OpMatrixTimesScalar].operands.push(OperandId, "'Matrix'"); - InstructionDesc[OpMatrixTimesScalar].operands.push(OperandId, "'Scalar'"); - - InstructionDesc[OpVectorTimesMatrix].operands.push(OperandId, "'Vector'"); - InstructionDesc[OpVectorTimesMatrix].operands.push(OperandId, "'Matrix'"); - - InstructionDesc[OpMatrixTimesVector].operands.push(OperandId, "'Matrix'"); - InstructionDesc[OpMatrixTimesVector].operands.push(OperandId, "'Vector'"); - - InstructionDesc[OpMatrixTimesMatrix].operands.push(OperandId, "'LeftMatrix'"); - InstructionDesc[OpMatrixTimesMatrix].operands.push(OperandId, "'RightMatrix'"); - - InstructionDesc[OpOuterProduct].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpOuterProduct].operands.push(OperandId, "'Vector 2'"); - - InstructionDesc[OpDot].operands.push(OperandId, "'Vector 1'"); - InstructionDesc[OpDot].operands.push(OperandId, "'Vector 2'"); - - InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIAddCarry].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpISubBorrow].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUMulExtended].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSMulExtended].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftRightLogical].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpShiftRightArithmetic].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftRightArithmetic].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpShiftLeftLogical].operands.push(OperandId, "'Base'"); - InstructionDesc[OpShiftLeftLogical].operands.push(OperandId, "'Shift'"); - - InstructionDesc[OpLogicalOr].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalOr].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalAnd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalAnd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpLogicalNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpLogicalNot].operands.push(OperandId, "'Operand'"); - - InstructionDesc[OpBitwiseOr].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseOr].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitwiseXor].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseXor].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitwiseAnd].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpBitwiseAnd].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Insert'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldInsert].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldSExtract].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Base'"); - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Offset'"); - InstructionDesc[OpBitFieldUExtract].operands.push(OperandId, "'Count'"); - - InstructionDesc[OpBitReverse].operands.push(OperandId, "'Base'"); - - InstructionDesc[OpBitCount].operands.push(OperandId, "'Base'"); - - InstructionDesc[OpSelect].operands.push(OperandId, "'Condition'"); - InstructionDesc[OpSelect].operands.push(OperandId, "'Object 1'"); - InstructionDesc[OpSelect].operands.push(OperandId, "'Object 2'"); - - InstructionDesc[OpIEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpIEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpINotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpINotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordNotEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordNotEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpULessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpULessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordLessThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordLessThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordGreaterThan].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordGreaterThan].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpULessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpULessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordLessThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordLessThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpUGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpUGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpSGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpSGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFOrdGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFOrdGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpFUnordGreaterThanEqual].operands.push(OperandId, "'Operand 1'"); - InstructionDesc[OpFUnordGreaterThanEqual].operands.push(OperandId, "'Operand 2'"); - - InstructionDesc[OpDPdx].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdy].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidth].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdxFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdyFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidthFine].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdxCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpDPdyCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpFwidthCoarse].operands.push(OperandId, "'P'"); - - InstructionDesc[OpEmitStreamVertex].operands.push(OperandId, "'Stream'"); - - InstructionDesc[OpEndStreamPrimitive].operands.push(OperandId, "'Stream'"); - - InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpControlBarrier].operands.push(OperandScope, "'Memory'"); - InstructionDesc[OpControlBarrier].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpMemoryBarrier].operands.push(OperandScope, "'Memory'"); - InstructionDesc[OpMemoryBarrier].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Image'"); - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageTexelPointer].operands.push(OperandId, "'Sample'"); - - InstructionDesc[OpAtomicLoad].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicLoad].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicLoad].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicStore].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicStore].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicStore].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicStore].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicExchange].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicExchange].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandMemorySemantics, "'Equal'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandMemorySemantics, "'Unequal'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Value'"); - InstructionDesc[OpAtomicCompareExchange].operands.push(OperandId, "'Comparator'"); - - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandMemorySemantics, "'Equal'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandMemorySemantics, "'Unequal'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Value'"); - InstructionDesc[OpAtomicCompareExchangeWeak].operands.push(OperandId, "'Comparator'"); - - InstructionDesc[OpAtomicIIncrement].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIIncrement].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIIncrement].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicIDecrement].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIDecrement].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIDecrement].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFAddEXT].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFAddEXT].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicFAddEXT].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicISub].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicUMin].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicUMin].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicUMax].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicUMax].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicSMin].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicSMin].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicFMinEXT].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFMinEXT].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFMinEXT].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicFMinEXT].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicFMaxEXT].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicAnd].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicOr].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicOr].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicOr].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicOr].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicXor].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicXor].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicXor].operands.push(OperandMemorySemantics, "'Semantics'"); - InstructionDesc[OpAtomicXor].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFlagTestAndSet].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpAtomicFlagClear].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpAtomicFlagClear].operands.push(OperandScope, "'Scope'"); - InstructionDesc[OpAtomicFlagClear].operands.push(OperandMemorySemantics, "'Semantics'"); - - InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Merge Block'"); - InstructionDesc[OpLoopMerge].operands.push(OperandId, "'Continue Target'"); - InstructionDesc[OpLoopMerge].operands.push(OperandLoop, ""); - InstructionDesc[OpLoopMerge].operands.push(OperandOptionalLiteral, ""); - - InstructionDesc[OpSelectionMerge].operands.push(OperandId, "'Merge Block'"); - InstructionDesc[OpSelectionMerge].operands.push(OperandSelect, ""); - - InstructionDesc[OpBranch].operands.push(OperandId, "'Target Label'"); - - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'Condition'"); - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'True Label'"); - InstructionDesc[OpBranchConditional].operands.push(OperandId, "'False Label'"); - InstructionDesc[OpBranchConditional].operands.push(OperandVariableLiterals, "'Branch weights'"); - - InstructionDesc[OpSwitch].operands.push(OperandId, "'Selector'"); - InstructionDesc[OpSwitch].operands.push(OperandId, "'Default'"); - InstructionDesc[OpSwitch].operands.push(OperandVariableLiteralId, "'Target'"); - - - InstructionDesc[OpReturnValue].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpLifetimeStart].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLifetimeStart].operands.push(OperandLiteralNumber, "'Size'"); - - InstructionDesc[OpLifetimeStop].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpLifetimeStop].operands.push(OperandLiteralNumber, "'Size'"); - - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Destination'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Source'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Num Elements'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpGroupAsyncCopy].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpGroupWaitEvents].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpGroupWaitEvents].operands.push(OperandId, "'Events List'"); - - InstructionDesc[OpGroupAll].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAll].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpGroupAny].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupAny].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpGroupBroadcast].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupBroadcast].operands.push(OperandId, "'Value'"); - InstructionDesc[OpGroupBroadcast].operands.push(OperandId, "'LocalId'"); - - InstructionDesc[OpGroupIAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupIAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupIAdd].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupFAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFAdd].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupUMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMin].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupSMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMin].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMin].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupUMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMax].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupSMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMax].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMax].operands.push(OperandId, "X"); - - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Index'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReservedReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Index'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReservedWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpCommitReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpCommitWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpIsValidReserveId].operands.push(OperandId, "'Reserve Id'"); - - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGetNumPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGetMaxPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupReserveReadPipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Num Packets'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupReserveWritePipePackets].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupCommitReadPipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Pipe'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Reserve Id'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Size'"); - InstructionDesc[OpGroupCommitWritePipe].operands.push(OperandId, "'Packet Alignment'"); - - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'GlobalWorkSize'"); - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'LocalWorkSize'"); - InstructionDesc[OpBuildNDRange].operands.push(OperandId, "'GlobalWorkOffset'"); - - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Event'"); - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Profiling Info'"); - InstructionDesc[OpCaptureEventProfilingInfo].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpSetUserEventStatus].operands.push(OperandId, "'Event'"); - InstructionDesc[OpSetUserEventStatus].operands.push(OperandId, "'Status'"); - - InstructionDesc[OpIsValidEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpRetainEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpReleaseEvent].operands.push(OperandId, "'Event'"); - - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelWorkGroupSize].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelPreferredWorkGroupSizeMultiple].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelNDrangeSubGroupCount].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpGetKernelNDrangeMaxSubGroupSize].operands.push(OperandId, "'Param Align'"); - - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Queue'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Flags'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'ND Range'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Wait Events'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Ret Event'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Invoke'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param Size'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandId, "'Param Align'"); - InstructionDesc[OpEnqueueKernel].operands.push(OperandVariableIds, "'Local Size'"); - - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Queue'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Num Events'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Wait Events'"); - InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Ret Event'"); - - InstructionDesc[OpGroupNonUniformElect].operands.push(OperandScope, "'Execution'"); - - InstructionDesc[OpGroupNonUniformAll].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformAll].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformAny].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformAny].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformAllEqual].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformAllEqual].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBroadcast].operands.push(OperandId, "ID"); - - InstructionDesc[OpGroupNonUniformBroadcastFirst].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBroadcastFirst].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallot].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallot].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformInverseBallot].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformInverseBallot].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBallotBitExtract].operands.push(OperandId, "Bit"); - - InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBallotBitCount].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallotFindLSB].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotFindLSB].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformBallotFindMSB].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBallotFindMSB].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffle].operands.push(OperandId, "'Id'"); - - InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffleXor].operands.push(OperandId, "Mask"); - - InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffleUp].operands.push(OperandId, "Offset"); - - InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformShuffleDown].operands.push(OperandId, "Offset"); - - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformIAdd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFAdd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformIMul].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFMul].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformSMin].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformUMin].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFMin].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformSMax].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformUMax].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformFMax].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBitwiseAnd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBitwiseOr].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformBitwiseXor].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformLogicalAnd].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformLogicalOr].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformLogicalXor].operands.push(OperandId, "'ClusterSize'", true); - - InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformQuadBroadcast].operands.push(OperandId, "'Id'"); - - InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X"); - InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "'Direction'"); - - InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupFirstInvocationKHR].operands.push(OperandId, "'Value'"); - - InstructionDesc[OpSubgroupAnyKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAnyKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupAllKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAllKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpSubgroupAllEqualKHR].operands.push(OperandId, "'Predicate'"); - - InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Value'"); - InstructionDesc[OpSubgroupReadInvocationKHR].operands.push(OperandId, "'Index'"); - - InstructionDesc[OpModuleProcessed].operands.push(OperandLiteralString, "'process'"); - - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandId, "'X'"); - - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandScope, "'Execution'"); - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'"); - InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandId, "X"); - - InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Image'"); - InstructionDesc[OpFragmentMaskFetchAMD].operands.push(OperandId, "'Coordinate'"); - - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Image'"); - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpFragmentFetchAMD].operands.push(OperandId, "'Fragment Index'"); - - InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X"); - - InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false); - - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Miss Index'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Origin'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Direction'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpTraceNV].setResultAndType(false, false); - - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Flags'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Cull Mask'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Miss Index'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Origin'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Ray Direction'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Time'"); - InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpTraceRayMotionNV].setResultAndType(false, false); - - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Flags'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Cull Mask'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Miss Index'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Origin'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Ray Direction'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpTraceRayKHR].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpTraceRayKHR].setResultAndType(false, false); - - InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Parameter'"); - InstructionDesc[OpReportIntersectionKHR].operands.push(OperandId, "'Hit Kind'"); - - InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false); - - InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false); - - InstructionDesc[OpTerminateRayNV].setResultAndType(false, false); - - InstructionDesc[OpTerminateRayKHR].setResultAndType(false, false); - - InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index"); - InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID"); - InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false); - - InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "SBT Record Index"); - InstructionDesc[OpExecuteCallableKHR].operands.push(OperandId, "CallableData"); - InstructionDesc[OpExecuteCallableKHR].setResultAndType(false, false); - - InstructionDesc[OpConvertUToAccelerationStructureKHR].operands.push(OperandId, "Value"); - InstructionDesc[OpConvertUToAccelerationStructureKHR].setResultAndType(true, true); - - // Ray Query - InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false); - InstructionDesc[OpTypeRayQueryKHR].setResultAndType(true, false); - - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'AccelerationS'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'RayFlags'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'CullMask'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmin'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpRayQueryInitializeKHR].operands.push(OperandId, "'Tmax'"); - InstructionDesc[OpRayQueryInitializeKHR].setResultAndType(false, false); - - InstructionDesc[OpRayQueryTerminateKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryTerminateKHR].setResultAndType(false, false); - - InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGenerateIntersectionKHR].operands.push(OperandId, "'THit'"); - InstructionDesc[OpRayQueryGenerateIntersectionKHR].setResultAndType(false, false); - - InstructionDesc[OpRayQueryConfirmIntersectionKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryConfirmIntersectionKHR].setResultAndType(false, false); - - InstructionDesc[OpRayQueryProceedKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryProceedKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionTypeKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionTypeKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetRayTMinKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetRayTMinKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetRayFlagsKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetRayFlagsKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionTKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionTKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceCustomIndexKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceIdKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionGeometryIndexKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionPrimitiveIndexKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionBarycentricsKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionFrontFaceKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionCandidateAABBOpaqueKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionObjectRayDirectionKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionObjectRayOriginKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetWorldRayDirectionKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetWorldRayOriginKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetWorldRayOriginKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionObjectToWorldKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionWorldToObjectKHR].setResultAndType(true, true); - - InstructionDesc[OpRayQueryGetIntersectionTriangleVertexPositionsKHR].operands.push(OperandId, "'RayQuery'"); - InstructionDesc[OpRayQueryGetIntersectionTriangleVertexPositionsKHR].operands.push(OperandId, "'Committed'"); - InstructionDesc[OpRayQueryGetIntersectionTriangleVertexPositionsKHR].setResultAndType(true, true); - - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'"); - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'"); - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Granularity'"); - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coarse'"); - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandVariableIds, "", true); - - InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Index Offset'"); - InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Packed Indices'"); - - InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'groupCountX'"); - InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'groupCountY'"); - InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'groupCountZ'"); - InstructionDesc[OpEmitMeshTasksEXT].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpEmitMeshTasksEXT].setResultAndType(false, false); - - InstructionDesc[OpSetMeshOutputsEXT].operands.push(OperandId, "'vertexCount'"); - InstructionDesc[OpSetMeshOutputsEXT].operands.push(OperandId, "'primitiveCount'"); - InstructionDesc[OpSetMeshOutputsEXT].setResultAndType(false, false); - - - InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Component Type'"); - InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Scope'"); - InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Rows'"); - InstructionDesc[OpTypeCooperativeMatrixNV].operands.push(OperandId, "'Columns'"); - - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "'Column Major'"); - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandMemoryAccess, "'Memory Access'"); - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpCooperativeMatrixLoadNV].operands.push(OperandId, "", true); - - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Object'"); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "'Column Major'"); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandMemoryAccess, "'Memory Access'"); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpCooperativeMatrixStoreNV].operands.push(OperandId, "", true); - - InstructionDesc[OpCooperativeMatrixMulAddNV].operands.push(OperandId, "'A'"); - InstructionDesc[OpCooperativeMatrixMulAddNV].operands.push(OperandId, "'B'"); - InstructionDesc[OpCooperativeMatrixMulAddNV].operands.push(OperandId, "'C'"); - - InstructionDesc[OpCooperativeMatrixLengthNV].operands.push(OperandId, "'Type'"); - - InstructionDesc[OpTypeCooperativeMatrixKHR].operands.push(OperandId, "'Component Type'"); - InstructionDesc[OpTypeCooperativeMatrixKHR].operands.push(OperandId, "'Scope'"); - InstructionDesc[OpTypeCooperativeMatrixKHR].operands.push(OperandId, "'Rows'"); - InstructionDesc[OpTypeCooperativeMatrixKHR].operands.push(OperandId, "'Columns'"); - InstructionDesc[OpTypeCooperativeMatrixKHR].operands.push(OperandId, "'Use'"); - - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandId, "'Memory Layout'"); - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandMemoryAccess, "'Memory Access'"); - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpCooperativeMatrixLoadKHR].operands.push(OperandId, "", true); - - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandId, "'Pointer'"); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandId, "'Object'"); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandId, "'Memory Layout'"); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandId, "'Stride'"); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandMemoryAccess, "'Memory Access'"); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandLiteralNumber, "", true); - InstructionDesc[OpCooperativeMatrixStoreKHR].operands.push(OperandId, "", true); - - InstructionDesc[OpCooperativeMatrixMulAddKHR].operands.push(OperandId, "'A'"); - InstructionDesc[OpCooperativeMatrixMulAddKHR].operands.push(OperandId, "'B'"); - InstructionDesc[OpCooperativeMatrixMulAddKHR].operands.push(OperandId, "'C'"); - InstructionDesc[OpCooperativeMatrixMulAddKHR].operands.push(OperandCooperativeMatrixOperands, "'Cooperative Matrix Operands'", true); - - InstructionDesc[OpCooperativeMatrixLengthKHR].operands.push(OperandId, "'Type'"); - - InstructionDesc[OpDemoteToHelperInvocationEXT].setResultAndType(false, false); - - InstructionDesc[OpReadClockKHR].operands.push(OperandScope, "'Scope'"); - - InstructionDesc[OpTypeHitObjectNV].setResultAndType(true, false); - - InstructionDesc[OpHitObjectGetShaderRecordBufferHandleNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetShaderRecordBufferHandleNV].setResultAndType(true, true); - - InstructionDesc[OpReorderThreadWithHintNV].operands.push(OperandId, "'Hint'"); - InstructionDesc[OpReorderThreadWithHintNV].operands.push(OperandId, "'Bits'"); - InstructionDesc[OpReorderThreadWithHintNV].setResultAndType(false, false); - - InstructionDesc[OpReorderThreadWithHitObjectNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpReorderThreadWithHitObjectNV].operands.push(OperandId, "'Hint'"); - InstructionDesc[OpReorderThreadWithHitObjectNV].operands.push(OperandId, "'Bits'"); - InstructionDesc[OpReorderThreadWithHitObjectNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectGetCurrentTimeNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetCurrentTimeNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetHitKindNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetHitKindNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetPrimitiveIndexNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetPrimitiveIndexNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetGeometryIndexNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetGeometryIndexNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetInstanceIdNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetInstanceIdNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetInstanceCustomIndexNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetInstanceCustomIndexNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetObjectRayDirectionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetObjectRayDirectionNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetObjectRayOriginNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetObjectRayOriginNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetWorldRayDirectionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetWorldRayDirectionNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetWorldRayOriginNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetWorldRayOriginNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetWorldToObjectNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetWorldToObjectNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetObjectToWorldNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetObjectToWorldNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetRayTMaxNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetRayTMaxNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetRayTMinNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetRayTMinNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetShaderBindingTableRecordIndexNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetShaderBindingTableRecordIndexNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectIsEmptyNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectIsEmptyNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectIsHitNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectIsHitNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectIsMissNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectIsMissNV].setResultAndType(true, true); - - InstructionDesc[OpHitObjectGetAttributesNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectGetAttributesNV].operands.push(OperandId, "'HitObjectAttribute'"); - InstructionDesc[OpHitObjectGetAttributesNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectExecuteShaderNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectExecuteShaderNV].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpHitObjectExecuteShaderNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'InstanceId'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'PrimitiveId'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'GeometryIndex'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'HitKind'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordHitNV].operands.push(OperandId, "'HitObject Attribute'"); - InstructionDesc[OpHitObjectRecordHitNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'InstanceId'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'PrimitiveId'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'GeometryIndex'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'HitKind'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'Current Time'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].operands.push(OperandId, "'HitObject Attribute'"); - InstructionDesc[OpHitObjectRecordHitMotionNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'InstanceId'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'PrimitiveId'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'GeometryIndex'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'HitKind'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'SBT Record Index'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].operands.push(OperandId, "'HitObject Attribute'"); - InstructionDesc[OpHitObjectRecordHitWithIndexNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'InstanceId'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'PrimitiveId'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'GeometryIndex'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'HitKind'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'SBT Record Index'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'Current Time'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].operands.push(OperandId, "'HitObject Attribute'"); - InstructionDesc[OpHitObjectRecordHitWithIndexMotionNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'SBT Index'"); - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordMissNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordMissNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'SBT Index'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].operands.push(OperandId, "'Current Time'"); - InstructionDesc[OpHitObjectRecordMissMotionNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectRecordEmptyNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectRecordEmptyNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'RayFlags'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Cullmask'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Miss Index'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectTraceRayNV].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpHitObjectTraceRayNV].setResultAndType(false, false); - - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'HitObject'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'RayFlags'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Cullmask'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'SBT Record Offset'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'SBT Record Stride'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Miss Index'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Origin'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'TMin'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Direction'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'TMax'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Time'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].operands.push(OperandId, "'Payload'"); - InstructionDesc[OpHitObjectTraceRayMotionNV].setResultAndType(false, false); - - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Instance ID'"); - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Geometry Index'"); - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Primitive Index'"); - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].operands.push(OperandId, "'Barycentrics'"); - InstructionDesc[OpFetchMicroTriangleVertexBarycentricNV].setResultAndType(true, true); - - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Acceleration Structure'"); - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Instance ID'"); - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Geometry Index'"); - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Primitive Index'"); - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].operands.push(OperandId, "'Barycentrics'"); - InstructionDesc[OpFetchMicroTriangleVertexPositionNV].setResultAndType(true, true); - - InstructionDesc[OpColorAttachmentReadEXT].operands.push(OperandId, "'Attachment'"); - InstructionDesc[OpColorAttachmentReadEXT].operands.push(OperandId, "'Sample'", true); - InstructionDesc[OpStencilAttachmentReadEXT].operands.push(OperandId, "'Sample'", true); - InstructionDesc[OpDepthAttachmentReadEXT].operands.push(OperandId, "'Sample'", true); - - InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandId, "'source texture'"); - InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandId, "'texture coordinates'"); - InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandId, "'weights texture'"); - InstructionDesc[OpImageSampleWeightedQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageSampleWeightedQCOM].setResultAndType(true, true); - - InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandId, "'source texture'"); - InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandId, "'texture coordinates'"); - InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandId, "'box size'"); - InstructionDesc[OpImageBoxFilterQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageBoxFilterQCOM].setResultAndType(true, true); - - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'target texture'"); - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'target coordinates'"); - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'reference texture'"); - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'reference coordinates'"); - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandId, "'block size'"); - InstructionDesc[OpImageBlockMatchSADQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageBlockMatchSADQCOM].setResultAndType(true, true); - - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'target texture'"); - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'target coordinates'"); - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'reference texture'"); - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'reference coordinates'"); - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandId, "'block size'"); - InstructionDesc[OpImageBlockMatchSSDQCOM].operands.push(OperandImageOperands, "", true); - InstructionDesc[OpImageBlockMatchSSDQCOM].setResultAndType(true, true); - }); -} - -}; // end spv namespace diff --git a/3rdparty/glslang/SPIRV/doc.h b/3rdparty/glslang/SPIRV/doc.h deleted file mode 100644 index 52152991..00000000 --- a/3rdparty/glslang/SPIRV/doc.h +++ /dev/null @@ -1,260 +0,0 @@ -// -// Copyright (C) 2014-2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Parameterize the SPIR-V enumerants. -// - -#pragma once - -#include "spirv.hpp" - -#include - -namespace spv { - -// Fill in all the parameters -void Parameterize(); - -// Return the English names of all the enums. -const char* SourceString(int); -const char* AddressingString(int); -const char* MemoryString(int); -const char* ExecutionModelString(int); -const char* ExecutionModeString(int); -const char* StorageClassString(int); -const char* DecorationString(int); -const char* BuiltInString(int); -const char* DimensionString(int); -const char* SelectControlString(int); -const char* LoopControlString(int); -const char* FunctionControlString(int); -const char* SamplerAddressingModeString(int); -const char* SamplerFilterModeString(int); -const char* ImageFormatString(int); -const char* ImageChannelOrderString(int); -const char* ImageChannelTypeString(int); -const char* ImageChannelDataTypeString(int type); -const char* ImageOperandsString(int format); -const char* ImageOperands(int); -const char* FPFastMathString(int); -const char* FPRoundingModeString(int); -const char* LinkageTypeString(int); -const char* FuncParamAttrString(int); -const char* AccessQualifierString(int); -const char* MemorySemanticsString(int); -const char* MemoryAccessString(int); -const char* ExecutionScopeString(int); -const char* GroupOperationString(int); -const char* KernelEnqueueFlagsString(int); -const char* KernelProfilingInfoString(int); -const char* CapabilityString(int); -const char* OpcodeString(int); -const char* ScopeString(int mem); - -// For grouping opcodes into subsections -enum OpcodeClass { - OpClassMisc, - OpClassDebug, - OpClassAnnotate, - OpClassExtension, - OpClassMode, - OpClassType, - OpClassConstant, - OpClassMemory, - OpClassFunction, - OpClassImage, - OpClassConvert, - OpClassComposite, - OpClassArithmetic, - OpClassBit, - OpClassRelationalLogical, - OpClassDerivative, - OpClassFlowControl, - OpClassAtomic, - OpClassPrimitive, - OpClassBarrier, - OpClassGroup, - OpClassDeviceSideEnqueue, - OpClassPipe, - - OpClassCount, - OpClassMissing // all instructions start out as missing -}; - -// For parameterizing operands. -enum OperandClass { - OperandNone, - OperandId, - OperandVariableIds, - OperandOptionalLiteral, - OperandOptionalLiteralString, - OperandVariableLiterals, - OperandVariableIdLiteral, - OperandVariableLiteralId, - OperandLiteralNumber, - OperandLiteralString, - OperandVariableLiteralStrings, - OperandSource, - OperandExecutionModel, - OperandAddressing, - OperandMemory, - OperandExecutionMode, - OperandStorage, - OperandDimensionality, - OperandSamplerAddressingMode, - OperandSamplerFilterMode, - OperandSamplerImageFormat, - OperandImageChannelOrder, - OperandImageChannelDataType, - OperandImageOperands, - OperandFPFastMath, - OperandFPRoundingMode, - OperandLinkageType, - OperandAccessQualifier, - OperandFuncParamAttr, - OperandDecoration, - OperandBuiltIn, - OperandSelect, - OperandLoop, - OperandFunction, - OperandMemorySemantics, - OperandMemoryAccess, - OperandScope, - OperandGroupOperation, - OperandKernelEnqueueFlags, - OperandKernelProfilingInfo, - OperandCapability, - OperandCooperativeMatrixOperands, - - OperandOpcode, - - OperandCount -}; - -// Any specific enum can have a set of capabilities that allow it: -typedef std::vector EnumCaps; - -// Parameterize a set of operands with their OperandClass(es) and descriptions. -class OperandParameters { -public: - OperandParameters() { } - void push(OperandClass oc, const char* d, bool opt = false) - { - opClass.push_back(oc); - desc.push_back(d); - optional.push_back(opt); - } - void setOptional(); - OperandClass getClass(int op) const { return opClass[op]; } - const char* getDesc(int op) const { return desc[op]; } - bool isOptional(int op) const { return optional[op]; } - int getNum() const { return (int)opClass.size(); } - -protected: - std::vector opClass; - std::vector desc; - std::vector optional; -}; - -// Parameterize an enumerant -class EnumParameters { -public: - EnumParameters() : desc(nullptr) { } - const char* desc; -}; - -// Parameterize a set of enumerants that form an enum -class EnumDefinition : public EnumParameters { -public: - EnumDefinition() : - ceiling(0), bitmask(false), getName(nullptr), enumParams(nullptr), operandParams(nullptr) { } - void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false) - { - ceiling = ceil; - getName = name; - bitmask = mask; - enumParams = ep; - } - void setOperands(OperandParameters* op) { operandParams = op; } - int ceiling; // ceiling of enumerants - bool bitmask; // true if these enumerants combine into a bitmask - const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift) - EnumParameters* enumParams; // parameters for each individual enumerant - OperandParameters* operandParams; // sets of operands -}; - -// Parameterize an instruction's logical format, including its known set of operands, -// per OperandParameters above. -class InstructionParameters { -public: - InstructionParameters() : - opDesc("TBD"), - opClass(OpClassMissing), - typePresent(true), // most normal, only exceptions have to be spelled out - resultPresent(true) // most normal, only exceptions have to be spelled out - { } - - void setResultAndType(bool r, bool t) - { - resultPresent = r; - typePresent = t; - } - - bool hasResult() const { return resultPresent != 0; } - bool hasType() const { return typePresent != 0; } - - const char* opDesc; - OpcodeClass opClass; - OperandParameters operands; - -protected: - bool typePresent : 1; - bool resultPresent : 1; -}; - -// The set of objects that hold all the instruction/operand -// parameterization information. -extern InstructionParameters InstructionDesc[]; - -// These hold definitions of the enumerants used for operands -extern EnumDefinition OperandClassParams[]; - -const char* GetOperandDesc(OperandClass operand); -void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false); -const char* AccessQualifierString(int attr); - -void PrintOperands(const OperandParameters& operands, int reservedOperands); - -} // end namespace spv diff --git a/3rdparty/glslang/SPIRV/hex_float.h b/3rdparty/glslang/SPIRV/hex_float.h deleted file mode 100644 index 785e8af1..00000000 --- a/3rdparty/glslang/SPIRV/hex_float.h +++ /dev/null @@ -1,1065 +0,0 @@ -// 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_UTIL_HEX_FLOAT_H_ -#define LIBSPIRV_UTIL_HEX_FLOAT_H_ - -#include -#include -#include -#include -#include -#include -#include - -#include "bitutils.h" - -namespace spvutils { - -class Float16 { - public: - Float16(uint16_t v) : val(v) {} - Float16() {} - static bool isNan(const Float16& val) { - return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) != 0); - } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(const Float16& val) { - return ((val.val & 0x7C00) == 0x7C00) && ((val.val & 0x3FF) == 0); - } - Float16(const Float16& other) { val = other.val; } - uint16_t get_value() const { return val; } - - // Returns the maximum normal value. - static Float16 max() { return Float16(0x7bff); } - // Returns the lowest normal value. - static Float16 lowest() { return Float16(0xfbff); } - - private: - uint16_t val; -}; - -// To specialize this type, you must override uint_type to define -// an unsigned integer that can fit your floating point type. -// You must also add a isNan function that returns true if -// a value is Nan. -template -struct FloatProxyTraits { - typedef void uint_type; -}; - -template <> -struct FloatProxyTraits { - typedef uint32_t uint_type; - static bool isNan(float f) { return std::isnan(f); } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(float f) { return std::isinf(f); } - // Returns the maximum normal value. - static float max() { return std::numeric_limits::max(); } - // Returns the lowest normal value. - static float lowest() { return std::numeric_limits::lowest(); } -}; - -template <> -struct FloatProxyTraits { - typedef uint64_t uint_type; - static bool isNan(double f) { return std::isnan(f); } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(double f) { return std::isinf(f); } - // Returns the maximum normal value. - static double max() { return std::numeric_limits::max(); } - // Returns the lowest normal value. - static double lowest() { return std::numeric_limits::lowest(); } -}; - -template <> -struct FloatProxyTraits { - typedef uint16_t uint_type; - static bool isNan(Float16 f) { return Float16::isNan(f); } - // Returns true if the given value is any kind of infinity. - static bool isInfinity(Float16 f) { return Float16::isInfinity(f); } - // Returns the maximum normal value. - static Float16 max() { return Float16::max(); } - // Returns the lowest normal value. - static Float16 lowest() { return Float16::lowest(); } -}; - -// Since copying a floating point number (especially if it is NaN) -// does not guarantee that bits are preserved, this class lets us -// store the type and use it as a float when necessary. -template -class FloatProxy { - public: - typedef typename FloatProxyTraits::uint_type uint_type; - - // Since this is to act similar to the normal floats, - // do not initialize the data by default. - FloatProxy() {} - - // Intentionally non-explicit. This is a proxy type so - // implicit conversions allow us to use it more transparently. - FloatProxy(T val) { data_ = BitwiseCast(val); } - - // Intentionally non-explicit. This is a proxy type so - // implicit conversions allow us to use it more transparently. - FloatProxy(uint_type val) { data_ = val; } - - // This is helpful to have and is guaranteed not to stomp bits. - FloatProxy operator-() const { - return static_cast(data_ ^ - (uint_type(0x1) << (sizeof(T) * 8 - 1))); - } - - // Returns the data as a floating point value. - T getAsFloat() const { return BitwiseCast(data_); } - - // Returns the raw data. - uint_type data() const { return data_; } - - // Returns true if the value represents any type of NaN. - bool isNan() { return FloatProxyTraits::isNan(getAsFloat()); } - // Returns true if the value represents any type of infinity. - bool isInfinity() { return FloatProxyTraits::isInfinity(getAsFloat()); } - - // Returns the maximum normal value. - static FloatProxy max() { - return FloatProxy(FloatProxyTraits::max()); - } - // Returns the lowest normal value. - static FloatProxy lowest() { - return FloatProxy(FloatProxyTraits::lowest()); - } - - private: - uint_type data_; -}; - -template -bool operator==(const FloatProxy& first, const FloatProxy& second) { - return first.data() == second.data(); -} - -// Reads a FloatProxy value as a normal float from a stream. -template -std::istream& operator>>(std::istream& is, FloatProxy& value) { - T float_val; - is >> float_val; - value = FloatProxy(float_val); - return is; -} - -// This is an example traits. It is not meant to be used in practice, but will -// be the default for any non-specialized type. -template -struct HexFloatTraits { - // Integer type that can store this hex-float. - typedef void uint_type; - // Signed integer type that can store this hex-float. - typedef void int_type; - // The numerical type that this HexFloat represents. - typedef void underlying_type; - // The type needed to construct the underlying type. - typedef void native_type; - // The number of bits that are actually relevant in the uint_type. - // This allows us to deal with, for example, 24-bit values in a 32-bit - // integer. - static const uint32_t num_used_bits = 0; - // Number of bits that represent the exponent. - static const uint32_t num_exponent_bits = 0; - // Number of bits that represent the fractional part. - static const uint32_t num_fraction_bits = 0; - // The bias of the exponent. (How much we need to subtract from the stored - // value to get the correct value.) - static const uint32_t exponent_bias = 0; -}; - -// Traits for IEEE float. -// 1 sign bit, 8 exponent bits, 23 fractional bits. -template <> -struct HexFloatTraits> { - typedef uint32_t uint_type; - typedef int32_t int_type; - typedef FloatProxy underlying_type; - typedef float native_type; - static const uint_type num_used_bits = 32; - static const uint_type num_exponent_bits = 8; - static const uint_type num_fraction_bits = 23; - static const uint_type exponent_bias = 127; -}; - -// Traits for IEEE double. -// 1 sign bit, 11 exponent bits, 52 fractional bits. -template <> -struct HexFloatTraits> { - typedef uint64_t uint_type; - typedef int64_t int_type; - typedef FloatProxy underlying_type; - typedef double native_type; - static const uint_type num_used_bits = 64; - static const uint_type num_exponent_bits = 11; - static const uint_type num_fraction_bits = 52; - static const uint_type exponent_bias = 1023; -}; - -// Traits for IEEE half. -// 1 sign bit, 5 exponent bits, 10 fractional bits. -template <> -struct HexFloatTraits> { - typedef uint16_t uint_type; - typedef int16_t int_type; - typedef uint16_t underlying_type; - typedef uint16_t native_type; - static const uint_type num_used_bits = 16; - static const uint_type num_exponent_bits = 5; - static const uint_type num_fraction_bits = 10; - static const uint_type exponent_bias = 15; -}; - -enum round_direction { - kRoundToZero, - kRoundToNearestEven, - kRoundToPositiveInfinity, - kRoundToNegativeInfinity -}; - -// Template class that houses a floating pointer number. -// It exposes a number of constants based on the provided traits to -// assist in interpreting the bits of the value. -template > -class HexFloat { - public: - typedef typename Traits::uint_type uint_type; - typedef typename Traits::int_type int_type; - typedef typename Traits::underlying_type underlying_type; - typedef typename Traits::native_type native_type; - - explicit HexFloat(T f) : value_(f) {} - - T value() const { return value_; } - void set_value(T f) { value_ = f; } - - // These are all written like this because it is convenient to have - // compile-time constants for all of these values. - - // Pass-through values to save typing. - static const uint32_t num_used_bits = Traits::num_used_bits; - static const uint32_t exponent_bias = Traits::exponent_bias; - static const uint32_t num_exponent_bits = Traits::num_exponent_bits; - static const uint32_t num_fraction_bits = Traits::num_fraction_bits; - - // Number of bits to shift left to set the highest relevant bit. - static const uint32_t top_bit_left_shift = num_used_bits - 1; - // How many nibbles (hex characters) the fractional part takes up. - static const uint32_t fraction_nibbles = (num_fraction_bits + 3) / 4; - // If the fractional part does not fit evenly into a hex character (4-bits) - // then we have to left-shift to get rid of leading 0s. This is the amount - // we have to shift (might be 0). - static const uint32_t num_overflow_bits = - fraction_nibbles * 4 - num_fraction_bits; - - // The representation of the fraction, not the actual bits. This - // includes the leading bit that is usually implicit. - static const uint_type fraction_represent_mask = - spvutils::SetBits::get; - - // The topmost bit in the nibble-aligned fraction. - static const uint_type fraction_top_bit = - uint_type(1) << (num_fraction_bits + num_overflow_bits - 1); - - // The least significant bit in the exponent, which is also the bit - // immediately to the left of the significand. - static const uint_type first_exponent_bit = uint_type(1) - << (num_fraction_bits); - - // The mask for the encoded fraction. It does not include the - // implicit bit. - static const uint_type fraction_encode_mask = - spvutils::SetBits::get; - - // The bit that is used as a sign. - static const uint_type sign_mask = uint_type(1) << top_bit_left_shift; - - // The bits that represent the exponent. - static const uint_type exponent_mask = - spvutils::SetBits::get; - - // How far left the exponent is shifted. - static const uint32_t exponent_left_shift = num_fraction_bits; - - // How far from the right edge the fraction is shifted. - static const uint32_t fraction_right_shift = - static_cast(sizeof(uint_type) * 8) - num_fraction_bits; - - // The maximum representable unbiased exponent. - static const int_type max_exponent = - (exponent_mask >> num_fraction_bits) - exponent_bias; - // The minimum representable exponent for normalized numbers. - static const int_type min_exponent = -static_cast(exponent_bias); - - // Returns the bits associated with the value. - uint_type getBits() const { return spvutils::BitwiseCast(value_); } - - // Returns the bits associated with the value, without the leading sign bit. - uint_type getUnsignedBits() const { - return static_cast(spvutils::BitwiseCast(value_) & - ~sign_mask); - } - - // Returns the bits associated with the exponent, shifted to start at the - // lsb of the type. - const uint_type getExponentBits() const { - return static_cast((getBits() & exponent_mask) >> - num_fraction_bits); - } - - // Returns the exponent in unbiased form. This is the exponent in the - // human-friendly form. - const int_type getUnbiasedExponent() const { - return static_cast(getExponentBits() - exponent_bias); - } - - // Returns just the significand bits from the value. - const uint_type getSignificandBits() const { - return getBits() & fraction_encode_mask; - } - - // If the number was normalized, returns the unbiased exponent. - // If the number was denormal, normalize the exponent first. - const int_type getUnbiasedNormalizedExponent() const { - if ((getBits() & ~sign_mask) == 0) { // special case if everything is 0 - return 0; - } - int_type exp = getUnbiasedExponent(); - if (exp == min_exponent) { // We are in denorm land. - uint_type significand_bits = getSignificandBits(); - while ((significand_bits & (first_exponent_bit >> 1)) == 0) { - significand_bits = static_cast(significand_bits << 1); - exp = static_cast(exp - 1); - } - significand_bits &= fraction_encode_mask; - } - return exp; - } - - // Returns the signficand after it has been normalized. - const uint_type getNormalizedSignificand() const { - int_type unbiased_exponent = getUnbiasedNormalizedExponent(); - uint_type significand = getSignificandBits(); - for (int_type i = unbiased_exponent; i <= min_exponent; ++i) { - significand = static_cast(significand << 1); - } - significand &= fraction_encode_mask; - return significand; - } - - // Returns true if this number represents a negative value. - bool isNegative() const { return (getBits() & sign_mask) != 0; } - - // Sets this HexFloat from the individual components. - // Note this assumes EVERY significand is normalized, and has an implicit - // leading one. This means that the only way that this method will set 0, - // is if you set a number so denormalized that it underflows. - // Do not use this method with raw bits extracted from a subnormal number, - // since subnormals do not have an implicit leading 1 in the significand. - // The significand is also expected to be in the - // lowest-most num_fraction_bits of the uint_type. - // The exponent is expected to be unbiased, meaning an exponent of - // 0 actually means 0. - // If underflow_round_up is set, then on underflow, if a number is non-0 - // and would underflow, we round up to the smallest denorm. - void setFromSignUnbiasedExponentAndNormalizedSignificand( - bool negative, int_type exponent, uint_type significand, - bool round_denorm_up) { - bool significand_is_zero = significand == 0; - - if (exponent <= min_exponent) { - // If this was denormalized, then we have to shift the bit on, meaning - // the significand is not zero. - significand_is_zero = false; - significand |= first_exponent_bit; - significand = static_cast(significand >> 1); - } - - while (exponent < min_exponent) { - significand = static_cast(significand >> 1); - ++exponent; - } - - if (exponent == min_exponent) { - if (significand == 0 && !significand_is_zero && round_denorm_up) { - significand = static_cast(0x1); - } - } - - uint_type new_value = 0; - if (negative) { - new_value = static_cast(new_value | sign_mask); - } - exponent = static_cast(exponent + exponent_bias); - assert(exponent >= 0); - - // put it all together - exponent = static_cast((exponent << exponent_left_shift) & - exponent_mask); - significand = static_cast(significand & fraction_encode_mask); - new_value = static_cast(new_value | (exponent | significand)); - value_ = BitwiseCast(new_value); - } - - // Increments the significand of this number by the given amount. - // If this would spill the significand into the implicit bit, - // carry is set to true and the significand is shifted to fit into - // the correct location, otherwise carry is set to false. - // All significands and to_increment are assumed to be within the bounds - // for a valid significand. - static uint_type incrementSignificand(uint_type significand, - uint_type to_increment, bool* carry) { - significand = static_cast(significand + to_increment); - *carry = false; - if (significand & first_exponent_bit) { - *carry = true; - // The implicit 1-bit will have carried, so we should zero-out the - // top bit and shift back. - significand = static_cast(significand & ~first_exponent_bit); - significand = static_cast(significand >> 1); - } - return significand; - } - - // These exist because MSVC throws warnings on negative right-shifts - // even if they are not going to be executed. Eg: - // constant_number < 0? 0: constant_number - // These convert the negative left-shifts into right shifts. - - template - uint_type negatable_left_shift(int_type N, uint_type val) - { - if(N >= 0) - return val << N; - - return val >> -N; - } - - template - uint_type negatable_right_shift(int_type N, uint_type val) - { - if(N >= 0) - return val >> N; - - return val << -N; - } - - // Returns the significand, rounded to fit in a significand in - // other_T. This is shifted so that the most significant - // bit of the rounded number lines up with the most significant bit - // of the returned significand. - template - typename other_T::uint_type getRoundedNormalizedSignificand( - round_direction dir, bool* carry_bit) { - typedef typename other_T::uint_type other_uint_type; - static const int_type num_throwaway_bits = - static_cast(num_fraction_bits) - - static_cast(other_T::num_fraction_bits); - - static const uint_type last_significant_bit = - (num_throwaway_bits < 0) - ? 0 - : negatable_left_shift(num_throwaway_bits, 1u); - static const uint_type first_rounded_bit = - (num_throwaway_bits < 1) - ? 0 - : negatable_left_shift(num_throwaway_bits - 1, 1u); - - static const uint_type throwaway_mask_bits = - num_throwaway_bits > 0 ? num_throwaway_bits : 0; - static const uint_type throwaway_mask = - spvutils::SetBits::get; - - *carry_bit = false; - other_uint_type out_val = 0; - uint_type significand = getNormalizedSignificand(); - // If we are up-casting, then we just have to shift to the right location. - if (num_throwaway_bits <= 0) { - out_val = static_cast(significand); - uint_type shift_amount = static_cast(-num_throwaway_bits); - out_val = static_cast(out_val << shift_amount); - return out_val; - } - - // If every non-representable bit is 0, then we don't have any casting to - // do. - if ((significand & throwaway_mask) == 0) { - return static_cast( - negatable_right_shift(num_throwaway_bits, significand)); - } - - bool round_away_from_zero = false; - // We actually have to narrow the significand here, so we have to follow the - // rounding rules. - switch (dir) { - case kRoundToZero: - break; - case kRoundToPositiveInfinity: - round_away_from_zero = !isNegative(); - break; - case kRoundToNegativeInfinity: - round_away_from_zero = isNegative(); - break; - case kRoundToNearestEven: - // Have to round down, round bit is 0 - if ((first_rounded_bit & significand) == 0) { - break; - } - if (((significand & throwaway_mask) & ~first_rounded_bit) != 0) { - // If any subsequent bit of the rounded portion is non-0 then we round - // up. - round_away_from_zero = true; - break; - } - // We are exactly half-way between 2 numbers, pick even. - if ((significand & last_significant_bit) != 0) { - // 1 for our last bit, round up. - round_away_from_zero = true; - break; - } - break; - } - - if (round_away_from_zero) { - return static_cast( - negatable_right_shift(num_throwaway_bits, incrementSignificand( - significand, last_significant_bit, carry_bit))); - } else { - return static_cast( - negatable_right_shift(num_throwaway_bits, significand)); - } - } - - // Casts this value to another HexFloat. If the cast is widening, - // then round_dir is ignored. If the cast is narrowing, then - // the result is rounded in the direction specified. - // This number will retain Nan and Inf values. - // It will also saturate to Inf if the number overflows, and - // underflow to (0 or min depending on rounding) if the number underflows. - template - void castTo(other_T& other, round_direction round_dir) { - other = other_T(static_cast(0)); - bool negate = isNegative(); - if (getUnsignedBits() == 0) { - if (negate) { - other.set_value(-other.value()); - } - return; - } - uint_type significand = getSignificandBits(); - bool carried = false; - typename other_T::uint_type rounded_significand = - getRoundedNormalizedSignificand(round_dir, &carried); - - int_type exponent = getUnbiasedExponent(); - if (exponent == min_exponent) { - // If we are denormal, normalize the exponent, so that we can encode - // easily. - exponent = static_cast(exponent + 1); - for (uint_type check_bit = first_exponent_bit >> 1; check_bit != 0; - check_bit = static_cast(check_bit >> 1)) { - exponent = static_cast(exponent - 1); - if (check_bit & significand) break; - } - } - - bool is_nan = - (getBits() & exponent_mask) == exponent_mask && significand != 0; - bool is_inf = - !is_nan && - ((exponent + carried) > static_cast(other_T::exponent_bias) || - (significand == 0 && (getBits() & exponent_mask) == exponent_mask)); - - // If we are Nan or Inf we should pass that through. - if (is_inf) { - other.set_value(BitwiseCast( - static_cast( - (negate ? other_T::sign_mask : 0) | other_T::exponent_mask))); - return; - } - if (is_nan) { - typename other_T::uint_type shifted_significand; - shifted_significand = static_cast( - negatable_left_shift( - static_cast(other_T::num_fraction_bits) - - static_cast(num_fraction_bits), significand)); - - // We are some sort of Nan. We try to keep the bit-pattern of the Nan - // as close as possible. If we had to shift off bits so we are 0, then we - // just set the last bit. - other.set_value(BitwiseCast( - static_cast( - (negate ? other_T::sign_mask : 0) | other_T::exponent_mask | - (shifted_significand == 0 ? 0x1 : shifted_significand)))); - return; - } - - bool round_underflow_up = - isNegative() ? round_dir == kRoundToNegativeInfinity - : round_dir == kRoundToPositiveInfinity; - typedef typename other_T::int_type other_int_type; - // setFromSignUnbiasedExponentAndNormalizedSignificand will - // zero out any underflowing value (but retain the sign). - other.setFromSignUnbiasedExponentAndNormalizedSignificand( - negate, static_cast(exponent), rounded_significand, - round_underflow_up); - return; - } - - private: - T value_; - - static_assert(num_used_bits == - Traits::num_exponent_bits + Traits::num_fraction_bits + 1, - "The number of bits do not fit"); - static_assert(sizeof(T) == sizeof(uint_type), "The type sizes do not match"); -}; - -// Returns 4 bits represented by the hex character. -inline uint8_t get_nibble_from_character(int character) { - const char* dec = "0123456789"; - const char* lower = "abcdef"; - const char* upper = "ABCDEF"; - const char* p = nullptr; - if ((p = strchr(dec, character))) { - return static_cast(p - dec); - } else if ((p = strchr(lower, character))) { - return static_cast(p - lower + 0xa); - } else if ((p = strchr(upper, character))) { - return static_cast(p - upper + 0xa); - } - - assert(false && "This was called with a non-hex character"); - return 0; -} - -// Outputs the given HexFloat to the stream. -template -std::ostream& operator<<(std::ostream& os, const HexFloat& value) { - typedef HexFloat HF; - typedef typename HF::uint_type uint_type; - typedef typename HF::int_type int_type; - - static_assert(HF::num_used_bits != 0, - "num_used_bits must be non-zero for a valid float"); - static_assert(HF::num_exponent_bits != 0, - "num_exponent_bits must be non-zero for a valid float"); - static_assert(HF::num_fraction_bits != 0, - "num_fractin_bits must be non-zero for a valid float"); - - const uint_type bits = spvutils::BitwiseCast(value.value()); - const char* const sign = (bits & HF::sign_mask) ? "-" : ""; - const uint_type exponent = static_cast( - (bits & HF::exponent_mask) >> HF::num_fraction_bits); - - uint_type fraction = static_cast((bits & HF::fraction_encode_mask) - << HF::num_overflow_bits); - - const bool is_zero = exponent == 0 && fraction == 0; - const bool is_denorm = exponent == 0 && !is_zero; - - // exponent contains the biased exponent we have to convert it back into - // the normal range. - int_type int_exponent = static_cast(exponent - HF::exponent_bias); - // If the number is all zeros, then we actually have to NOT shift the - // exponent. - int_exponent = is_zero ? 0 : int_exponent; - - // If we are denorm, then start shifting, and decreasing the exponent until - // our leading bit is 1. - - if (is_denorm) { - while ((fraction & HF::fraction_top_bit) == 0) { - fraction = static_cast(fraction << 1); - int_exponent = static_cast(int_exponent - 1); - } - // Since this is denormalized, we have to consume the leading 1 since it - // will end up being implicit. - fraction = static_cast(fraction << 1); // eat the leading 1 - fraction &= HF::fraction_represent_mask; - } - - uint_type fraction_nibbles = HF::fraction_nibbles; - // We do not have to display any trailing 0s, since this represents the - // fractional part. - while (fraction_nibbles > 0 && (fraction & 0xF) == 0) { - // Shift off any trailing values; - fraction = static_cast(fraction >> 4); - --fraction_nibbles; - } - - const auto saved_flags = os.flags(); - const auto saved_fill = os.fill(); - - os << sign << "0x" << (is_zero ? '0' : '1'); - if (fraction_nibbles) { - // Make sure to keep the leading 0s in place, since this is the fractional - // part. - os << "." << std::setw(static_cast(fraction_nibbles)) - << std::setfill('0') << std::hex << fraction; - } - os << "p" << std::dec << (int_exponent >= 0 ? "+" : "") << int_exponent; - - os.flags(saved_flags); - os.fill(saved_fill); - - return os; -} - -// Returns true if negate_value is true and the next character on the -// input stream is a plus or minus sign. In that case we also set the fail bit -// on the stream and set the value to the zero value for its type. -template -inline bool RejectParseDueToLeadingSign(std::istream& is, bool negate_value, - HexFloat& value) { - if (negate_value) { - auto next_char = is.peek(); - if (next_char == '-' || next_char == '+') { - // Fail the parse. Emulate standard behaviour by setting the value to - // the zero value, and set the fail bit on the stream. - value = HexFloat(typename HexFloat::uint_type(0)); - is.setstate(std::ios_base::failbit); - return true; - } - } - return false; -} - -// Parses a floating point number from the given stream and stores it into the -// value parameter. -// If negate_value is true then the number may not have a leading minus or -// plus, and if it successfully parses, then the number is negated before -// being stored into the value parameter. -// If the value cannot be correctly parsed or overflows the target floating -// point type, then set the fail bit on the stream. -// TODO(dneto): Promise C++11 standard behavior in how the value is set in -// the error case, but only after all target platforms implement it correctly. -// In particular, the Microsoft C++ runtime appears to be out of spec. -template -inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value, - HexFloat& value) { - if (RejectParseDueToLeadingSign(is, negate_value, value)) { - return is; - } - T val; - is >> val; - if (negate_value) { - val = -val; - } - value.set_value(val); - // In the failure case, map -0.0 to 0.0. - if (is.fail() && value.getUnsignedBits() == 0u) { - value = HexFloat(typename HexFloat::uint_type(0)); - } - if (val.isInfinity()) { - // Fail the parse. Emulate standard behaviour by setting the value to - // the closest normal value, and set the fail bit on the stream. - value.set_value((value.isNegative() || negate_value) ? T::lowest() - : T::max()); - is.setstate(std::ios_base::failbit); - } - return is; -} - -// Specialization of ParseNormalFloat for FloatProxy values. -// This will parse the float as it were a 32-bit floating point number, -// and then round it down to fit into a Float16 value. -// The number is rounded towards zero. -// If negate_value is true then the number may not have a leading minus or -// plus, and if it successfully parses, then the number is negated before -// being stored into the value parameter. -// If the value cannot be correctly parsed or overflows the target floating -// point type, then set the fail bit on the stream. -// TODO(dneto): Promise C++11 standard behavior in how the value is set in -// the error case, but only after all target platforms implement it correctly. -// In particular, the Microsoft C++ runtime appears to be out of spec. -template <> -inline std::istream& -ParseNormalFloat, HexFloatTraits>>( - std::istream& is, bool negate_value, - HexFloat, HexFloatTraits>>& value) { - // First parse as a 32-bit float. - HexFloat> float_val(0.0f); - ParseNormalFloat(is, negate_value, float_val); - - // Then convert to 16-bit float, saturating at infinities, and - // rounding toward zero. - float_val.castTo(value, kRoundToZero); - - // Overflow on 16-bit behaves the same as for 32- and 64-bit: set the - // fail bit and set the lowest or highest value. - if (Float16::isInfinity(value.value().getAsFloat())) { - value.set_value(value.isNegative() ? Float16::lowest() : Float16::max()); - is.setstate(std::ios_base::failbit); - } - return is; -} - -// Reads a HexFloat from the given stream. -// If the float is not encoded as a hex-float then it will be parsed -// as a regular float. -// This may fail if your stream does not support at least one unget. -// Nan values can be encoded with "0x1.p+exponent_bias". -// This would normally overflow a float and round to -// infinity but this special pattern is the exact representation for a NaN, -// and therefore is actually encoded as the correct NaN. To encode inf, -// either 0x0p+exponent_bias can be specified or any exponent greater than -// exponent_bias. -// Examples using IEEE 32-bit float encoding. -// 0x1.0p+128 (+inf) -// -0x1.0p-128 (-inf) -// -// 0x1.1p+128 (+Nan) -// -0x1.1p+128 (-Nan) -// -// 0x1p+129 (+inf) -// -0x1p+129 (-inf) -template -std::istream& operator>>(std::istream& is, HexFloat& value) { - using HF = HexFloat; - using uint_type = typename HF::uint_type; - using int_type = typename HF::int_type; - - value.set_value(static_cast(0.f)); - - if (is.flags() & std::ios::skipws) { - // If the user wants to skip whitespace , then we should obey that. - while (std::isspace(is.peek())) { - is.get(); - } - } - - auto next_char = is.peek(); - bool negate_value = false; - - if (next_char != '-' && next_char != '0') { - return ParseNormalFloat(is, negate_value, value); - } - - if (next_char == '-') { - negate_value = true; - is.get(); - next_char = is.peek(); - } - - if (next_char == '0') { - is.get(); // We may have to unget this. - auto maybe_hex_start = is.peek(); - if (maybe_hex_start != 'x' && maybe_hex_start != 'X') { - is.unget(); - return ParseNormalFloat(is, negate_value, value); - } else { - is.get(); // Throw away the 'x'; - } - } else { - return ParseNormalFloat(is, negate_value, value); - } - - // This "looks" like a hex-float so treat it as one. - bool seen_p = false; - bool seen_dot = false; - uint_type fraction_index = 0; - - uint_type fraction = 0; - int_type exponent = HF::exponent_bias; - - // Strip off leading zeros so we don't have to special-case them later. - while ((next_char = is.peek()) == '0') { - is.get(); - } - - bool is_denorm = - true; // Assume denorm "representation" until we hear otherwise. - // NB: This does not mean the value is actually denorm, - // it just means that it was written 0. - bool bits_written = false; // Stays false until we write a bit. - while (!seen_p && !seen_dot) { - // Handle characters that are left of the fractional part. - if (next_char == '.') { - seen_dot = true; - } else if (next_char == 'p') { - seen_p = true; - } else if (::isxdigit(next_char)) { - // We know this is not denormalized since we have stripped all leading - // zeroes and we are not a ".". - is_denorm = false; - int number = get_nibble_from_character(next_char); - for (int i = 0; i < 4; ++i, number <<= 1) { - uint_type write_bit = (number & 0x8) ? 0x1 : 0x0; - if (bits_written) { - // If we are here the bits represented belong in the fractional - // part of the float, and we have to adjust the exponent accordingly. - fraction = static_cast( - fraction | - static_cast( - write_bit << (HF::top_bit_left_shift - fraction_index++))); - exponent = static_cast(exponent + 1); - } - bits_written |= write_bit != 0; - } - } else { - // We have not found our exponent yet, so we have to fail. - is.setstate(std::ios::failbit); - return is; - } - is.get(); - next_char = is.peek(); - } - bits_written = false; - while (seen_dot && !seen_p) { - // Handle only fractional parts now. - if (next_char == 'p') { - seen_p = true; - } else if (::isxdigit(next_char)) { - int number = get_nibble_from_character(next_char); - for (int i = 0; i < 4; ++i, number <<= 1) { - uint_type write_bit = (number & 0x8) ? 0x01 : 0x00; - bits_written |= write_bit != 0; - if (is_denorm && !bits_written) { - // Handle modifying the exponent here this way we can handle - // an arbitrary number of hex values without overflowing our - // integer. - exponent = static_cast(exponent - 1); - } else { - fraction = static_cast( - fraction | - static_cast( - write_bit << (HF::top_bit_left_shift - fraction_index++))); - } - } - } else { - // We still have not found our 'p' exponent yet, so this is not a valid - // hex-float. - is.setstate(std::ios::failbit); - return is; - } - is.get(); - next_char = is.peek(); - } - - bool seen_sign = false; - int8_t exponent_sign = 1; - int_type written_exponent = 0; - while (true) { - if ((next_char == '-' || next_char == '+')) { - if (seen_sign) { - is.setstate(std::ios::failbit); - return is; - } - seen_sign = true; - exponent_sign = (next_char == '-') ? -1 : 1; - } else if (::isdigit(next_char)) { - // Hex-floats express their exponent as decimal. - written_exponent = static_cast(written_exponent * 10); - written_exponent = - static_cast(written_exponent + (next_char - '0')); - } else { - break; - } - is.get(); - next_char = is.peek(); - } - - written_exponent = static_cast(written_exponent * exponent_sign); - exponent = static_cast(exponent + written_exponent); - - bool is_zero = is_denorm && (fraction == 0); - if (is_denorm && !is_zero) { - fraction = static_cast(fraction << 1); - exponent = static_cast(exponent - 1); - } else if (is_zero) { - exponent = 0; - } - - if (exponent <= 0 && !is_zero) { - fraction = static_cast(fraction >> 1); - fraction |= static_cast(1) << HF::top_bit_left_shift; - } - - fraction = (fraction >> HF::fraction_right_shift) & HF::fraction_encode_mask; - - const int_type max_exponent = - SetBits::get; - - // Handle actual denorm numbers - while (exponent < 0 && !is_zero) { - fraction = static_cast(fraction >> 1); - exponent = static_cast(exponent + 1); - - fraction &= HF::fraction_encode_mask; - if (fraction == 0) { - // We have underflowed our fraction. We should clamp to zero. - is_zero = true; - exponent = 0; - } - } - - // We have overflowed so we should be inf/-inf. - if (exponent > max_exponent) { - exponent = max_exponent; - fraction = 0; - } - - uint_type output_bits = static_cast( - static_cast(negate_value ? 1 : 0) << HF::top_bit_left_shift); - output_bits |= fraction; - - uint_type shifted_exponent = static_cast( - static_cast(exponent << HF::exponent_left_shift) & - HF::exponent_mask); - output_bits |= shifted_exponent; - - T output_float = spvutils::BitwiseCast(output_bits); - value.set_value(output_float); - - return is; -} - -// Writes a FloatProxy value to a stream. -// Zero and normal numbers are printed in the usual notation, but with -// enough digits to fully reproduce the value. Other values (subnormal, -// NaN, and infinity) are printed as a hex float. -template -std::ostream& operator<<(std::ostream& os, const FloatProxy& value) { - auto float_val = value.getAsFloat(); - switch (std::fpclassify(float_val)) { - case FP_ZERO: - case FP_NORMAL: { - auto saved_precision = os.precision(); - os.precision(std::numeric_limits::digits10); - os << float_val; - os.precision(saved_precision); - } break; - default: - os << HexFloat>(value); - break; - } - return os; -} - -template <> -inline std::ostream& operator<<(std::ostream& os, - const FloatProxy& value) { - os << HexFloat>(value); - return os; -} -} - -#endif // LIBSPIRV_UTIL_HEX_FLOAT_H_ diff --git a/3rdparty/glslang/SPIRV/spirv.hpp b/3rdparty/glslang/SPIRV/spirv.hpp deleted file mode 100644 index 5999aba9..00000000 --- a/3rdparty/glslang/SPIRV/spirv.hpp +++ /dev/null @@ -1,2796 +0,0 @@ -// Copyright (c) 2014-2020 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. - -// This header is automatically generated by the same tool that creates -// the Binary Section of the SPIR-V specification. - -// Enumeration tokens for SPIR-V, in various styles: -// C, C++, C++11, JSON, Lua, Python, C#, D, Beef -// -// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL -// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL -// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL -// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL -// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] -// - C# will use enum classes in the Specification class located in the "Spv" namespace, -// e.g.: Spv.Specification.SourceLanguage.GLSL -// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL -// - Beef will use enum classes in the Specification class located in the "Spv" namespace, -// e.g.: Spv.Specification.SourceLanguage.GLSL -// -// Some tokens act like mask values, which can be OR'd together, -// while others are mutually exclusive. The mask-like ones have -// "Mask" in their name, and a parallel enum that has the shift -// amount (1 << x) for each corresponding enumerant. - -#ifndef spirv_HPP -#define spirv_HPP - -namespace spv { - -typedef unsigned int Id; - -#define SPV_VERSION 0x10600 -#define SPV_REVISION 1 - -static const unsigned int MagicNumber = 0x07230203; -static const unsigned int Version = 0x00010600; -static const unsigned int Revision = 1; -static const unsigned int OpCodeMask = 0xffff; -static const unsigned int WordCountShift = 16; - -enum SourceLanguage { - SourceLanguageUnknown = 0, - SourceLanguageESSL = 1, - SourceLanguageGLSL = 2, - SourceLanguageOpenCL_C = 3, - SourceLanguageOpenCL_CPP = 4, - SourceLanguageHLSL = 5, - SourceLanguageCPP_for_OpenCL = 6, - SourceLanguageSYCL = 7, - SourceLanguageMax = 0x7fffffff, -}; - -enum ExecutionModel { - ExecutionModelVertex = 0, - ExecutionModelTessellationControl = 1, - ExecutionModelTessellationEvaluation = 2, - ExecutionModelGeometry = 3, - ExecutionModelFragment = 4, - ExecutionModelGLCompute = 5, - ExecutionModelKernel = 6, - ExecutionModelTaskNV = 5267, - ExecutionModelMeshNV = 5268, - ExecutionModelRayGenerationKHR = 5313, - ExecutionModelRayGenerationNV = 5313, - ExecutionModelIntersectionKHR = 5314, - ExecutionModelIntersectionNV = 5314, - ExecutionModelAnyHitKHR = 5315, - ExecutionModelAnyHitNV = 5315, - ExecutionModelClosestHitKHR = 5316, - ExecutionModelClosestHitNV = 5316, - ExecutionModelMissKHR = 5317, - ExecutionModelMissNV = 5317, - ExecutionModelCallableKHR = 5318, - ExecutionModelCallableNV = 5318, - ExecutionModelTaskEXT = 5364, - ExecutionModelMeshEXT = 5365, - ExecutionModelMax = 0x7fffffff, -}; - -enum AddressingModel { - AddressingModelLogical = 0, - AddressingModelPhysical32 = 1, - AddressingModelPhysical64 = 2, - AddressingModelPhysicalStorageBuffer64 = 5348, - AddressingModelPhysicalStorageBuffer64EXT = 5348, - AddressingModelMax = 0x7fffffff, -}; - -enum MemoryModel { - MemoryModelSimple = 0, - MemoryModelGLSL450 = 1, - MemoryModelOpenCL = 2, - MemoryModelVulkan = 3, - MemoryModelVulkanKHR = 3, - MemoryModelMax = 0x7fffffff, -}; - -enum ExecutionMode { - ExecutionModeInvocations = 0, - ExecutionModeSpacingEqual = 1, - ExecutionModeSpacingFractionalEven = 2, - ExecutionModeSpacingFractionalOdd = 3, - ExecutionModeVertexOrderCw = 4, - ExecutionModeVertexOrderCcw = 5, - ExecutionModePixelCenterInteger = 6, - ExecutionModeOriginUpperLeft = 7, - ExecutionModeOriginLowerLeft = 8, - ExecutionModeEarlyFragmentTests = 9, - ExecutionModePointMode = 10, - ExecutionModeXfb = 11, - ExecutionModeDepthReplacing = 12, - ExecutionModeDepthGreater = 14, - ExecutionModeDepthLess = 15, - ExecutionModeDepthUnchanged = 16, - ExecutionModeLocalSize = 17, - ExecutionModeLocalSizeHint = 18, - ExecutionModeInputPoints = 19, - ExecutionModeInputLines = 20, - ExecutionModeInputLinesAdjacency = 21, - ExecutionModeTriangles = 22, - ExecutionModeInputTrianglesAdjacency = 23, - ExecutionModeQuads = 24, - ExecutionModeIsolines = 25, - ExecutionModeOutputVertices = 26, - ExecutionModeOutputPoints = 27, - ExecutionModeOutputLineStrip = 28, - ExecutionModeOutputTriangleStrip = 29, - ExecutionModeVecTypeHint = 30, - ExecutionModeContractionOff = 31, - ExecutionModeInitializer = 33, - ExecutionModeFinalizer = 34, - ExecutionModeSubgroupSize = 35, - ExecutionModeSubgroupsPerWorkgroup = 36, - ExecutionModeSubgroupsPerWorkgroupId = 37, - ExecutionModeLocalSizeId = 38, - ExecutionModeLocalSizeHintId = 39, - ExecutionModeNonCoherentColorAttachmentReadEXT = 4169, - ExecutionModeNonCoherentDepthAttachmentReadEXT = 4170, - ExecutionModeNonCoherentStencilAttachmentReadEXT = 4171, - ExecutionModeSubgroupUniformControlFlowKHR = 4421, - ExecutionModePostDepthCoverage = 4446, - ExecutionModeDenormPreserve = 4459, - ExecutionModeDenormFlushToZero = 4460, - ExecutionModeSignedZeroInfNanPreserve = 4461, - ExecutionModeRoundingModeRTE = 4462, - ExecutionModeRoundingModeRTZ = 4463, - ExecutionModeEarlyAndLateFragmentTestsAMD = 5017, - ExecutionModeStencilRefReplacingEXT = 5027, - ExecutionModeStencilRefUnchangedFrontAMD = 5079, - ExecutionModeStencilRefGreaterFrontAMD = 5080, - ExecutionModeStencilRefLessFrontAMD = 5081, - ExecutionModeStencilRefUnchangedBackAMD = 5082, - ExecutionModeStencilRefGreaterBackAMD = 5083, - ExecutionModeStencilRefLessBackAMD = 5084, - ExecutionModeOutputLinesEXT = 5269, - ExecutionModeOutputLinesNV = 5269, - ExecutionModeOutputPrimitivesEXT = 5270, - ExecutionModeOutputPrimitivesNV = 5270, - ExecutionModeDerivativeGroupQuadsNV = 5289, - ExecutionModeDerivativeGroupLinearNV = 5290, - ExecutionModeOutputTrianglesEXT = 5298, - ExecutionModeOutputTrianglesNV = 5298, - ExecutionModePixelInterlockOrderedEXT = 5366, - ExecutionModePixelInterlockUnorderedEXT = 5367, - ExecutionModeSampleInterlockOrderedEXT = 5368, - ExecutionModeSampleInterlockUnorderedEXT = 5369, - ExecutionModeShadingRateInterlockOrderedEXT = 5370, - ExecutionModeShadingRateInterlockUnorderedEXT = 5371, - ExecutionModeSharedLocalMemorySizeINTEL = 5618, - ExecutionModeRoundingModeRTPINTEL = 5620, - ExecutionModeRoundingModeRTNINTEL = 5621, - ExecutionModeFloatingPointModeALTINTEL = 5622, - ExecutionModeFloatingPointModeIEEEINTEL = 5623, - ExecutionModeMaxWorkgroupSizeINTEL = 5893, - ExecutionModeMaxWorkDimINTEL = 5894, - ExecutionModeNoGlobalOffsetINTEL = 5895, - ExecutionModeNumSIMDWorkitemsINTEL = 5896, - ExecutionModeSchedulerTargetFmaxMhzINTEL = 5903, - ExecutionModeStreamingInterfaceINTEL = 6154, - ExecutionModeNamedBarrierCountINTEL = 6417, - ExecutionModeMax = 0x7fffffff, -}; - -enum StorageClass { - StorageClassUniformConstant = 0, - StorageClassInput = 1, - StorageClassUniform = 2, - StorageClassOutput = 3, - StorageClassWorkgroup = 4, - StorageClassCrossWorkgroup = 5, - StorageClassPrivate = 6, - StorageClassFunction = 7, - StorageClassGeneric = 8, - StorageClassPushConstant = 9, - StorageClassAtomicCounter = 10, - StorageClassImage = 11, - StorageClassStorageBuffer = 12, - StorageClassTileImageEXT = 4172, - StorageClassCallableDataKHR = 5328, - StorageClassCallableDataNV = 5328, - StorageClassIncomingCallableDataKHR = 5329, - StorageClassIncomingCallableDataNV = 5329, - StorageClassRayPayloadKHR = 5338, - StorageClassRayPayloadNV = 5338, - StorageClassHitAttributeKHR = 5339, - StorageClassHitAttributeNV = 5339, - StorageClassIncomingRayPayloadKHR = 5342, - StorageClassIncomingRayPayloadNV = 5342, - StorageClassShaderRecordBufferKHR = 5343, - StorageClassShaderRecordBufferNV = 5343, - StorageClassPhysicalStorageBuffer = 5349, - StorageClassPhysicalStorageBufferEXT = 5349, - StorageClassHitObjectAttributeNV = 5385, - StorageClassTaskPayloadWorkgroupEXT = 5402, - StorageClassCodeSectionINTEL = 5605, - StorageClassDeviceOnlyINTEL = 5936, - StorageClassHostOnlyINTEL = 5937, - StorageClassMax = 0x7fffffff, -}; - -enum Dim { - Dim1D = 0, - Dim2D = 1, - Dim3D = 2, - DimCube = 3, - DimRect = 4, - DimBuffer = 5, - DimSubpassData = 6, - DimTileImageDataEXT = 4173, - DimMax = 0x7fffffff, -}; - -enum SamplerAddressingMode { - SamplerAddressingModeNone = 0, - SamplerAddressingModeClampToEdge = 1, - SamplerAddressingModeClamp = 2, - SamplerAddressingModeRepeat = 3, - SamplerAddressingModeRepeatMirrored = 4, - SamplerAddressingModeMax = 0x7fffffff, -}; - -enum SamplerFilterMode { - SamplerFilterModeNearest = 0, - SamplerFilterModeLinear = 1, - SamplerFilterModeMax = 0x7fffffff, -}; - -enum ImageFormat { - ImageFormatUnknown = 0, - ImageFormatRgba32f = 1, - ImageFormatRgba16f = 2, - ImageFormatR32f = 3, - ImageFormatRgba8 = 4, - ImageFormatRgba8Snorm = 5, - ImageFormatRg32f = 6, - ImageFormatRg16f = 7, - ImageFormatR11fG11fB10f = 8, - ImageFormatR16f = 9, - ImageFormatRgba16 = 10, - ImageFormatRgb10A2 = 11, - ImageFormatRg16 = 12, - ImageFormatRg8 = 13, - ImageFormatR16 = 14, - ImageFormatR8 = 15, - ImageFormatRgba16Snorm = 16, - ImageFormatRg16Snorm = 17, - ImageFormatRg8Snorm = 18, - ImageFormatR16Snorm = 19, - ImageFormatR8Snorm = 20, - ImageFormatRgba32i = 21, - ImageFormatRgba16i = 22, - ImageFormatRgba8i = 23, - ImageFormatR32i = 24, - ImageFormatRg32i = 25, - ImageFormatRg16i = 26, - ImageFormatRg8i = 27, - ImageFormatR16i = 28, - ImageFormatR8i = 29, - ImageFormatRgba32ui = 30, - ImageFormatRgba16ui = 31, - ImageFormatRgba8ui = 32, - ImageFormatR32ui = 33, - ImageFormatRgb10a2ui = 34, - ImageFormatRg32ui = 35, - ImageFormatRg16ui = 36, - ImageFormatRg8ui = 37, - ImageFormatR16ui = 38, - ImageFormatR8ui = 39, - ImageFormatR64ui = 40, - ImageFormatR64i = 41, - ImageFormatMax = 0x7fffffff, -}; - -enum ImageChannelOrder { - ImageChannelOrderR = 0, - ImageChannelOrderA = 1, - ImageChannelOrderRG = 2, - ImageChannelOrderRA = 3, - ImageChannelOrderRGB = 4, - ImageChannelOrderRGBA = 5, - ImageChannelOrderBGRA = 6, - ImageChannelOrderARGB = 7, - ImageChannelOrderIntensity = 8, - ImageChannelOrderLuminance = 9, - ImageChannelOrderRx = 10, - ImageChannelOrderRGx = 11, - ImageChannelOrderRGBx = 12, - ImageChannelOrderDepth = 13, - ImageChannelOrderDepthStencil = 14, - ImageChannelOrdersRGB = 15, - ImageChannelOrdersRGBx = 16, - ImageChannelOrdersRGBA = 17, - ImageChannelOrdersBGRA = 18, - ImageChannelOrderABGR = 19, - ImageChannelOrderMax = 0x7fffffff, -}; - -enum ImageChannelDataType { - ImageChannelDataTypeSnormInt8 = 0, - ImageChannelDataTypeSnormInt16 = 1, - ImageChannelDataTypeUnormInt8 = 2, - ImageChannelDataTypeUnormInt16 = 3, - ImageChannelDataTypeUnormShort565 = 4, - ImageChannelDataTypeUnormShort555 = 5, - ImageChannelDataTypeUnormInt101010 = 6, - ImageChannelDataTypeSignedInt8 = 7, - ImageChannelDataTypeSignedInt16 = 8, - ImageChannelDataTypeSignedInt32 = 9, - ImageChannelDataTypeUnsignedInt8 = 10, - ImageChannelDataTypeUnsignedInt16 = 11, - ImageChannelDataTypeUnsignedInt32 = 12, - ImageChannelDataTypeHalfFloat = 13, - ImageChannelDataTypeFloat = 14, - ImageChannelDataTypeUnormInt24 = 15, - ImageChannelDataTypeUnormInt101010_2 = 16, - ImageChannelDataTypeMax = 0x7fffffff, -}; - -enum ImageOperandsShift { - ImageOperandsBiasShift = 0, - ImageOperandsLodShift = 1, - ImageOperandsGradShift = 2, - ImageOperandsConstOffsetShift = 3, - ImageOperandsOffsetShift = 4, - ImageOperandsConstOffsetsShift = 5, - ImageOperandsSampleShift = 6, - ImageOperandsMinLodShift = 7, - ImageOperandsMakeTexelAvailableShift = 8, - ImageOperandsMakeTexelAvailableKHRShift = 8, - ImageOperandsMakeTexelVisibleShift = 9, - ImageOperandsMakeTexelVisibleKHRShift = 9, - ImageOperandsNonPrivateTexelShift = 10, - ImageOperandsNonPrivateTexelKHRShift = 10, - ImageOperandsVolatileTexelShift = 11, - ImageOperandsVolatileTexelKHRShift = 11, - ImageOperandsSignExtendShift = 12, - ImageOperandsZeroExtendShift = 13, - ImageOperandsNontemporalShift = 14, - ImageOperandsOffsetsShift = 16, - ImageOperandsMax = 0x7fffffff, -}; - -enum ImageOperandsMask { - ImageOperandsMaskNone = 0, - ImageOperandsBiasMask = 0x00000001, - ImageOperandsLodMask = 0x00000002, - ImageOperandsGradMask = 0x00000004, - ImageOperandsConstOffsetMask = 0x00000008, - ImageOperandsOffsetMask = 0x00000010, - ImageOperandsConstOffsetsMask = 0x00000020, - ImageOperandsSampleMask = 0x00000040, - ImageOperandsMinLodMask = 0x00000080, - ImageOperandsMakeTexelAvailableMask = 0x00000100, - ImageOperandsMakeTexelAvailableKHRMask = 0x00000100, - ImageOperandsMakeTexelVisibleMask = 0x00000200, - ImageOperandsMakeTexelVisibleKHRMask = 0x00000200, - ImageOperandsNonPrivateTexelMask = 0x00000400, - ImageOperandsNonPrivateTexelKHRMask = 0x00000400, - ImageOperandsVolatileTexelMask = 0x00000800, - ImageOperandsVolatileTexelKHRMask = 0x00000800, - ImageOperandsSignExtendMask = 0x00001000, - ImageOperandsZeroExtendMask = 0x00002000, - ImageOperandsNontemporalMask = 0x00004000, - ImageOperandsOffsetsMask = 0x00010000, -}; - -enum FPFastMathModeShift { - FPFastMathModeNotNaNShift = 0, - FPFastMathModeNotInfShift = 1, - FPFastMathModeNSZShift = 2, - FPFastMathModeAllowRecipShift = 3, - FPFastMathModeFastShift = 4, - FPFastMathModeAllowContractFastINTELShift = 16, - FPFastMathModeAllowReassocINTELShift = 17, - FPFastMathModeMax = 0x7fffffff, -}; - -enum FPFastMathModeMask { - FPFastMathModeMaskNone = 0, - FPFastMathModeNotNaNMask = 0x00000001, - FPFastMathModeNotInfMask = 0x00000002, - FPFastMathModeNSZMask = 0x00000004, - FPFastMathModeAllowRecipMask = 0x00000008, - FPFastMathModeFastMask = 0x00000010, - FPFastMathModeAllowContractFastINTELMask = 0x00010000, - FPFastMathModeAllowReassocINTELMask = 0x00020000, -}; - -enum FPRoundingMode { - FPRoundingModeRTE = 0, - FPRoundingModeRTZ = 1, - FPRoundingModeRTP = 2, - FPRoundingModeRTN = 3, - FPRoundingModeMax = 0x7fffffff, -}; - -enum LinkageType { - LinkageTypeExport = 0, - LinkageTypeImport = 1, - LinkageTypeLinkOnceODR = 2, - LinkageTypeMax = 0x7fffffff, -}; - -enum AccessQualifier { - AccessQualifierReadOnly = 0, - AccessQualifierWriteOnly = 1, - AccessQualifierReadWrite = 2, - AccessQualifierMax = 0x7fffffff, -}; - -enum FunctionParameterAttribute { - FunctionParameterAttributeZext = 0, - FunctionParameterAttributeSext = 1, - FunctionParameterAttributeByVal = 2, - FunctionParameterAttributeSret = 3, - FunctionParameterAttributeNoAlias = 4, - FunctionParameterAttributeNoCapture = 5, - FunctionParameterAttributeNoWrite = 6, - FunctionParameterAttributeNoReadWrite = 7, - FunctionParameterAttributeRuntimeAlignedINTEL = 5940, - FunctionParameterAttributeMax = 0x7fffffff, -}; - -enum Decoration { - DecorationRelaxedPrecision = 0, - DecorationSpecId = 1, - DecorationBlock = 2, - DecorationBufferBlock = 3, - DecorationRowMajor = 4, - DecorationColMajor = 5, - DecorationArrayStride = 6, - DecorationMatrixStride = 7, - DecorationGLSLShared = 8, - DecorationGLSLPacked = 9, - DecorationCPacked = 10, - DecorationBuiltIn = 11, - DecorationNoPerspective = 13, - DecorationFlat = 14, - DecorationPatch = 15, - DecorationCentroid = 16, - DecorationSample = 17, - DecorationInvariant = 18, - DecorationRestrict = 19, - DecorationAliased = 20, - DecorationVolatile = 21, - DecorationConstant = 22, - DecorationCoherent = 23, - DecorationNonWritable = 24, - DecorationNonReadable = 25, - DecorationUniform = 26, - DecorationUniformId = 27, - DecorationSaturatedConversion = 28, - DecorationStream = 29, - DecorationLocation = 30, - DecorationComponent = 31, - DecorationIndex = 32, - DecorationBinding = 33, - DecorationDescriptorSet = 34, - DecorationOffset = 35, - DecorationXfbBuffer = 36, - DecorationXfbStride = 37, - DecorationFuncParamAttr = 38, - DecorationFPRoundingMode = 39, - DecorationFPFastMathMode = 40, - DecorationLinkageAttributes = 41, - DecorationNoContraction = 42, - DecorationInputAttachmentIndex = 43, - DecorationAlignment = 44, - DecorationMaxByteOffset = 45, - DecorationAlignmentId = 46, - DecorationMaxByteOffsetId = 47, - DecorationNoSignedWrap = 4469, - DecorationNoUnsignedWrap = 4470, - DecorationWeightTextureQCOM = 4487, - DecorationBlockMatchTextureQCOM = 4488, - DecorationExplicitInterpAMD = 4999, - DecorationOverrideCoverageNV = 5248, - DecorationPassthroughNV = 5250, - DecorationViewportRelativeNV = 5252, - DecorationSecondaryViewportRelativeNV = 5256, - DecorationPerPrimitiveEXT = 5271, - DecorationPerPrimitiveNV = 5271, - DecorationPerViewNV = 5272, - DecorationPerTaskNV = 5273, - DecorationPerVertexKHR = 5285, - DecorationPerVertexNV = 5285, - DecorationNonUniform = 5300, - DecorationNonUniformEXT = 5300, - DecorationRestrictPointer = 5355, - DecorationRestrictPointerEXT = 5355, - DecorationAliasedPointer = 5356, - DecorationAliasedPointerEXT = 5356, - DecorationHitObjectShaderRecordBufferNV = 5386, - DecorationBindlessSamplerNV = 5398, - DecorationBindlessImageNV = 5399, - DecorationBoundSamplerNV = 5400, - DecorationBoundImageNV = 5401, - DecorationSIMTCallINTEL = 5599, - DecorationReferencedIndirectlyINTEL = 5602, - DecorationClobberINTEL = 5607, - DecorationSideEffectsINTEL = 5608, - DecorationVectorComputeVariableINTEL = 5624, - DecorationFuncParamIOKindINTEL = 5625, - DecorationVectorComputeFunctionINTEL = 5626, - DecorationStackCallINTEL = 5627, - DecorationGlobalVariableOffsetINTEL = 5628, - DecorationCounterBuffer = 5634, - DecorationHlslCounterBufferGOOGLE = 5634, - DecorationHlslSemanticGOOGLE = 5635, - DecorationUserSemantic = 5635, - DecorationUserTypeGOOGLE = 5636, - DecorationFunctionRoundingModeINTEL = 5822, - DecorationFunctionDenormModeINTEL = 5823, - DecorationRegisterINTEL = 5825, - DecorationMemoryINTEL = 5826, - DecorationNumbanksINTEL = 5827, - DecorationBankwidthINTEL = 5828, - DecorationMaxPrivateCopiesINTEL = 5829, - DecorationSinglepumpINTEL = 5830, - DecorationDoublepumpINTEL = 5831, - DecorationMaxReplicatesINTEL = 5832, - DecorationSimpleDualPortINTEL = 5833, - DecorationMergeINTEL = 5834, - DecorationBankBitsINTEL = 5835, - DecorationForcePow2DepthINTEL = 5836, - DecorationBurstCoalesceINTEL = 5899, - DecorationCacheSizeINTEL = 5900, - DecorationDontStaticallyCoalesceINTEL = 5901, - DecorationPrefetchINTEL = 5902, - DecorationStallEnableINTEL = 5905, - DecorationFuseLoopsInFunctionINTEL = 5907, - DecorationMathOpDSPModeINTEL = 5909, - DecorationAliasScopeINTEL = 5914, - DecorationNoAliasINTEL = 5915, - DecorationInitiationIntervalINTEL = 5917, - DecorationMaxConcurrencyINTEL = 5918, - DecorationPipelineEnableINTEL = 5919, - DecorationBufferLocationINTEL = 5921, - DecorationIOPipeStorageINTEL = 5944, - DecorationFunctionFloatingPointModeINTEL = 6080, - DecorationSingleElementVectorINTEL = 6085, - DecorationVectorComputeCallableFunctionINTEL = 6087, - DecorationMediaBlockIOINTEL = 6140, - DecorationConduitKernelArgumentINTEL = 6175, - DecorationRegisterMapKernelArgumentINTEL = 6176, - DecorationMMHostInterfaceAddressWidthINTEL = 6177, - DecorationMMHostInterfaceDataWidthINTEL = 6178, - DecorationMMHostInterfaceLatencyINTEL = 6179, - DecorationMMHostInterfaceReadWriteModeINTEL = 6180, - DecorationMMHostInterfaceMaxBurstINTEL = 6181, - DecorationMMHostInterfaceWaitRequestINTEL = 6182, - DecorationStableKernelArgumentINTEL = 6183, - DecorationMax = 0x7fffffff, -}; - -enum BuiltIn { - BuiltInPosition = 0, - BuiltInPointSize = 1, - BuiltInClipDistance = 3, - BuiltInCullDistance = 4, - BuiltInVertexId = 5, - BuiltInInstanceId = 6, - BuiltInPrimitiveId = 7, - BuiltInInvocationId = 8, - BuiltInLayer = 9, - BuiltInViewportIndex = 10, - BuiltInTessLevelOuter = 11, - BuiltInTessLevelInner = 12, - BuiltInTessCoord = 13, - BuiltInPatchVertices = 14, - BuiltInFragCoord = 15, - BuiltInPointCoord = 16, - BuiltInFrontFacing = 17, - BuiltInSampleId = 18, - BuiltInSamplePosition = 19, - BuiltInSampleMask = 20, - BuiltInFragDepth = 22, - BuiltInHelperInvocation = 23, - BuiltInNumWorkgroups = 24, - BuiltInWorkgroupSize = 25, - BuiltInWorkgroupId = 26, - BuiltInLocalInvocationId = 27, - BuiltInGlobalInvocationId = 28, - BuiltInLocalInvocationIndex = 29, - BuiltInWorkDim = 30, - BuiltInGlobalSize = 31, - BuiltInEnqueuedWorkgroupSize = 32, - BuiltInGlobalOffset = 33, - BuiltInGlobalLinearId = 34, - BuiltInSubgroupSize = 36, - BuiltInSubgroupMaxSize = 37, - BuiltInNumSubgroups = 38, - BuiltInNumEnqueuedSubgroups = 39, - BuiltInSubgroupId = 40, - BuiltInSubgroupLocalInvocationId = 41, - BuiltInVertexIndex = 42, - BuiltInInstanceIndex = 43, - BuiltInCoreIDARM = 4160, - BuiltInCoreCountARM = 4161, - BuiltInCoreMaxIDARM = 4162, - BuiltInWarpIDARM = 4163, - BuiltInWarpMaxIDARM = 4164, - BuiltInSubgroupEqMask = 4416, - BuiltInSubgroupEqMaskKHR = 4416, - BuiltInSubgroupGeMask = 4417, - BuiltInSubgroupGeMaskKHR = 4417, - BuiltInSubgroupGtMask = 4418, - BuiltInSubgroupGtMaskKHR = 4418, - BuiltInSubgroupLeMask = 4419, - BuiltInSubgroupLeMaskKHR = 4419, - BuiltInSubgroupLtMask = 4420, - BuiltInSubgroupLtMaskKHR = 4420, - BuiltInBaseVertex = 4424, - BuiltInBaseInstance = 4425, - BuiltInDrawIndex = 4426, - BuiltInPrimitiveShadingRateKHR = 4432, - BuiltInDeviceIndex = 4438, - BuiltInViewIndex = 4440, - BuiltInShadingRateKHR = 4444, - BuiltInBaryCoordNoPerspAMD = 4992, - BuiltInBaryCoordNoPerspCentroidAMD = 4993, - BuiltInBaryCoordNoPerspSampleAMD = 4994, - BuiltInBaryCoordSmoothAMD = 4995, - BuiltInBaryCoordSmoothCentroidAMD = 4996, - BuiltInBaryCoordSmoothSampleAMD = 4997, - BuiltInBaryCoordPullModelAMD = 4998, - BuiltInFragStencilRefEXT = 5014, - BuiltInViewportMaskNV = 5253, - BuiltInSecondaryPositionNV = 5257, - BuiltInSecondaryViewportMaskNV = 5258, - BuiltInPositionPerViewNV = 5261, - BuiltInViewportMaskPerViewNV = 5262, - BuiltInFullyCoveredEXT = 5264, - BuiltInTaskCountNV = 5274, - BuiltInPrimitiveCountNV = 5275, - BuiltInPrimitiveIndicesNV = 5276, - BuiltInClipDistancePerViewNV = 5277, - BuiltInCullDistancePerViewNV = 5278, - BuiltInLayerPerViewNV = 5279, - BuiltInMeshViewCountNV = 5280, - BuiltInMeshViewIndicesNV = 5281, - BuiltInBaryCoordKHR = 5286, - BuiltInBaryCoordNV = 5286, - BuiltInBaryCoordNoPerspKHR = 5287, - BuiltInBaryCoordNoPerspNV = 5287, - BuiltInFragSizeEXT = 5292, - BuiltInFragmentSizeNV = 5292, - BuiltInFragInvocationCountEXT = 5293, - BuiltInInvocationsPerPixelNV = 5293, - BuiltInPrimitivePointIndicesEXT = 5294, - BuiltInPrimitiveLineIndicesEXT = 5295, - BuiltInPrimitiveTriangleIndicesEXT = 5296, - BuiltInCullPrimitiveEXT = 5299, - BuiltInLaunchIdKHR = 5319, - BuiltInLaunchIdNV = 5319, - BuiltInLaunchSizeKHR = 5320, - BuiltInLaunchSizeNV = 5320, - BuiltInWorldRayOriginKHR = 5321, - BuiltInWorldRayOriginNV = 5321, - BuiltInWorldRayDirectionKHR = 5322, - BuiltInWorldRayDirectionNV = 5322, - BuiltInObjectRayOriginKHR = 5323, - BuiltInObjectRayOriginNV = 5323, - BuiltInObjectRayDirectionKHR = 5324, - BuiltInObjectRayDirectionNV = 5324, - BuiltInRayTminKHR = 5325, - BuiltInRayTminNV = 5325, - BuiltInRayTmaxKHR = 5326, - BuiltInRayTmaxNV = 5326, - BuiltInInstanceCustomIndexKHR = 5327, - BuiltInInstanceCustomIndexNV = 5327, - BuiltInObjectToWorldKHR = 5330, - BuiltInObjectToWorldNV = 5330, - BuiltInWorldToObjectKHR = 5331, - BuiltInWorldToObjectNV = 5331, - BuiltInHitTNV = 5332, - BuiltInHitKindKHR = 5333, - BuiltInHitKindNV = 5333, - BuiltInCurrentRayTimeNV = 5334, - BuiltInHitTriangleVertexPositionsKHR = 5335, - BuiltInHitMicroTriangleVertexPositionsNV = 5337, - BuiltInHitMicroTriangleVertexBarycentricsNV = 5344, - BuiltInHitKindFrontFacingMicroTriangleNV = 5405, - BuiltInHitKindBackFacingMicroTriangleNV = 5406, - BuiltInIncomingRayFlagsKHR = 5351, - BuiltInIncomingRayFlagsNV = 5351, - BuiltInRayGeometryIndexKHR = 5352, - BuiltInWarpsPerSMNV = 5374, - BuiltInSMCountNV = 5375, - BuiltInWarpIDNV = 5376, - BuiltInSMIDNV = 5377, - BuiltInCullMaskKHR = 6021, - BuiltInMax = 0x7fffffff, -}; - -enum SelectionControlShift { - SelectionControlFlattenShift = 0, - SelectionControlDontFlattenShift = 1, - SelectionControlMax = 0x7fffffff, -}; - -enum SelectionControlMask { - SelectionControlMaskNone = 0, - SelectionControlFlattenMask = 0x00000001, - SelectionControlDontFlattenMask = 0x00000002, -}; - -enum LoopControlShift { - LoopControlUnrollShift = 0, - LoopControlDontUnrollShift = 1, - LoopControlDependencyInfiniteShift = 2, - LoopControlDependencyLengthShift = 3, - LoopControlMinIterationsShift = 4, - LoopControlMaxIterationsShift = 5, - LoopControlIterationMultipleShift = 6, - LoopControlPeelCountShift = 7, - LoopControlPartialCountShift = 8, - LoopControlInitiationIntervalINTELShift = 16, - LoopControlMaxConcurrencyINTELShift = 17, - LoopControlDependencyArrayINTELShift = 18, - LoopControlPipelineEnableINTELShift = 19, - LoopControlLoopCoalesceINTELShift = 20, - LoopControlMaxInterleavingINTELShift = 21, - LoopControlSpeculatedIterationsINTELShift = 22, - LoopControlNoFusionINTELShift = 23, - LoopControlLoopCountINTELShift = 24, - LoopControlMaxReinvocationDelayINTELShift = 25, - LoopControlMax = 0x7fffffff, -}; - -enum LoopControlMask { - LoopControlMaskNone = 0, - LoopControlUnrollMask = 0x00000001, - LoopControlDontUnrollMask = 0x00000002, - LoopControlDependencyInfiniteMask = 0x00000004, - LoopControlDependencyLengthMask = 0x00000008, - LoopControlMinIterationsMask = 0x00000010, - LoopControlMaxIterationsMask = 0x00000020, - LoopControlIterationMultipleMask = 0x00000040, - LoopControlPeelCountMask = 0x00000080, - LoopControlPartialCountMask = 0x00000100, - LoopControlInitiationIntervalINTELMask = 0x00010000, - LoopControlMaxConcurrencyINTELMask = 0x00020000, - LoopControlDependencyArrayINTELMask = 0x00040000, - LoopControlPipelineEnableINTELMask = 0x00080000, - LoopControlLoopCoalesceINTELMask = 0x00100000, - LoopControlMaxInterleavingINTELMask = 0x00200000, - LoopControlSpeculatedIterationsINTELMask = 0x00400000, - LoopControlNoFusionINTELMask = 0x00800000, - LoopControlLoopCountINTELMask = 0x01000000, - LoopControlMaxReinvocationDelayINTELMask = 0x02000000, -}; - -enum FunctionControlShift { - FunctionControlInlineShift = 0, - FunctionControlDontInlineShift = 1, - FunctionControlPureShift = 2, - FunctionControlConstShift = 3, - FunctionControlOptNoneINTELShift = 16, - FunctionControlMax = 0x7fffffff, -}; - -enum FunctionControlMask { - FunctionControlMaskNone = 0, - FunctionControlInlineMask = 0x00000001, - FunctionControlDontInlineMask = 0x00000002, - FunctionControlPureMask = 0x00000004, - FunctionControlConstMask = 0x00000008, - FunctionControlOptNoneINTELMask = 0x00010000, -}; - -enum MemorySemanticsShift { - MemorySemanticsAcquireShift = 1, - MemorySemanticsReleaseShift = 2, - MemorySemanticsAcquireReleaseShift = 3, - MemorySemanticsSequentiallyConsistentShift = 4, - MemorySemanticsUniformMemoryShift = 6, - MemorySemanticsSubgroupMemoryShift = 7, - MemorySemanticsWorkgroupMemoryShift = 8, - MemorySemanticsCrossWorkgroupMemoryShift = 9, - MemorySemanticsAtomicCounterMemoryShift = 10, - MemorySemanticsImageMemoryShift = 11, - MemorySemanticsOutputMemoryShift = 12, - MemorySemanticsOutputMemoryKHRShift = 12, - MemorySemanticsMakeAvailableShift = 13, - MemorySemanticsMakeAvailableKHRShift = 13, - MemorySemanticsMakeVisibleShift = 14, - MemorySemanticsMakeVisibleKHRShift = 14, - MemorySemanticsVolatileShift = 15, - MemorySemanticsMax = 0x7fffffff, -}; - -enum MemorySemanticsMask { - MemorySemanticsMaskNone = 0, - MemorySemanticsAcquireMask = 0x00000002, - MemorySemanticsReleaseMask = 0x00000004, - MemorySemanticsAcquireReleaseMask = 0x00000008, - MemorySemanticsSequentiallyConsistentMask = 0x00000010, - MemorySemanticsUniformMemoryMask = 0x00000040, - MemorySemanticsSubgroupMemoryMask = 0x00000080, - MemorySemanticsWorkgroupMemoryMask = 0x00000100, - MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, - MemorySemanticsAtomicCounterMemoryMask = 0x00000400, - MemorySemanticsImageMemoryMask = 0x00000800, - MemorySemanticsOutputMemoryMask = 0x00001000, - MemorySemanticsOutputMemoryKHRMask = 0x00001000, - MemorySemanticsMakeAvailableMask = 0x00002000, - MemorySemanticsMakeAvailableKHRMask = 0x00002000, - MemorySemanticsMakeVisibleMask = 0x00004000, - MemorySemanticsMakeVisibleKHRMask = 0x00004000, - MemorySemanticsVolatileMask = 0x00008000, -}; - -enum MemoryAccessShift { - MemoryAccessVolatileShift = 0, - MemoryAccessAlignedShift = 1, - MemoryAccessNontemporalShift = 2, - MemoryAccessMakePointerAvailableShift = 3, - MemoryAccessMakePointerAvailableKHRShift = 3, - MemoryAccessMakePointerVisibleShift = 4, - MemoryAccessMakePointerVisibleKHRShift = 4, - MemoryAccessNonPrivatePointerShift = 5, - MemoryAccessNonPrivatePointerKHRShift = 5, - MemoryAccessAliasScopeINTELMaskShift = 16, - MemoryAccessNoAliasINTELMaskShift = 17, - MemoryAccessMax = 0x7fffffff, -}; - -enum MemoryAccessMask { - MemoryAccessMaskNone = 0, - MemoryAccessVolatileMask = 0x00000001, - MemoryAccessAlignedMask = 0x00000002, - MemoryAccessNontemporalMask = 0x00000004, - MemoryAccessMakePointerAvailableMask = 0x00000008, - MemoryAccessMakePointerAvailableKHRMask = 0x00000008, - MemoryAccessMakePointerVisibleMask = 0x00000010, - MemoryAccessMakePointerVisibleKHRMask = 0x00000010, - MemoryAccessNonPrivatePointerMask = 0x00000020, - MemoryAccessNonPrivatePointerKHRMask = 0x00000020, - MemoryAccessAliasScopeINTELMaskMask = 0x00010000, - MemoryAccessNoAliasINTELMaskMask = 0x00020000, -}; - -enum Scope { - ScopeCrossDevice = 0, - ScopeDevice = 1, - ScopeWorkgroup = 2, - ScopeSubgroup = 3, - ScopeInvocation = 4, - ScopeQueueFamily = 5, - ScopeQueueFamilyKHR = 5, - ScopeShaderCallKHR = 6, - ScopeMax = 0x7fffffff, -}; - -enum GroupOperation { - GroupOperationReduce = 0, - GroupOperationInclusiveScan = 1, - GroupOperationExclusiveScan = 2, - GroupOperationClusteredReduce = 3, - GroupOperationPartitionedReduceNV = 6, - GroupOperationPartitionedInclusiveScanNV = 7, - GroupOperationPartitionedExclusiveScanNV = 8, - GroupOperationMax = 0x7fffffff, -}; - -enum KernelEnqueueFlags { - KernelEnqueueFlagsNoWait = 0, - KernelEnqueueFlagsWaitKernel = 1, - KernelEnqueueFlagsWaitWorkGroup = 2, - KernelEnqueueFlagsMax = 0x7fffffff, -}; - -enum KernelProfilingInfoShift { - KernelProfilingInfoCmdExecTimeShift = 0, - KernelProfilingInfoMax = 0x7fffffff, -}; - -enum KernelProfilingInfoMask { - KernelProfilingInfoMaskNone = 0, - KernelProfilingInfoCmdExecTimeMask = 0x00000001, -}; - -enum Capability { - CapabilityMatrix = 0, - CapabilityShader = 1, - CapabilityGeometry = 2, - CapabilityTessellation = 3, - CapabilityAddresses = 4, - CapabilityLinkage = 5, - CapabilityKernel = 6, - CapabilityVector16 = 7, - CapabilityFloat16Buffer = 8, - CapabilityFloat16 = 9, - CapabilityFloat64 = 10, - CapabilityInt64 = 11, - CapabilityInt64Atomics = 12, - CapabilityImageBasic = 13, - CapabilityImageReadWrite = 14, - CapabilityImageMipmap = 15, - CapabilityPipes = 17, - CapabilityGroups = 18, - CapabilityDeviceEnqueue = 19, - CapabilityLiteralSampler = 20, - CapabilityAtomicStorage = 21, - CapabilityInt16 = 22, - CapabilityTessellationPointSize = 23, - CapabilityGeometryPointSize = 24, - CapabilityImageGatherExtended = 25, - CapabilityStorageImageMultisample = 27, - CapabilityUniformBufferArrayDynamicIndexing = 28, - CapabilitySampledImageArrayDynamicIndexing = 29, - CapabilityStorageBufferArrayDynamicIndexing = 30, - CapabilityStorageImageArrayDynamicIndexing = 31, - CapabilityClipDistance = 32, - CapabilityCullDistance = 33, - CapabilityImageCubeArray = 34, - CapabilitySampleRateShading = 35, - CapabilityImageRect = 36, - CapabilitySampledRect = 37, - CapabilityGenericPointer = 38, - CapabilityInt8 = 39, - CapabilityInputAttachment = 40, - CapabilitySparseResidency = 41, - CapabilityMinLod = 42, - CapabilitySampled1D = 43, - CapabilityImage1D = 44, - CapabilitySampledCubeArray = 45, - CapabilitySampledBuffer = 46, - CapabilityImageBuffer = 47, - CapabilityImageMSArray = 48, - CapabilityStorageImageExtendedFormats = 49, - CapabilityImageQuery = 50, - CapabilityDerivativeControl = 51, - CapabilityInterpolationFunction = 52, - CapabilityTransformFeedback = 53, - CapabilityGeometryStreams = 54, - CapabilityStorageImageReadWithoutFormat = 55, - CapabilityStorageImageWriteWithoutFormat = 56, - CapabilityMultiViewport = 57, - CapabilitySubgroupDispatch = 58, - CapabilityNamedBarrier = 59, - CapabilityPipeStorage = 60, - CapabilityGroupNonUniform = 61, - CapabilityGroupNonUniformVote = 62, - CapabilityGroupNonUniformArithmetic = 63, - CapabilityGroupNonUniformBallot = 64, - CapabilityGroupNonUniformShuffle = 65, - CapabilityGroupNonUniformShuffleRelative = 66, - CapabilityGroupNonUniformClustered = 67, - CapabilityGroupNonUniformQuad = 68, - CapabilityShaderLayer = 69, - CapabilityShaderViewportIndex = 70, - CapabilityUniformDecoration = 71, - CapabilityCoreBuiltinsARM = 4165, - CapabilityTileImageColorReadAccessEXT = 4166, - CapabilityTileImageDepthReadAccessEXT = 4167, - CapabilityTileImageStencilReadAccessEXT = 4168, - CapabilityFragmentShadingRateKHR = 4422, - CapabilitySubgroupBallotKHR = 4423, - CapabilityDrawParameters = 4427, - CapabilityWorkgroupMemoryExplicitLayoutKHR = 4428, - CapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR = 4429, - CapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR = 4430, - CapabilitySubgroupVoteKHR = 4431, - CapabilityStorageBuffer16BitAccess = 4433, - CapabilityStorageUniformBufferBlock16 = 4433, - CapabilityStorageUniform16 = 4434, - CapabilityUniformAndStorageBuffer16BitAccess = 4434, - CapabilityStoragePushConstant16 = 4435, - CapabilityStorageInputOutput16 = 4436, - CapabilityDeviceGroup = 4437, - CapabilityMultiView = 4439, - CapabilityVariablePointersStorageBuffer = 4441, - CapabilityVariablePointers = 4442, - CapabilityAtomicStorageOps = 4445, - CapabilitySampleMaskPostDepthCoverage = 4447, - CapabilityStorageBuffer8BitAccess = 4448, - CapabilityUniformAndStorageBuffer8BitAccess = 4449, - CapabilityStoragePushConstant8 = 4450, - CapabilityDenormPreserve = 4464, - CapabilityDenormFlushToZero = 4465, - CapabilitySignedZeroInfNanPreserve = 4466, - CapabilityRoundingModeRTE = 4467, - CapabilityRoundingModeRTZ = 4468, - CapabilityRayQueryProvisionalKHR = 4471, - CapabilityRayQueryKHR = 4472, - CapabilityRayTraversalPrimitiveCullingKHR = 4478, - CapabilityRayTracingKHR = 4479, - CapabilityTextureSampleWeightedQCOM = 4484, - CapabilityTextureBoxFilterQCOM = 4485, - CapabilityTextureBlockMatchQCOM = 4486, - CapabilityFloat16ImageAMD = 5008, - CapabilityImageGatherBiasLodAMD = 5009, - CapabilityFragmentMaskAMD = 5010, - CapabilityStencilExportEXT = 5013, - CapabilityImageReadWriteLodAMD = 5015, - CapabilityInt64ImageEXT = 5016, - CapabilityShaderClockKHR = 5055, - CapabilitySampleMaskOverrideCoverageNV = 5249, - CapabilityGeometryShaderPassthroughNV = 5251, - CapabilityShaderViewportIndexLayerEXT = 5254, - CapabilityShaderViewportIndexLayerNV = 5254, - CapabilityShaderViewportMaskNV = 5255, - CapabilityShaderStereoViewNV = 5259, - CapabilityPerViewAttributesNV = 5260, - CapabilityFragmentFullyCoveredEXT = 5265, - CapabilityMeshShadingNV = 5266, - CapabilityImageFootprintNV = 5282, - CapabilityMeshShadingEXT = 5283, - CapabilityFragmentBarycentricKHR = 5284, - CapabilityFragmentBarycentricNV = 5284, - CapabilityComputeDerivativeGroupQuadsNV = 5288, - CapabilityFragmentDensityEXT = 5291, - CapabilityShadingRateNV = 5291, - CapabilityGroupNonUniformPartitionedNV = 5297, - CapabilityShaderNonUniform = 5301, - CapabilityShaderNonUniformEXT = 5301, - CapabilityRuntimeDescriptorArray = 5302, - CapabilityRuntimeDescriptorArrayEXT = 5302, - CapabilityInputAttachmentArrayDynamicIndexing = 5303, - CapabilityInputAttachmentArrayDynamicIndexingEXT = 5303, - CapabilityUniformTexelBufferArrayDynamicIndexing = 5304, - CapabilityUniformTexelBufferArrayDynamicIndexingEXT = 5304, - CapabilityStorageTexelBufferArrayDynamicIndexing = 5305, - CapabilityStorageTexelBufferArrayDynamicIndexingEXT = 5305, - CapabilityUniformBufferArrayNonUniformIndexing = 5306, - CapabilityUniformBufferArrayNonUniformIndexingEXT = 5306, - CapabilitySampledImageArrayNonUniformIndexing = 5307, - CapabilitySampledImageArrayNonUniformIndexingEXT = 5307, - CapabilityStorageBufferArrayNonUniformIndexing = 5308, - CapabilityStorageBufferArrayNonUniformIndexingEXT = 5308, - CapabilityStorageImageArrayNonUniformIndexing = 5309, - CapabilityStorageImageArrayNonUniformIndexingEXT = 5309, - CapabilityInputAttachmentArrayNonUniformIndexing = 5310, - CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, - CapabilityUniformTexelBufferArrayNonUniformIndexing = 5311, - CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, - CapabilityStorageTexelBufferArrayNonUniformIndexing = 5312, - CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, - CapabilityRayTracingPositionFetchKHR = 5336, - CapabilityRayTracingNV = 5340, - CapabilityRayTracingMotionBlurNV = 5341, - CapabilityVulkanMemoryModel = 5345, - CapabilityVulkanMemoryModelKHR = 5345, - CapabilityVulkanMemoryModelDeviceScope = 5346, - CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, - CapabilityPhysicalStorageBufferAddresses = 5347, - CapabilityPhysicalStorageBufferAddressesEXT = 5347, - CapabilityComputeDerivativeGroupLinearNV = 5350, - CapabilityRayTracingProvisionalKHR = 5353, - CapabilityCooperativeMatrixNV = 5357, - CapabilityFragmentShaderSampleInterlockEXT = 5363, - CapabilityFragmentShaderShadingRateInterlockEXT = 5372, - CapabilityShaderSMBuiltinsNV = 5373, - CapabilityFragmentShaderPixelInterlockEXT = 5378, - CapabilityDemoteToHelperInvocation = 5379, - CapabilityDemoteToHelperInvocationEXT = 5379, - CapabilityDisplacementMicromapNV = 5380, - CapabilityRayTracingDisplacementMicromapNV = 5409, - CapabilityRayTracingOpacityMicromapEXT = 5381, - CapabilityShaderInvocationReorderNV = 5383, - CapabilityBindlessTextureNV = 5390, - CapabilityRayQueryPositionFetchKHR = 5391, - CapabilitySubgroupShuffleINTEL = 5568, - CapabilitySubgroupBufferBlockIOINTEL = 5569, - CapabilitySubgroupImageBlockIOINTEL = 5570, - CapabilitySubgroupImageMediaBlockIOINTEL = 5579, - CapabilityRoundToInfinityINTEL = 5582, - CapabilityFloatingPointModeINTEL = 5583, - CapabilityIntegerFunctions2INTEL = 5584, - CapabilityFunctionPointersINTEL = 5603, - CapabilityIndirectReferencesINTEL = 5604, - CapabilityAsmINTEL = 5606, - CapabilityAtomicFloat32MinMaxEXT = 5612, - CapabilityAtomicFloat64MinMaxEXT = 5613, - CapabilityAtomicFloat16MinMaxEXT = 5616, - CapabilityVectorComputeINTEL = 5617, - CapabilityVectorAnyINTEL = 5619, - CapabilityExpectAssumeKHR = 5629, - CapabilitySubgroupAvcMotionEstimationINTEL = 5696, - CapabilitySubgroupAvcMotionEstimationIntraINTEL = 5697, - CapabilitySubgroupAvcMotionEstimationChromaINTEL = 5698, - CapabilityVariableLengthArrayINTEL = 5817, - CapabilityFunctionFloatControlINTEL = 5821, - CapabilityFPGAMemoryAttributesINTEL = 5824, - CapabilityFPFastMathModeINTEL = 5837, - CapabilityArbitraryPrecisionIntegersINTEL = 5844, - CapabilityArbitraryPrecisionFloatingPointINTEL = 5845, - CapabilityUnstructuredLoopControlsINTEL = 5886, - CapabilityFPGALoopControlsINTEL = 5888, - CapabilityKernelAttributesINTEL = 5892, - CapabilityFPGAKernelAttributesINTEL = 5897, - CapabilityFPGAMemoryAccessesINTEL = 5898, - CapabilityFPGAClusterAttributesINTEL = 5904, - CapabilityLoopFuseINTEL = 5906, - CapabilityFPGADSPControlINTEL = 5908, - CapabilityMemoryAccessAliasingINTEL = 5910, - CapabilityFPGAInvocationPipeliningAttributesINTEL = 5916, - CapabilityFPGABufferLocationINTEL = 5920, - CapabilityArbitraryPrecisionFixedPointINTEL = 5922, - CapabilityUSMStorageClassesINTEL = 5935, - CapabilityRuntimeAlignedAttributeINTEL = 5939, - CapabilityIOPipesINTEL = 5943, - CapabilityBlockingPipesINTEL = 5945, - CapabilityFPGARegINTEL = 5948, - CapabilityDotProductInputAll = 6016, - CapabilityDotProductInputAllKHR = 6016, - CapabilityDotProductInput4x8Bit = 6017, - CapabilityDotProductInput4x8BitKHR = 6017, - CapabilityDotProductInput4x8BitPacked = 6018, - CapabilityDotProductInput4x8BitPackedKHR = 6018, - CapabilityDotProduct = 6019, - CapabilityDotProductKHR = 6019, - CapabilityRayCullMaskKHR = 6020, - CapabilityCooperativeMatrixKHR = 6022, - CapabilityBitInstructions = 6025, - CapabilityGroupNonUniformRotateKHR = 6026, - CapabilityAtomicFloat32AddEXT = 6033, - CapabilityAtomicFloat64AddEXT = 6034, - CapabilityLongConstantCompositeINTEL = 6089, - CapabilityOptNoneINTEL = 6094, - CapabilityAtomicFloat16AddEXT = 6095, - CapabilityDebugInfoModuleINTEL = 6114, - CapabilitySplitBarrierINTEL = 6141, - CapabilityFPGAArgumentInterfacesINTEL = 6174, - CapabilityGroupUniformArithmeticKHR = 6400, - CapabilityMax = 0x7fffffff, -}; - -enum RayFlagsShift { - RayFlagsOpaqueKHRShift = 0, - RayFlagsNoOpaqueKHRShift = 1, - RayFlagsTerminateOnFirstHitKHRShift = 2, - RayFlagsSkipClosestHitShaderKHRShift = 3, - RayFlagsCullBackFacingTrianglesKHRShift = 4, - RayFlagsCullFrontFacingTrianglesKHRShift = 5, - RayFlagsCullOpaqueKHRShift = 6, - RayFlagsCullNoOpaqueKHRShift = 7, - RayFlagsSkipTrianglesKHRShift = 8, - RayFlagsSkipAABBsKHRShift = 9, - RayFlagsForceOpacityMicromap2StateEXTShift = 10, - RayFlagsMax = 0x7fffffff, -}; - -enum RayFlagsMask { - RayFlagsMaskNone = 0, - RayFlagsOpaqueKHRMask = 0x00000001, - RayFlagsNoOpaqueKHRMask = 0x00000002, - RayFlagsTerminateOnFirstHitKHRMask = 0x00000004, - RayFlagsSkipClosestHitShaderKHRMask = 0x00000008, - RayFlagsCullBackFacingTrianglesKHRMask = 0x00000010, - RayFlagsCullFrontFacingTrianglesKHRMask = 0x00000020, - RayFlagsCullOpaqueKHRMask = 0x00000040, - RayFlagsCullNoOpaqueKHRMask = 0x00000080, - RayFlagsSkipTrianglesKHRMask = 0x00000100, - RayFlagsSkipAABBsKHRMask = 0x00000200, - RayFlagsForceOpacityMicromap2StateEXTMask = 0x00000400, -}; - -enum RayQueryIntersection { - RayQueryIntersectionRayQueryCandidateIntersectionKHR = 0, - RayQueryIntersectionRayQueryCommittedIntersectionKHR = 1, - RayQueryIntersectionMax = 0x7fffffff, -}; - -enum RayQueryCommittedIntersectionType { - RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionNoneKHR = 0, - RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionTriangleKHR = 1, - RayQueryCommittedIntersectionTypeRayQueryCommittedIntersectionGeneratedKHR = 2, - RayQueryCommittedIntersectionTypeMax = 0x7fffffff, -}; - -enum RayQueryCandidateIntersectionType { - RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionTriangleKHR = 0, - RayQueryCandidateIntersectionTypeRayQueryCandidateIntersectionAABBKHR = 1, - RayQueryCandidateIntersectionTypeMax = 0x7fffffff, -}; - -enum FragmentShadingRateShift { - FragmentShadingRateVertical2PixelsShift = 0, - FragmentShadingRateVertical4PixelsShift = 1, - FragmentShadingRateHorizontal2PixelsShift = 2, - FragmentShadingRateHorizontal4PixelsShift = 3, - FragmentShadingRateMax = 0x7fffffff, -}; - -enum FragmentShadingRateMask { - FragmentShadingRateMaskNone = 0, - FragmentShadingRateVertical2PixelsMask = 0x00000001, - FragmentShadingRateVertical4PixelsMask = 0x00000002, - FragmentShadingRateHorizontal2PixelsMask = 0x00000004, - FragmentShadingRateHorizontal4PixelsMask = 0x00000008, -}; - -enum FPDenormMode { - FPDenormModePreserve = 0, - FPDenormModeFlushToZero = 1, - FPDenormModeMax = 0x7fffffff, -}; - -enum FPOperationMode { - FPOperationModeIEEE = 0, - FPOperationModeALT = 1, - FPOperationModeMax = 0x7fffffff, -}; - -enum QuantizationModes { - QuantizationModesTRN = 0, - QuantizationModesTRN_ZERO = 1, - QuantizationModesRND = 2, - QuantizationModesRND_ZERO = 3, - QuantizationModesRND_INF = 4, - QuantizationModesRND_MIN_INF = 5, - QuantizationModesRND_CONV = 6, - QuantizationModesRND_CONV_ODD = 7, - QuantizationModesMax = 0x7fffffff, -}; - -enum OverflowModes { - OverflowModesWRAP = 0, - OverflowModesSAT = 1, - OverflowModesSAT_ZERO = 2, - OverflowModesSAT_SYM = 3, - OverflowModesMax = 0x7fffffff, -}; - -enum PackedVectorFormat { - PackedVectorFormatPackedVectorFormat4x8Bit = 0, - PackedVectorFormatPackedVectorFormat4x8BitKHR = 0, - PackedVectorFormatMax = 0x7fffffff, -}; - -enum CooperativeMatrixOperandsShift { - CooperativeMatrixOperandsMatrixASignedComponentsKHRShift = 0, - CooperativeMatrixOperandsMatrixBSignedComponentsKHRShift = 1, - CooperativeMatrixOperandsMatrixCSignedComponentsKHRShift = 2, - CooperativeMatrixOperandsMatrixResultSignedComponentsKHRShift = 3, - CooperativeMatrixOperandsSaturatingAccumulationKHRShift = 4, - CooperativeMatrixOperandsMax = 0x7fffffff, -}; - -enum CooperativeMatrixOperandsMask { - CooperativeMatrixOperandsMaskNone = 0, - CooperativeMatrixOperandsMatrixASignedComponentsKHRMask = 0x00000001, - CooperativeMatrixOperandsMatrixBSignedComponentsKHRMask = 0x00000002, - CooperativeMatrixOperandsMatrixCSignedComponentsKHRMask = 0x00000004, - CooperativeMatrixOperandsMatrixResultSignedComponentsKHRMask = 0x00000008, - CooperativeMatrixOperandsSaturatingAccumulationKHRMask = 0x00000010, -}; - -enum CooperativeMatrixLayout { - CooperativeMatrixLayoutRowMajorKHR = 0, - CooperativeMatrixLayoutColumnMajorKHR = 1, - CooperativeMatrixLayoutMax = 0x7fffffff, -}; - -enum CooperativeMatrixUse { - CooperativeMatrixUseMatrixAKHR = 0, - CooperativeMatrixUseMatrixBKHR = 1, - CooperativeMatrixUseMatrixAccumulatorKHR = 2, - CooperativeMatrixUseMax = 0x7fffffff, -}; - -enum Op { - OpNop = 0, - OpUndef = 1, - OpSourceContinued = 2, - OpSource = 3, - OpSourceExtension = 4, - OpName = 5, - OpMemberName = 6, - OpString = 7, - OpLine = 8, - OpExtension = 10, - OpExtInstImport = 11, - OpExtInst = 12, - OpMemoryModel = 14, - OpEntryPoint = 15, - OpExecutionMode = 16, - OpCapability = 17, - OpTypeVoid = 19, - OpTypeBool = 20, - OpTypeInt = 21, - OpTypeFloat = 22, - OpTypeVector = 23, - OpTypeMatrix = 24, - OpTypeImage = 25, - OpTypeSampler = 26, - OpTypeSampledImage = 27, - OpTypeArray = 28, - OpTypeRuntimeArray = 29, - OpTypeStruct = 30, - OpTypeOpaque = 31, - OpTypePointer = 32, - OpTypeFunction = 33, - OpTypeEvent = 34, - OpTypeDeviceEvent = 35, - OpTypeReserveId = 36, - OpTypeQueue = 37, - OpTypePipe = 38, - OpTypeForwardPointer = 39, - OpConstantTrue = 41, - OpConstantFalse = 42, - OpConstant = 43, - OpConstantComposite = 44, - OpConstantSampler = 45, - OpConstantNull = 46, - OpSpecConstantTrue = 48, - OpSpecConstantFalse = 49, - OpSpecConstant = 50, - OpSpecConstantComposite = 51, - OpSpecConstantOp = 52, - OpFunction = 54, - OpFunctionParameter = 55, - OpFunctionEnd = 56, - OpFunctionCall = 57, - OpVariable = 59, - OpImageTexelPointer = 60, - OpLoad = 61, - OpStore = 62, - OpCopyMemory = 63, - OpCopyMemorySized = 64, - OpAccessChain = 65, - OpInBoundsAccessChain = 66, - OpPtrAccessChain = 67, - OpArrayLength = 68, - OpGenericPtrMemSemantics = 69, - OpInBoundsPtrAccessChain = 70, - OpDecorate = 71, - OpMemberDecorate = 72, - OpDecorationGroup = 73, - OpGroupDecorate = 74, - OpGroupMemberDecorate = 75, - OpVectorExtractDynamic = 77, - OpVectorInsertDynamic = 78, - OpVectorShuffle = 79, - OpCompositeConstruct = 80, - OpCompositeExtract = 81, - OpCompositeInsert = 82, - OpCopyObject = 83, - OpTranspose = 84, - OpSampledImage = 86, - OpImageSampleImplicitLod = 87, - OpImageSampleExplicitLod = 88, - OpImageSampleDrefImplicitLod = 89, - OpImageSampleDrefExplicitLod = 90, - OpImageSampleProjImplicitLod = 91, - OpImageSampleProjExplicitLod = 92, - OpImageSampleProjDrefImplicitLod = 93, - OpImageSampleProjDrefExplicitLod = 94, - OpImageFetch = 95, - OpImageGather = 96, - OpImageDrefGather = 97, - OpImageRead = 98, - OpImageWrite = 99, - OpImage = 100, - OpImageQueryFormat = 101, - OpImageQueryOrder = 102, - OpImageQuerySizeLod = 103, - OpImageQuerySize = 104, - OpImageQueryLod = 105, - OpImageQueryLevels = 106, - OpImageQuerySamples = 107, - OpConvertFToU = 109, - OpConvertFToS = 110, - OpConvertSToF = 111, - OpConvertUToF = 112, - OpUConvert = 113, - OpSConvert = 114, - OpFConvert = 115, - OpQuantizeToF16 = 116, - OpConvertPtrToU = 117, - OpSatConvertSToU = 118, - OpSatConvertUToS = 119, - OpConvertUToPtr = 120, - OpPtrCastToGeneric = 121, - OpGenericCastToPtr = 122, - OpGenericCastToPtrExplicit = 123, - OpBitcast = 124, - OpSNegate = 126, - OpFNegate = 127, - OpIAdd = 128, - OpFAdd = 129, - OpISub = 130, - OpFSub = 131, - OpIMul = 132, - OpFMul = 133, - OpUDiv = 134, - OpSDiv = 135, - OpFDiv = 136, - OpUMod = 137, - OpSRem = 138, - OpSMod = 139, - OpFRem = 140, - OpFMod = 141, - OpVectorTimesScalar = 142, - OpMatrixTimesScalar = 143, - OpVectorTimesMatrix = 144, - OpMatrixTimesVector = 145, - OpMatrixTimesMatrix = 146, - OpOuterProduct = 147, - OpDot = 148, - OpIAddCarry = 149, - OpISubBorrow = 150, - OpUMulExtended = 151, - OpSMulExtended = 152, - OpAny = 154, - OpAll = 155, - OpIsNan = 156, - OpIsInf = 157, - OpIsFinite = 158, - OpIsNormal = 159, - OpSignBitSet = 160, - OpLessOrGreater = 161, - OpOrdered = 162, - OpUnordered = 163, - OpLogicalEqual = 164, - OpLogicalNotEqual = 165, - OpLogicalOr = 166, - OpLogicalAnd = 167, - OpLogicalNot = 168, - OpSelect = 169, - OpIEqual = 170, - OpINotEqual = 171, - OpUGreaterThan = 172, - OpSGreaterThan = 173, - OpUGreaterThanEqual = 174, - OpSGreaterThanEqual = 175, - OpULessThan = 176, - OpSLessThan = 177, - OpULessThanEqual = 178, - OpSLessThanEqual = 179, - OpFOrdEqual = 180, - OpFUnordEqual = 181, - OpFOrdNotEqual = 182, - OpFUnordNotEqual = 183, - OpFOrdLessThan = 184, - OpFUnordLessThan = 185, - OpFOrdGreaterThan = 186, - OpFUnordGreaterThan = 187, - OpFOrdLessThanEqual = 188, - OpFUnordLessThanEqual = 189, - OpFOrdGreaterThanEqual = 190, - OpFUnordGreaterThanEqual = 191, - OpShiftRightLogical = 194, - OpShiftRightArithmetic = 195, - OpShiftLeftLogical = 196, - OpBitwiseOr = 197, - OpBitwiseXor = 198, - OpBitwiseAnd = 199, - OpNot = 200, - OpBitFieldInsert = 201, - OpBitFieldSExtract = 202, - OpBitFieldUExtract = 203, - OpBitReverse = 204, - OpBitCount = 205, - OpDPdx = 207, - OpDPdy = 208, - OpFwidth = 209, - OpDPdxFine = 210, - OpDPdyFine = 211, - OpFwidthFine = 212, - OpDPdxCoarse = 213, - OpDPdyCoarse = 214, - OpFwidthCoarse = 215, - OpEmitVertex = 218, - OpEndPrimitive = 219, - OpEmitStreamVertex = 220, - OpEndStreamPrimitive = 221, - OpControlBarrier = 224, - OpMemoryBarrier = 225, - OpAtomicLoad = 227, - OpAtomicStore = 228, - OpAtomicExchange = 229, - OpAtomicCompareExchange = 230, - OpAtomicCompareExchangeWeak = 231, - OpAtomicIIncrement = 232, - OpAtomicIDecrement = 233, - OpAtomicIAdd = 234, - OpAtomicISub = 235, - OpAtomicSMin = 236, - OpAtomicUMin = 237, - OpAtomicSMax = 238, - OpAtomicUMax = 239, - OpAtomicAnd = 240, - OpAtomicOr = 241, - OpAtomicXor = 242, - OpPhi = 245, - OpLoopMerge = 246, - OpSelectionMerge = 247, - OpLabel = 248, - OpBranch = 249, - OpBranchConditional = 250, - OpSwitch = 251, - OpKill = 252, - OpReturn = 253, - OpReturnValue = 254, - OpUnreachable = 255, - OpLifetimeStart = 256, - OpLifetimeStop = 257, - OpGroupAsyncCopy = 259, - OpGroupWaitEvents = 260, - OpGroupAll = 261, - OpGroupAny = 262, - OpGroupBroadcast = 263, - OpGroupIAdd = 264, - OpGroupFAdd = 265, - OpGroupFMin = 266, - OpGroupUMin = 267, - OpGroupSMin = 268, - OpGroupFMax = 269, - OpGroupUMax = 270, - OpGroupSMax = 271, - OpReadPipe = 274, - OpWritePipe = 275, - OpReservedReadPipe = 276, - OpReservedWritePipe = 277, - OpReserveReadPipePackets = 278, - OpReserveWritePipePackets = 279, - OpCommitReadPipe = 280, - OpCommitWritePipe = 281, - OpIsValidReserveId = 282, - OpGetNumPipePackets = 283, - OpGetMaxPipePackets = 284, - OpGroupReserveReadPipePackets = 285, - OpGroupReserveWritePipePackets = 286, - OpGroupCommitReadPipe = 287, - OpGroupCommitWritePipe = 288, - OpEnqueueMarker = 291, - OpEnqueueKernel = 292, - OpGetKernelNDrangeSubGroupCount = 293, - OpGetKernelNDrangeMaxSubGroupSize = 294, - OpGetKernelWorkGroupSize = 295, - OpGetKernelPreferredWorkGroupSizeMultiple = 296, - OpRetainEvent = 297, - OpReleaseEvent = 298, - OpCreateUserEvent = 299, - OpIsValidEvent = 300, - OpSetUserEventStatus = 301, - OpCaptureEventProfilingInfo = 302, - OpGetDefaultQueue = 303, - OpBuildNDRange = 304, - OpImageSparseSampleImplicitLod = 305, - OpImageSparseSampleExplicitLod = 306, - OpImageSparseSampleDrefImplicitLod = 307, - OpImageSparseSampleDrefExplicitLod = 308, - OpImageSparseSampleProjImplicitLod = 309, - OpImageSparseSampleProjExplicitLod = 310, - OpImageSparseSampleProjDrefImplicitLod = 311, - OpImageSparseSampleProjDrefExplicitLod = 312, - OpImageSparseFetch = 313, - OpImageSparseGather = 314, - OpImageSparseDrefGather = 315, - OpImageSparseTexelsResident = 316, - OpNoLine = 317, - OpAtomicFlagTestAndSet = 318, - OpAtomicFlagClear = 319, - OpImageSparseRead = 320, - OpSizeOf = 321, - OpTypePipeStorage = 322, - OpConstantPipeStorage = 323, - OpCreatePipeFromPipeStorage = 324, - OpGetKernelLocalSizeForSubgroupCount = 325, - OpGetKernelMaxNumSubgroups = 326, - OpTypeNamedBarrier = 327, - OpNamedBarrierInitialize = 328, - OpMemoryNamedBarrier = 329, - OpModuleProcessed = 330, - OpExecutionModeId = 331, - OpDecorateId = 332, - OpGroupNonUniformElect = 333, - OpGroupNonUniformAll = 334, - OpGroupNonUniformAny = 335, - OpGroupNonUniformAllEqual = 336, - OpGroupNonUniformBroadcast = 337, - OpGroupNonUniformBroadcastFirst = 338, - OpGroupNonUniformBallot = 339, - OpGroupNonUniformInverseBallot = 340, - OpGroupNonUniformBallotBitExtract = 341, - OpGroupNonUniformBallotBitCount = 342, - OpGroupNonUniformBallotFindLSB = 343, - OpGroupNonUniformBallotFindMSB = 344, - OpGroupNonUniformShuffle = 345, - OpGroupNonUniformShuffleXor = 346, - OpGroupNonUniformShuffleUp = 347, - OpGroupNonUniformShuffleDown = 348, - OpGroupNonUniformIAdd = 349, - OpGroupNonUniformFAdd = 350, - OpGroupNonUniformIMul = 351, - OpGroupNonUniformFMul = 352, - OpGroupNonUniformSMin = 353, - OpGroupNonUniformUMin = 354, - OpGroupNonUniformFMin = 355, - OpGroupNonUniformSMax = 356, - OpGroupNonUniformUMax = 357, - OpGroupNonUniformFMax = 358, - OpGroupNonUniformBitwiseAnd = 359, - OpGroupNonUniformBitwiseOr = 360, - OpGroupNonUniformBitwiseXor = 361, - OpGroupNonUniformLogicalAnd = 362, - OpGroupNonUniformLogicalOr = 363, - OpGroupNonUniformLogicalXor = 364, - OpGroupNonUniformQuadBroadcast = 365, - OpGroupNonUniformQuadSwap = 366, - OpCopyLogical = 400, - OpPtrEqual = 401, - OpPtrNotEqual = 402, - OpPtrDiff = 403, - OpColorAttachmentReadEXT = 4160, - OpDepthAttachmentReadEXT = 4161, - OpStencilAttachmentReadEXT = 4162, - OpTerminateInvocation = 4416, - OpSubgroupBallotKHR = 4421, - OpSubgroupFirstInvocationKHR = 4422, - OpSubgroupAllKHR = 4428, - OpSubgroupAnyKHR = 4429, - OpSubgroupAllEqualKHR = 4430, - OpGroupNonUniformRotateKHR = 4431, - OpSubgroupReadInvocationKHR = 4432, - OpTraceRayKHR = 4445, - OpExecuteCallableKHR = 4446, - OpConvertUToAccelerationStructureKHR = 4447, - OpIgnoreIntersectionKHR = 4448, - OpTerminateRayKHR = 4449, - OpSDot = 4450, - OpSDotKHR = 4450, - OpUDot = 4451, - OpUDotKHR = 4451, - OpSUDot = 4452, - OpSUDotKHR = 4452, - OpSDotAccSat = 4453, - OpSDotAccSatKHR = 4453, - OpUDotAccSat = 4454, - OpUDotAccSatKHR = 4454, - OpSUDotAccSat = 4455, - OpSUDotAccSatKHR = 4455, - OpTypeCooperativeMatrixKHR = 4456, - OpCooperativeMatrixLoadKHR = 4457, - OpCooperativeMatrixStoreKHR = 4458, - OpCooperativeMatrixMulAddKHR = 4459, - OpCooperativeMatrixLengthKHR = 4460, - OpTypeRayQueryKHR = 4472, - OpRayQueryInitializeKHR = 4473, - OpRayQueryTerminateKHR = 4474, - OpRayQueryGenerateIntersectionKHR = 4475, - OpRayQueryConfirmIntersectionKHR = 4476, - OpRayQueryProceedKHR = 4477, - OpRayQueryGetIntersectionTypeKHR = 4479, - OpImageSampleWeightedQCOM = 4480, - OpImageBoxFilterQCOM = 4481, - OpImageBlockMatchSSDQCOM = 4482, - OpImageBlockMatchSADQCOM = 4483, - OpGroupIAddNonUniformAMD = 5000, - OpGroupFAddNonUniformAMD = 5001, - OpGroupFMinNonUniformAMD = 5002, - OpGroupUMinNonUniformAMD = 5003, - OpGroupSMinNonUniformAMD = 5004, - OpGroupFMaxNonUniformAMD = 5005, - OpGroupUMaxNonUniformAMD = 5006, - OpGroupSMaxNonUniformAMD = 5007, - OpFragmentMaskFetchAMD = 5011, - OpFragmentFetchAMD = 5012, - OpReadClockKHR = 5056, - OpHitObjectRecordHitMotionNV = 5249, - OpHitObjectRecordHitWithIndexMotionNV = 5250, - OpHitObjectRecordMissMotionNV = 5251, - OpHitObjectGetWorldToObjectNV = 5252, - OpHitObjectGetObjectToWorldNV = 5253, - OpHitObjectGetObjectRayDirectionNV = 5254, - OpHitObjectGetObjectRayOriginNV = 5255, - OpHitObjectTraceRayMotionNV = 5256, - OpHitObjectGetShaderRecordBufferHandleNV = 5257, - OpHitObjectGetShaderBindingTableRecordIndexNV = 5258, - OpHitObjectRecordEmptyNV = 5259, - OpHitObjectTraceRayNV = 5260, - OpHitObjectRecordHitNV = 5261, - OpHitObjectRecordHitWithIndexNV = 5262, - OpHitObjectRecordMissNV = 5263, - OpHitObjectExecuteShaderNV = 5264, - OpHitObjectGetCurrentTimeNV = 5265, - OpHitObjectGetAttributesNV = 5266, - OpHitObjectGetHitKindNV = 5267, - OpHitObjectGetPrimitiveIndexNV = 5268, - OpHitObjectGetGeometryIndexNV = 5269, - OpHitObjectGetInstanceIdNV = 5270, - OpHitObjectGetInstanceCustomIndexNV = 5271, - OpHitObjectGetWorldRayDirectionNV = 5272, - OpHitObjectGetWorldRayOriginNV = 5273, - OpHitObjectGetRayTMaxNV = 5274, - OpHitObjectGetRayTMinNV = 5275, - OpHitObjectIsEmptyNV = 5276, - OpHitObjectIsHitNV = 5277, - OpHitObjectIsMissNV = 5278, - OpReorderThreadWithHitObjectNV = 5279, - OpReorderThreadWithHintNV = 5280, - OpTypeHitObjectNV = 5281, - OpImageSampleFootprintNV = 5283, - OpEmitMeshTasksEXT = 5294, - OpSetMeshOutputsEXT = 5295, - OpGroupNonUniformPartitionNV = 5296, - OpWritePackedPrimitiveIndices4x8NV = 5299, - OpFetchMicroTriangleVertexPositionNV = 5300, - OpFetchMicroTriangleVertexBarycentricNV = 5301, - OpReportIntersectionKHR = 5334, - OpReportIntersectionNV = 5334, - OpIgnoreIntersectionNV = 5335, - OpTerminateRayNV = 5336, - OpTraceNV = 5337, - OpTraceMotionNV = 5338, - OpTraceRayMotionNV = 5339, - OpRayQueryGetIntersectionTriangleVertexPositionsKHR = 5340, - OpTypeAccelerationStructureKHR = 5341, - OpTypeAccelerationStructureNV = 5341, - OpExecuteCallableNV = 5344, - OpTypeCooperativeMatrixNV = 5358, - OpCooperativeMatrixLoadNV = 5359, - OpCooperativeMatrixStoreNV = 5360, - OpCooperativeMatrixMulAddNV = 5361, - OpCooperativeMatrixLengthNV = 5362, - OpBeginInvocationInterlockEXT = 5364, - OpEndInvocationInterlockEXT = 5365, - OpDemoteToHelperInvocation = 5380, - OpDemoteToHelperInvocationEXT = 5380, - OpIsHelperInvocationEXT = 5381, - OpConvertUToImageNV = 5391, - OpConvertUToSamplerNV = 5392, - OpConvertImageToUNV = 5393, - OpConvertSamplerToUNV = 5394, - OpConvertUToSampledImageNV = 5395, - OpConvertSampledImageToUNV = 5396, - OpSamplerImageAddressingModeNV = 5397, - OpSubgroupShuffleINTEL = 5571, - OpSubgroupShuffleDownINTEL = 5572, - OpSubgroupShuffleUpINTEL = 5573, - OpSubgroupShuffleXorINTEL = 5574, - OpSubgroupBlockReadINTEL = 5575, - OpSubgroupBlockWriteINTEL = 5576, - OpSubgroupImageBlockReadINTEL = 5577, - OpSubgroupImageBlockWriteINTEL = 5578, - OpSubgroupImageMediaBlockReadINTEL = 5580, - OpSubgroupImageMediaBlockWriteINTEL = 5581, - OpUCountLeadingZerosINTEL = 5585, - OpUCountTrailingZerosINTEL = 5586, - OpAbsISubINTEL = 5587, - OpAbsUSubINTEL = 5588, - OpIAddSatINTEL = 5589, - OpUAddSatINTEL = 5590, - OpIAverageINTEL = 5591, - OpUAverageINTEL = 5592, - OpIAverageRoundedINTEL = 5593, - OpUAverageRoundedINTEL = 5594, - OpISubSatINTEL = 5595, - OpUSubSatINTEL = 5596, - OpIMul32x16INTEL = 5597, - OpUMul32x16INTEL = 5598, - OpConstantFunctionPointerINTEL = 5600, - OpFunctionPointerCallINTEL = 5601, - OpAsmTargetINTEL = 5609, - OpAsmINTEL = 5610, - OpAsmCallINTEL = 5611, - OpAtomicFMinEXT = 5614, - OpAtomicFMaxEXT = 5615, - OpAssumeTrueKHR = 5630, - OpExpectKHR = 5631, - OpDecorateString = 5632, - OpDecorateStringGOOGLE = 5632, - OpMemberDecorateString = 5633, - OpMemberDecorateStringGOOGLE = 5633, - OpVmeImageINTEL = 5699, - OpTypeVmeImageINTEL = 5700, - OpTypeAvcImePayloadINTEL = 5701, - OpTypeAvcRefPayloadINTEL = 5702, - OpTypeAvcSicPayloadINTEL = 5703, - OpTypeAvcMcePayloadINTEL = 5704, - OpTypeAvcMceResultINTEL = 5705, - OpTypeAvcImeResultINTEL = 5706, - OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707, - OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708, - OpTypeAvcImeSingleReferenceStreaminINTEL = 5709, - OpTypeAvcImeDualReferenceStreaminINTEL = 5710, - OpTypeAvcRefResultINTEL = 5711, - OpTypeAvcSicResultINTEL = 5712, - OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713, - OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714, - OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715, - OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716, - OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717, - OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718, - OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719, - OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720, - OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721, - OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722, - OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723, - OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724, - OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725, - OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726, - OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727, - OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728, - OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729, - OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730, - OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731, - OpSubgroupAvcMceConvertToImePayloadINTEL = 5732, - OpSubgroupAvcMceConvertToImeResultINTEL = 5733, - OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734, - OpSubgroupAvcMceConvertToRefResultINTEL = 5735, - OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736, - OpSubgroupAvcMceConvertToSicResultINTEL = 5737, - OpSubgroupAvcMceGetMotionVectorsINTEL = 5738, - OpSubgroupAvcMceGetInterDistortionsINTEL = 5739, - OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740, - OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741, - OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742, - OpSubgroupAvcMceGetInterDirectionsINTEL = 5743, - OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744, - OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745, - OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746, - OpSubgroupAvcImeInitializeINTEL = 5747, - OpSubgroupAvcImeSetSingleReferenceINTEL = 5748, - OpSubgroupAvcImeSetDualReferenceINTEL = 5749, - OpSubgroupAvcImeRefWindowSizeINTEL = 5750, - OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751, - OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752, - OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753, - OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754, - OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755, - OpSubgroupAvcImeSetWeightedSadINTEL = 5756, - OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757, - OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758, - OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759, - OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760, - OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761, - OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762, - OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763, - OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764, - OpSubgroupAvcImeConvertToMceResultINTEL = 5765, - OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766, - OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767, - OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768, - OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769, - OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770, - OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771, - OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772, - OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773, - OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774, - OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775, - OpSubgroupAvcImeGetBorderReachedINTEL = 5776, - OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777, - OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778, - OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779, - OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780, - OpSubgroupAvcFmeInitializeINTEL = 5781, - OpSubgroupAvcBmeInitializeINTEL = 5782, - OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783, - OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784, - OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785, - OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786, - OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787, - OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788, - OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789, - OpSubgroupAvcRefConvertToMceResultINTEL = 5790, - OpSubgroupAvcSicInitializeINTEL = 5791, - OpSubgroupAvcSicConfigureSkcINTEL = 5792, - OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793, - OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794, - OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795, - OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796, - OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797, - OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798, - OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799, - OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800, - OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801, - OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802, - OpSubgroupAvcSicEvaluateIpeINTEL = 5803, - OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804, - OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805, - OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806, - OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807, - OpSubgroupAvcSicConvertToMceResultINTEL = 5808, - OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809, - OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810, - OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811, - OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812, - OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813, - OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814, - OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815, - OpSubgroupAvcSicGetInterRawSadsINTEL = 5816, - OpVariableLengthArrayINTEL = 5818, - OpSaveMemoryINTEL = 5819, - OpRestoreMemoryINTEL = 5820, - OpArbitraryFloatSinCosPiINTEL = 5840, - OpArbitraryFloatCastINTEL = 5841, - OpArbitraryFloatCastFromIntINTEL = 5842, - OpArbitraryFloatCastToIntINTEL = 5843, - OpArbitraryFloatAddINTEL = 5846, - OpArbitraryFloatSubINTEL = 5847, - OpArbitraryFloatMulINTEL = 5848, - OpArbitraryFloatDivINTEL = 5849, - OpArbitraryFloatGTINTEL = 5850, - OpArbitraryFloatGEINTEL = 5851, - OpArbitraryFloatLTINTEL = 5852, - OpArbitraryFloatLEINTEL = 5853, - OpArbitraryFloatEQINTEL = 5854, - OpArbitraryFloatRecipINTEL = 5855, - OpArbitraryFloatRSqrtINTEL = 5856, - OpArbitraryFloatCbrtINTEL = 5857, - OpArbitraryFloatHypotINTEL = 5858, - OpArbitraryFloatSqrtINTEL = 5859, - OpArbitraryFloatLogINTEL = 5860, - OpArbitraryFloatLog2INTEL = 5861, - OpArbitraryFloatLog10INTEL = 5862, - OpArbitraryFloatLog1pINTEL = 5863, - OpArbitraryFloatExpINTEL = 5864, - OpArbitraryFloatExp2INTEL = 5865, - OpArbitraryFloatExp10INTEL = 5866, - OpArbitraryFloatExpm1INTEL = 5867, - OpArbitraryFloatSinINTEL = 5868, - OpArbitraryFloatCosINTEL = 5869, - OpArbitraryFloatSinCosINTEL = 5870, - OpArbitraryFloatSinPiINTEL = 5871, - OpArbitraryFloatCosPiINTEL = 5872, - OpArbitraryFloatASinINTEL = 5873, - OpArbitraryFloatASinPiINTEL = 5874, - OpArbitraryFloatACosINTEL = 5875, - OpArbitraryFloatACosPiINTEL = 5876, - OpArbitraryFloatATanINTEL = 5877, - OpArbitraryFloatATanPiINTEL = 5878, - OpArbitraryFloatATan2INTEL = 5879, - OpArbitraryFloatPowINTEL = 5880, - OpArbitraryFloatPowRINTEL = 5881, - OpArbitraryFloatPowNINTEL = 5882, - OpLoopControlINTEL = 5887, - OpAliasDomainDeclINTEL = 5911, - OpAliasScopeDeclINTEL = 5912, - OpAliasScopeListDeclINTEL = 5913, - OpFixedSqrtINTEL = 5923, - OpFixedRecipINTEL = 5924, - OpFixedRsqrtINTEL = 5925, - OpFixedSinINTEL = 5926, - OpFixedCosINTEL = 5927, - OpFixedSinCosINTEL = 5928, - OpFixedSinPiINTEL = 5929, - OpFixedCosPiINTEL = 5930, - OpFixedSinCosPiINTEL = 5931, - OpFixedLogINTEL = 5932, - OpFixedExpINTEL = 5933, - OpPtrCastToCrossWorkgroupINTEL = 5934, - OpCrossWorkgroupCastToPtrINTEL = 5938, - OpReadPipeBlockingINTEL = 5946, - OpWritePipeBlockingINTEL = 5947, - OpFPGARegINTEL = 5949, - OpRayQueryGetRayTMinKHR = 6016, - OpRayQueryGetRayFlagsKHR = 6017, - OpRayQueryGetIntersectionTKHR = 6018, - OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019, - OpRayQueryGetIntersectionInstanceIdKHR = 6020, - OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021, - OpRayQueryGetIntersectionGeometryIndexKHR = 6022, - OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023, - OpRayQueryGetIntersectionBarycentricsKHR = 6024, - OpRayQueryGetIntersectionFrontFaceKHR = 6025, - OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026, - OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027, - OpRayQueryGetIntersectionObjectRayOriginKHR = 6028, - OpRayQueryGetWorldRayDirectionKHR = 6029, - OpRayQueryGetWorldRayOriginKHR = 6030, - OpRayQueryGetIntersectionObjectToWorldKHR = 6031, - OpRayQueryGetIntersectionWorldToObjectKHR = 6032, - OpAtomicFAddEXT = 6035, - OpTypeBufferSurfaceINTEL = 6086, - OpTypeStructContinuedINTEL = 6090, - OpConstantCompositeContinuedINTEL = 6091, - OpSpecConstantCompositeContinuedINTEL = 6092, - OpControlBarrierArriveINTEL = 6142, - OpControlBarrierWaitINTEL = 6143, - OpGroupIMulKHR = 6401, - OpGroupFMulKHR = 6402, - OpGroupBitwiseAndKHR = 6403, - OpGroupBitwiseOrKHR = 6404, - OpGroupBitwiseXorKHR = 6405, - OpGroupLogicalAndKHR = 6406, - OpGroupLogicalOrKHR = 6407, - OpGroupLogicalXorKHR = 6408, - OpMax = 0x7fffffff, -}; - -#ifdef SPV_ENABLE_UTILITY_CODE -#ifndef __cplusplus -#include -#endif -inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) { - *hasResult = *hasResultType = false; - switch (opcode) { - default: /* unknown opcode */ break; - case OpNop: *hasResult = false; *hasResultType = false; break; - case OpUndef: *hasResult = true; *hasResultType = true; break; - case OpSourceContinued: *hasResult = false; *hasResultType = false; break; - case OpSource: *hasResult = false; *hasResultType = false; break; - case OpSourceExtension: *hasResult = false; *hasResultType = false; break; - case OpName: *hasResult = false; *hasResultType = false; break; - case OpMemberName: *hasResult = false; *hasResultType = false; break; - case OpString: *hasResult = true; *hasResultType = false; break; - case OpLine: *hasResult = false; *hasResultType = false; break; - case OpExtension: *hasResult = false; *hasResultType = false; break; - case OpExtInstImport: *hasResult = true; *hasResultType = false; break; - case OpExtInst: *hasResult = true; *hasResultType = true; break; - case OpMemoryModel: *hasResult = false; *hasResultType = false; break; - case OpEntryPoint: *hasResult = false; *hasResultType = false; break; - case OpExecutionMode: *hasResult = false; *hasResultType = false; break; - case OpCapability: *hasResult = false; *hasResultType = false; break; - case OpTypeVoid: *hasResult = true; *hasResultType = false; break; - case OpTypeBool: *hasResult = true; *hasResultType = false; break; - case OpTypeInt: *hasResult = true; *hasResultType = false; break; - case OpTypeFloat: *hasResult = true; *hasResultType = false; break; - case OpTypeVector: *hasResult = true; *hasResultType = false; break; - case OpTypeMatrix: *hasResult = true; *hasResultType = false; break; - case OpTypeImage: *hasResult = true; *hasResultType = false; break; - case OpTypeSampler: *hasResult = true; *hasResultType = false; break; - case OpTypeSampledImage: *hasResult = true; *hasResultType = false; break; - case OpTypeArray: *hasResult = true; *hasResultType = false; break; - case OpTypeRuntimeArray: *hasResult = true; *hasResultType = false; break; - case OpTypeStruct: *hasResult = true; *hasResultType = false; break; - case OpTypeOpaque: *hasResult = true; *hasResultType = false; break; - case OpTypePointer: *hasResult = true; *hasResultType = false; break; - case OpTypeFunction: *hasResult = true; *hasResultType = false; break; - case OpTypeEvent: *hasResult = true; *hasResultType = false; break; - case OpTypeDeviceEvent: *hasResult = true; *hasResultType = false; break; - case OpTypeReserveId: *hasResult = true; *hasResultType = false; break; - case OpTypeQueue: *hasResult = true; *hasResultType = false; break; - case OpTypePipe: *hasResult = true; *hasResultType = false; break; - case OpTypeForwardPointer: *hasResult = false; *hasResultType = false; break; - case OpConstantTrue: *hasResult = true; *hasResultType = true; break; - case OpConstantFalse: *hasResult = true; *hasResultType = true; break; - case OpConstant: *hasResult = true; *hasResultType = true; break; - case OpConstantComposite: *hasResult = true; *hasResultType = true; break; - case OpConstantSampler: *hasResult = true; *hasResultType = true; break; - case OpConstantNull: *hasResult = true; *hasResultType = true; break; - case OpSpecConstantTrue: *hasResult = true; *hasResultType = true; break; - case OpSpecConstantFalse: *hasResult = true; *hasResultType = true; break; - case OpSpecConstant: *hasResult = true; *hasResultType = true; break; - case OpSpecConstantComposite: *hasResult = true; *hasResultType = true; break; - case OpSpecConstantOp: *hasResult = true; *hasResultType = true; break; - case OpFunction: *hasResult = true; *hasResultType = true; break; - case OpFunctionParameter: *hasResult = true; *hasResultType = true; break; - case OpFunctionEnd: *hasResult = false; *hasResultType = false; break; - case OpFunctionCall: *hasResult = true; *hasResultType = true; break; - case OpVariable: *hasResult = true; *hasResultType = true; break; - case OpImageTexelPointer: *hasResult = true; *hasResultType = true; break; - case OpLoad: *hasResult = true; *hasResultType = true; break; - case OpStore: *hasResult = false; *hasResultType = false; break; - case OpCopyMemory: *hasResult = false; *hasResultType = false; break; - case OpCopyMemorySized: *hasResult = false; *hasResultType = false; break; - case OpAccessChain: *hasResult = true; *hasResultType = true; break; - case OpInBoundsAccessChain: *hasResult = true; *hasResultType = true; break; - case OpPtrAccessChain: *hasResult = true; *hasResultType = true; break; - case OpArrayLength: *hasResult = true; *hasResultType = true; break; - case OpGenericPtrMemSemantics: *hasResult = true; *hasResultType = true; break; - case OpInBoundsPtrAccessChain: *hasResult = true; *hasResultType = true; break; - case OpDecorate: *hasResult = false; *hasResultType = false; break; - case OpMemberDecorate: *hasResult = false; *hasResultType = false; break; - case OpDecorationGroup: *hasResult = true; *hasResultType = false; break; - case OpGroupDecorate: *hasResult = false; *hasResultType = false; break; - case OpGroupMemberDecorate: *hasResult = false; *hasResultType = false; break; - case OpVectorExtractDynamic: *hasResult = true; *hasResultType = true; break; - case OpVectorInsertDynamic: *hasResult = true; *hasResultType = true; break; - case OpVectorShuffle: *hasResult = true; *hasResultType = true; break; - case OpCompositeConstruct: *hasResult = true; *hasResultType = true; break; - case OpCompositeExtract: *hasResult = true; *hasResultType = true; break; - case OpCompositeInsert: *hasResult = true; *hasResultType = true; break; - case OpCopyObject: *hasResult = true; *hasResultType = true; break; - case OpTranspose: *hasResult = true; *hasResultType = true; break; - case OpSampledImage: *hasResult = true; *hasResultType = true; break; - case OpImageSampleImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageFetch: *hasResult = true; *hasResultType = true; break; - case OpImageGather: *hasResult = true; *hasResultType = true; break; - case OpImageDrefGather: *hasResult = true; *hasResultType = true; break; - case OpImageRead: *hasResult = true; *hasResultType = true; break; - case OpImageWrite: *hasResult = false; *hasResultType = false; break; - case OpImage: *hasResult = true; *hasResultType = true; break; - case OpImageQueryFormat: *hasResult = true; *hasResultType = true; break; - case OpImageQueryOrder: *hasResult = true; *hasResultType = true; break; - case OpImageQuerySizeLod: *hasResult = true; *hasResultType = true; break; - case OpImageQuerySize: *hasResult = true; *hasResultType = true; break; - case OpImageQueryLod: *hasResult = true; *hasResultType = true; break; - case OpImageQueryLevels: *hasResult = true; *hasResultType = true; break; - case OpImageQuerySamples: *hasResult = true; *hasResultType = true; break; - case OpConvertFToU: *hasResult = true; *hasResultType = true; break; - case OpConvertFToS: *hasResult = true; *hasResultType = true; break; - case OpConvertSToF: *hasResult = true; *hasResultType = true; break; - case OpConvertUToF: *hasResult = true; *hasResultType = true; break; - case OpUConvert: *hasResult = true; *hasResultType = true; break; - case OpSConvert: *hasResult = true; *hasResultType = true; break; - case OpFConvert: *hasResult = true; *hasResultType = true; break; - case OpQuantizeToF16: *hasResult = true; *hasResultType = true; break; - case OpConvertPtrToU: *hasResult = true; *hasResultType = true; break; - case OpSatConvertSToU: *hasResult = true; *hasResultType = true; break; - case OpSatConvertUToS: *hasResult = true; *hasResultType = true; break; - case OpConvertUToPtr: *hasResult = true; *hasResultType = true; break; - case OpPtrCastToGeneric: *hasResult = true; *hasResultType = true; break; - case OpGenericCastToPtr: *hasResult = true; *hasResultType = true; break; - case OpGenericCastToPtrExplicit: *hasResult = true; *hasResultType = true; break; - case OpBitcast: *hasResult = true; *hasResultType = true; break; - case OpSNegate: *hasResult = true; *hasResultType = true; break; - case OpFNegate: *hasResult = true; *hasResultType = true; break; - case OpIAdd: *hasResult = true; *hasResultType = true; break; - case OpFAdd: *hasResult = true; *hasResultType = true; break; - case OpISub: *hasResult = true; *hasResultType = true; break; - case OpFSub: *hasResult = true; *hasResultType = true; break; - case OpIMul: *hasResult = true; *hasResultType = true; break; - case OpFMul: *hasResult = true; *hasResultType = true; break; - case OpUDiv: *hasResult = true; *hasResultType = true; break; - case OpSDiv: *hasResult = true; *hasResultType = true; break; - case OpFDiv: *hasResult = true; *hasResultType = true; break; - case OpUMod: *hasResult = true; *hasResultType = true; break; - case OpSRem: *hasResult = true; *hasResultType = true; break; - case OpSMod: *hasResult = true; *hasResultType = true; break; - case OpFRem: *hasResult = true; *hasResultType = true; break; - case OpFMod: *hasResult = true; *hasResultType = true; break; - case OpVectorTimesScalar: *hasResult = true; *hasResultType = true; break; - case OpMatrixTimesScalar: *hasResult = true; *hasResultType = true; break; - case OpVectorTimesMatrix: *hasResult = true; *hasResultType = true; break; - case OpMatrixTimesVector: *hasResult = true; *hasResultType = true; break; - case OpMatrixTimesMatrix: *hasResult = true; *hasResultType = true; break; - case OpOuterProduct: *hasResult = true; *hasResultType = true; break; - case OpDot: *hasResult = true; *hasResultType = true; break; - case OpIAddCarry: *hasResult = true; *hasResultType = true; break; - case OpISubBorrow: *hasResult = true; *hasResultType = true; break; - case OpUMulExtended: *hasResult = true; *hasResultType = true; break; - case OpSMulExtended: *hasResult = true; *hasResultType = true; break; - case OpAny: *hasResult = true; *hasResultType = true; break; - case OpAll: *hasResult = true; *hasResultType = true; break; - case OpIsNan: *hasResult = true; *hasResultType = true; break; - case OpIsInf: *hasResult = true; *hasResultType = true; break; - case OpIsFinite: *hasResult = true; *hasResultType = true; break; - case OpIsNormal: *hasResult = true; *hasResultType = true; break; - case OpSignBitSet: *hasResult = true; *hasResultType = true; break; - case OpLessOrGreater: *hasResult = true; *hasResultType = true; break; - case OpOrdered: *hasResult = true; *hasResultType = true; break; - case OpUnordered: *hasResult = true; *hasResultType = true; break; - case OpLogicalEqual: *hasResult = true; *hasResultType = true; break; - case OpLogicalNotEqual: *hasResult = true; *hasResultType = true; break; - case OpLogicalOr: *hasResult = true; *hasResultType = true; break; - case OpLogicalAnd: *hasResult = true; *hasResultType = true; break; - case OpLogicalNot: *hasResult = true; *hasResultType = true; break; - case OpSelect: *hasResult = true; *hasResultType = true; break; - case OpIEqual: *hasResult = true; *hasResultType = true; break; - case OpINotEqual: *hasResult = true; *hasResultType = true; break; - case OpUGreaterThan: *hasResult = true; *hasResultType = true; break; - case OpSGreaterThan: *hasResult = true; *hasResultType = true; break; - case OpUGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case OpSGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case OpULessThan: *hasResult = true; *hasResultType = true; break; - case OpSLessThan: *hasResult = true; *hasResultType = true; break; - case OpULessThanEqual: *hasResult = true; *hasResultType = true; break; - case OpSLessThanEqual: *hasResult = true; *hasResultType = true; break; - case OpFOrdEqual: *hasResult = true; *hasResultType = true; break; - case OpFUnordEqual: *hasResult = true; *hasResultType = true; break; - case OpFOrdNotEqual: *hasResult = true; *hasResultType = true; break; - case OpFUnordNotEqual: *hasResult = true; *hasResultType = true; break; - case OpFOrdLessThan: *hasResult = true; *hasResultType = true; break; - case OpFUnordLessThan: *hasResult = true; *hasResultType = true; break; - case OpFOrdGreaterThan: *hasResult = true; *hasResultType = true; break; - case OpFUnordGreaterThan: *hasResult = true; *hasResultType = true; break; - case OpFOrdLessThanEqual: *hasResult = true; *hasResultType = true; break; - case OpFUnordLessThanEqual: *hasResult = true; *hasResultType = true; break; - case OpFOrdGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case OpFUnordGreaterThanEqual: *hasResult = true; *hasResultType = true; break; - case OpShiftRightLogical: *hasResult = true; *hasResultType = true; break; - case OpShiftRightArithmetic: *hasResult = true; *hasResultType = true; break; - case OpShiftLeftLogical: *hasResult = true; *hasResultType = true; break; - case OpBitwiseOr: *hasResult = true; *hasResultType = true; break; - case OpBitwiseXor: *hasResult = true; *hasResultType = true; break; - case OpBitwiseAnd: *hasResult = true; *hasResultType = true; break; - case OpNot: *hasResult = true; *hasResultType = true; break; - case OpBitFieldInsert: *hasResult = true; *hasResultType = true; break; - case OpBitFieldSExtract: *hasResult = true; *hasResultType = true; break; - case OpBitFieldUExtract: *hasResult = true; *hasResultType = true; break; - case OpBitReverse: *hasResult = true; *hasResultType = true; break; - case OpBitCount: *hasResult = true; *hasResultType = true; break; - case OpDPdx: *hasResult = true; *hasResultType = true; break; - case OpDPdy: *hasResult = true; *hasResultType = true; break; - case OpFwidth: *hasResult = true; *hasResultType = true; break; - case OpDPdxFine: *hasResult = true; *hasResultType = true; break; - case OpDPdyFine: *hasResult = true; *hasResultType = true; break; - case OpFwidthFine: *hasResult = true; *hasResultType = true; break; - case OpDPdxCoarse: *hasResult = true; *hasResultType = true; break; - case OpDPdyCoarse: *hasResult = true; *hasResultType = true; break; - case OpFwidthCoarse: *hasResult = true; *hasResultType = true; break; - case OpEmitVertex: *hasResult = false; *hasResultType = false; break; - case OpEndPrimitive: *hasResult = false; *hasResultType = false; break; - case OpEmitStreamVertex: *hasResult = false; *hasResultType = false; break; - case OpEndStreamPrimitive: *hasResult = false; *hasResultType = false; break; - case OpControlBarrier: *hasResult = false; *hasResultType = false; break; - case OpMemoryBarrier: *hasResult = false; *hasResultType = false; break; - case OpAtomicLoad: *hasResult = true; *hasResultType = true; break; - case OpAtomicStore: *hasResult = false; *hasResultType = false; break; - case OpAtomicExchange: *hasResult = true; *hasResultType = true; break; - case OpAtomicCompareExchange: *hasResult = true; *hasResultType = true; break; - case OpAtomicCompareExchangeWeak: *hasResult = true; *hasResultType = true; break; - case OpAtomicIIncrement: *hasResult = true; *hasResultType = true; break; - case OpAtomicIDecrement: *hasResult = true; *hasResultType = true; break; - case OpAtomicIAdd: *hasResult = true; *hasResultType = true; break; - case OpAtomicISub: *hasResult = true; *hasResultType = true; break; - case OpAtomicSMin: *hasResult = true; *hasResultType = true; break; - case OpAtomicUMin: *hasResult = true; *hasResultType = true; break; - case OpAtomicSMax: *hasResult = true; *hasResultType = true; break; - case OpAtomicUMax: *hasResult = true; *hasResultType = true; break; - case OpAtomicAnd: *hasResult = true; *hasResultType = true; break; - case OpAtomicOr: *hasResult = true; *hasResultType = true; break; - case OpAtomicXor: *hasResult = true; *hasResultType = true; break; - case OpPhi: *hasResult = true; *hasResultType = true; break; - case OpLoopMerge: *hasResult = false; *hasResultType = false; break; - case OpSelectionMerge: *hasResult = false; *hasResultType = false; break; - case OpLabel: *hasResult = true; *hasResultType = false; break; - case OpBranch: *hasResult = false; *hasResultType = false; break; - case OpBranchConditional: *hasResult = false; *hasResultType = false; break; - case OpSwitch: *hasResult = false; *hasResultType = false; break; - case OpKill: *hasResult = false; *hasResultType = false; break; - case OpReturn: *hasResult = false; *hasResultType = false; break; - case OpReturnValue: *hasResult = false; *hasResultType = false; break; - case OpUnreachable: *hasResult = false; *hasResultType = false; break; - case OpLifetimeStart: *hasResult = false; *hasResultType = false; break; - case OpLifetimeStop: *hasResult = false; *hasResultType = false; break; - case OpGroupAsyncCopy: *hasResult = true; *hasResultType = true; break; - case OpGroupWaitEvents: *hasResult = false; *hasResultType = false; break; - case OpGroupAll: *hasResult = true; *hasResultType = true; break; - case OpGroupAny: *hasResult = true; *hasResultType = true; break; - case OpGroupBroadcast: *hasResult = true; *hasResultType = true; break; - case OpGroupIAdd: *hasResult = true; *hasResultType = true; break; - case OpGroupFAdd: *hasResult = true; *hasResultType = true; break; - case OpGroupFMin: *hasResult = true; *hasResultType = true; break; - case OpGroupUMin: *hasResult = true; *hasResultType = true; break; - case OpGroupSMin: *hasResult = true; *hasResultType = true; break; - case OpGroupFMax: *hasResult = true; *hasResultType = true; break; - case OpGroupUMax: *hasResult = true; *hasResultType = true; break; - case OpGroupSMax: *hasResult = true; *hasResultType = true; break; - case OpReadPipe: *hasResult = true; *hasResultType = true; break; - case OpWritePipe: *hasResult = true; *hasResultType = true; break; - case OpReservedReadPipe: *hasResult = true; *hasResultType = true; break; - case OpReservedWritePipe: *hasResult = true; *hasResultType = true; break; - case OpReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; - case OpReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; - case OpCommitReadPipe: *hasResult = false; *hasResultType = false; break; - case OpCommitWritePipe: *hasResult = false; *hasResultType = false; break; - case OpIsValidReserveId: *hasResult = true; *hasResultType = true; break; - case OpGetNumPipePackets: *hasResult = true; *hasResultType = true; break; - case OpGetMaxPipePackets: *hasResult = true; *hasResultType = true; break; - case OpGroupReserveReadPipePackets: *hasResult = true; *hasResultType = true; break; - case OpGroupReserveWritePipePackets: *hasResult = true; *hasResultType = true; break; - case OpGroupCommitReadPipe: *hasResult = false; *hasResultType = false; break; - case OpGroupCommitWritePipe: *hasResult = false; *hasResultType = false; break; - case OpEnqueueMarker: *hasResult = true; *hasResultType = true; break; - case OpEnqueueKernel: *hasResult = true; *hasResultType = true; break; - case OpGetKernelNDrangeSubGroupCount: *hasResult = true; *hasResultType = true; break; - case OpGetKernelNDrangeMaxSubGroupSize: *hasResult = true; *hasResultType = true; break; - case OpGetKernelWorkGroupSize: *hasResult = true; *hasResultType = true; break; - case OpGetKernelPreferredWorkGroupSizeMultiple: *hasResult = true; *hasResultType = true; break; - case OpRetainEvent: *hasResult = false; *hasResultType = false; break; - case OpReleaseEvent: *hasResult = false; *hasResultType = false; break; - case OpCreateUserEvent: *hasResult = true; *hasResultType = true; break; - case OpIsValidEvent: *hasResult = true; *hasResultType = true; break; - case OpSetUserEventStatus: *hasResult = false; *hasResultType = false; break; - case OpCaptureEventProfilingInfo: *hasResult = false; *hasResultType = false; break; - case OpGetDefaultQueue: *hasResult = true; *hasResultType = true; break; - case OpBuildNDRange: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleProjImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleProjExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleProjDrefImplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseSampleProjDrefExplicitLod: *hasResult = true; *hasResultType = true; break; - case OpImageSparseFetch: *hasResult = true; *hasResultType = true; break; - case OpImageSparseGather: *hasResult = true; *hasResultType = true; break; - case OpImageSparseDrefGather: *hasResult = true; *hasResultType = true; break; - case OpImageSparseTexelsResident: *hasResult = true; *hasResultType = true; break; - case OpNoLine: *hasResult = false; *hasResultType = false; break; - case OpAtomicFlagTestAndSet: *hasResult = true; *hasResultType = true; break; - case OpAtomicFlagClear: *hasResult = false; *hasResultType = false; break; - case OpImageSparseRead: *hasResult = true; *hasResultType = true; break; - case OpSizeOf: *hasResult = true; *hasResultType = true; break; - case OpTypePipeStorage: *hasResult = true; *hasResultType = false; break; - case OpConstantPipeStorage: *hasResult = true; *hasResultType = true; break; - case OpCreatePipeFromPipeStorage: *hasResult = true; *hasResultType = true; break; - case OpGetKernelLocalSizeForSubgroupCount: *hasResult = true; *hasResultType = true; break; - case OpGetKernelMaxNumSubgroups: *hasResult = true; *hasResultType = true; break; - case OpTypeNamedBarrier: *hasResult = true; *hasResultType = false; break; - case OpNamedBarrierInitialize: *hasResult = true; *hasResultType = true; break; - case OpMemoryNamedBarrier: *hasResult = false; *hasResultType = false; break; - case OpModuleProcessed: *hasResult = false; *hasResultType = false; break; - case OpExecutionModeId: *hasResult = false; *hasResultType = false; break; - case OpDecorateId: *hasResult = false; *hasResultType = false; break; - case OpGroupNonUniformElect: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformAll: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformAny: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformAllEqual: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBroadcast: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBroadcastFirst: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBallot: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformInverseBallot: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBallotBitExtract: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBallotBitCount: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBallotFindLSB: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBallotFindMSB: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformShuffle: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformShuffleXor: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformShuffleUp: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformShuffleDown: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformIAdd: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformFAdd: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformIMul: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformFMul: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformSMin: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformUMin: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformFMin: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformSMax: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformUMax: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformFMax: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBitwiseAnd: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBitwiseOr: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformBitwiseXor: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformLogicalAnd: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformLogicalOr: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformLogicalXor: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformQuadBroadcast: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformQuadSwap: *hasResult = true; *hasResultType = true; break; - case OpCopyLogical: *hasResult = true; *hasResultType = true; break; - case OpPtrEqual: *hasResult = true; *hasResultType = true; break; - case OpPtrNotEqual: *hasResult = true; *hasResultType = true; break; - case OpPtrDiff: *hasResult = true; *hasResultType = true; break; - case OpColorAttachmentReadEXT: *hasResult = true; *hasResultType = true; break; - case OpDepthAttachmentReadEXT: *hasResult = true; *hasResultType = true; break; - case OpStencilAttachmentReadEXT: *hasResult = true; *hasResultType = true; break; - case OpTerminateInvocation: *hasResult = false; *hasResultType = false; break; - case OpSubgroupBallotKHR: *hasResult = true; *hasResultType = true; break; - case OpSubgroupFirstInvocationKHR: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupNonUniformRotateKHR: *hasResult = true; *hasResultType = true; break; - case OpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break; - case OpTraceRayKHR: *hasResult = false; *hasResultType = false; break; - case OpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break; - case OpConvertUToAccelerationStructureKHR: *hasResult = true; *hasResultType = true; break; - case OpIgnoreIntersectionKHR: *hasResult = false; *hasResultType = false; break; - case OpTerminateRayKHR: *hasResult = false; *hasResultType = false; break; - case OpSDot: *hasResult = true; *hasResultType = true; break; - case OpUDot: *hasResult = true; *hasResultType = true; break; - case OpSUDot: *hasResult = true; *hasResultType = true; break; - case OpSDotAccSat: *hasResult = true; *hasResultType = true; break; - case OpUDotAccSat: *hasResult = true; *hasResultType = true; break; - case OpSUDotAccSat: *hasResult = true; *hasResultType = true; break; - case OpTypeCooperativeMatrixKHR: *hasResult = true; *hasResultType = false; break; - case OpCooperativeMatrixLoadKHR: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixStoreKHR: *hasResult = false; *hasResultType = false; break; - case OpCooperativeMatrixMulAddKHR: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixLengthKHR: *hasResult = true; *hasResultType = true; break; - case OpTypeRayQueryKHR: *hasResult = true; *hasResultType = false; break; - case OpRayQueryInitializeKHR: *hasResult = false; *hasResultType = false; break; - case OpRayQueryTerminateKHR: *hasResult = false; *hasResultType = false; break; - case OpRayQueryGenerateIntersectionKHR: *hasResult = false; *hasResultType = false; break; - case OpRayQueryConfirmIntersectionKHR: *hasResult = false; *hasResultType = false; break; - case OpRayQueryProceedKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionTypeKHR: *hasResult = true; *hasResultType = true; break; - case OpImageSampleWeightedQCOM: *hasResult = true; *hasResultType = true; break; - case OpImageBoxFilterQCOM: *hasResult = true; *hasResultType = true; break; - case OpImageBlockMatchSSDQCOM: *hasResult = true; *hasResultType = true; break; - case OpImageBlockMatchSADQCOM: *hasResult = true; *hasResultType = true; break; - case OpGroupIAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupFAddNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupFMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupUMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupSMinNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupFMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupUMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpGroupSMaxNonUniformAMD: *hasResult = true; *hasResultType = true; break; - case OpFragmentMaskFetchAMD: *hasResult = true; *hasResultType = true; break; - case OpFragmentFetchAMD: *hasResult = true; *hasResultType = true; break; - case OpReadClockKHR: *hasResult = true; *hasResultType = true; break; - case OpHitObjectRecordHitMotionNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectRecordHitWithIndexMotionNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectRecordMissMotionNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectGetWorldToObjectNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetObjectToWorldNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetObjectRayDirectionNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetObjectRayOriginNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectTraceRayMotionNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectGetShaderRecordBufferHandleNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetShaderBindingTableRecordIndexNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectRecordEmptyNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectTraceRayNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectRecordHitNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectRecordHitWithIndexNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectRecordMissNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectExecuteShaderNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectGetCurrentTimeNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetAttributesNV: *hasResult = false; *hasResultType = false; break; - case OpHitObjectGetHitKindNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetPrimitiveIndexNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetGeometryIndexNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetInstanceIdNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetInstanceCustomIndexNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetWorldRayDirectionNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetWorldRayOriginNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetRayTMaxNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectGetRayTMinNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectIsEmptyNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectIsHitNV: *hasResult = true; *hasResultType = true; break; - case OpHitObjectIsMissNV: *hasResult = true; *hasResultType = true; break; - case OpReorderThreadWithHitObjectNV: *hasResult = false; *hasResultType = false; break; - case OpReorderThreadWithHintNV: *hasResult = false; *hasResultType = false; break; - case OpTypeHitObjectNV: *hasResult = true; *hasResultType = false; break; - case OpImageSampleFootprintNV: *hasResult = true; *hasResultType = true; break; - case OpEmitMeshTasksEXT: *hasResult = false; *hasResultType = false; break; - case OpSetMeshOutputsEXT: *hasResult = false; *hasResultType = false; break; - case OpGroupNonUniformPartitionNV: *hasResult = true; *hasResultType = true; break; - case OpWritePackedPrimitiveIndices4x8NV: *hasResult = false; *hasResultType = false; break; - case OpReportIntersectionNV: *hasResult = true; *hasResultType = true; break; - case OpIgnoreIntersectionNV: *hasResult = false; *hasResultType = false; break; - case OpTerminateRayNV: *hasResult = false; *hasResultType = false; break; - case OpTraceNV: *hasResult = false; *hasResultType = false; break; - case OpTraceMotionNV: *hasResult = false; *hasResultType = false; break; - case OpTraceRayMotionNV: *hasResult = false; *hasResultType = false; break; - case OpRayQueryGetIntersectionTriangleVertexPositionsKHR: *hasResult = true; *hasResultType = true; break; - case OpTypeAccelerationStructureNV: *hasResult = true; *hasResultType = false; break; - case OpExecuteCallableNV: *hasResult = false; *hasResultType = false; break; - case OpTypeCooperativeMatrixNV: *hasResult = true; *hasResultType = false; break; - case OpCooperativeMatrixLoadNV: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixStoreNV: *hasResult = false; *hasResultType = false; break; - case OpCooperativeMatrixMulAddNV: *hasResult = true; *hasResultType = true; break; - case OpCooperativeMatrixLengthNV: *hasResult = true; *hasResultType = true; break; - case OpBeginInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; - case OpEndInvocationInterlockEXT: *hasResult = false; *hasResultType = false; break; - case OpDemoteToHelperInvocation: *hasResult = false; *hasResultType = false; break; - case OpIsHelperInvocationEXT: *hasResult = true; *hasResultType = true; break; - case OpConvertUToImageNV: *hasResult = true; *hasResultType = true; break; - case OpConvertUToSamplerNV: *hasResult = true; *hasResultType = true; break; - case OpConvertImageToUNV: *hasResult = true; *hasResultType = true; break; - case OpConvertSamplerToUNV: *hasResult = true; *hasResultType = true; break; - case OpConvertUToSampledImageNV: *hasResult = true; *hasResultType = true; break; - case OpConvertSampledImageToUNV: *hasResult = true; *hasResultType = true; break; - case OpSamplerImageAddressingModeNV: *hasResult = false; *hasResultType = false; break; - case OpSubgroupShuffleINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupShuffleDownINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupShuffleUpINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupShuffleXorINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupBlockReadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; - case OpSubgroupImageBlockReadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupImageBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; - case OpSubgroupImageMediaBlockReadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupImageMediaBlockWriteINTEL: *hasResult = false; *hasResultType = false; break; - case OpUCountLeadingZerosINTEL: *hasResult = true; *hasResultType = true; break; - case OpUCountTrailingZerosINTEL: *hasResult = true; *hasResultType = true; break; - case OpAbsISubINTEL: *hasResult = true; *hasResultType = true; break; - case OpAbsUSubINTEL: *hasResult = true; *hasResultType = true; break; - case OpIAddSatINTEL: *hasResult = true; *hasResultType = true; break; - case OpUAddSatINTEL: *hasResult = true; *hasResultType = true; break; - case OpIAverageINTEL: *hasResult = true; *hasResultType = true; break; - case OpUAverageINTEL: *hasResult = true; *hasResultType = true; break; - case OpIAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; - case OpUAverageRoundedINTEL: *hasResult = true; *hasResultType = true; break; - case OpISubSatINTEL: *hasResult = true; *hasResultType = true; break; - case OpUSubSatINTEL: *hasResult = true; *hasResultType = true; break; - case OpIMul32x16INTEL: *hasResult = true; *hasResultType = true; break; - case OpUMul32x16INTEL: *hasResult = true; *hasResultType = true; break; - case OpConstantFunctionPointerINTEL: *hasResult = true; *hasResultType = true; break; - case OpFunctionPointerCallINTEL: *hasResult = true; *hasResultType = true; break; - case OpAsmTargetINTEL: *hasResult = true; *hasResultType = true; break; - case OpAsmINTEL: *hasResult = true; *hasResultType = true; break; - case OpAsmCallINTEL: *hasResult = true; *hasResultType = true; break; - case OpAtomicFMinEXT: *hasResult = true; *hasResultType = true; break; - case OpAtomicFMaxEXT: *hasResult = true; *hasResultType = true; break; - case OpAssumeTrueKHR: *hasResult = false; *hasResultType = false; break; - case OpExpectKHR: *hasResult = true; *hasResultType = true; break; - case OpDecorateString: *hasResult = false; *hasResultType = false; break; - case OpMemberDecorateString: *hasResult = false; *hasResultType = false; break; - case OpVmeImageINTEL: *hasResult = true; *hasResultType = true; break; - case OpTypeVmeImageINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImePayloadINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcRefPayloadINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcSicPayloadINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcMcePayloadINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcMceResultINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImeResultINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImeResultSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImeResultDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImeSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcImeDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcRefResultINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeAvcSicResultINTEL: *hasResult = true; *hasResultType = false; break; - case OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetInterShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetInterDirectionPenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetAcOnlyHaarINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToImePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToImeResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToRefPayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToRefResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToSicPayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceConvertToSicResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetBestInterDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterMajorShapeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterMinorShapeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterDirectionsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeRefWindowSizeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeAdjustRefOffsetINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetMaxMotionVectorCountINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeSetWeightedSadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetSingleReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetDualReferenceStreaminINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeStripDualReferenceStreamoutINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetBorderReachedINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcFmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcBmeInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefSetBidirectionalMixDisableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcRefConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicInitializeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicConfigureSkcINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicConfigureIpeLumaINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicConfigureIpeLumaChromaINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetMotionVectorMaskINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicConvertToMcePayloadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetBilinearFilterEnableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicEvaluateIpeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicEvaluateWithDualReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicConvertToMceResultINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetIpeLumaShapeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetPackedIpeLumaModesINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetIpeChromaModeINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL: *hasResult = true; *hasResultType = true; break; - case OpSubgroupAvcSicGetInterRawSadsINTEL: *hasResult = true; *hasResultType = true; break; - case OpVariableLengthArrayINTEL: *hasResult = true; *hasResultType = true; break; - case OpSaveMemoryINTEL: *hasResult = true; *hasResultType = true; break; - case OpRestoreMemoryINTEL: *hasResult = false; *hasResultType = false; break; - case OpArbitraryFloatSinCosPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCastINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCastFromIntINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCastToIntINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatAddINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatSubINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatMulINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatDivINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatGTINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatGEINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLTINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLEINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatEQINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatRecipINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatRSqrtINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCbrtINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatHypotINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatSqrtINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLogINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLog2INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLog10INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatLog1pINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatExpINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatExp2INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatExp10INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatExpm1INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatSinINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCosINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatSinCosINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatSinPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatCosPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatASinINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatASinPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatACosINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatACosPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatATanINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatATanPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatATan2INTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatPowINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatPowRINTEL: *hasResult = true; *hasResultType = true; break; - case OpArbitraryFloatPowNINTEL: *hasResult = true; *hasResultType = true; break; - case OpLoopControlINTEL: *hasResult = false; *hasResultType = false; break; - case OpAliasDomainDeclINTEL: *hasResult = true; *hasResultType = false; break; - case OpAliasScopeDeclINTEL: *hasResult = true; *hasResultType = false; break; - case OpAliasScopeListDeclINTEL: *hasResult = true; *hasResultType = false; break; - case OpFixedSqrtINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedRecipINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedRsqrtINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedSinINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedCosINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedSinCosINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedSinPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedCosPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedSinCosPiINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedLogINTEL: *hasResult = true; *hasResultType = true; break; - case OpFixedExpINTEL: *hasResult = true; *hasResultType = true; break; - case OpPtrCastToCrossWorkgroupINTEL: *hasResult = true; *hasResultType = true; break; - case OpCrossWorkgroupCastToPtrINTEL: *hasResult = true; *hasResultType = true; break; - case OpReadPipeBlockingINTEL: *hasResult = true; *hasResultType = true; break; - case OpWritePipeBlockingINTEL: *hasResult = true; *hasResultType = true; break; - case OpFPGARegINTEL: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetRayTMinKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetRayFlagsKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionTKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionInstanceCustomIndexKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionInstanceIdKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionGeometryIndexKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionPrimitiveIndexKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionBarycentricsKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionFrontFaceKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionObjectRayDirectionKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionObjectRayOriginKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetWorldRayDirectionKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetWorldRayOriginKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionObjectToWorldKHR: *hasResult = true; *hasResultType = true; break; - case OpRayQueryGetIntersectionWorldToObjectKHR: *hasResult = true; *hasResultType = true; break; - case OpAtomicFAddEXT: *hasResult = true; *hasResultType = true; break; - case OpTypeBufferSurfaceINTEL: *hasResult = true; *hasResultType = false; break; - case OpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break; - case OpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break; - case OpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break; - case OpControlBarrierArriveINTEL: *hasResult = false; *hasResultType = false; break; - case OpControlBarrierWaitINTEL: *hasResult = false; *hasResultType = false; break; - case OpGroupIMulKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupFMulKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupBitwiseAndKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupBitwiseOrKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupBitwiseXorKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupLogicalAndKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupLogicalOrKHR: *hasResult = true; *hasResultType = true; break; - case OpGroupLogicalXorKHR: *hasResult = true; *hasResultType = true; break; - } -} -#endif /* SPV_ENABLE_UTILITY_CODE */ - -// Overload bitwise operators for mask bit combining - -inline ImageOperandsMask operator|(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) | unsigned(b)); } -inline ImageOperandsMask operator&(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) & unsigned(b)); } -inline ImageOperandsMask operator^(ImageOperandsMask a, ImageOperandsMask b) { return ImageOperandsMask(unsigned(a) ^ unsigned(b)); } -inline ImageOperandsMask operator~(ImageOperandsMask a) { return ImageOperandsMask(~unsigned(a)); } -inline FPFastMathModeMask operator|(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) | unsigned(b)); } -inline FPFastMathModeMask operator&(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) & unsigned(b)); } -inline FPFastMathModeMask operator^(FPFastMathModeMask a, FPFastMathModeMask b) { return FPFastMathModeMask(unsigned(a) ^ unsigned(b)); } -inline FPFastMathModeMask operator~(FPFastMathModeMask a) { return FPFastMathModeMask(~unsigned(a)); } -inline SelectionControlMask operator|(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) | unsigned(b)); } -inline SelectionControlMask operator&(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) & unsigned(b)); } -inline SelectionControlMask operator^(SelectionControlMask a, SelectionControlMask b) { return SelectionControlMask(unsigned(a) ^ unsigned(b)); } -inline SelectionControlMask operator~(SelectionControlMask a) { return SelectionControlMask(~unsigned(a)); } -inline LoopControlMask operator|(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) | unsigned(b)); } -inline LoopControlMask operator&(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) & unsigned(b)); } -inline LoopControlMask operator^(LoopControlMask a, LoopControlMask b) { return LoopControlMask(unsigned(a) ^ unsigned(b)); } -inline LoopControlMask operator~(LoopControlMask a) { return LoopControlMask(~unsigned(a)); } -inline FunctionControlMask operator|(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) | unsigned(b)); } -inline FunctionControlMask operator&(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) & unsigned(b)); } -inline FunctionControlMask operator^(FunctionControlMask a, FunctionControlMask b) { return FunctionControlMask(unsigned(a) ^ unsigned(b)); } -inline FunctionControlMask operator~(FunctionControlMask a) { return FunctionControlMask(~unsigned(a)); } -inline MemorySemanticsMask operator|(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) | unsigned(b)); } -inline MemorySemanticsMask operator&(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) & unsigned(b)); } -inline MemorySemanticsMask operator^(MemorySemanticsMask a, MemorySemanticsMask b) { return MemorySemanticsMask(unsigned(a) ^ unsigned(b)); } -inline MemorySemanticsMask operator~(MemorySemanticsMask a) { return MemorySemanticsMask(~unsigned(a)); } -inline MemoryAccessMask operator|(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) | unsigned(b)); } -inline MemoryAccessMask operator&(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) & unsigned(b)); } -inline MemoryAccessMask operator^(MemoryAccessMask a, MemoryAccessMask b) { return MemoryAccessMask(unsigned(a) ^ unsigned(b)); } -inline MemoryAccessMask operator~(MemoryAccessMask a) { return MemoryAccessMask(~unsigned(a)); } -inline KernelProfilingInfoMask operator|(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) | unsigned(b)); } -inline KernelProfilingInfoMask operator&(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) & unsigned(b)); } -inline KernelProfilingInfoMask operator^(KernelProfilingInfoMask a, KernelProfilingInfoMask b) { return KernelProfilingInfoMask(unsigned(a) ^ unsigned(b)); } -inline KernelProfilingInfoMask operator~(KernelProfilingInfoMask a) { return KernelProfilingInfoMask(~unsigned(a)); } -inline RayFlagsMask operator|(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) | unsigned(b)); } -inline RayFlagsMask operator&(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) & unsigned(b)); } -inline RayFlagsMask operator^(RayFlagsMask a, RayFlagsMask b) { return RayFlagsMask(unsigned(a) ^ unsigned(b)); } -inline RayFlagsMask operator~(RayFlagsMask a) { return RayFlagsMask(~unsigned(a)); } -inline FragmentShadingRateMask operator|(FragmentShadingRateMask a, FragmentShadingRateMask b) { return FragmentShadingRateMask(unsigned(a) | unsigned(b)); } -inline FragmentShadingRateMask operator&(FragmentShadingRateMask a, FragmentShadingRateMask b) { return FragmentShadingRateMask(unsigned(a) & unsigned(b)); } -inline FragmentShadingRateMask operator^(FragmentShadingRateMask a, FragmentShadingRateMask b) { return FragmentShadingRateMask(unsigned(a) ^ unsigned(b)); } -inline FragmentShadingRateMask operator~(FragmentShadingRateMask a) { return FragmentShadingRateMask(~unsigned(a)); } -inline CooperativeMatrixOperandsMask operator|(CooperativeMatrixOperandsMask a, CooperativeMatrixOperandsMask b) { return CooperativeMatrixOperandsMask(unsigned(a) | unsigned(b)); } -inline CooperativeMatrixOperandsMask operator&(CooperativeMatrixOperandsMask a, CooperativeMatrixOperandsMask b) { return CooperativeMatrixOperandsMask(unsigned(a) & unsigned(b)); } -inline CooperativeMatrixOperandsMask operator^(CooperativeMatrixOperandsMask a, CooperativeMatrixOperandsMask b) { return CooperativeMatrixOperandsMask(unsigned(a) ^ unsigned(b)); } -inline CooperativeMatrixOperandsMask operator~(CooperativeMatrixOperandsMask a) { return CooperativeMatrixOperandsMask(~unsigned(a)); } - -} // end namespace spv - -#endif // #ifndef spirv_HPP - diff --git a/3rdparty/glslang/SPIRV/spvIR.h b/3rdparty/glslang/SPIRV/spvIR.h deleted file mode 100644 index 8849f42e..00000000 --- a/3rdparty/glslang/SPIRV/spvIR.h +++ /dev/null @@ -1,534 +0,0 @@ -// -// Copyright (C) 2014 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// SPIRV-IR -// -// Simple in-memory representation (IR) of SPIRV. Just for holding -// Each function's CFG of blocks. Has this hierarchy: -// - Module, which is a list of -// - Function, which is a list of -// - Block, which is a list of -// - Instruction -// - -#pragma once -#ifndef spvIR_H -#define spvIR_H - -#include "spirv.hpp" - -#include -#include -#include -#include -#include -#include -#include - -namespace spv { - -class Block; -class Function; -class Module; - -const Id NoResult = 0; -const Id NoType = 0; - -const Decoration NoPrecision = DecorationMax; - -#ifdef __GNUC__ -# define POTENTIALLY_UNUSED __attribute__((unused)) -#else -# define POTENTIALLY_UNUSED -#endif - -POTENTIALLY_UNUSED -const MemorySemanticsMask MemorySemanticsAllMemory = - (MemorySemanticsMask)(MemorySemanticsUniformMemoryMask | - MemorySemanticsWorkgroupMemoryMask | - MemorySemanticsAtomicCounterMemoryMask | - MemorySemanticsImageMemoryMask); - -struct IdImmediate { - bool isId; // true if word is an Id, false if word is an immediate - unsigned word; - IdImmediate(bool i, unsigned w) : isId(i), word(w) {} -}; - -// -// SPIR-V IR instruction. -// - -class Instruction { -public: - Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } - explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } - virtual ~Instruction() {} - void addIdOperand(Id id) { - // ids can't be 0 - assert(id); - operands.push_back(id); - idOperand.push_back(true); - } - void addImmediateOperand(unsigned int immediate) { - operands.push_back(immediate); - idOperand.push_back(false); - } - void setImmediateOperand(unsigned idx, unsigned int immediate) { - assert(!idOperand[idx]); - operands[idx] = immediate; - } - - void addStringOperand(const char* str) - { - unsigned int word = 0; - unsigned int shiftAmount = 0; - char c; - - do { - c = *(str++); - word |= ((unsigned int)c) << shiftAmount; - shiftAmount += 8; - if (shiftAmount == 32) { - addImmediateOperand(word); - word = 0; - shiftAmount = 0; - } - } while (c != 0); - - // deal with partial last word - if (shiftAmount > 0) { - addImmediateOperand(word); - } - } - bool isIdOperand(int op) const { return idOperand[op]; } - void setBlock(Block* b) { block = b; } - Block* getBlock() const { return block; } - Op getOpCode() const { return opCode; } - int getNumOperands() const - { - assert(operands.size() == idOperand.size()); - return (int)operands.size(); - } - Id getResultId() const { return resultId; } - Id getTypeId() const { return typeId; } - Id getIdOperand(int op) const { - assert(idOperand[op]); - return operands[op]; - } - unsigned int getImmediateOperand(int op) const { - assert(!idOperand[op]); - return operands[op]; - } - - // Write out the binary form. - void dump(std::vector& out) const - { - // Compute the wordCount - unsigned int wordCount = 1; - if (typeId) - ++wordCount; - if (resultId) - ++wordCount; - wordCount += (unsigned int)operands.size(); - - // Write out the beginning of the instruction - out.push_back(((wordCount) << WordCountShift) | opCode); - if (typeId) - out.push_back(typeId); - if (resultId) - out.push_back(resultId); - - // Write out the operands - for (int op = 0; op < (int)operands.size(); ++op) - out.push_back(operands[op]); - } - -protected: - Instruction(const Instruction&); - Id resultId; - Id typeId; - Op opCode; - std::vector operands; // operands, both and immediates (both are unsigned int) - std::vector idOperand; // true for operands that are , false for immediates - Block* block; -}; - -// -// SPIR-V IR block. -// - -class Block { -public: - Block(Id id, Function& parent); - virtual ~Block() - { - } - - Id getId() { return instructions.front()->getResultId(); } - - Function& getParent() const { return parent; } - void addInstruction(std::unique_ptr inst); - void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);} - void addLocalVariable(std::unique_ptr inst) { localVariables.push_back(std::move(inst)); } - const std::vector& getPredecessors() const { return predecessors; } - const std::vector& getSuccessors() const { return successors; } - const std::vector >& getInstructions() const { - return instructions; - } - const std::vector >& getLocalVariables() const { return localVariables; } - void setUnreachable() { unreachable = true; } - bool isUnreachable() const { return unreachable; } - // Returns the block's merge instruction, if one exists (otherwise null). - const Instruction* getMergeInstruction() const { - if (instructions.size() < 2) return nullptr; - const Instruction* nextToLast = (instructions.cend() - 2)->get(); - switch (nextToLast->getOpCode()) { - case OpSelectionMerge: - case OpLoopMerge: - return nextToLast; - default: - return nullptr; - } - return nullptr; - } - - // Change this block into a canonical dead merge block. Delete instructions - // as necessary. A canonical dead merge block has only an OpLabel and an - // OpUnreachable. - void rewriteAsCanonicalUnreachableMerge() { - assert(localVariables.empty()); - // Delete all instructions except for the label. - assert(instructions.size() > 0); - instructions.resize(1); - successors.clear(); - addInstruction(std::unique_ptr(new Instruction(OpUnreachable))); - } - // Change this block into a canonical dead continue target branching to the - // given header ID. Delete instructions as necessary. A canonical dead continue - // target has only an OpLabel and an unconditional branch back to the corresponding - // header. - void rewriteAsCanonicalUnreachableContinue(Block* header) { - assert(localVariables.empty()); - // Delete all instructions except for the label. - assert(instructions.size() > 0); - instructions.resize(1); - successors.clear(); - // Add OpBranch back to the header. - assert(header != nullptr); - Instruction* branch = new Instruction(OpBranch); - branch->addIdOperand(header->getId()); - addInstruction(std::unique_ptr(branch)); - successors.push_back(header); - } - - bool isTerminated() const - { - switch (instructions.back()->getOpCode()) { - case OpBranch: - case OpBranchConditional: - case OpSwitch: - case OpKill: - case OpTerminateInvocation: - case OpReturn: - case OpReturnValue: - case OpUnreachable: - return true; - default: - return false; - } - } - - void dump(std::vector& out) const - { - instructions[0]->dump(out); - for (int i = 0; i < (int)localVariables.size(); ++i) - localVariables[i]->dump(out); - for (int i = 1; i < (int)instructions.size(); ++i) - instructions[i]->dump(out); - } - -protected: - Block(const Block&); - Block& operator=(Block&); - - // To enforce keeping parent and ownership in sync: - friend Function; - - std::vector > instructions; - std::vector predecessors, successors; - std::vector > localVariables; - Function& parent; - - // track whether this block is known to be uncreachable (not necessarily - // true for all unreachable blocks, but should be set at least - // for the extraneous ones introduced by the builder). - bool unreachable; -}; - -// The different reasons for reaching a block in the inReadableOrder traversal. -enum ReachReason { - // Reachable from the entry block via transfers of control, i.e. branches. - ReachViaControlFlow = 0, - // A continue target that is not reachable via control flow. - ReachDeadContinue, - // A merge block that is not reachable via control flow. - ReachDeadMerge -}; - -// Traverses the control-flow graph rooted at root in an order suited for -// readable code generation. Invokes callback at every node in the traversal -// order. The callback arguments are: -// - the block, -// - the reason we reached the block, -// - if the reason was that block is an unreachable continue or unreachable merge block -// then the last parameter is the corresponding header block. -void inReadableOrder(Block* root, std::function callback); - -// -// SPIR-V IR Function. -// - -class Function { -public: - Function(Id id, Id resultType, Id functionType, Id firstParam, LinkageType linkage, const std::string& name, Module& parent); - virtual ~Function() - { - for (int i = 0; i < (int)parameterInstructions.size(); ++i) - delete parameterInstructions[i]; - - for (int i = 0; i < (int)blocks.size(); ++i) - delete blocks[i]; - } - Id getId() const { return functionInstruction.getResultId(); } - Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); } - Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); } - - void addBlock(Block* block) { blocks.push_back(block); } - void removeBlock(Block* block) - { - auto found = find(blocks.begin(), blocks.end(), block); - assert(found != blocks.end()); - blocks.erase(found); - delete block; - } - - Module& getParent() const { return parent; } - Block* getEntryBlock() const { return blocks.front(); } - Block* getLastBlock() const { return blocks.back(); } - const std::vector& getBlocks() const { return blocks; } - void addLocalVariable(std::unique_ptr inst); - Id getReturnType() const { return functionInstruction.getTypeId(); } - Id getFuncId() const { return functionInstruction.getResultId(); } - Id getFuncTypeId() const { return functionInstruction.getIdOperand(1); } - void setReturnPrecision(Decoration precision) - { - if (precision == DecorationRelaxedPrecision) - reducedPrecisionReturn = true; - } - Decoration getReturnPrecision() const - { return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; } - - void setDebugLineInfo(Id fileName, int line, int column) { - lineInstruction = std::unique_ptr{new Instruction(OpLine)}; - lineInstruction->addIdOperand(fileName); - lineInstruction->addImmediateOperand(line); - lineInstruction->addImmediateOperand(column); - } - bool hasDebugLineInfo() const { return lineInstruction != nullptr; } - - void setImplicitThis() { implicitThis = true; } - bool hasImplicitThis() const { return implicitThis; } - - void addParamPrecision(unsigned param, Decoration precision) - { - if (precision == DecorationRelaxedPrecision) - reducedPrecisionParams.insert(param); - } - Decoration getParamPrecision(unsigned param) const - { - return reducedPrecisionParams.find(param) != reducedPrecisionParams.end() ? - DecorationRelaxedPrecision : NoPrecision; - } - - void dump(std::vector& out) const - { - // OpLine - if (lineInstruction != nullptr) { - lineInstruction->dump(out); - } - - // OpFunction - functionInstruction.dump(out); - - // OpFunctionParameter - for (int p = 0; p < (int)parameterInstructions.size(); ++p) - parameterInstructions[p]->dump(out); - - // Blocks - inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); }); - Instruction end(0, 0, OpFunctionEnd); - end.dump(out); - } - - LinkageType getLinkType() const { return linkType; } - const char* getExportName() const { return exportName.c_str(); } - -protected: - Function(const Function&); - Function& operator=(Function&); - - Module& parent; - std::unique_ptr lineInstruction; - Instruction functionInstruction; - std::vector parameterInstructions; - std::vector blocks; - bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument - bool reducedPrecisionReturn; - std::set reducedPrecisionParams; // list of parameter indexes that need a relaxed precision arg - LinkageType linkType; - std::string exportName; -}; - -// -// SPIR-V IR Module. -// - -class Module { -public: - Module() {} - virtual ~Module() - { - // TODO delete things - } - - void addFunction(Function *fun) { functions.push_back(fun); } - - void mapInstruction(Instruction *instruction) - { - spv::Id resultId = instruction->getResultId(); - // map the instruction's result id - if (resultId >= idToInstruction.size()) - idToInstruction.resize(resultId + 16); - idToInstruction[resultId] = instruction; - } - - Instruction* getInstruction(Id id) const { return idToInstruction[id]; } - const std::vector& getFunctions() const { return functions; } - spv::Id getTypeId(Id resultId) const { - return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId(); - } - StorageClass getStorageClass(Id typeId) const - { - assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); - return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); - } - - void dump(std::vector& out) const - { - for (int f = 0; f < (int)functions.size(); ++f) - functions[f]->dump(out); - } - -protected: - Module(const Module&); - std::vector functions; - - // map from result id to instruction having that result id - std::vector idToInstruction; - - // map from a result id to its type id -}; - -// -// Implementation (it's here due to circular type definitions). -// - -// Add both -// - the OpFunction instruction -// - all the OpFunctionParameter instructions -__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, LinkageType linkage, const std::string& name, Module& parent) - : parent(parent), lineInstruction(nullptr), - functionInstruction(id, resultType, OpFunction), implicitThis(false), - reducedPrecisionReturn(false), - linkType(linkage) -{ - // OpFunction - functionInstruction.addImmediateOperand(FunctionControlMaskNone); - functionInstruction.addIdOperand(functionType); - parent.mapInstruction(&functionInstruction); - parent.addFunction(this); - - // OpFunctionParameter - Instruction* typeInst = parent.getInstruction(functionType); - int numParams = typeInst->getNumOperands() - 1; - for (int p = 0; p < numParams; ++p) { - Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter); - parent.mapInstruction(param); - parameterInstructions.push_back(param); - } - - // If importing/exporting, save the function name (without the mangled parameters) for the linkage decoration - if (linkType != LinkageTypeMax) { - exportName = name.substr(0, name.find_first_of('(')); - } -} - -__inline void Function::addLocalVariable(std::unique_ptr inst) -{ - Instruction* raw_instruction = inst.get(); - blocks[0]->addLocalVariable(std::move(inst)); - parent.mapInstruction(raw_instruction); -} - -__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false) -{ - instructions.push_back(std::unique_ptr(new Instruction(id, NoType, OpLabel))); - instructions.back()->setBlock(this); - parent.getParent().mapInstruction(instructions.back().get()); -} - -__inline void Block::addInstruction(std::unique_ptr inst) -{ - Instruction* raw_instruction = inst.get(); - instructions.push_back(std::move(inst)); - raw_instruction->setBlock(this); - if (raw_instruction->getResultId()) - parent.getParent().mapInstruction(raw_instruction); -} - -} // end spv namespace - -#endif // spvIR_H diff --git a/3rdparty/glslang/StandAlone/CMakeLists.txt b/3rdparty/glslang/StandAlone/CMakeLists.txt deleted file mode 100644 index 459657ab..00000000 --- a/3rdparty/glslang/StandAlone/CMakeLists.txt +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright (C) 2020-2023 The Khronos Group Inc. -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# Neither the name of The Khronos Group Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -find_package(Python3 REQUIRED) - -set(GLSLANG_INTRINSIC_H "${GLSLANG_GENERATED_INCLUDEDIR}/glslang/glsl_intrinsic_header.h") -set(GLSLANG_INTRINSIC_PY "${CMAKE_CURRENT_SOURCE_DIR}/../gen_extension_headers.py") -set(GLSLANG_INTRINSIC_HEADER_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../glslang/ExtensionHeaders") - -add_custom_command( - OUTPUT ${GLSLANG_INTRINSIC_H} - COMMAND Python3::Interpreter "${GLSLANG_INTRINSIC_PY}" - "-i" ${GLSLANG_INTRINSIC_HEADER_DIR} - "-o" ${GLSLANG_INTRINSIC_H} - DEPENDS ${GLSLANG_INTRINSIC_PY} - COMMENT "Generating ${GLSLANG_INTRINSIC_H}") - -set(SOURCES StandAlone.cpp DirStackFileIncluder.h ${GLSLANG_INTRINSIC_H}) - -add_executable(glslang-standalone ${SOURCES}) -if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") - target_compile_options(glslang-standalone PRIVATE -Wconversion) -elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC) - target_compile_options(glslang-standalone PRIVATE -Wshorten-64-to-32) -endif() -set_property(TARGET glslang-standalone PROPERTY FOLDER tools) -set_property(TARGET glslang-standalone PROPERTY OUTPUT_NAME glslang) -glslang_set_link_args(glslang-standalone) - -set(LIBRARIES - glslang - OSDependent - SPIRV - glslang-default-resource-limits) - -if(WIN32) - set(LIBRARIES ${LIBRARIES} psapi) -elseif(UNIX) - if(NOT ANDROID AND NOT QNX) - set(LIBRARIES ${LIBRARIES} pthread) - endif() -endif() - -target_link_libraries(glslang-standalone ${LIBRARIES}) -target_include_directories(glslang-standalone PUBLIC - $) - -if(ENABLE_SPVREMAPPER) - set(REMAPPER_SOURCES spirv-remap.cpp) - add_executable(spirv-remap ${REMAPPER_SOURCES}) - set_property(TARGET spirv-remap PROPERTY FOLDER tools) - glslang_set_link_args(spirv-remap) - target_link_libraries(spirv-remap SPVRemapper ${LIBRARIES}) -endif() - -if(WIN32) - source_group("Source" FILES ${SOURCES}) -endif() - -if(PROJECT_IS_TOP_LEVEL) - install(TARGETS glslang-standalone EXPORT glslang-targets) - - # Backward compatibility - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/glslang-standaloneTargets.cmake" " - message(WARNING \"Using `glslang-standaloneTargets.cmake` is deprecated: use `find_package(glslang)` to find glslang CMake targets.\") - - if (NOT TARGET glslang::glslang-standalone) - include(\"${CMAKE_INSTALL_FULL_LIBDIR}/cmake/${PROJECT_NAME}/glslang-targets.cmake\") - endif() - - add_library(glslang-standalone ALIAS glslang::glslang-standalone) - ") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/glslang-standaloneTargets.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) - - # Create a symbolic link to glslang named glslangValidator for backwards compatibility - set(legacy_glslang_name "glslangValidator${CMAKE_EXECUTABLE_SUFFIX}") - set(link_method create_symlink) - if (WIN32 OR MINGW) - set(link_method copy_if_different) - endif() - add_custom_command(TARGET glslang-standalone - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E ${link_method} $ ${legacy_glslang_name} - WORKING_DIRECTORY $) - - # Create the same symlink at install time - install(CODE "execute_process( \ - COMMAND ${CMAKE_COMMAND} -E ${link_method} $ ${legacy_glslang_name} \ - WORKING_DIRECTORY \$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})") - - if(ENABLE_SPVREMAPPER) - install(TARGETS spirv-remap EXPORT glslang-targets) - - # Backward compatibility - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/spirv-remapTargets.cmake" " - message(WARNING \"Using `spirv-remapTargets.cmake` is deprecated: use `find_package(glslang)` to find glslang CMake targets.\") - - if (NOT TARGET glslang::spirv-remap) - include(\"${CMAKE_INSTALL_FULL_LIBDIR}/cmake/${PROJECT_NAME}/glslang-targets.cmake\") - endif() - - add_library(spirv-remap ALIAS glslang::spirv-remap) - ") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/spirv-remapTargets.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) - endif() - -endif() diff --git a/3rdparty/glslang/StandAlone/DirStackFileIncluder.h b/3rdparty/glslang/StandAlone/DirStackFileIncluder.h deleted file mode 100644 index 5a33c78f..00000000 --- a/3rdparty/glslang/StandAlone/DirStackFileIncluder.h +++ /dev/null @@ -1,149 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2017 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include -#include -#include -#include -#include - -#include "./../glslang/Public/ShaderLang.h" - -// Default include class for normal include convention of search backward -// through the stack of active include paths (for nested includes). -// Can be overridden to customize. -class DirStackFileIncluder : public glslang::TShader::Includer { -public: - DirStackFileIncluder() : externalLocalDirectoryCount(0) { } - - virtual IncludeResult* includeLocal(const char* headerName, - const char* includerName, - size_t inclusionDepth) override - { - return readLocalPath(headerName, includerName, (int)inclusionDepth); - } - - virtual IncludeResult* includeSystem(const char* headerName, - const char* /*includerName*/, - size_t /*inclusionDepth*/) override - { - return readSystemPath(headerName); - } - - // Externally set directories. E.g., from a command-line -I. - // - Most-recently pushed are checked first. - // - All these are checked after the parse-time stack of local directories - // is checked. - // - This only applies to the "local" form of #include. - // - Makes its own copy of the path. - virtual void pushExternalLocalDirectory(const std::string& dir) - { - directoryStack.push_back(dir); - externalLocalDirectoryCount = (int)directoryStack.size(); - } - - virtual void releaseInclude(IncludeResult* result) override - { - if (result != nullptr) { - delete [] static_cast(result->userData); - delete result; - } - } - - virtual std::set getIncludedFiles() - { - return includedFiles; - } - - virtual ~DirStackFileIncluder() override { } - -protected: - typedef char tUserDataElement; - std::vector directoryStack; - int externalLocalDirectoryCount; - std::set includedFiles; - - // Search for a valid "local" path based on combining the stack of include - // directories and the nominal name of the header. - virtual IncludeResult* readLocalPath(const char* headerName, const char* includerName, int depth) - { - // Discard popped include directories, and - // initialize when at parse-time first level. - directoryStack.resize(depth + externalLocalDirectoryCount); - if (depth == 1) - directoryStack.back() = getDirectory(includerName); - - // Find a directory that works, using a reverse search of the include stack. - for (auto it = directoryStack.rbegin(); it != directoryStack.rend(); ++it) { - std::string path = *it + '/' + headerName; - std::replace(path.begin(), path.end(), '\\', '/'); - std::ifstream file(path, std::ios_base::binary | std::ios_base::ate); - if (file) { - directoryStack.push_back(getDirectory(path)); - includedFiles.insert(path); - return newIncludeResult(path, file, (int)file.tellg()); - } - } - - return nullptr; - } - - // Search for a valid path. - // Not implemented yet; returning nullptr signals failure to find. - virtual IncludeResult* readSystemPath(const char* /*headerName*/) const - { - return nullptr; - } - - // Do actual reading of the file, filling in a new include result. - virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const - { - char* content = new tUserDataElement [length]; - file.seekg(0, file.beg); - file.read(content, length); - return new IncludeResult(path, content, length, content); - } - - // If no path markers, return current working directory. - // Otherwise, strip file name and return path leading up to it. - virtual std::string getDirectory(const std::string path) const - { - size_t last = path.find_last_of("/\\"); - return last == std::string::npos ? "." : path.substr(0, last); - } -}; diff --git a/3rdparty/glslang/StandAlone/StandAlone.cpp b/3rdparty/glslang/StandAlone/StandAlone.cpp deleted file mode 100644 index ed3deccd..00000000 --- a/3rdparty/glslang/StandAlone/StandAlone.cpp +++ /dev/null @@ -1,2186 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013-2016 LunarG, Inc. -// Copyright (C) 2016-2020 Google, Inc. -// Modifications Copyright(C) 2021 Advanced Micro Devices, Inc.All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// this only applies to the standalone wrapper, not the front end in general -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include "glslang/Public/ResourceLimits.h" -#include "Worklist.h" -#include "DirStackFileIncluder.h" -#include "./../glslang/Include/ShHandle.h" -#include "./../glslang/Public/ShaderLang.h" -#include "../glslang/MachineIndependent/localintermediate.h" -#include "../SPIRV/GlslangToSpv.h" -#include "../SPIRV/GLSL.std.450.h" -#include "../SPIRV/doc.h" -#include "../SPIRV/disassemble.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../glslang/OSDependent/osinclude.h" - -// Build-time generated includes -#include "glslang/build_info.h" - -#include "glslang/glsl_intrinsic_header.h" - -extern "C" { - GLSLANG_EXPORT void ShOutputHtml(); -} - -// Command-line options -enum TOptions : uint64_t { - EOptionNone = 0, - EOptionIntermediate = (1ull << 0), - EOptionSuppressInfolog = (1ull << 1), - EOptionMemoryLeakMode = (1ull << 2), - EOptionRelaxedErrors = (1ull << 3), - EOptionGiveWarnings = (1ull << 4), - EOptionLinkProgram = (1ull << 5), - EOptionMultiThreaded = (1ull << 6), - EOptionDumpConfig = (1ull << 7), - EOptionDumpReflection = (1ull << 8), - EOptionSuppressWarnings = (1ull << 9), - EOptionDumpVersions = (1ull << 10), - EOptionSpv = (1ull << 11), - EOptionHumanReadableSpv = (1ull << 12), - EOptionVulkanRules = (1ull << 13), - EOptionDefaultDesktop = (1ull << 14), - EOptionOutputPreprocessed = (1ull << 15), - EOptionOutputHexadecimal = (1ull << 16), - EOptionReadHlsl = (1ull << 17), - EOptionCascadingErrors = (1ull << 18), - EOptionAutoMapBindings = (1ull << 19), - EOptionFlattenUniformArrays = (1ull << 20), - EOptionNoStorageFormat = (1ull << 21), - EOptionKeepUncalled = (1ull << 22), - EOptionHlslOffsets = (1ull << 23), - EOptionHlslIoMapping = (1ull << 24), - EOptionAutoMapLocations = (1ull << 25), - EOptionDebug = (1ull << 26), - EOptionStdin = (1ull << 27), - EOptionOptimizeDisable = (1ull << 28), - EOptionOptimizeSize = (1ull << 29), - EOptionInvertY = (1ull << 30), - EOptionDumpBareVersion = (1ull << 31), - EOptionCompileOnly = (1ull << 32), -}; -bool targetHlslFunctionality1 = false; -bool SpvToolsDisassembler = false; -bool SpvToolsValidate = false; -bool NaNClamp = false; -bool stripDebugInfo = false; -bool emitNonSemanticShaderDebugInfo = false; -bool emitNonSemanticShaderDebugSource = false; -bool beQuiet = false; -bool VulkanRulesRelaxed = false; -bool autoSampledTextures = false; - -// -// Return codes from main/exit(). -// -enum TFailCode { - ESuccess = 0, - EFailUsage, - EFailCompile, - EFailLink, - EFailCompilerCreate, - EFailThreadCreate, - EFailLinkerCreate -}; - -// -// Forward declarations. -// -EShLanguage FindLanguage(const std::string& name, bool parseSuffix=true); -void CompileFile(const char* fileName, ShHandle); -void usage(); -char* ReadFileData(const char* fileName); -void FreeFileData(char* data); -void InfoLogMsg(const char* msg, const char* name, const int num); - -// Globally track if any compile or link failure. -std::atomic CompileFailed{0}; -std::atomic LinkFailed{0}; -std::atomic CompileOrLinkFailed{0}; - -// array of unique places to leave the shader names and infologs for the asynchronous compiles -std::vector> WorkItems; - -std::string ConfigFile; - -// -// Parse either a .conf file provided by the user or the default from glslang::DefaultTBuiltInResource -// -void ProcessConfigFile() -{ - if (ConfigFile.size() == 0) - *GetResources() = *GetDefaultResources(); - else { - char* configString = ReadFileData(ConfigFile.c_str()); - DecodeResourceLimits(GetResources(), configString); - FreeFileData(configString); - } -} - -int ReflectOptions = EShReflectionDefault; -std::underlying_type_t Options = EOptionNone; -const char* ExecutableName = nullptr; -const char* binaryFileName = nullptr; -const char* depencyFileName = nullptr; -const char* entryPointName = nullptr; -const char* sourceEntryPointName = nullptr; -const char* shaderStageName = nullptr; -const char* variableName = nullptr; -bool HlslEnable16BitTypes = false; -bool HlslDX9compatible = false; -bool HlslDxPositionW = false; -bool EnhancedMsgs = false; -bool DumpBuiltinSymbols = false; -std::vector IncludeDirectoryList; - -// Source environment -// (source 'Client' is currently the same as target 'Client') -int ClientInputSemanticsVersion = 100; - -// Target environment -glslang::EShClient Client = glslang::EShClientNone; // will stay EShClientNone if only validating -glslang::EShTargetClientVersion ClientVersion; // not valid until Client is set -glslang::EShTargetLanguage TargetLanguage = glslang::EShTargetNone; -glslang::EShTargetLanguageVersion TargetVersion; // not valid until TargetLanguage is set - -// GLSL version -int GlslVersion = 0; // GLSL version specified on CLI, overrides #version in shader source - -std::vector Processes; // what should be recorded by OpModuleProcessed, or equivalent - -// Per descriptor-set binding base data -typedef std::map TPerSetBaseBinding; - -std::vector> uniformLocationOverrides; -int uniformBase = 0; - -std::array, glslang::EResCount> baseBinding; -std::array, glslang::EResCount> baseBindingForSet; -std::array, EShLangCount> baseResourceSetBinding; - -std::vector> blockStorageOverrides; - -bool setGlobalUniformBlock = false; -std::string globalUniformName; -unsigned int globalUniformBinding; -unsigned int globalUniformSet; - -bool setGlobalBufferBlock = false; -std::string atomicCounterBlockName; -unsigned int atomicCounterBlockSet; - -// Add things like "#define ..." to a preamble to use in the beginning of the shader. -class TPreamble { -public: - TPreamble() { } - - bool isSet() const { return text.size() > 0; } - const char* get() const { return text.c_str(); } - - // #define... - void addDef(std::string def) - { - text.append("#define "); - fixLine(def); - - Processes.push_back("define-macro "); - Processes.back().append(def); - - // The first "=" needs to turn into a space - const size_t equal = def.find_first_of("="); - if (equal != def.npos) - def[equal] = ' '; - - text.append(def); - text.append("\n"); - } - - // #undef... - void addUndef(std::string undef) - { - text.append("#undef "); - fixLine(undef); - - Processes.push_back("undef-macro "); - Processes.back().append(undef); - - text.append(undef); - text.append("\n"); - } - - void addText(std::string preambleText) - { - fixLine(preambleText); - - Processes.push_back("preamble-text"); - Processes.back().append(preambleText); - - text.append(preambleText); - text.append("\n"); - } - -protected: - void fixLine(std::string& line) - { - // Can't go past a newline in the line - const size_t end = line.find_first_of("\n"); - if (end != line.npos) - line = line.substr(0, end); - } - - std::string text; // contents of preamble -}; - -// Track the user's #define and #undef from the command line. -TPreamble UserPreamble; -std::string PreambleString; - -// -// Create the default name for saving a binary if -o is not provided. -// -const char* GetBinaryName(EShLanguage stage) -{ - const char* name; - if (binaryFileName == nullptr) { - switch (stage) { - case EShLangVertex: name = "vert.spv"; break; - case EShLangTessControl: name = "tesc.spv"; break; - case EShLangTessEvaluation: name = "tese.spv"; break; - case EShLangGeometry: name = "geom.spv"; break; - case EShLangFragment: name = "frag.spv"; break; - case EShLangCompute: name = "comp.spv"; break; - case EShLangRayGen: name = "rgen.spv"; break; - case EShLangIntersect: name = "rint.spv"; break; - case EShLangAnyHit: name = "rahit.spv"; break; - case EShLangClosestHit: name = "rchit.spv"; break; - case EShLangMiss: name = "rmiss.spv"; break; - case EShLangCallable: name = "rcall.spv"; break; - case EShLangMesh : name = "mesh.spv"; break; - case EShLangTask : name = "task.spv"; break; - default: name = "unknown"; break; - } - } else - name = binaryFileName; - - return name; -} - -// -// *.conf => this is a config file that can set limits/resources -// -bool SetConfigFile(const std::string& name) -{ - if (name.size() < 5) - return false; - - if (name.compare(name.size() - 5, 5, ".conf") == 0) { - ConfigFile = name; - return true; - } - - return false; -} - -// -// Give error and exit with failure code. -// -void Error(const char* message, const char* detail = nullptr) -{ - fprintf(stderr, "%s: Error: ", ExecutableName); - if (detail != nullptr) - fprintf(stderr, "%s: ", detail); - fprintf(stderr, "%s (use -h for usage)\n", message); - exit(EFailUsage); -} - -// -// Process an optional binding base of one the forms: -// --argname [stage] base // base for stage (if given) or all stages (if not) -// --argname [stage] [base set]... // set/base pairs: set the base for given binding set. - -// Where stage is one of the forms accepted by FindLanguage, and base is an integer -// -void ProcessBindingBase(int& argc, char**& argv, glslang::TResourceType res) -{ - if (argc < 2) - usage(); - - EShLanguage lang = EShLangCount; - int singleBase = 0; - TPerSetBaseBinding perSetBase; - int arg = 1; - - // Parse stage, if given - if (!isdigit(argv[arg][0])) { - if (argc < 3) // this form needs one more argument - usage(); - - lang = FindLanguage(argv[arg++], false); - } - - if ((argc - arg) >= 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) { - // Parse a per-set binding base - do { - const int baseNum = atoi(argv[arg++]); - const int setNum = atoi(argv[arg++]); - perSetBase[setNum] = baseNum; - } while ((argc - arg) >= 2 && isdigit(argv[arg + 0][0]) && isdigit(argv[arg + 1][0])); - } else { - // Parse single binding base - singleBase = atoi(argv[arg++]); - } - - argc -= (arg-1); - argv += (arg-1); - - // Set one or all languages - const int langMin = (lang < EShLangCount) ? lang+0 : 0; - const int langMax = (lang < EShLangCount) ? lang+1 : EShLangCount; - - for (int lang = langMin; lang < langMax; ++lang) { - if (!perSetBase.empty()) - baseBindingForSet[res][lang].insert(perSetBase.begin(), perSetBase.end()); - else - baseBinding[res][lang] = singleBase; - } -} - -void ProcessResourceSetBindingBase(int& argc, char**& argv, std::array, EShLangCount>& base) -{ - if (argc < 2) - usage(); - - if (!isdigit(argv[1][0])) { - if (argc < 3) // this form needs one more argument - usage(); - - // Parse form: --argname stage [regname set base...], or: - // --argname stage set - const EShLanguage lang = FindLanguage(argv[1], false); - - argc--; - argv++; - - while (argc > 1 && argv[1] != nullptr && argv[1][0] != '-') { - base[lang].push_back(argv[1]); - - argc--; - argv++; - } - - // Must have one arg, or a multiple of three (for [regname set binding] triples) - if (base[lang].size() != 1 && (base[lang].size() % 3) != 0) - usage(); - - } else { - // Parse form: --argname set - for (int lang=0; lang>& storage) -{ - if (argc < 3) - usage(); - - glslang::TBlockStorageClass blockStorage = glslang::EbsNone; - - std::string strBacking(argv[2]); - if (strBacking == "uniform") - blockStorage = glslang::EbsUniform; - else if (strBacking == "buffer") - blockStorage = glslang::EbsStorageBuffer; - else if (strBacking == "push_constant") - blockStorage = glslang::EbsPushConstant; - else { - printf("%s: invalid block storage\n", strBacking.c_str()); - usage(); - } - - storage.push_back(std::make_pair(std::string(argv[1]), blockStorage)); - - argc -= 2; - argv += 2; -} - -inline bool isNonDigit(char c) { - // a non-digit character valid in a glsl identifier - return (c == '_') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); -} - -// whether string isa valid identifier to be used in glsl -bool isValidIdentifier(const char* str) { - std::string idn(str); - - if (idn.length() == 0) { - return false; - } - - if (idn.length() >= 3 && idn.substr(0, 3) == "gl_") { - // identifiers startin with "gl_" are reserved - return false; - } - - if (!isNonDigit(idn[0])) { - return false; - } - - for (unsigned int i = 1; i < idn.length(); ++i) { - if (!(isdigit(idn[i]) || isNonDigit(idn[i]))) { - return false; - } - } - - return true; -} - -// Process settings for either the global buffer block or global unfirom block -// of the form: -// --argname name set binding -void ProcessGlobalBlockSettings(int& argc, char**& argv, std::string* name, unsigned int* set, unsigned int* binding) -{ - if (argc < 4) - usage(); - - unsigned int curArg = 1; - - assert(name || set || binding); - - if (name) { - if (!isValidIdentifier(argv[curArg])) { - printf("%s: invalid identifier\n", argv[curArg]); - usage(); - } - *name = argv[curArg]; - - curArg++; - } - - if (set) { - errno = 0; - int setVal = static_cast(::strtol(argv[curArg], nullptr, 10)); - if (errno || setVal < 0) { - printf("%s: invalid set\n", argv[curArg]); - usage(); - } - *set = setVal; - - curArg++; - } - - if (binding) { - errno = 0; - int bindingVal = static_cast(::strtol(argv[curArg], nullptr, 10)); - if (errno || bindingVal < 0) { - printf("%s: invalid binding\n", argv[curArg]); - usage(); - } - *binding = bindingVal; - - curArg++; - } - - argc -= (curArg - 1); - argv += (curArg - 1); -} - -// -// Do all command-line argument parsing. This includes building up the work-items -// to be processed later, and saving all the command-line options. -// -// Does not return (it exits) if command-line is fatally flawed. -// -void ProcessArguments(std::vector>& workItems, int argc, char* argv[]) -{ - for (int res = 0; res < glslang::EResCount; ++res) - baseBinding[res].fill(0); - - ExecutableName = argv[0]; - workItems.reserve(argc); - - const auto bumpArg = [&]() { - if (argc > 0) { - argc--; - argv++; - } - }; - - // read a string directly attached to a single-letter option - const auto getStringOperand = [&](const char* desc) { - if (argv[0][2] == 0) { - printf("%s must immediately follow option (no spaces)\n", desc); - exit(EFailUsage); - } - return argv[0] + 2; - }; - - // read a number attached to a single-letter option - const auto getAttachedNumber = [&](const char* desc) { - int num = atoi(argv[0] + 2); - if (num == 0) { - printf("%s: expected attached non-0 number\n", desc); - exit(EFailUsage); - } - return num; - }; - - // minimum needed (without overriding something else) to target Vulkan SPIR-V - const auto setVulkanSpv = []() { - if (Client == glslang::EShClientNone) - ClientVersion = glslang::EShTargetVulkan_1_0; - Client = glslang::EShClientVulkan; - Options |= EOptionSpv; - Options |= EOptionVulkanRules; - Options |= EOptionLinkProgram; - }; - - // minimum needed (without overriding something else) to target OpenGL SPIR-V - const auto setOpenGlSpv = []() { - if (Client == glslang::EShClientNone) - ClientVersion = glslang::EShTargetOpenGL_450; - Client = glslang::EShClientOpenGL; - Options |= EOptionSpv; - Options |= EOptionLinkProgram; - // undo a -H default to Vulkan - Options &= ~EOptionVulkanRules; - }; - - const auto getUniformOverride = [getStringOperand]() { - const char *arg = getStringOperand("-u:"); - const char *split = strchr(arg, ':'); - if (split == nullptr) { - printf("%s: missing location\n", arg); - exit(EFailUsage); - } - errno = 0; - int location = static_cast(::strtol(split + 1, nullptr, 10)); - if (errno) { - printf("%s: invalid location\n", arg); - exit(EFailUsage); - } - return std::make_pair(std::string(arg, split - arg), location); - }; - - for (bumpArg(); argc >= 1; bumpArg()) { - if (argv[0][0] == '-') { - switch (argv[0][1]) { - case '-': - { - std::string lowerword(argv[0]+2); - std::transform(lowerword.begin(), lowerword.end(), lowerword.begin(), ::tolower); - - // handle --word style options - if (lowerword == "auto-map-bindings" || // synonyms - lowerword == "auto-map-binding" || - lowerword == "amb") { - Options |= EOptionAutoMapBindings; - } else if (lowerword == "auto-map-locations" || // synonyms - lowerword == "aml") { - Options |= EOptionAutoMapLocations; - } else if (lowerword == "uniform-base") { - if (argc <= 1) - Error("no provided", lowerword.c_str()); - uniformBase = static_cast(::strtol(argv[1], nullptr, 10)); - bumpArg(); - break; - } else if (lowerword == "client") { - if (argc > 1) { - if (strcmp(argv[1], "vulkan100") == 0) - setVulkanSpv(); - else if (strcmp(argv[1], "opengl100") == 0) - setOpenGlSpv(); - else - Error("expects vulkan100 or opengl100", lowerword.c_str()); - } else - Error("expects vulkan100 or opengl100", lowerword.c_str()); - bumpArg(); - } else if (lowerword == "define-macro" || - lowerword == "d") { - if (argc > 1) - UserPreamble.addDef(argv[1]); - else - Error("expects ", argv[0]); - bumpArg(); - } else if (lowerword == "dump-builtin-symbols") { - DumpBuiltinSymbols = true; - } else if (lowerword == "entry-point") { - entryPointName = argv[1]; - if (argc <= 1) - Error("no provided", lowerword.c_str()); - bumpArg(); - } else if (lowerword == "flatten-uniform-arrays" || // synonyms - lowerword == "flatten-uniform-array" || - lowerword == "fua") { - Options |= EOptionFlattenUniformArrays; - } else if (lowerword == "glsl-version") { - if (argc > 1) { - if (strcmp(argv[1], "100") == 0) { - GlslVersion = 100; - } else if (strcmp(argv[1], "110") == 0) { - GlslVersion = 110; - } else if (strcmp(argv[1], "120") == 0) { - GlslVersion = 120; - } else if (strcmp(argv[1], "130") == 0) { - GlslVersion = 130; - } else if (strcmp(argv[1], "140") == 0) { - GlslVersion = 140; - } else if (strcmp(argv[1], "150") == 0) { - GlslVersion = 150; - } else if (strcmp(argv[1], "300es") == 0) { - GlslVersion = 300; - } else if (strcmp(argv[1], "310es") == 0) { - GlslVersion = 310; - } else if (strcmp(argv[1], "320es") == 0) { - GlslVersion = 320; - } else if (strcmp(argv[1], "330") == 0) { - GlslVersion = 330; - } else if (strcmp(argv[1], "400") == 0) { - GlslVersion = 400; - } else if (strcmp(argv[1], "410") == 0) { - GlslVersion = 410; - } else if (strcmp(argv[1], "420") == 0) { - GlslVersion = 420; - } else if (strcmp(argv[1], "430") == 0) { - GlslVersion = 430; - } else if (strcmp(argv[1], "440") == 0) { - GlslVersion = 440; - } else if (strcmp(argv[1], "450") == 0) { - GlslVersion = 450; - } else if (strcmp(argv[1], "460") == 0) { - GlslVersion = 460; - } else - Error("--glsl-version expected one of: 100, 110, 120, 130, 140, 150,\n" - "300es, 310es, 320es, 330\n" - "400, 410, 420, 430, 440, 450, 460"); - } - bumpArg(); - } else if (lowerword == "hlsl-offsets") { - Options |= EOptionHlslOffsets; - } else if (lowerword == "hlsl-iomap" || - lowerword == "hlsl-iomapper" || - lowerword == "hlsl-iomapping") { - Options |= EOptionHlslIoMapping; - } else if (lowerword == "hlsl-enable-16bit-types") { - HlslEnable16BitTypes = true; - } else if (lowerword == "hlsl-dx9-compatible") { - HlslDX9compatible = true; - } else if (lowerword == "hlsl-dx-position-w") { - HlslDxPositionW = true; - } else if (lowerword == "enhanced-msgs") { - EnhancedMsgs = true; - } else if (lowerword == "auto-sampled-textures") { - autoSampledTextures = true; - } else if (lowerword == "invert-y" || // synonyms - lowerword == "iy") { - Options |= EOptionInvertY; - } else if (lowerword == "keep-uncalled" || // synonyms - lowerword == "ku") { - Options |= EOptionKeepUncalled; - } else if (lowerword == "nan-clamp") { - NaNClamp = true; - } else if (lowerword == "no-storage-format" || // synonyms - lowerword == "nsf") { - Options |= EOptionNoStorageFormat; - } else if (lowerword == "preamble-text" || - lowerword == "p") { - if (argc > 1) - UserPreamble.addText(argv[1]); - else - Error("expects ", argv[0]); - bumpArg(); - } else if (lowerword == "relaxed-errors") { - Options |= EOptionRelaxedErrors; - } else if (lowerword == "reflect-strict-array-suffix") { - ReflectOptions |= EShReflectionStrictArraySuffix; - } else if (lowerword == "reflect-basic-array-suffix") { - ReflectOptions |= EShReflectionBasicArraySuffix; - } else if (lowerword == "reflect-intermediate-io") { - ReflectOptions |= EShReflectionIntermediateIO; - } else if (lowerword == "reflect-separate-buffers") { - ReflectOptions |= EShReflectionSeparateBuffers; - } else if (lowerword == "reflect-all-block-variables") { - ReflectOptions |= EShReflectionAllBlockVariables; - } else if (lowerword == "reflect-unwrap-io-blocks") { - ReflectOptions |= EShReflectionUnwrapIOBlocks; - } else if (lowerword == "reflect-all-io-variables") { - ReflectOptions |= EShReflectionAllIOVariables; - } else if (lowerword == "reflect-shared-std140-ubo") { - ReflectOptions |= EShReflectionSharedStd140UBO; - } else if (lowerword == "reflect-shared-std140-ssbo") { - ReflectOptions |= EShReflectionSharedStd140SSBO; - } else if (lowerword == "resource-set-bindings" || // synonyms - lowerword == "resource-set-binding" || - lowerword == "rsb") { - ProcessResourceSetBindingBase(argc, argv, baseResourceSetBinding); - } else if (lowerword == "set-block-storage" || - lowerword == "sbs") { - ProcessBlockStorage(argc, argv, blockStorageOverrides); - } else if (lowerword == "set-atomic-counter-block" || - lowerword == "sacb") { - ProcessGlobalBlockSettings(argc, argv, &atomicCounterBlockName, &atomicCounterBlockSet, nullptr); - setGlobalBufferBlock = true; - } else if (lowerword == "set-default-uniform-block" || - lowerword == "sdub") { - ProcessGlobalBlockSettings(argc, argv, &globalUniformName, &globalUniformSet, &globalUniformBinding); - setGlobalUniformBlock = true; - } else if (lowerword == "shift-image-bindings" || // synonyms - lowerword == "shift-image-binding" || - lowerword == "sib") { - ProcessBindingBase(argc, argv, glslang::EResImage); - } else if (lowerword == "shift-sampler-bindings" || // synonyms - lowerword == "shift-sampler-binding" || - lowerword == "ssb") { - ProcessBindingBase(argc, argv, glslang::EResSampler); - } else if (lowerword == "shift-uav-bindings" || // synonyms - lowerword == "shift-uav-binding" || - lowerword == "suavb") { - ProcessBindingBase(argc, argv, glslang::EResUav); - } else if (lowerword == "shift-texture-bindings" || // synonyms - lowerword == "shift-texture-binding" || - lowerword == "stb") { - ProcessBindingBase(argc, argv, glslang::EResTexture); - } else if (lowerword == "shift-ubo-bindings" || // synonyms - lowerword == "shift-ubo-binding" || - lowerword == "shift-cbuffer-bindings" || - lowerword == "shift-cbuffer-binding" || - lowerword == "sub" || - lowerword == "scb") { - ProcessBindingBase(argc, argv, glslang::EResUbo); - } else if (lowerword == "shift-ssbo-bindings" || // synonyms - lowerword == "shift-ssbo-binding" || - lowerword == "sbb") { - ProcessBindingBase(argc, argv, glslang::EResSsbo); - } else if (lowerword == "source-entrypoint" || // synonyms - lowerword == "sep") { - if (argc <= 1) - Error("no provided", lowerword.c_str()); - sourceEntryPointName = argv[1]; - bumpArg(); - break; - } else if (lowerword == "spirv-dis") { - SpvToolsDisassembler = true; - } else if (lowerword == "spirv-val") { - SpvToolsValidate = true; - } else if (lowerword == "stdin") { - Options |= EOptionStdin; - shaderStageName = argv[1]; - } else if (lowerword == "suppress-warnings") { - Options |= EOptionSuppressWarnings; - } else if (lowerword == "target-env") { - if (argc > 1) { - if (strcmp(argv[1], "vulkan1.0") == 0) { - setVulkanSpv(); - ClientVersion = glslang::EShTargetVulkan_1_0; - } else if (strcmp(argv[1], "vulkan1.1") == 0) { - setVulkanSpv(); - ClientVersion = glslang::EShTargetVulkan_1_1; - } else if (strcmp(argv[1], "vulkan1.2") == 0) { - setVulkanSpv(); - ClientVersion = glslang::EShTargetVulkan_1_2; - } else if (strcmp(argv[1], "vulkan1.3") == 0) { - setVulkanSpv(); - ClientVersion = glslang::EShTargetVulkan_1_3; - } else if (strcmp(argv[1], "opengl") == 0) { - setOpenGlSpv(); - ClientVersion = glslang::EShTargetOpenGL_450; - } else if (strcmp(argv[1], "spirv1.0") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_0; - } else if (strcmp(argv[1], "spirv1.1") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_1; - } else if (strcmp(argv[1], "spirv1.2") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_2; - } else if (strcmp(argv[1], "spirv1.3") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_3; - } else if (strcmp(argv[1], "spirv1.4") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_4; - } else if (strcmp(argv[1], "spirv1.5") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_5; - } else if (strcmp(argv[1], "spirv1.6") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_6; - } else - Error("--target-env expected one of: vulkan1.0, vulkan1.1, vulkan1.2,\n" - "vulkan1.3, opengl, spirv1.0, spirv1.1, spirv1.2, spirv1.3,\n" - "spirv1.4, spirv1.5 or spirv1.6"); - } - bumpArg(); - } else if (lowerword == "undef-macro" || - lowerword == "u") { - if (argc > 1) - UserPreamble.addUndef(argv[1]); - else - Error("expects ", argv[0]); - bumpArg(); - } else if (lowerword == "variable-name" || // synonyms - lowerword == "vn") { - Options |= EOptionOutputHexadecimal; - if (argc <= 1) - Error("no provided", lowerword.c_str()); - variableName = argv[1]; - bumpArg(); - break; - } else if (lowerword == "quiet") { - beQuiet = true; - } else if (lowerword == "depfile") { - if (argc <= 1) - Error("no provided", lowerword.c_str()); - depencyFileName = argv[1]; - bumpArg(); - } else if (lowerword == "version") { - Options |= EOptionDumpVersions; - } else if (lowerword == "no-link") { - Options |= EOptionCompileOnly; - } else if (lowerword == "help") { - usage(); - break; - } else { - Error("unrecognized command-line option", argv[0]); - } - } - break; - case 'C': - Options |= EOptionCascadingErrors; - break; - case 'D': - if (argv[0][2] == 0) - Options |= EOptionReadHlsl; - else - UserPreamble.addDef(getStringOperand("-D")); - break; - case 'u': - uniformLocationOverrides.push_back(getUniformOverride()); - break; - case 'E': - Options |= EOptionOutputPreprocessed; - break; - case 'G': - // OpenGL client - setOpenGlSpv(); - if (argv[0][2] != 0) - ClientInputSemanticsVersion = getAttachedNumber("-G client input semantics"); - if (ClientInputSemanticsVersion != 100) - Error("unknown client version for -G, should be 100"); - break; - case 'H': - Options |= EOptionHumanReadableSpv; - if ((Options & EOptionSpv) == 0) { - // default to Vulkan - setVulkanSpv(); - } - break; - case 'I': - IncludeDirectoryList.push_back(getStringOperand("-I include path")); - break; - case 'O': - if (argv[0][2] == 'd') - Options |= EOptionOptimizeDisable; - else if (argv[0][2] == 's') -#if ENABLE_OPT - Options |= EOptionOptimizeSize; -#else - Error("-Os not available; optimizer not linked"); -#endif - else - Error("unknown -O option"); - break; - case 'P': - UserPreamble.addText(getStringOperand("-P")); - break; - case 'R': - VulkanRulesRelaxed = true; - break; - case 'S': - if (argc <= 1) - Error("no specified for -S"); - shaderStageName = argv[1]; - bumpArg(); - break; - case 'U': - UserPreamble.addUndef(getStringOperand("-U")); - break; - case 'V': - setVulkanSpv(); - if (argv[0][2] != 0) - ClientInputSemanticsVersion = getAttachedNumber("-V client input semantics"); - if (ClientInputSemanticsVersion != 100) - Error("unknown client version for -V, should be 100"); - break; - case 'c': - Options |= EOptionDumpConfig; - break; - case 'd': - if (strncmp(&argv[0][1], "dumpversion", strlen(&argv[0][1]) + 1) == 0 || - strncmp(&argv[0][1], "dumpfullversion", strlen(&argv[0][1]) + 1) == 0) - Options |= EOptionDumpBareVersion; - else - Options |= EOptionDefaultDesktop; - break; - case 'e': - entryPointName = argv[1]; - if (argc <= 1) - Error("no provided for -e"); - bumpArg(); - break; - case 'f': - if (strcmp(&argv[0][2], "hlsl_functionality1") == 0) - targetHlslFunctionality1 = true; - else - Error("-f: expected hlsl_functionality1"); - break; - case 'g': - // Override previous -g or -g0 argument - stripDebugInfo = false; - emitNonSemanticShaderDebugInfo = false; - Options &= ~EOptionDebug; - if (argv[0][2] == '0') - stripDebugInfo = true; - else { - Options |= EOptionDebug; - if (argv[0][2] == 'V') { - emitNonSemanticShaderDebugInfo = true; - if (argv[0][3] == 'S') { - emitNonSemanticShaderDebugSource = true; - } else { - emitNonSemanticShaderDebugSource = false; - } - } - } - break; - case 'h': - usage(); - break; - case 'i': - Options |= EOptionIntermediate; - break; - case 'l': - Options |= EOptionLinkProgram; - break; - case 'm': - Options |= EOptionMemoryLeakMode; - break; - case 'o': - if (argc <= 1) - Error("no provided for -o"); - binaryFileName = argv[1]; - bumpArg(); - break; - case 'q': - Options |= EOptionDumpReflection; - break; - case 'r': - Options |= EOptionRelaxedErrors; - break; - case 's': - Options |= EOptionSuppressInfolog; - break; - case 't': - Options |= EOptionMultiThreaded; - break; - case 'v': - Options |= EOptionDumpVersions; - break; - case 'w': - Options |= EOptionSuppressWarnings; - break; - case 'x': - Options |= EOptionOutputHexadecimal; - break; - default: - Error("unrecognized command-line option", argv[0]); - break; - } - } else { - std::string name(argv[0]); - if (! SetConfigFile(name)) { - workItems.push_back(std::unique_ptr(new glslang::TWorkItem(name))); - } - } - } - - // Make sure that -S is always specified if --stdin is specified - if ((Options & EOptionStdin) && shaderStageName == nullptr) - Error("must provide -S when --stdin is given"); - - // Make sure that -E is not specified alongside linking (which includes SPV generation) - // Or things that require linking - if (Options & EOptionOutputPreprocessed) { - if (Options & EOptionLinkProgram) - Error("can't use -E when linking is selected"); - if (Options & EOptionDumpReflection) - Error("reflection requires linking, which can't be used when -E when is selected"); - } - - // reflection requires linking - if ((Options & EOptionDumpReflection) && !(Options & EOptionLinkProgram)) - Error("reflection requires -l for linking"); - - // -o or -x makes no sense if there is no target binary - if (binaryFileName && (Options & EOptionSpv) == 0) - Error("no binary generation requested (e.g., -V)"); - - if ((Options & EOptionFlattenUniformArrays) != 0 && - (Options & EOptionReadHlsl) == 0) - Error("uniform array flattening only valid when compiling HLSL source."); - - if ((Options & EOptionReadHlsl) && (Client == glslang::EShClientOpenGL)) { - Error("Using HLSL input under OpenGL semantics is not currently supported."); - } - - // rationalize client and target language - if (TargetLanguage == glslang::EShTargetNone) { - switch (ClientVersion) { - case glslang::EShTargetVulkan_1_0: - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_0; - break; - case glslang::EShTargetVulkan_1_1: - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_3; - break; - case glslang::EShTargetVulkan_1_2: - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_5; - break; - case glslang::EShTargetVulkan_1_3: - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_6; - break; - case glslang::EShTargetOpenGL_450: - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_0; - break; - default: - break; - } - } - if (TargetLanguage != glslang::EShTargetNone && Client == glslang::EShClientNone) - Error("To generate SPIR-V, also specify client semantics. See -G and -V."); -} - -// -// Translate the meaningful subset of command-line options to parser-behavior options. -// -void SetMessageOptions(EShMessages& messages) -{ - if (Options & EOptionRelaxedErrors) - messages = (EShMessages)(messages | EShMsgRelaxedErrors); - if (Options & EOptionIntermediate) - messages = (EShMessages)(messages | EShMsgAST); - if (Options & EOptionSuppressWarnings) - messages = (EShMessages)(messages | EShMsgSuppressWarnings); - if (Options & EOptionSpv) - messages = (EShMessages)(messages | EShMsgSpvRules); - if (Options & EOptionVulkanRules) - messages = (EShMessages)(messages | EShMsgVulkanRules); - if (Options & EOptionOutputPreprocessed) - messages = (EShMessages)(messages | EShMsgOnlyPreprocessor); - if (Options & EOptionReadHlsl) - messages = (EShMessages)(messages | EShMsgReadHlsl); - if (Options & EOptionCascadingErrors) - messages = (EShMessages)(messages | EShMsgCascadingErrors); - if (Options & EOptionKeepUncalled) - messages = (EShMessages)(messages | EShMsgKeepUncalled); - if (Options & EOptionHlslOffsets) - messages = (EShMessages)(messages | EShMsgHlslOffsets); - if (Options & EOptionDebug) - messages = (EShMessages)(messages | EShMsgDebugInfo); - if (HlslEnable16BitTypes) - messages = (EShMessages)(messages | EShMsgHlslEnable16BitTypes); - if ((Options & EOptionOptimizeDisable) || !ENABLE_OPT) - messages = (EShMessages)(messages | EShMsgHlslLegalization); - if (HlslDX9compatible) - messages = (EShMessages)(messages | EShMsgHlslDX9Compatible); - if (DumpBuiltinSymbols) - messages = (EShMessages)(messages | EShMsgBuiltinSymbolTable); - if (EnhancedMsgs) - messages = (EShMessages)(messages | EShMsgEnhanced); -} - -// -// Thread entry point, for non-linking asynchronous mode. -// -void CompileShaders(glslang::TWorklist& worklist) -{ - if (Options & EOptionDebug) - Error("cannot generate debug information unless linking to generate code"); - - // NOTE: TWorkList::remove is thread-safe - glslang::TWorkItem* workItem; - if (Options & EOptionStdin) { - if (worklist.remove(workItem)) { - ShHandle compiler = ShConstructCompiler(FindLanguage("stdin"), 0); - if (compiler == nullptr) - return; - - CompileFile("stdin", compiler); - - if (! (Options & EOptionSuppressInfolog)) - workItem->results = ShGetInfoLog(compiler); - - ShDestruct(compiler); - } - } else { - while (worklist.remove(workItem)) { - ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), 0); - if (compiler == nullptr) - return; - - CompileFile(workItem->name.c_str(), compiler); - - if (! (Options & EOptionSuppressInfolog)) - workItem->results = ShGetInfoLog(compiler); - - ShDestruct(compiler); - } - } -} - -// Outputs the given string, but only if it is non-null and non-empty. -// This prevents erroneous newlines from appearing. -void PutsIfNonEmpty(const char* str) -{ - if (str && str[0]) { - puts(str); - } -} - -// Outputs the given string to stderr, but only if it is non-null and non-empty. -// This prevents erroneous newlines from appearing. -void StderrIfNonEmpty(const char* str) -{ - if (str && str[0]) - fprintf(stderr, "%s\n", str); -} - -// Simple bundling of what makes a compilation unit for ease in passing around, -// and separation of handling file IO versus API (programmatic) compilation. -struct ShaderCompUnit { - EShLanguage stage; - static const int maxCount = 1; - int count; // live number of strings/names - const char* text[maxCount]; // memory owned/managed externally - std::string fileName[maxCount]; // hold's the memory, but... - const char* fileNameList[maxCount]; // downstream interface wants pointers - - ShaderCompUnit(EShLanguage stage) : stage(stage), count(0) { } - - ShaderCompUnit(const ShaderCompUnit& rhs) - { - stage = rhs.stage; - count = rhs.count; - for (int i = 0; i < count; ++i) { - fileName[i] = rhs.fileName[i]; - text[i] = rhs.text[i]; - fileNameList[i] = rhs.fileName[i].c_str(); - } - } - - void addString(std::string& ifileName, const char* itext) - { - assert(count < maxCount); - fileName[count] = ifileName; - text[count] = itext; - fileNameList[count] = fileName[count].c_str(); - ++count; - } -}; - -// Writes a string into a depfile, escaping some special characters following the Makefile rules. -static void writeEscapedDepString(std::ofstream& file, const std::string& str) -{ - for (char c : str) { - switch (c) { - case ' ': - case ':': - case '#': - case '[': - case ']': - case '\\': - file << '\\'; - break; - case '$': - file << '$'; - break; - } - file << c; - } -} - -// Writes a depfile similar to gcc -MMD foo.c -bool writeDepFile(std::string depfile, std::vector& binaryFiles, const std::vector& sources) -{ - std::ofstream file(depfile); - if (file.fail()) - return false; - - for (auto binaryFile = binaryFiles.begin(); binaryFile != binaryFiles.end(); binaryFile++) { - writeEscapedDepString(file, *binaryFile); - file << ":"; - for (auto sourceFile = sources.begin(); sourceFile != sources.end(); sourceFile++) { - file << " "; - writeEscapedDepString(file, *sourceFile); - } - file << std::endl; - } - return true; -} - -// -// For linking mode: Will independently parse each compilation unit, but then put them -// in the same program and link them together, making at most one linked module per -// pipeline stage. -// -// Uses the new C++ interface instead of the old handle-based interface. -// - -void CompileAndLinkShaderUnits(std::vector compUnits) -{ - // keep track of what to free - std::list shaders; - - EShMessages messages = EShMsgDefault; - SetMessageOptions(messages); - - DirStackFileIncluder includer; - std::for_each(IncludeDirectoryList.rbegin(), IncludeDirectoryList.rend(), [&includer](const std::string& dir) { - includer.pushExternalLocalDirectory(dir); }); - - std::vector sources; - - // - // Per-shader processing... - // - - glslang::TProgram& program = *new glslang::TProgram; - const bool compileOnly = (Options & EOptionCompileOnly) != 0; - for (auto it = compUnits.cbegin(); it != compUnits.cend(); ++it) { - const auto &compUnit = *it; - for (int i = 0; i < compUnit.count; i++) { - sources.push_back(compUnit.fileNameList[i]); - } - glslang::TShader* shader = new glslang::TShader(compUnit.stage); - shader->setStringsWithLengthsAndNames(compUnit.text, nullptr, compUnit.fileNameList, compUnit.count); - if (entryPointName) - shader->setEntryPoint(entryPointName); - if (sourceEntryPointName) { - if (entryPointName == nullptr) - printf("Warning: Changing source entry point name without setting an entry-point name.\n" - "Use '-e '.\n"); - shader->setSourceEntryPoint(sourceEntryPointName); - } - - if (compileOnly) - shader->setCompileOnly(); - - shader->setOverrideVersion(GlslVersion); - - std::string intrinsicString = getIntrinsic(compUnit.text, compUnit.count); - - PreambleString = ""; - if (UserPreamble.isSet()) - PreambleString.append(UserPreamble.get()); - - if (!intrinsicString.empty()) - PreambleString.append(intrinsicString); - - shader->setPreamble(PreambleString.c_str()); - shader->addProcesses(Processes); - - // Set IO mapper binding shift values - for (int r = 0; r < glslang::EResCount; ++r) { - const glslang::TResourceType res = glslang::TResourceType(r); - - // Set base bindings - shader->setShiftBinding(res, baseBinding[res][compUnit.stage]); - - // Set bindings for particular resource sets - // TODO: use a range based for loop here, when available in all environments. - for (auto i = baseBindingForSet[res][compUnit.stage].begin(); - i != baseBindingForSet[res][compUnit.stage].end(); ++i) - shader->setShiftBindingForSet(res, i->second, i->first); - } - shader->setNoStorageFormat((Options & EOptionNoStorageFormat) != 0); - shader->setResourceSetBinding(baseResourceSetBinding[compUnit.stage]); - - if (autoSampledTextures) - shader->setTextureSamplerTransformMode(EShTexSampTransUpgradeTextureRemoveSampler); - - if (Options & EOptionAutoMapBindings) - shader->setAutoMapBindings(true); - - if (Options & EOptionAutoMapLocations) - shader->setAutoMapLocations(true); - - for (auto& uniOverride : uniformLocationOverrides) { - shader->addUniformLocationOverride(uniOverride.first.c_str(), - uniOverride.second); - } - - shader->setUniformLocationBase(uniformBase); - - if (VulkanRulesRelaxed) { - for (auto& storageOverride : blockStorageOverrides) { - shader->addBlockStorageOverride(storageOverride.first.c_str(), - storageOverride.second); - } - - if (setGlobalBufferBlock) { - shader->setAtomicCounterBlockName(atomicCounterBlockName.c_str()); - shader->setAtomicCounterBlockSet(atomicCounterBlockSet); - } - - if (setGlobalUniformBlock) { - shader->setGlobalUniformBlockName(globalUniformName.c_str()); - shader->setGlobalUniformSet(globalUniformSet); - shader->setGlobalUniformBinding(globalUniformBinding); - } - } - - shader->setNanMinMaxClamp(NaNClamp); - -#ifdef ENABLE_HLSL - shader->setFlattenUniformArrays((Options & EOptionFlattenUniformArrays) != 0); - if (Options & EOptionHlslIoMapping) - shader->setHlslIoMapping(true); -#endif - - if (Options & EOptionInvertY) - shader->setInvertY(true); - - if (HlslDxPositionW) - shader->setDxPositionW(true); - - if (EnhancedMsgs) - shader->setEnhancedMsgs(); - - if (emitNonSemanticShaderDebugInfo) - shader->setDebugInfo(true); - - // Set up the environment, some subsettings take precedence over earlier - // ways of setting things. - if (Options & EOptionSpv) { - shader->setEnvInput((Options & EOptionReadHlsl) ? glslang::EShSourceHlsl - : glslang::EShSourceGlsl, - compUnit.stage, Client, ClientInputSemanticsVersion); - shader->setEnvClient(Client, ClientVersion); - shader->setEnvTarget(TargetLanguage, TargetVersion); -#ifdef ENABLE_HLSL - if (targetHlslFunctionality1) - shader->setEnvTargetHlslFunctionality1(); -#endif - if (VulkanRulesRelaxed) - shader->setEnvInputVulkanRulesRelaxed(); - } - - shaders.push_back(shader); - - const int defaultVersion = Options & EOptionDefaultDesktop ? 110 : 100; - - if (Options & EOptionOutputPreprocessed) { - std::string str; - if (shader->preprocess(GetResources(), defaultVersion, ENoProfile, false, false, messages, &str, includer)) { - PutsIfNonEmpty(str.c_str()); - } else { - CompileFailed = 1; - } - StderrIfNonEmpty(shader->getInfoLog()); - StderrIfNonEmpty(shader->getInfoDebugLog()); - continue; - } - - if (! shader->parse(GetResources(), defaultVersion, false, messages, includer)) - CompileFailed = 1; - - if (!compileOnly) - program.addShader(shader); - - if (! (Options & EOptionSuppressInfolog) && - ! (Options & EOptionMemoryLeakMode)) { - if (!beQuiet) - PutsIfNonEmpty(compUnit.fileName[0].c_str()); - PutsIfNonEmpty(shader->getInfoLog()); - PutsIfNonEmpty(shader->getInfoDebugLog()); - } - } - - // - // Program-level processing... - // - - if (!compileOnly) { - // Link - if (!(Options & EOptionOutputPreprocessed) && !program.link(messages)) - LinkFailed = true; - - // Map IO - if (Options & EOptionSpv) { - if (!program.mapIO()) - LinkFailed = true; - } - - // Report - if (!(Options & EOptionSuppressInfolog) && !(Options & EOptionMemoryLeakMode)) { - PutsIfNonEmpty(program.getInfoLog()); - PutsIfNonEmpty(program.getInfoDebugLog()); - } - - // Reflect - if (Options & EOptionDumpReflection) { - program.buildReflection(ReflectOptions); - program.dumpReflection(); - } - } - - std::vector outputFiles; - - // Dump SPIR-V - if (Options & EOptionSpv) { - CompileOrLinkFailed.fetch_or(CompileFailed); - CompileOrLinkFailed.fetch_or(LinkFailed); - if (static_cast(CompileOrLinkFailed.load())) - printf("SPIR-V is not generated for failed compile or link\n"); - else { - std::vector intermediates; - if (!compileOnly) { - for (int stage = 0; stage < EShLangCount; ++stage) { - if (auto* i = program.getIntermediate((EShLanguage)stage)) { - intermediates.emplace_back(i); - } - } - } else { - for (const auto* shader : shaders) { - if (auto* i = shader->getIntermediate()) { - intermediates.emplace_back(i); - } - } - } - for (auto* intermediate : intermediates) { - std::vector spirv; - spv::SpvBuildLogger logger; - glslang::SpvOptions spvOptions; - if (Options & EOptionDebug) { - spvOptions.generateDebugInfo = true; - if (emitNonSemanticShaderDebugInfo) { - spvOptions.emitNonSemanticShaderDebugInfo = true; - if (emitNonSemanticShaderDebugSource) { - spvOptions.emitNonSemanticShaderDebugSource = true; - } - } - } else if (stripDebugInfo) - spvOptions.stripDebugInfo = true; - spvOptions.disableOptimizer = (Options & EOptionOptimizeDisable) != 0; - spvOptions.optimizeSize = (Options & EOptionOptimizeSize) != 0; - spvOptions.disassemble = SpvToolsDisassembler; - spvOptions.validate = SpvToolsValidate; - spvOptions.compileOnly = compileOnly; - glslang::GlslangToSpv(*intermediate, spirv, &logger, &spvOptions); - - // Dump the spv to a file or stdout, etc., but only if not doing - // memory/perf testing, as it's not internal to programmatic use. - if (!(Options & EOptionMemoryLeakMode)) { - printf("%s", logger.getAllMessages().c_str()); - const auto filename = GetBinaryName(intermediate->getStage()); - if (Options & EOptionOutputHexadecimal) { - if (!glslang::OutputSpvHex(spirv, filename, variableName)) - exit(EFailUsage); - } else { - if (!glslang::OutputSpvBin(spirv, filename)) - exit(EFailUsage); - } - - outputFiles.push_back(filename); - if (!SpvToolsDisassembler && (Options & EOptionHumanReadableSpv)) - spv::Disassemble(std::cout, spirv); - } - } - } - } - - CompileOrLinkFailed.fetch_or(CompileFailed); - CompileOrLinkFailed.fetch_or(LinkFailed); - if (depencyFileName && !static_cast(CompileOrLinkFailed.load())) { - std::set includedFiles = includer.getIncludedFiles(); - sources.insert(sources.end(), includedFiles.begin(), includedFiles.end()); - - writeDepFile(depencyFileName, outputFiles, sources); - } - - // Free everything up, program has to go before the shaders - // because it might have merged stuff from the shaders, and - // the stuff from the shaders has to have its destructors called - // before the pools holding the memory in the shaders is freed. - delete &program; - while (shaders.size() > 0) { - delete shaders.back(); - shaders.pop_back(); - } -} - -// -// Do file IO part of compile and link, handing off the pure -// API/programmatic mode to CompileAndLinkShaderUnits(), which can -// be put in a loop for testing memory footprint and performance. -// -// This is just for linking mode: meaning all the shaders will be put into the -// the same program linked together. -// -// This means there are a limited number of work items (not multi-threading mode) -// and that the point is testing at the linking level. Hence, to enable -// performance and memory testing, the actual compile/link can be put in -// a loop, independent of processing the work items and file IO. -// -void CompileAndLinkShaderFiles(glslang::TWorklist& Worklist) -{ - std::vector compUnits; - - // If this is using stdin, we can't really detect multiple different file - // units by input type. We need to assume that we're just being given one - // file of a certain type. - if ((Options & EOptionStdin) != 0) { - ShaderCompUnit compUnit(FindLanguage("stdin")); - std::istreambuf_iterator begin(std::cin), end; - std::string tempString(begin, end); - char* fileText = strdup(tempString.c_str()); - std::string fileName = "stdin"; - compUnit.addString(fileName, fileText); - compUnits.push_back(compUnit); - } else { - // Transfer all the work items from to a simple list of - // of compilation units. (We don't care about the thread - // work-item distribution properties in this path, which - // is okay due to the limited number of shaders, know since - // they are all getting linked together.) - glslang::TWorkItem* workItem; - while (Worklist.remove(workItem)) { - ShaderCompUnit compUnit(FindLanguage(workItem->name)); - char* fileText = ReadFileData(workItem->name.c_str()); - if (fileText == nullptr) - usage(); - compUnit.addString(workItem->name, fileText); - compUnits.push_back(compUnit); - } - } - - // Actual call to programmatic processing of compile and link, - // in a loop for testing memory and performance. This part contains - // all the perf/memory that a programmatic consumer will care about. - for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) { - for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) - CompileAndLinkShaderUnits(compUnits); - - if (Options & EOptionMemoryLeakMode) - glslang::OS_DumpMemoryCounters(); - } - - // free memory from ReadFileData, which got stored in a const char* - // as the first string above - for (auto it = compUnits.begin(); it != compUnits.end(); ++it) - FreeFileData(const_cast(it->text[0])); -} - -int singleMain() -{ - glslang::TWorklist workList; - std::for_each(WorkItems.begin(), WorkItems.end(), [&workList](std::unique_ptr& item) { - assert(item); - workList.add(item.get()); - }); - - if (Options & EOptionDumpConfig) { - printf("%s", GetDefaultTBuiltInResourceString().c_str()); - if (workList.empty()) - return ESuccess; - } - - if (Options & EOptionDumpBareVersion) { - printf("%d:%d.%d.%d%s\n", glslang::GetSpirvGeneratorVersion(), GLSLANG_VERSION_MAJOR, GLSLANG_VERSION_MINOR, - GLSLANG_VERSION_PATCH, GLSLANG_VERSION_FLAVOR); - if (workList.empty()) - return ESuccess; - } else if (Options & EOptionDumpVersions) { - printf("Glslang Version: %d:%d.%d.%d%s\n", glslang::GetSpirvGeneratorVersion(), GLSLANG_VERSION_MAJOR, - GLSLANG_VERSION_MINOR, GLSLANG_VERSION_PATCH, GLSLANG_VERSION_FLAVOR); - printf("ESSL Version: %s\n", glslang::GetEsslVersionString()); - printf("GLSL Version: %s\n", glslang::GetGlslVersionString()); - std::string spirvVersion; - glslang::GetSpirvVersion(spirvVersion); - printf("SPIR-V Version %s\n", spirvVersion.c_str()); - printf("GLSL.std.450 Version %d, Revision %d\n", GLSLstd450Version, GLSLstd450Revision); - printf("Khronos Tool ID %d\n", glslang::GetKhronosToolId()); - printf("SPIR-V Generator Version %d\n", glslang::GetSpirvGeneratorVersion()); - printf("GL_KHR_vulkan_glsl version %d\n", 100); - printf("ARB_GL_gl_spirv version %d\n", 100); - if (workList.empty()) - return ESuccess; - } - - if (workList.empty() && ((Options & EOptionStdin) == 0)) { - usage(); - } - - if (Options & EOptionStdin) { - WorkItems.push_back(std::unique_ptr{new glslang::TWorkItem("stdin")}); - workList.add(WorkItems.back().get()); - } - - ProcessConfigFile(); - - if ((Options & EOptionReadHlsl) && !((Options & EOptionOutputPreprocessed) || (Options & EOptionSpv))) - Error("HLSL requires SPIR-V code generation (or preprocessing only)"); - - // - // Two modes: - // 1) linking all arguments together, single-threaded, new C++ interface - // 2) independent arguments, can be tackled by multiple asynchronous threads, for testing thread safety, using the old handle interface - // - if (Options & (EOptionLinkProgram | EOptionOutputPreprocessed)) { - glslang::InitializeProcess(); - glslang::InitializeProcess(); // also test reference counting of users - glslang::InitializeProcess(); // also test reference counting of users - glslang::FinalizeProcess(); // also test reference counting of users - glslang::FinalizeProcess(); // also test reference counting of users - CompileAndLinkShaderFiles(workList); - glslang::FinalizeProcess(); - } else { - ShInitialize(); - ShInitialize(); // also test reference counting of users - ShFinalize(); // also test reference counting of users - - bool printShaderNames = workList.size() > 1; - - if (Options & EOptionMultiThreaded) { - std::array threads; - for (unsigned int t = 0; t < threads.size(); ++t) { - threads[t] = std::thread(CompileShaders, std::ref(workList)); - if (threads[t].get_id() == std::thread::id()) { - fprintf(stderr, "Failed to create thread\n"); - return EFailThreadCreate; - } - } - - std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); }); - } else - CompileShaders(workList); - - // Print out all the resulting infologs - for (size_t w = 0; w < WorkItems.size(); ++w) { - if (WorkItems[w]) { - if (printShaderNames || WorkItems[w]->results.size() > 0) - PutsIfNonEmpty(WorkItems[w]->name.c_str()); - PutsIfNonEmpty(WorkItems[w]->results.c_str()); - } - } - - ShFinalize(); - } - - if (CompileFailed.load()) - return EFailCompile; - if (LinkFailed.load()) - return EFailLink; - - return 0; -} - -int C_DECL main(int argc, char* argv[]) -{ - ProcessArguments(WorkItems, argc, argv); - - int ret = 0; - - // Loop over the entire init/finalize cycle to watch memory changes - const int iterations = 1; - if (iterations > 1) - glslang::OS_DumpMemoryCounters(); - for (int i = 0; i < iterations; ++i) { - ret = singleMain(); - if (iterations > 1) - glslang::OS_DumpMemoryCounters(); - } - - return ret; -} - -// -// Deduce the language from the filename. Files must end in one of the -// following extensions: -// -// .vert = vertex -// .tesc = tessellation control -// .tese = tessellation evaluation -// .geom = geometry -// .frag = fragment -// .comp = compute -// .rgen = ray generation -// .rint = ray intersection -// .rahit = ray any hit -// .rchit = ray closest hit -// .rmiss = ray miss -// .rcall = ray callable -// .mesh = mesh -// .task = task -// Additionally, the file names may end in ..glsl and ..hlsl -// where is one of the stages listed above. -// -EShLanguage FindLanguage(const std::string& name, bool parseStageName) -{ - std::string stageName; - if (shaderStageName) - stageName = shaderStageName; - else if (parseStageName) { - // Note: "first" extension means "first from the end", i.e. - // if the file is named foo.vert.glsl, then "glsl" is first, - // "vert" is second. - size_t firstExtStart = name.find_last_of("."); - bool hasFirstExt = firstExtStart != std::string::npos; - size_t secondExtStart = hasFirstExt ? name.find_last_of(".", firstExtStart - 1) : std::string::npos; - bool hasSecondExt = secondExtStart != std::string::npos; - std::string firstExt = name.substr(firstExtStart + 1, std::string::npos); - bool usesUnifiedExt = hasFirstExt && (firstExt == "glsl" || firstExt == "hlsl"); - if (usesUnifiedExt && firstExt == "hlsl") - Options |= EOptionReadHlsl; - if (hasFirstExt && !usesUnifiedExt) - stageName = firstExt; - else if (usesUnifiedExt && hasSecondExt) - stageName = name.substr(secondExtStart + 1, firstExtStart - secondExtStart - 1); - else { - usage(); - return EShLangVertex; - } - } else - stageName = name; - - if (stageName == "vert") - return EShLangVertex; - else if (stageName == "tesc") - return EShLangTessControl; - else if (stageName == "tese") - return EShLangTessEvaluation; - else if (stageName == "geom") - return EShLangGeometry; - else if (stageName == "frag") - return EShLangFragment; - else if (stageName == "comp") - return EShLangCompute; - else if (stageName == "rgen") - return EShLangRayGen; - else if (stageName == "rint") - return EShLangIntersect; - else if (stageName == "rahit") - return EShLangAnyHit; - else if (stageName == "rchit") - return EShLangClosestHit; - else if (stageName == "rmiss") - return EShLangMiss; - else if (stageName == "rcall") - return EShLangCallable; - else if (stageName == "mesh") - return EShLangMesh; - else if (stageName == "task") - return EShLangTask; - - usage(); - return EShLangVertex; -} - -// -// Read a file's data into a string, and compile it using the old interface ShCompile, -// for non-linkable results. -// -void CompileFile(const char* fileName, ShHandle compiler) -{ - int ret = 0; - char* shaderString; - if ((Options & EOptionStdin) != 0) { - std::istreambuf_iterator begin(std::cin), end; - std::string tempString(begin, end); - shaderString = strdup(tempString.c_str()); - } else { - shaderString = ReadFileData(fileName); - } - - // move to length-based strings, rather than null-terminated strings - int* lengths = new int[1]; - lengths[0] = (int)strlen(shaderString); - - EShMessages messages = EShMsgDefault; - SetMessageOptions(messages); - - if (UserPreamble.isSet()) - Error("-D, -U and -P options require -l (linking)\n"); - - for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) { - for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) { - // ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); - ret = ShCompile(compiler, &shaderString, 1, nullptr, EShOptNone, GetResources(), 0, - (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); - // const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err", - // "or should be l", "ine 1", "string 5\n", "float glo", "bal", - // ";\n#error should be line 2\n void main() {", "global = 2.3;}" }; - // const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" }; - // ret = ShCompile(compiler, multi, 7, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); - } - - if (Options & EOptionMemoryLeakMode) - glslang::OS_DumpMemoryCounters(); - } - - delete [] lengths; - FreeFileData(shaderString); - - if (ret == 0) - CompileFailed = true; -} - -// -// print usage to stdout -// -void usage() -{ - printf("Usage: glslang [option]... [file]...\n" - "\n" - "'file' can end in . for auto-stage classification, where is:\n" - " .conf to provide a config file that replaces the default configuration\n" - " (see -c option below for generating a template)\n" - " .vert for a vertex shader\n" - " .tesc for a tessellation control shader\n" - " .tese for a tessellation evaluation shader\n" - " .geom for a geometry shader\n" - " .frag for a fragment shader\n" - " .comp for a compute shader\n" - " .mesh for a mesh shader\n" - " .task for a task shader\n" - " .rgen for a ray generation shader\n" - " .rint for a ray intersection shader\n" - " .rahit for a ray any hit shader\n" - " .rchit for a ray closest hit shader\n" - " .rmiss for a ray miss shader\n" - " .rcall for a ray callable shader\n" - " .glsl for .vert.glsl, .tesc.glsl, ..., .comp.glsl compound suffixes\n" - " .hlsl for .vert.hlsl, .tesc.hlsl, ..., .comp.hlsl compound suffixes\n" - "\n" - "Options:\n" - " -C cascading errors; risk crash from accumulation of error recoveries\n" - " -D input is HLSL (this is the default when any suffix is .hlsl)\n" - " -D | --define-macro | --D \n" - " define a pre-processor macro\n" - " -E print pre-processed GLSL; cannot be used with -l;\n" - " errors will appear on stderr\n" - " -G[ver] create SPIR-V binary, under OpenGL semantics; turns on -l;\n" - " default file name is .spv (-o overrides this);\n" - " 'ver', when present, is the version of the input semantics,\n" - " which will appear in #define GL_SPIRV ver;\n" - " '--client opengl100' is the same as -G100;\n" - " a '--target-env' for OpenGL will also imply '-G';\n" - " currently only supports GLSL\n" - " -H print human readable form of SPIR-V; turns on -V\n" - " -I add dir to the include search path; includer's directory\n" - " is searched first, followed by left-to-right order of -I\n" - " -Od disables optimization; may cause illegal SPIR-V for HLSL\n" - " -Os optimizes SPIR-V to minimize size\n" - " -P | --preamble-text | --P \n" - " inject custom preamble text, which is treated as if it\n" - " appeared immediately after the version declaration (if any).\n" - " -R use relaxed verification rules for generating Vulkan SPIR-V,\n" - " allowing the use of default uniforms, atomic_uints, and\n" - " gl_VertexID and gl_InstanceID keywords.\n" - " -S uses specified stage rather than parsing the file extension\n" - " choices for are vert, tesc, tese, geom, frag, or comp\n" - " -U | --undef-macro | --U \n" - " undefine a pre-processor macro\n" - " -V[ver] create SPIR-V binary, under Vulkan semantics; turns on -l;\n" - " default file name is .spv (-o overrides this)\n" - " 'ver', when present, is the version of the input semantics,\n" - " which will appear in #define VULKAN ver\n" - " '--client vulkan100' is the same as -V100\n" - " a '--target-env' for Vulkan will also imply '-V'\n" - " -c configuration dump;\n" - " creates the default configuration file (redirect to a .conf file)\n" - " -d default to desktop (#version 110) when there is no shader #version\n" - " (default is ES version 100)\n" - " -e | --entry-point \n" - " specify as the entry-point function name\n" - " -f{hlsl_functionality1}\n" - " 'hlsl_functionality1' enables use of the\n" - " SPV_GOOGLE_hlsl_functionality1 extension\n" - " -g generate debug information\n" - " -g0 strip debug information\n" - " -gV generate nonsemantic shader debug information\n" - " -gVS generate nonsemantic shader debug information with source\n" - " -h print this usage message\n" - " -i intermediate tree (glslang AST) is printed out\n" - " -l link all input files together to form a single module\n" - " -m memory leak mode\n" - " -o save binary to , requires a binary option (e.g., -V)\n" - " -q dump reflection query database; requires -l for linking\n" - " -r | --relaxed-errors" - " relaxed GLSL semantic error-checking mode\n" - " -s silence syntax and semantic error reporting\n" - " -t multi-threaded mode\n" - " -v | --version\n" - " print version strings\n" - " -w | --suppress-warnings\n" - " suppress GLSL warnings, except as required by \"#extension : warn\"\n" - " -x save binary output as text-based 32-bit hexadecimal numbers\n" - " -u: specify a uniform location override for --aml\n" - " --uniform-base set a base to use for generated uniform locations\n" - " --auto-map-bindings | --amb automatically bind uniform variables\n" - " without explicit bindings\n" - " --auto-map-locations | --aml automatically locate input/output lacking\n" - " 'location' (fragile, not cross stage)\n" - " --auto-sampled-textures Removes sampler variables and converts\n" - " existing textures to sampled textures\n" - " --client {vulkan|opengl} see -V and -G\n" - " --depfile writes depfile for build systems\n" - " --dump-builtin-symbols prints builtin symbol table prior each compile\n" - " -dumpfullversion | -dumpversion print bare major.minor.patchlevel\n" - " --flatten-uniform-arrays | --fua flatten uniform texture/sampler arrays to\n" - " scalars\n" - " --glsl-version {100 | 110 | 120 | 130 | 140 | 150 |\n" - " 300es | 310es | 320es | 330\n" - " 400 | 410 | 420 | 430 | 440 | 450 | 460}\n" - " set GLSL version, overrides #version\n" - " in shader sourcen\n" - " --hlsl-offsets allow block offsets to follow HLSL rules\n" - " works independently of source language\n" - " --hlsl-iomap perform IO mapping in HLSL register space\n" - " --hlsl-enable-16bit-types allow 16-bit types in SPIR-V for HLSL\n" - " --hlsl-dx9-compatible interprets sampler declarations as a\n" - " texture/sampler combo like DirectX9 would,\n" - " and recognizes DirectX9-specific semantics\n" - " --hlsl-dx-position-w W component of SV_Position in HLSL fragment\n" - " shaders compatible with DirectX\n" - " --invert-y | --iy invert position.Y output in vertex shader\n" - " --enhanced-msgs print more readable error messages (GLSL only)\n" - " --keep-uncalled | --ku don't eliminate uncalled functions\n" - " --nan-clamp favor non-NaN operand in min, max, and clamp\n" - " --no-storage-format | --nsf use Unknown image format\n" - " --quiet do not print anything to stdout, unless\n" - " requested by another option\n" - " --reflect-strict-array-suffix use strict array suffix rules when\n" - " reflecting\n" - " --reflect-basic-array-suffix arrays of basic types will have trailing [0]\n" - " --reflect-intermediate-io reflection includes inputs/outputs of linked\n" - " shaders rather than just vertex/fragment\n" - " --reflect-separate-buffers reflect buffer variables and blocks\n" - " separately to uniforms\n" - " --reflect-all-block-variables reflect all variables in blocks, whether\n" - " inactive or active\n" - " --reflect-unwrap-io-blocks unwrap input/output blocks the same as\n" - " uniform blocks\n" - " --resource-set-binding [stage] name set binding\n" - " set descriptor set and binding for\n" - " individual resources\n" - " --resource-set-binding [stage] set\n" - " set descriptor set for all resources\n" - " --rsb synonym for --resource-set-binding\n" - " --set-block-backing name {uniform|buffer|push_constant}\n" - " changes the backing type of a uniform, buffer,\n" - " or push_constant block declared in\n" - " in the program, when using -R option.\n" - " This can be used to change the backing\n" - " for existing blocks as well as implicit ones\n" - " such as 'gl_DefaultUniformBlock'.\n" - " --sbs synonym for set-block-storage\n" - " --set-atomic-counter-block name set\n" - " set name, and descriptor set for\n" - " atomic counter blocks, with -R opt\n" - " --sacb synonym for set-atomic-counter-block\n" - " --set-default-uniform-block name set binding\n" - " set name, descriptor set, and binding for\n" - " global default-uniform-block, with -R opt\n" - " --sdub synonym for set-default-uniform-block\n" - " --shift-image-binding [stage] num\n" - " base binding number for images (uav)\n" - " --shift-image-binding [stage] [num set]...\n" - " per-descriptor-set shift values\n" - " --sib synonym for --shift-image-binding\n" - " --shift-sampler-binding [stage] num\n" - " base binding number for samplers\n" - " --shift-sampler-binding [stage] [num set]...\n" - " per-descriptor-set shift values\n" - " --ssb synonym for --shift-sampler-binding\n" - " --shift-ssbo-binding [stage] num base binding number for SSBOs\n" - " --shift-ssbo-binding [stage] [num set]...\n" - " per-descriptor-set shift values\n" - " --sbb synonym for --shift-ssbo-binding\n" - " --shift-texture-binding [stage] num\n" - " base binding number for textures\n" - " --shift-texture-binding [stage] [num set]...\n" - " per-descriptor-set shift values\n" - " --stb synonym for --shift-texture-binding\n" - " --shift-uav-binding [stage] num base binding number for UAVs\n" - " --shift-uav-binding [stage] [num set]...\n" - " per-descriptor-set shift values\n" - " --suavb synonym for --shift-uav-binding\n" - " --shift-UBO-binding [stage] num base binding number for UBOs\n" - " --shift-UBO-binding [stage] [num set]...\n" - " per-descriptor-set shift values\n" - " --sub synonym for --shift-UBO-binding\n" - " --shift-cbuffer-binding | --scb synonyms for --shift-UBO-binding\n" - " --spirv-dis output standard-form disassembly; works only\n" - " when a SPIR-V generation option is also used\n" - " --spirv-val execute the SPIRV-Tools validator\n" - " --source-entrypoint the given shader source function is\n" - " renamed to be the given in -e\n" - " --sep synonym for --source-entrypoint\n" - " --stdin read from stdin instead of from a file;\n" - " requires providing the shader stage using -S\n" - " --target-env {vulkan1.0 | vulkan1.1 | vulkan1.2 | vulkan1.3 | opengl |\n" - " spirv1.0 | spirv1.1 | spirv1.2 | spirv1.3 | spirv1.4 |\n" - " spirv1.5 | spirv1.6}\n" - " Set the execution environment that the\n" - " generated code will be executed in.\n" - " Defaults to:\n" - " * vulkan1.0 under --client vulkan\n" - " * opengl under --client opengl\n" - " * spirv1.0 under --target-env vulkan1.0\n" - " * spirv1.3 under --target-env vulkan1.1\n" - " * spirv1.5 under --target-env vulkan1.2\n" - " * spirv1.6 under --target-env vulkan1.3\n" - " Multiple --target-env can be specified.\n" - " --variable-name \n" - " --vn creates a C header file that contains a\n" - " uint32_t array named \n" - " initialized with the shader binary code\n" - " --no-link Only compile shader; do not link (GLSL-only)\n" - " NOTE: this option will set the export linkage\n" - " attribute on all functions\n"); - - exit(EFailUsage); -} - -#if !defined _MSC_VER && !defined MINGW_HAS_SECURE_API - -#include - -int fopen_s( - FILE** pFile, - const char* filename, - const char* mode -) -{ - if (!pFile || !filename || !mode) { - return EINVAL; - } - - FILE* f = fopen(filename, mode); - if (! f) { - if (errno != 0) { - return errno; - } else { - return ENOENT; - } - } - *pFile = f; - - return 0; -} - -#endif - -// -// Malloc a string of sufficient size and read a string into it. -// -char* ReadFileData(const char* fileName) -{ - FILE *in = nullptr; - int errorCode = fopen_s(&in, fileName, "r"); - if (errorCode || in == nullptr) - Error("unable to open input file"); - - int count = 0; - while (fgetc(in) != EOF) - count++; - - fseek(in, 0, SEEK_SET); - - char* return_data = (char*)malloc(count + 1); // freed in FreeFileData() - if ((int)fread(return_data, 1, count, in) != count) { - free(return_data); - Error("can't read input file"); - } - - return_data[count] = '\0'; - fclose(in); - - return return_data; -} - -void FreeFileData(char* data) -{ - free(data); -} - -void InfoLogMsg(const char* msg, const char* name, const int num) -{ - if (num >= 0 ) - printf("#### %s %s %d INFO LOG ####\n", msg, name, num); - else - printf("#### %s %s INFO LOG ####\n", msg, name); -} diff --git a/3rdparty/glslang/StandAlone/Worklist.h b/3rdparty/glslang/StandAlone/Worklist.h deleted file mode 100644 index 91b6f516..00000000 --- a/3rdparty/glslang/StandAlone/Worklist.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// Copyright (C) 2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -#ifndef WORKLIST_H_INCLUDED -#define WORKLIST_H_INCLUDED - -#include "../glslang/OSDependent/osinclude.h" -#include -#include -#include - -namespace glslang { - - class TWorkItem { - public: - TWorkItem() { } - explicit TWorkItem(const std::string& s) : - name(s) { } - std::string name; - std::string results; - std::string resultsIndex; - }; - - class TWorklist { - public: - TWorklist() { } - virtual ~TWorklist() { } - - void add(TWorkItem* item) - { - std::lock_guard guard(mutex); - worklist.push_back(item); - } - - bool remove(TWorkItem*& item) - { - std::lock_guard guard(mutex); - - if (worklist.empty()) - return false; - item = worklist.front(); - worklist.pop_front(); - - return true; - } - - int size() - { - return (int)worklist.size(); - } - - bool empty() - { - return worklist.empty(); - } - - protected: - std::mutex mutex; - std::list worklist; - }; - -} // end namespace glslang - -#endif // WORKLIST_H_INCLUDED diff --git a/3rdparty/glslang/StandAlone/spirv-remap.cpp b/3rdparty/glslang/StandAlone/spirv-remap.cpp deleted file mode 100644 index 1bd4a2d6..00000000 --- a/3rdparty/glslang/StandAlone/spirv-remap.cpp +++ /dev/null @@ -1,402 +0,0 @@ -// -// Copyright (C) 2015 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include -#include -#include -#include -#include - -// -// Include remapper -// -#include "../SPIRV/SPVRemapper.h" - -namespace { - - typedef unsigned int SpvWord; - - // Poor man's basename: given a complete path, return file portion. - // E.g: - // Linux: /foo/bar/test -> test - // Win: c:\foo\bar\test -> test - // It's not very efficient, but that doesn't matter for our minimal-duty use. - // Using boost::filesystem would be better in many ways, but want to avoid that dependency. - - // OS dependent path separator (avoiding boost::filesystem dependency) -#if defined(_WIN32) - char path_sep_char() { return '\\'; } -#else - char path_sep_char() { return '/'; } -#endif - - std::string basename(const std::string filename) - { - const size_t sepLoc = filename.find_last_of(path_sep_char()); - - return (sepLoc == filename.npos) ? filename : filename.substr(sepLoc+1); - } - - void errHandler(const std::string& str) { - std::cout << str << std::endl; - exit(5); - } - - void logHandler(const std::string& str) { - std::cout << str << std::endl; - } - - // Read word stream from disk - void read(std::vector& spv, const std::string& inFilename, int verbosity) - { - std::ifstream fp; - - if (verbosity > 0) - logHandler(std::string(" reading: ") + inFilename); - - spv.clear(); - fp.open(inFilename, std::fstream::in | std::fstream::binary); - - if (fp.fail()) - errHandler("error opening file for read: "); - - // Reserve space (for efficiency, not for correctness) - fp.seekg(0, fp.end); - spv.reserve(size_t(fp.tellg()) / sizeof(SpvWord)); - fp.seekg(0, fp.beg); - - while (!fp.eof()) { - SpvWord inWord; - fp.read((char *)&inWord, sizeof(inWord)); - - if (!fp.eof()) { - spv.push_back(inWord); - if (fp.fail()) - errHandler(std::string("error reading file: ") + inFilename); - } - } - } - - // Read strings from a file - void read(std::vector& strings, const std::string& inFilename, int verbosity) - { - std::ifstream fp; - - if (verbosity > 0) - logHandler(std::string(" reading: ") + inFilename); - - strings.clear(); - fp.open(inFilename, std::fstream::in); - - if (fp.fail()) - errHandler("error opening file for read: "); - - std::string line; - while (std::getline(fp, line)) - { - // Ignore empty lines and lines starting with the comment marker '#'. - if (line.length() == 0 || line[0] == '#') { - continue; - } - - strings.push_back(line); - } - } - - void write(std::vector& spv, const std::string& outFile, int verbosity) - { - if (outFile.empty()) - errHandler("missing output filename."); - - std::ofstream fp; - - if (verbosity > 0) - logHandler(std::string(" writing: ") + outFile); - - fp.open(outFile, std::fstream::out | std::fstream::binary); - - if (fp.fail()) - errHandler(std::string("error opening file for write: ") + outFile); - - for (auto it = spv.cbegin(); it != spv.cend(); ++it) { - SpvWord word = *it; - fp.write((char *)&word, sizeof(word)); - if (fp.fail()) - errHandler(std::string("error writing file: ") + outFile); - } - - // file is closed by destructor - } - - // Print helpful usage message to stdout, and exit - void usage(const char* const name, const char* const msg = nullptr) - { - if (msg) - std::cout << msg << std::endl << std::endl; - - std::cout << "Usage: " << std::endl; - - std::cout << " " << basename(name) - << " [-v[v[...]] | --verbose [int]]" - << " [--map (all|types|names|funcs)]" - << " [--dce (all|types|funcs)]" - << " [--opt (all|loadstore)]" - << " [--strip-all | --strip all | -s]" - << " [--strip-white-list]" - << " [--do-everything]" - << " --input | -i file1 [file2...] --output|-o DESTDIR | destfile1 [destfile2...]" - << std::endl; - - std::cout << " " << basename(name) << " [--version | -V]" << std::endl; - std::cout << " " << basename(name) << " [--help | -?]" << std::endl; - - exit(5); - } - - // grind through each SPIR in turn - void execute(const std::vector& inputFiles, - const std::vector& outputDirOrFiles, - const bool isSingleOutputDir, - const std::string& whiteListFile, - int opts, - int verbosity) - { - std::vector whiteListStrings; - if (!whiteListFile.empty()) - read(whiteListStrings, whiteListFile, verbosity); - - for (std::size_t ii=0; ii spv; - read(spv, inputFiles[ii], verbosity); - - spv::spirvbin_t(verbosity).remap(spv, whiteListStrings, opts); - - if (isSingleOutputDir) { - // write all outputs to same directory - const std::string outFile = outputDirOrFiles[0] + path_sep_char() + basename(inputFiles[ii]); - write(spv, outFile, verbosity); - } else { - // write each input to its associated output - write(spv, outputDirOrFiles[ii], verbosity); - } - } - - if (verbosity > 0) - std::cout << "Done: " << inputFiles.size() << " file(s) processed" << std::endl; - } - - // Parse command line options - void parseCmdLine(int argc, - char** argv, - std::vector& inputFiles, - std::vector& outputDirOrFiles, - std::string& stripWhiteListFile, - int& options, - int& verbosity) - { - if (argc < 2) - usage(argv[0]); - - verbosity = 0; - options = spv::spirvbin_t::NONE; - - // Parse command line. - // boost::program_options would be quite a bit nicer, but we don't want to - // introduce a dependency on boost. - for (int a=1; a inputFiles; - std::vector outputDirOrFiles; - std::string whiteListFile; - int opts; - int verbosity; - - // handle errors by exiting - spv::spirvbin_t::registerErrorHandler(errHandler); - - // Log messages to std::cout - spv::spirvbin_t::registerLogHandler(logHandler); - - if (argc < 2) - usage(argv[0]); - - parseCmdLine(argc, argv, inputFiles, outputDirOrFiles, whiteListFile, opts, verbosity); - - if (outputDirOrFiles.empty()) - usage(argv[0], "Output directory or file(s) required."); - - const bool isMultiInput = inputFiles.size() > 1; - const bool isMultiOutput = outputDirOrFiles.size() > 1; - const bool isSingleOutputDir = !isMultiOutput && std::filesystem::is_directory(outputDirOrFiles[0]); - - if (isMultiInput && !isMultiOutput && !isSingleOutputDir) - usage(argv[0], "Output is not a directory."); - - - if (isMultiInput && isMultiOutput && (outputDirOrFiles.size() != inputFiles.size())) - usage(argv[0], "Output must be either a single directory or one output file per input."); - - // Main operations: read, remap, and write. - execute(inputFiles, outputDirOrFiles, isSingleOutputDir, whiteListFile, opts, verbosity); - - // If we get here, everything went OK! Nothing more to be done. -} diff --git a/3rdparty/glslang/build_info.h.tmpl b/3rdparty/glslang/build_info.h.tmpl deleted file mode 100644 index 60cb5bbe..00000000 --- a/3rdparty/glslang/build_info.h.tmpl +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (C) 2020 The Khronos Group Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of The Khronos Group Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef GLSLANG_BUILD_INFO -#define GLSLANG_BUILD_INFO - -#define GLSLANG_VERSION_MAJOR @major@ -#define GLSLANG_VERSION_MINOR @minor@ -#define GLSLANG_VERSION_PATCH @patch@ -#define GLSLANG_VERSION_FLAVOR "@flavor@" - -#define GLSLANG_VERSION_GREATER_THAN(major, minor, patch) \ - ((GLSLANG_VERSION_MAJOR) > (major) || ((major) == GLSLANG_VERSION_MAJOR && \ - ((GLSLANG_VERSION_MINOR) > (minor) || ((minor) == GLSLANG_VERSION_MINOR && \ - (GLSLANG_VERSION_PATCH) > (patch))))) - -#define GLSLANG_VERSION_GREATER_OR_EQUAL_TO(major, minor, patch) \ - ((GLSLANG_VERSION_MAJOR) > (major) || ((major) == GLSLANG_VERSION_MAJOR && \ - ((GLSLANG_VERSION_MINOR) > (minor) || ((minor) == GLSLANG_VERSION_MINOR && \ - (GLSLANG_VERSION_PATCH >= (patch)))))) - -#define GLSLANG_VERSION_LESS_THAN(major, minor, patch) \ - ((GLSLANG_VERSION_MAJOR) < (major) || ((major) == GLSLANG_VERSION_MAJOR && \ - ((GLSLANG_VERSION_MINOR) < (minor) || ((minor) == GLSLANG_VERSION_MINOR && \ - (GLSLANG_VERSION_PATCH) < (patch))))) - -#define GLSLANG_VERSION_LESS_OR_EQUAL_TO(major, minor, patch) \ - ((GLSLANG_VERSION_MAJOR) < (major) || ((major) == GLSLANG_VERSION_MAJOR && \ - ((GLSLANG_VERSION_MINOR) < (minor) || ((minor) == GLSLANG_VERSION_MINOR && \ - (GLSLANG_VERSION_PATCH <= (patch)))))) - -#endif // GLSLANG_BUILD_INFO diff --git a/3rdparty/glslang/glslang/CInterface/glslang_c_interface.cpp b/3rdparty/glslang/glslang/CInterface/glslang_c_interface.cpp deleted file mode 100644 index 870698f2..00000000 --- a/3rdparty/glslang/glslang/CInterface/glslang_c_interface.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/** - This code is based on the glslang_c_interface implementation by Viktor Latypov -**/ - -/** -BSD 2-Clause License - -Copyright (c) 2019, Viktor Latypov -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**/ - -#include "glslang/Include/glslang_c_interface.h" - -#include "StandAlone/DirStackFileIncluder.h" -#include "glslang/Public/ResourceLimits.h" -#include "glslang/Include/ShHandle.h" - -#include "glslang/Include/ResourceLimits.h" -#include "glslang/MachineIndependent/Versions.h" -#include "glslang/MachineIndependent/localintermediate.h" - -static_assert(int(GLSLANG_STAGE_COUNT) == EShLangCount, ""); -static_assert(int(GLSLANG_STAGE_MASK_COUNT) == EShLanguageMaskCount, ""); -static_assert(int(GLSLANG_SOURCE_COUNT) == glslang::EShSourceCount, ""); -static_assert(int(GLSLANG_CLIENT_COUNT) == glslang::EShClientCount, ""); -static_assert(int(GLSLANG_TARGET_COUNT) == glslang::EShTargetCount, ""); -static_assert(int(GLSLANG_TARGET_CLIENT_VERSION_COUNT) == glslang::EShTargetClientVersionCount, ""); -static_assert(int(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT) == glslang::EShTargetLanguageVersionCount, ""); -static_assert(int(GLSLANG_OPT_LEVEL_COUNT) == EshOptLevelCount, ""); -static_assert(int(GLSLANG_TEX_SAMP_TRANS_COUNT) == EShTexSampTransCount, ""); -static_assert(int(GLSLANG_MSG_COUNT) == EShMsgCount, ""); -static_assert(int(GLSLANG_REFLECTION_COUNT) == EShReflectionCount, ""); -static_assert(int(GLSLANG_PROFILE_COUNT) == EProfileCount, ""); -static_assert(sizeof(glslang_limits_t) == sizeof(TLimits), ""); -static_assert(sizeof(glslang_resource_t) == sizeof(TBuiltInResource), ""); - -typedef struct glslang_shader_s { - glslang::TShader* shader; - std::string preprocessedGLSL; -} glslang_shader_t; - -typedef struct glslang_program_s { - glslang::TProgram* program; - std::vector spirv; - std::string loggerMessages; -} glslang_program_t; - -/* Wrapper/Adapter for C glsl_include_callbacks_t functions - - This class contains a 'glsl_include_callbacks_t' structure - with C include_local/include_system callback pointers. - - This class implement TShader::Includer interface - by redirecting C++ virtual methods to C callbacks. - - The 'IncludeResult' instances produced by this Includer - contain a reference to glsl_include_result_t C structure - to allow its lifetime management by another C callback - (CallbackIncluder::callbacks::free_include_result) -*/ -class CallbackIncluder : public glslang::TShader::Includer { -public: - CallbackIncluder(glsl_include_callbacks_t _callbacks, void* _context) : callbacks(_callbacks), context(_context) {} - - virtual ~CallbackIncluder() {} - - virtual IncludeResult* includeSystem(const char* headerName, const char* includerName, - size_t inclusionDepth) override - { - if (this->callbacks.include_system) { - glsl_include_result_t* result = - this->callbacks.include_system(this->context, headerName, includerName, inclusionDepth); - return makeIncludeResult(result); - } - - return glslang::TShader::Includer::includeSystem(headerName, includerName, inclusionDepth); - } - - virtual IncludeResult* includeLocal(const char* headerName, const char* includerName, - size_t inclusionDepth) override - { - if (this->callbacks.include_local) { - glsl_include_result_t* result = - this->callbacks.include_local(this->context, headerName, includerName, inclusionDepth); - return makeIncludeResult(result); - } - - return glslang::TShader::Includer::includeLocal(headerName, includerName, inclusionDepth); - } - - /* This function only calls free_include_result callback - when the IncludeResult instance is allocated by a C function */ - virtual void releaseInclude(IncludeResult* result) override - { - if (result == nullptr) - return; - - if (this->callbacks.free_include_result) { - this->callbacks.free_include_result(this->context, static_cast(result->userData)); - } - - delete result; - } - -private: - CallbackIncluder() {} - - IncludeResult* makeIncludeResult(glsl_include_result_t* result) { - if (!result) { - return nullptr; - } - - return new glslang::TShader::Includer::IncludeResult( - std::string(result->header_name), result->header_data, result->header_length, result); - } - - /* C callback pointers */ - glsl_include_callbacks_t callbacks; - /* User-defined context */ - void* context; -}; - -GLSLANG_EXPORT int glslang_initialize_process() { return static_cast(glslang::InitializeProcess()); } - -GLSLANG_EXPORT void glslang_finalize_process() { glslang::FinalizeProcess(); } - -static EShLanguage c_shader_stage(glslang_stage_t stage) -{ - switch (stage) { - case GLSLANG_STAGE_VERTEX: - return EShLangVertex; - case GLSLANG_STAGE_TESSCONTROL: - return EShLangTessControl; - case GLSLANG_STAGE_TESSEVALUATION: - return EShLangTessEvaluation; - case GLSLANG_STAGE_GEOMETRY: - return EShLangGeometry; - case GLSLANG_STAGE_FRAGMENT: - return EShLangFragment; - case GLSLANG_STAGE_COMPUTE: - return EShLangCompute; - case GLSLANG_STAGE_RAYGEN_NV: - return EShLangRayGen; - case GLSLANG_STAGE_INTERSECT_NV: - return EShLangIntersect; - case GLSLANG_STAGE_ANYHIT_NV: - return EShLangAnyHit; - case GLSLANG_STAGE_CLOSESTHIT_NV: - return EShLangClosestHit; - case GLSLANG_STAGE_MISS_NV: - return EShLangMiss; - case GLSLANG_STAGE_CALLABLE_NV: - return EShLangCallable; - case GLSLANG_STAGE_TASK: - return EShLangTask; - case GLSLANG_STAGE_MESH: - return EShLangMesh; - default: - break; - } - return EShLangCount; -} - -static int c_shader_messages(glslang_messages_t messages) -{ -#define CONVERT_MSG(in, out) \ - if ((messages & in) == in) \ - res |= out; - - int res = 0; - - CONVERT_MSG(GLSLANG_MSG_RELAXED_ERRORS_BIT, EShMsgRelaxedErrors); - CONVERT_MSG(GLSLANG_MSG_SUPPRESS_WARNINGS_BIT, EShMsgSuppressWarnings); - CONVERT_MSG(GLSLANG_MSG_AST_BIT, EShMsgAST); - CONVERT_MSG(GLSLANG_MSG_SPV_RULES_BIT, EShMsgSpvRules); - CONVERT_MSG(GLSLANG_MSG_VULKAN_RULES_BIT, EShMsgVulkanRules); - CONVERT_MSG(GLSLANG_MSG_ONLY_PREPROCESSOR_BIT, EShMsgOnlyPreprocessor); - CONVERT_MSG(GLSLANG_MSG_READ_HLSL_BIT, EShMsgReadHlsl); - CONVERT_MSG(GLSLANG_MSG_CASCADING_ERRORS_BIT, EShMsgCascadingErrors); - CONVERT_MSG(GLSLANG_MSG_KEEP_UNCALLED_BIT, EShMsgKeepUncalled); - CONVERT_MSG(GLSLANG_MSG_HLSL_OFFSETS_BIT, EShMsgHlslOffsets); - CONVERT_MSG(GLSLANG_MSG_DEBUG_INFO_BIT, EShMsgDebugInfo); - CONVERT_MSG(GLSLANG_MSG_HLSL_ENABLE_16BIT_TYPES_BIT, EShMsgHlslEnable16BitTypes); - CONVERT_MSG(GLSLANG_MSG_HLSL_LEGALIZATION_BIT, EShMsgHlslLegalization); - CONVERT_MSG(GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT, EShMsgHlslDX9Compatible); - CONVERT_MSG(GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT, EShMsgBuiltinSymbolTable); - return res; -#undef CONVERT_MSG -} - -static glslang::EShTargetLanguageVersion -c_shader_target_language_version(glslang_target_language_version_t target_language_version) -{ - switch (target_language_version) { - case GLSLANG_TARGET_SPV_1_0: - return glslang::EShTargetSpv_1_0; - case GLSLANG_TARGET_SPV_1_1: - return glslang::EShTargetSpv_1_1; - case GLSLANG_TARGET_SPV_1_2: - return glslang::EShTargetSpv_1_2; - case GLSLANG_TARGET_SPV_1_3: - return glslang::EShTargetSpv_1_3; - case GLSLANG_TARGET_SPV_1_4: - return glslang::EShTargetSpv_1_4; - case GLSLANG_TARGET_SPV_1_5: - return glslang::EShTargetSpv_1_5; - case GLSLANG_TARGET_SPV_1_6: - return glslang::EShTargetSpv_1_6; - default: - break; - } - return glslang::EShTargetSpv_1_0; -} - -static glslang::EShClient c_shader_client(glslang_client_t client) -{ - switch (client) { - case GLSLANG_CLIENT_VULKAN: - return glslang::EShClientVulkan; - case GLSLANG_CLIENT_OPENGL: - return glslang::EShClientOpenGL; - default: - break; - } - - return glslang::EShClientNone; -} - -static glslang::EShTargetClientVersion c_shader_client_version(glslang_target_client_version_t client_version) -{ - switch (client_version) { - case GLSLANG_TARGET_VULKAN_1_1: - return glslang::EShTargetVulkan_1_1; - case GLSLANG_TARGET_VULKAN_1_2: - return glslang::EShTargetVulkan_1_2; - case GLSLANG_TARGET_VULKAN_1_3: - return glslang::EShTargetVulkan_1_3; - case GLSLANG_TARGET_OPENGL_450: - return glslang::EShTargetOpenGL_450; - default: - break; - } - - return glslang::EShTargetVulkan_1_0; -} - -static glslang::EShTargetLanguage c_shader_target_language(glslang_target_language_t target_language) -{ - if (target_language == GLSLANG_TARGET_NONE) - return glslang::EShTargetNone; - - return glslang::EShTargetSpv; -} - -static glslang::EShSource c_shader_source(glslang_source_t source) -{ - switch (source) { - case GLSLANG_SOURCE_GLSL: - return glslang::EShSourceGlsl; - case GLSLANG_SOURCE_HLSL: - return glslang::EShSourceHlsl; - default: - break; - } - - return glslang::EShSourceNone; -} - -static EProfile c_shader_profile(glslang_profile_t profile) -{ - switch (profile) { - case GLSLANG_BAD_PROFILE: - return EBadProfile; - case GLSLANG_NO_PROFILE: - return ENoProfile; - case GLSLANG_CORE_PROFILE: - return ECoreProfile; - case GLSLANG_COMPATIBILITY_PROFILE: - return ECompatibilityProfile; - case GLSLANG_ES_PROFILE: - return EEsProfile; - case GLSLANG_PROFILE_COUNT: // Should not use this - break; - } - - return EProfile(); -} - -GLSLANG_EXPORT glslang_shader_t* glslang_shader_create(const glslang_input_t* input) -{ - if (!input || !input->code) { - printf("Error creating shader: null input(%p)/input->code\n", input); - - if (input) - printf("input->code = %p\n", input->code); - - return nullptr; - } - - glslang_shader_t* shader = new glslang_shader_t(); - - shader->shader = new glslang::TShader(c_shader_stage(input->stage)); - shader->shader->setStrings(&input->code, 1); - shader->shader->setEnvInput(c_shader_source(input->language), c_shader_stage(input->stage), - c_shader_client(input->client), input->default_version); - shader->shader->setEnvClient(c_shader_client(input->client), c_shader_client_version(input->client_version)); - shader->shader->setEnvTarget(c_shader_target_language(input->target_language), - c_shader_target_language_version(input->target_language_version)); - - return shader; -} - -GLSLANG_EXPORT void glslang_shader_set_preamble(glslang_shader_t* shader, const char* s) { - shader->shader->setPreamble(s); -} - -GLSLANG_EXPORT void glslang_shader_shift_binding(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base) -{ - const glslang::TResourceType res_type = glslang::TResourceType(res); - shader->shader->setShiftBinding(res_type, base); -} - -GLSLANG_EXPORT void glslang_shader_shift_binding_for_set(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base, unsigned int set) -{ - const glslang::TResourceType res_type = glslang::TResourceType(res); - shader->shader->setShiftBindingForSet(res_type, base, set); -} - -GLSLANG_EXPORT void glslang_shader_set_options(glslang_shader_t* shader, int options) -{ - if (options & GLSLANG_SHADER_AUTO_MAP_BINDINGS) { - shader->shader->setAutoMapBindings(true); - } - - if (options & GLSLANG_SHADER_AUTO_MAP_LOCATIONS) { - shader->shader->setAutoMapLocations(true); - } - - if (options & GLSLANG_SHADER_VULKAN_RULES_RELAXED) { - shader->shader->setEnvInputVulkanRulesRelaxed(); - } -} - -GLSLANG_EXPORT void glslang_shader_set_glsl_version(glslang_shader_t* shader, int version) -{ - shader->shader->setOverrideVersion(version); -} - -GLSLANG_EXPORT const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader) -{ - return shader->preprocessedGLSL.c_str(); -} - -GLSLANG_EXPORT int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input) -{ - DirStackFileIncluder dirStackFileIncluder; - CallbackIncluder callbackIncluder(input->callbacks, input->callbacks_ctx); - glslang::TShader::Includer& Includer = (input->callbacks.include_local||input->callbacks.include_system) - ? static_cast(callbackIncluder) - : static_cast(dirStackFileIncluder); - return shader->shader->preprocess( - reinterpret_cast(input->resource), - input->default_version, - c_shader_profile(input->default_profile), - input->force_default_version_and_profile != 0, - input->forward_compatible != 0, - (EShMessages)c_shader_messages(input->messages), - &shader->preprocessedGLSL, - Includer - ); -} - -GLSLANG_EXPORT int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input) -{ - const char* preprocessedCStr = shader->preprocessedGLSL.c_str(); - shader->shader->setStrings(&preprocessedCStr, 1); - - return shader->shader->parse( - reinterpret_cast(input->resource), - input->default_version, - input->forward_compatible != 0, - (EShMessages)c_shader_messages(input->messages) - ); -} - -GLSLANG_EXPORT const char* glslang_shader_get_info_log(glslang_shader_t* shader) { return shader->shader->getInfoLog(); } - -GLSLANG_EXPORT const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader) { return shader->shader->getInfoDebugLog(); } - -GLSLANG_EXPORT void glslang_shader_delete(glslang_shader_t* shader) -{ - if (!shader) - return; - - delete (shader->shader); - delete (shader); -} - -GLSLANG_EXPORT glslang_program_t* glslang_program_create() -{ - glslang_program_t* p = new glslang_program_t(); - p->program = new glslang::TProgram(); - return p; -} - -GLSLANG_EXPORT void glslang_program_delete(glslang_program_t* program) -{ - if (!program) - return; - - delete (program->program); - delete (program); -} - -GLSLANG_EXPORT void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader) -{ - program->program->addShader(shader->shader); -} - -GLSLANG_EXPORT int glslang_program_link(glslang_program_t* program, int messages) -{ - return (int)program->program->link((EShMessages)messages); -} - -GLSLANG_EXPORT void glslang_program_add_source_text(glslang_program_t* program, glslang_stage_t stage, const char* text, size_t len) { - glslang::TIntermediate* intermediate = program->program->getIntermediate(c_shader_stage(stage)); - intermediate->addSourceText(text, len); -} - -GLSLANG_EXPORT void glslang_program_set_source_file(glslang_program_t* program, glslang_stage_t stage, const char* file) { - glslang::TIntermediate* intermediate = program->program->getIntermediate(c_shader_stage(stage)); - intermediate->setSourceFile(file); -} - -GLSLANG_EXPORT int glslang_program_map_io(glslang_program_t* program) -{ - return (int)program->program->mapIO(); -} - -GLSLANG_EXPORT const char* glslang_program_get_info_log(glslang_program_t* program) -{ - return program->program->getInfoLog(); -} - -GLSLANG_EXPORT const char* glslang_program_get_info_debug_log(glslang_program_t* program) -{ - return program->program->getInfoDebugLog(); -} diff --git a/3rdparty/glslang/glslang/CMakeLists.txt b/3rdparty/glslang/glslang/CMakeLists.txt deleted file mode 100644 index 37eecaad..00000000 --- a/3rdparty/glslang/glslang/CMakeLists.txt +++ /dev/null @@ -1,285 +0,0 @@ -# Copyright (C) 2020 The Khronos Group Inc. -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# Neither the name of The Khronos Group Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -if(WIN32) - add_subdirectory(OSDependent/Windows) -elseif(UNIX OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia" OR ANDROID) - add_subdirectory(OSDependent/Unix) -else() - message("unknown platform") -endif() - -if(EMSCRIPTEN OR ENABLE_GLSLANG_JS) - # May be enabled on non-Emscripten builds for binary-size testing. - add_subdirectory(OSDependent/Web) -endif() - -################################################################################ -# GenericCodeGen -################################################################################ -add_library(GenericCodeGen STATIC - GenericCodeGen/CodeGen.cpp - GenericCodeGen/Link.cpp) -set_property(TARGET GenericCodeGen PROPERTY POSITION_INDEPENDENT_CODE ON) -set_property(TARGET GenericCodeGen PROPERTY FOLDER glslang) - -################################################################################ -# MachineIndependent -################################################################################ -set(MACHINEINDEPENDENT_SOURCES - MachineIndependent/glslang.y - MachineIndependent/glslang_tab.cpp - MachineIndependent/attribute.cpp - MachineIndependent/Constant.cpp - MachineIndependent/iomapper.cpp - MachineIndependent/InfoSink.cpp - MachineIndependent/Initialize.cpp - MachineIndependent/IntermTraverse.cpp - MachineIndependent/Intermediate.cpp - MachineIndependent/ParseContextBase.cpp - MachineIndependent/ParseHelper.cpp - MachineIndependent/PoolAlloc.cpp - MachineIndependent/RemoveTree.cpp - MachineIndependent/Scan.cpp - MachineIndependent/ShaderLang.cpp - MachineIndependent/SpirvIntrinsics.cpp - MachineIndependent/SymbolTable.cpp - MachineIndependent/Versions.cpp - MachineIndependent/intermOut.cpp - MachineIndependent/limits.cpp - MachineIndependent/linkValidate.cpp - MachineIndependent/parseConst.cpp - MachineIndependent/reflection.cpp - MachineIndependent/preprocessor/Pp.cpp - MachineIndependent/preprocessor/PpAtom.cpp - MachineIndependent/preprocessor/PpContext.cpp - MachineIndependent/preprocessor/PpScanner.cpp - MachineIndependent/preprocessor/PpTokens.cpp - MachineIndependent/propagateNoContraction.cpp -) - -set(MACHINEINDEPENDENT_HEADERS - MachineIndependent/attribute.h - MachineIndependent/glslang_tab.cpp.h - MachineIndependent/gl_types.h - MachineIndependent/Initialize.h - MachineIndependent/iomapper.h - MachineIndependent/LiveTraverser.h - MachineIndependent/localintermediate.h - MachineIndependent/ParseHelper.h - MachineIndependent/reflection.h - MachineIndependent/RemoveTree.h - MachineIndependent/Scan.h - MachineIndependent/ScanContext.h - MachineIndependent/SymbolTable.h - MachineIndependent/Versions.h - MachineIndependent/parseVersions.h - MachineIndependent/propagateNoContraction.h - MachineIndependent/preprocessor/PpContext.h - MachineIndependent/preprocessor/PpTokens.h -) - -if(ENABLE_HLSL) - list(APPEND MACHINEINDEPENDENT_SOURCES - HLSL/hlslAttributes.cpp - HLSL/hlslParseHelper.cpp - HLSL/hlslScanContext.cpp - HLSL/hlslOpMap.cpp - HLSL/hlslTokenStream.cpp - HLSL/hlslGrammar.cpp - HLSL/hlslParseables.cpp) - - list(APPEND MACHINEINDEPENDENT_HEADERS - HLSL/hlslAttributes.h - HLSL/hlslParseHelper.h - HLSL/hlslTokens.h - HLSL/hlslScanContext.h - HLSL/hlslOpMap.h - HLSL/hlslTokenStream.h - HLSL/hlslGrammar.h - HLSL/hlslParseables.h) -endif() - -add_library(MachineIndependent STATIC ${MACHINEINDEPENDENT_SOURCES} ${MACHINEINDEPENDENT_HEADERS}) -set_property(TARGET MachineIndependent PROPERTY POSITION_INDEPENDENT_CODE ON) -set_property(TARGET MachineIndependent PROPERTY FOLDER glslang) - -if (NOT MSVC) - # -Wunused-but-set-variable is triggered in code generated by bison that we do not control. Turn this warning off, but only for the generated. - set_source_files_properties(MachineIndependent/glslang_tab.cpp PROPERTIES COMPILE_FLAGS -Wno-unused-but-set-variable) -endif() - -glslang_add_build_info_dependency(MachineIndependent) - -glslang_pch(MachineIndependent MachineIndependent/pch.h) - -target_link_libraries(MachineIndependent PRIVATE OSDependent GenericCodeGen) - -################################################################################ -# glslang -################################################################################ -set(GLSLANG_SOURCES - CInterface/glslang_c_interface.cpp) - -set(GLSLANG_HEADERS - Public/ShaderLang.h - Include/arrays.h - Include/BaseTypes.h - Include/Common.h - Include/ConstantUnion.h - Include/glslang_c_interface.h - Include/glslang_c_shader_types.h - Include/InfoSink.h - Include/InitializeGlobals.h - Include/intermediate.h - Include/PoolAlloc.h - Include/ResourceLimits.h - Include/ShHandle.h - Include/SpirvIntrinsics.h - Include/Types.h) - -add_library(glslang ${LIB_TYPE} ${GLSLANG_SOURCES} ${GLSLANG_HEADERS}) -set_target_properties(glslang PROPERTIES - FOLDER glslang - POSITION_INDEPENDENT_CODE ON - VERSION "${GLSLANG_VERSION}" - SOVERSION "${GLSLANG_VERSION_MAJOR}") -target_link_libraries(glslang PRIVATE OSDependent MachineIndependent) -target_include_directories(glslang PUBLIC - $ - $) - -glslang_add_build_info_dependency(glslang) - -glslang_only_export_explicit_symbols(glslang) - -if(WIN32 AND BUILD_SHARED_LIBS) - set_target_properties(glslang PROPERTIES PREFIX "") -endif() - -################################################################################ -# ResourceLimits -################################################################################ -set(RESOURCELIMITS_SOURCES - ResourceLimits/ResourceLimits.cpp - ResourceLimits/resource_limits_c.cpp -) - -set(RESOURCELIMITS_HEADERS - Public/ResourceLimits.h - Public/resource_limits_c.h -) - -add_library(glslang-default-resource-limits ${RESOURCELIMITS_SOURCES} ${RESOURCELIMITS_HEADERS}) -set_target_properties(glslang-default-resource-limits PROPERTIES - VERSION "${GLSLANG_VERSION}" - SOVERSION "${GLSLANG_VERSION_MAJOR}" - FOLDER glslang - POSITION_INDEPENDENT_CODE ON) - -target_include_directories(glslang-default-resource-limits PUBLIC - $ - $) - -################################################################################ -# source_groups -################################################################################ -if(WIN32) - source_group("Public" REGULAR_EXPRESSION "Public/*") - source_group("MachineIndependent" REGULAR_EXPRESSION "MachineIndependent/[^/]*") - source_group("Include" REGULAR_EXPRESSION "Include/[^/]*") - source_group("GenericCodeGen" REGULAR_EXPRESSION "GenericCodeGen/*") - source_group("MachineIndependent\\Preprocessor" REGULAR_EXPRESSION "MachineIndependent/preprocessor/*") - source_group("HLSL" REGULAR_EXPRESSION "HLSL/*") - source_group("CInterface" REGULAR_EXPRESSION "CInterface/*") -endif() - -################################################################################ -# install -################################################################################ -if(PROJECT_IS_TOP_LEVEL) - install(TARGETS glslang EXPORT glslang-targets) - if(NOT BUILD_SHARED_LIBS) - install(TARGETS MachineIndependent EXPORT glslang-targets) - install(TARGETS GenericCodeGen EXPORT glslang-targets) - - # Backward compatibility - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/glslangTargets.cmake" " - message(WARNING \"Using `glslangTargets.cmake` is deprecated: use `find_package(glslang)` to find glslang CMake targets.\") - - if (NOT TARGET glslang::glslang) - include(\"${CMAKE_INSTALL_FULL_LIBDIR}/cmake/${PROJECT_NAME}/glslang-targets.cmake\") - endif() - - if(${BUILD_SHARED_LIBS}) - add_library(glslang ALIAS glslang::glslang) - else() - add_library(glslang ALIAS glslang::glslang) - add_library(MachineIndependent ALIAS glslang::MachineIndependent) - add_library(GenericCodeGen ALIAS glslang::GenericCodeGen) - endif() - ") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/glslangTargets.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) - endif() - - set(PUBLIC_HEADERS - Public/ResourceLimits.h - Public/ShaderLang.h - Public/resource_limits_c.h - Include/glslang_c_interface.h - Include/glslang_c_shader_types.h - Include/ResourceLimits.h - MachineIndependent/Versions.h) - - foreach(file ${PUBLIC_HEADERS}) - get_filename_component(dir ${file} DIRECTORY) - install(FILES ${file} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/${dir}) - endforeach() - - install(FILES ${GLSLANG_BUILD_INFO_H} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang) - - install(TARGETS glslang-default-resource-limits EXPORT glslang-targets) - - # Backward compatibility - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/glslang-default-resource-limitsTargets.cmake" " - message(WARNING \"Using `glslang-default-resource-limitsTargets.cmake` is deprecated: use `find_package(glslang)` to find glslang CMake targets.\") - - if (NOT TARGET glslang::glslang-default-resource-limits) - include(\"\${CMAKE_INSTALL_FULL_LIBDIR}/cmake/${PROJECT_NAME}/glslang-targets.cmake\") - endif() - - add_library(glslang-default-resource-limits ALIAS glslang::glslang-default-resource-limits) - ") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/glslang-default-resource-limitsTargets.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) - -endif() diff --git a/3rdparty/glslang/glslang/ExtensionHeaders/GL_EXT_shader_realtime_clock.glsl b/3rdparty/glslang/glslang/ExtensionHeaders/GL_EXT_shader_realtime_clock.glsl deleted file mode 100644 index 7cf545d9..00000000 --- a/3rdparty/glslang/glslang/ExtensionHeaders/GL_EXT_shader_realtime_clock.glsl +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013-2016 LunarG, Inc. -// Copyright (C) 2016-2020 Google, Inc. -// Modifications Copyright(C) 2021 Advanced Micro Devices, Inc.All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - diff --git a/3rdparty/glslang/glslang/GenericCodeGen/CodeGen.cpp b/3rdparty/glslang/glslang/GenericCodeGen/CodeGen.cpp deleted file mode 100644 index 1ef24496..00000000 --- a/3rdparty/glslang/glslang/GenericCodeGen/CodeGen.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/Common.h" -#include "../Include/ShHandle.h" -#include "../MachineIndependent/Versions.h" - -// -// Here is where real machine specific high-level data would be defined. -// -class TGenericCompiler : public TCompiler { -public: - TGenericCompiler(EShLanguage l) : TCompiler(l, infoSink) {} - virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile); - TInfoSink infoSink; -}; - -// -// This function must be provided to create the actual -// compile object used by higher level code. It returns -// a subclass of TCompiler. -// -TCompiler* ConstructCompiler(EShLanguage language, int) { return new TGenericCompiler(language); } - -// -// Delete the compiler made by ConstructCompiler -// -void DeleteCompiler(TCompiler* compiler) -{ - delete compiler; -} - -// -// Generate code from the given parse tree -// -bool TGenericCompiler::compile(TIntermNode* /*root*/, int /*version*/, EProfile /*profile*/) -{ - haveValidObjectCode = true; - - return haveValidObjectCode; -} diff --git a/3rdparty/glslang/glslang/GenericCodeGen/Link.cpp b/3rdparty/glslang/glslang/GenericCodeGen/Link.cpp deleted file mode 100644 index 5df39b81..00000000 --- a/3rdparty/glslang/glslang/GenericCodeGen/Link.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// The top level algorithms for linking multiple -// shaders together. -// -#include "../Include/Common.h" -#include "../Include/ShHandle.h" - -// -// Actual link object, derived from the shader handle base classes. -// -class TGenericLinker : public TLinker { -public: - TGenericLinker(EShExecutable e) : TLinker(e, infoSink) {} - bool link(TCompilerList&, TUniformMap*) { return true; } - void getAttributeBindings(ShBindingTable const **) const { } - TInfoSink infoSink; -}; - -// -// The internal view of a uniform/float object exchanged with the driver. -// -class TUniformLinkedMap : public TUniformMap { -public: - TUniformLinkedMap() { } - virtual int getLocation(const char*) { return 0; } -}; - -TShHandleBase* ConstructLinker(EShExecutable executable, int) { return new TGenericLinker(executable); } - -void DeleteLinker(TShHandleBase* linker) -{ - delete linker; -} - -TUniformMap* ConstructUniformMap() -{ - return new TUniformLinkedMap(); -} - -void DeleteUniformMap(TUniformMap* map) -{ - delete map; -} - -TShHandleBase* ConstructBindings() -{ - return nullptr; -} - -void DeleteBindingList(TShHandleBase* bindingList) -{ - delete bindingList; -} diff --git a/3rdparty/glslang/glslang/HLSL/hlslAttributes.cpp b/3rdparty/glslang/glslang/HLSL/hlslAttributes.cpp deleted file mode 100644 index 97305493..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslAttributes.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// -// Copyright (C) 2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "hlslAttributes.h" -#include "hlslParseHelper.h" - -namespace glslang { - // Map the given string to an attribute enum from TAttributeType, - // or EatNone if invalid. - TAttributeType HlslParseContext::attributeFromName(const TString& nameSpace, const TString& name) const - { - // handle names within a namespace - - if (nameSpace == "vk") { - if (name == "input_attachment_index") - return EatInputAttachment; - else if (name == "location") - return EatLocation; - else if (name == "binding") - return EatBinding; - else if (name == "global_cbuffer_binding") - return EatGlobalBinding; - else if (name == "builtin") - return EatBuiltIn; - else if (name == "constant_id") - return EatConstantId; - else if (name == "push_constant") - return EatPushConstant; - } else if (nameSpace == "spv") { - if (name == "format_rgba32f") return EatFormatRgba32f; - if (name == "format_rgba16f") return EatFormatRgba16f; - if (name == "format_r32f") return EatFormatR32f; - if (name == "format_rgba8") return EatFormatRgba8; - if (name == "format_rgba8snorm") return EatFormatRgba8Snorm; - if (name == "format_rg32f") return EatFormatRg32f; - if (name == "format_rg16f") return EatFormatRg16f; - if (name == "format_r11fg11fb10f") return EatFormatR11fG11fB10f; - if (name == "format_r16f") return EatFormatR16f; - if (name == "format_rgba16") return EatFormatRgba16; - if (name == "format_rgb10a2") return EatFormatRgb10A2; - if (name == "format_rg16") return EatFormatRg16; - if (name == "format_rg8") return EatFormatRg8; - if (name == "format_r16") return EatFormatR16; - if (name == "format_r8") return EatFormatR8; - if (name == "format_rgba16snorm") return EatFormatRgba16Snorm; - if (name == "format_rg16snorm") return EatFormatRg16Snorm; - if (name == "format_rg8snorm") return EatFormatRg8Snorm; - if (name == "format_r16snorm") return EatFormatR16Snorm; - if (name == "format_r8snorm") return EatFormatR8Snorm; - if (name == "format_rgba32i") return EatFormatRgba32i; - if (name == "format_rgba16i") return EatFormatRgba16i; - if (name == "format_rgba8i") return EatFormatRgba8i; - if (name == "format_r32i") return EatFormatR32i; - if (name == "format_rg32i") return EatFormatRg32i; - if (name == "format_rg16i") return EatFormatRg16i; - if (name == "format_rg8i") return EatFormatRg8i; - if (name == "format_r16i") return EatFormatR16i; - if (name == "format_r8i") return EatFormatR8i; - if (name == "format_rgba32ui") return EatFormatRgba32ui; - if (name == "format_rgba16ui") return EatFormatRgba16ui; - if (name == "format_rgba8ui") return EatFormatRgba8ui; - if (name == "format_r32ui") return EatFormatR32ui; - if (name == "format_rgb10a2ui") return EatFormatRgb10a2ui; - if (name == "format_rg32ui") return EatFormatRg32ui; - if (name == "format_rg16ui") return EatFormatRg16ui; - if (name == "format_rg8ui") return EatFormatRg8ui; - if (name == "format_r16ui") return EatFormatR16ui; - if (name == "format_r8ui") return EatFormatR8ui; - - if (name == "nonwritable") return EatNonWritable; - if (name == "nonreadable") return EatNonReadable; - - if (name == "export") return EatExport; - } else if (nameSpace.size() > 0) - return EatNone; - - // handle names with no namespace - - if (name == "allow_uav_condition") - return EatAllow_uav_condition; - else if (name == "branch") - return EatBranch; - else if (name == "call") - return EatCall; - else if (name == "domain") - return EatDomain; - else if (name == "earlydepthstencil") - return EatEarlyDepthStencil; - else if (name == "fastopt") - return EatFastOpt; - else if (name == "flatten") - return EatFlatten; - else if (name == "forcecase") - return EatForceCase; - else if (name == "instance") - return EatInstance; - else if (name == "maxtessfactor") - return EatMaxTessFactor; - else if (name == "maxvertexcount") - return EatMaxVertexCount; - else if (name == "numthreads") - return EatNumThreads; - else if (name == "outputcontrolpoints") - return EatOutputControlPoints; - else if (name == "outputtopology") - return EatOutputTopology; - else if (name == "partitioning") - return EatPartitioning; - else if (name == "patchconstantfunc") - return EatPatchConstantFunc; - else if (name == "unroll") - return EatUnroll; - else if (name == "loop") - return EatLoop; - else - return EatNone; - } - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/HLSL/hlslAttributes.h b/3rdparty/glslang/glslang/HLSL/hlslAttributes.h deleted file mode 100644 index 62faa5b8..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslAttributes.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (C) 2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef HLSLATTRIBUTES_H_ -#define HLSLATTRIBUTES_H_ - -#include -#include - -#include "../MachineIndependent/attribute.h" -#include "../MachineIndependent/SymbolTable.h" -#include "hlslScanContext.h" - -namespace glslang { - - class TFunctionDeclarator { - public: - TFunctionDeclarator() : function(nullptr), body(nullptr) { } - TSourceLoc loc; - TFunction* function; - TAttributes attributes; - TVector* body; - }; - -} // end namespace glslang - -#endif // HLSLATTRIBUTES_H_ diff --git a/3rdparty/glslang/glslang/HLSL/hlslGrammar.cpp b/3rdparty/glslang/glslang/HLSL/hlslGrammar.cpp deleted file mode 100644 index 11c0e45e..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslGrammar.cpp +++ /dev/null @@ -1,4483 +0,0 @@ -// -// Copyright (C) 2016-2018 Google, Inc. -// Copyright (C) 2016 LunarG, Inc. -// Copyright (C) 2023 Mobica Limited. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// This is a set of mutually recursive methods implementing the HLSL grammar. -// Generally, each returns -// - through an argument: a type specifically appropriate to which rule it -// recognized -// - through the return value: true/false to indicate whether or not it -// recognized its rule -// -// As much as possible, only grammar recognition should happen in this file, -// with all other work being farmed out to hlslParseHelper.cpp, which in turn -// will build the AST. -// -// The next token, yet to be "accepted" is always sitting in 'token'. -// When a method says it accepts a rule, that means all tokens involved -// in the rule will have been consumed, and none left in 'token'. -// - -#include "hlslTokens.h" -#include "hlslGrammar.h" -#include "hlslAttributes.h" - -namespace glslang { - -// Root entry point to this recursive decent parser. -// Return true if compilation unit was successfully accepted. -bool HlslGrammar::parse() -{ - advanceToken(); - return acceptCompilationUnit(); -} - -void HlslGrammar::expected(const char* syntax) -{ - parseContext.error(token.loc, "Expected", syntax, ""); -} - -void HlslGrammar::unimplemented(const char* error) -{ - parseContext.error(token.loc, "Unimplemented", error, ""); -} - -// IDENTIFIER -// THIS -// type that can be used as IDENTIFIER -// -// Only process the next token if it is an identifier. -// Return true if it was an identifier. -bool HlslGrammar::acceptIdentifier(HlslToken& idToken) -{ - // IDENTIFIER - if (peekTokenClass(EHTokIdentifier)) { - idToken = token; - advanceToken(); - return true; - } - - // THIS - // -> maps to the IDENTIFIER spelled with the internal special name for 'this' - if (peekTokenClass(EHTokThis)) { - idToken = token; - advanceToken(); - idToken.tokenClass = EHTokIdentifier; - idToken.string = NewPoolTString(intermediate.implicitThisName); - return true; - } - - // type that can be used as IDENTIFIER - - // Even though "sample", "bool", "float", etc keywords (for types, interpolation modifiers), - // they ARE still accepted as identifiers. This is not a dense space: e.g, "void" is not a - // valid identifier, nor is "linear". This code special cases the known instances of this, so - // e.g, "int sample;" or "float float;" is accepted. Other cases can be added here if needed. - - const char* idString = getTypeString(peek()); - if (idString == nullptr) - return false; - - token.string = NewPoolTString(idString); - token.tokenClass = EHTokIdentifier; - idToken = token; - typeIdentifiers = true; - - advanceToken(); - - return true; -} - -// compilationUnit -// : declaration_list EOF -// -bool HlslGrammar::acceptCompilationUnit() -{ - if (! acceptDeclarationList(unitNode)) - return false; - - if (! peekTokenClass(EHTokNone)) - return false; - - // set root of AST - if (unitNode && !unitNode->getAsAggregate()) - unitNode = intermediate.growAggregate(nullptr, unitNode); - intermediate.setTreeRoot(unitNode); - - return true; -} - -// Recognize the following, but with the extra condition that it can be -// successfully terminated by EOF or '}'. -// -// declaration_list -// : list of declaration_or_semicolon followed by EOF or RIGHT_BRACE -// -// declaration_or_semicolon -// : declaration -// : SEMICOLON -// -bool HlslGrammar::acceptDeclarationList(TIntermNode*& nodeList) -{ - do { - // HLSL allows extra semicolons between global declarations - do { } while (acceptTokenClass(EHTokSemicolon)); - - // EOF or RIGHT_BRACE - if (peekTokenClass(EHTokNone) || peekTokenClass(EHTokRightBrace)) - return true; - - // declaration - if (! acceptDeclaration(nodeList)) { - expected("declaration"); - return false; - } - } while (true); - - return true; -} - -// sampler_state -// : LEFT_BRACE [sampler_state_assignment ... ] RIGHT_BRACE -// -// sampler_state_assignment -// : sampler_state_identifier EQUAL value SEMICOLON -// -// sampler_state_identifier -// : ADDRESSU -// | ADDRESSV -// | ADDRESSW -// | BORDERCOLOR -// | FILTER -// | MAXANISOTROPY -// | MAXLOD -// | MINLOD -// | MIPLODBIAS -// -bool HlslGrammar::acceptSamplerState() -{ - // TODO: this should be genericized to accept a list of valid tokens and - // return token/value pairs. Presently it is specific to texture values. - - if (! acceptTokenClass(EHTokLeftBrace)) - return true; - - parseContext.warn(token.loc, "unimplemented", "immediate sampler state", ""); - - do { - // read state name - HlslToken state; - if (! acceptIdentifier(state)) - break; // end of list - - // FXC accepts any case - TString stateName = *state.string; - std::transform(stateName.begin(), stateName.end(), stateName.begin(), ::tolower); - - if (! acceptTokenClass(EHTokAssign)) { - expected("assign"); - return false; - } - - if (stateName == "minlod" || stateName == "maxlod") { - if (! peekTokenClass(EHTokIntConstant)) { - expected("integer"); - return false; - } - - TIntermTyped* lod = nullptr; - if (! acceptLiteral(lod)) // should never fail, since we just looked for an integer - return false; - } else if (stateName == "maxanisotropy") { - if (! peekTokenClass(EHTokIntConstant)) { - expected("integer"); - return false; - } - - TIntermTyped* maxAnisotropy = nullptr; - if (! acceptLiteral(maxAnisotropy)) // should never fail, since we just looked for an integer - return false; - } else if (stateName == "filter") { - HlslToken filterMode; - if (! acceptIdentifier(filterMode)) { - expected("filter mode"); - return false; - } - } else if (stateName == "addressu" || stateName == "addressv" || stateName == "addressw") { - HlslToken addrMode; - if (! acceptIdentifier(addrMode)) { - expected("texture address mode"); - return false; - } - } else if (stateName == "miplodbias") { - TIntermTyped* lodBias = nullptr; - if (! acceptLiteral(lodBias)) { - expected("lod bias"); - return false; - } - } else if (stateName == "bordercolor") { - return false; - } else { - expected("texture state"); - return false; - } - - // SEMICOLON - if (! acceptTokenClass(EHTokSemicolon)) { - expected("semicolon"); - return false; - } - } while (true); - - if (! acceptTokenClass(EHTokRightBrace)) - return false; - - return true; -} - -// sampler_declaration_dx9 -// : SAMPLER identifier EQUAL sampler_type sampler_state -// -bool HlslGrammar::acceptSamplerDeclarationDX9(TType& /*type*/) -{ - if (! acceptTokenClass(EHTokSampler)) - return false; - - // TODO: remove this when DX9 style declarations are implemented. - unimplemented("Direct3D 9 sampler declaration"); - - // read sampler name - HlslToken name; - if (! acceptIdentifier(name)) { - expected("sampler name"); - return false; - } - - if (! acceptTokenClass(EHTokAssign)) { - expected("="); - return false; - } - - return false; -} - -// declaration -// : attributes attributed_declaration -// | NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE -// -// attributed_declaration -// : sampler_declaration_dx9 post_decls SEMICOLON -// | fully_specified_type // for cbuffer/tbuffer -// | fully_specified_type declarator_list SEMICOLON // for non cbuffer/tbuffer -// | fully_specified_type identifier function_parameters post_decls compound_statement // function definition -// | fully_specified_type identifier sampler_state post_decls compound_statement // sampler definition -// | typedef declaration -// -// declarator_list -// : declarator COMMA declarator COMMA declarator... // zero or more declarators -// -// declarator -// : identifier array_specifier post_decls -// | identifier array_specifier post_decls EQUAL assignment_expression -// | identifier function_parameters post_decls // function prototype -// -// Parsing has to go pretty far in to know whether it's a variable, prototype, or -// function definition, so the implementation below doesn't perfectly divide up the grammar -// as above. (The 'identifier' in the first item in init_declarator list is the -// same as 'identifier' for function declarations.) -// -// This can generate more than one subtree, one per initializer or a function body. -// All initializer subtrees are put in their own aggregate node, making one top-level -// node for all the initializers. Each function created is a top-level node to grow -// into the passed-in nodeList. -// -// If 'nodeList' is passed in as non-null, it must be an aggregate to extend for -// each top-level node the declaration creates. Otherwise, if only one top-level -// node in generated here, that is want is returned in nodeList. -// -bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList) -{ - // NAMESPACE IDENTIFIER LEFT_BRACE declaration_list RIGHT_BRACE - if (acceptTokenClass(EHTokNamespace)) { - HlslToken namespaceToken; - if (!acceptIdentifier(namespaceToken)) { - expected("namespace name"); - return false; - } - parseContext.pushNamespace(*namespaceToken.string); - if (!acceptTokenClass(EHTokLeftBrace)) { - expected("{"); - return false; - } - if (!acceptDeclarationList(nodeList)) { - expected("declaration list"); - return false; - } - if (!acceptTokenClass(EHTokRightBrace)) { - expected("}"); - return false; - } - parseContext.popNamespace(); - return true; - } - - bool declarator_list = false; // true when processing comma separation - - // attributes - TFunctionDeclarator declarator; - acceptAttributes(declarator.attributes); - - // typedef - bool typedefDecl = acceptTokenClass(EHTokTypedef); - - TType declaredType; - - // DX9 sampler declaration use a different syntax - // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to - // be possible to simultaneously compile D3D10+ style shaders and DX9 shaders. If we want to compile DX9 - // HLSL shaders, this will have to be a master level switch - // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used - // For that reason, this line is commented out - // if (acceptSamplerDeclarationDX9(declaredType)) - // return true; - - bool forbidDeclarators = (peekTokenClass(EHTokCBuffer) || peekTokenClass(EHTokTBuffer)); - // fully_specified_type - if (! acceptFullySpecifiedType(declaredType, nodeList, declarator.attributes, forbidDeclarators)) - return false; - - // cbuffer and tbuffer end with the closing '}'. - // No semicolon is included. - if (forbidDeclarators) - return true; - - // Check if there are invalid in/out qualifiers - switch (declaredType.getQualifier().storage) { - case EvqIn: - case EvqOut: - case EvqInOut: - parseContext.error(token.loc, "in/out qualifiers are only valid on parameters", token.string->c_str(), ""); - default: - break; - } - - // declarator_list - // : declarator - // : identifier - HlslToken idToken; - TIntermAggregate* initializers = nullptr; - while (acceptIdentifier(idToken)) { - TString *fullName = idToken.string; - if (parseContext.symbolTable.atGlobalLevel()) - parseContext.getFullNamespaceName(fullName); - if (peekTokenClass(EHTokLeftParen)) { - // looks like function parameters - - // merge in the attributes into the return type - parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType, true); - - // Potentially rename shader entry point function. No-op most of the time. - parseContext.renameShaderFunction(fullName); - - // function_parameters - declarator.function = new TFunction(fullName, declaredType); - if (!acceptFunctionParameters(*declarator.function)) { - expected("function parameter list"); - return false; - } - - // post_decls - acceptPostDecls(declarator.function->getWritableType().getQualifier()); - - // compound_statement (function body definition) or just a prototype? - declarator.loc = token.loc; - if (peekTokenClass(EHTokLeftBrace)) { - if (declarator_list) - parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", ""); - if (typedefDecl) - parseContext.error(idToken.loc, "function body can't be in a typedef", "{", ""); - return acceptFunctionDefinition(declarator, nodeList, nullptr); - } else { - if (typedefDecl) - parseContext.error(idToken.loc, "function typedefs not implemented", "{", ""); - parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true); - } - } else { - // A variable declaration. - - // merge in the attributes, the first time around, into the shared type - if (! declarator_list) - parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType); - - // Fix the storage qualifier if it's a global. - if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel()) - declaredType.getQualifier().storage = EvqUniform; - - // recognize array_specifier - TArraySizes* arraySizes = nullptr; - acceptArraySpecifier(arraySizes); - - // We can handle multiple variables per type declaration, so - // the number of types can expand when arrayness is different. - TType variableType; - variableType.shallowCopy(declaredType); - - // In the most general case, arrayness is potentially coming both from the - // declared type and from the variable: "int[] a[];" or just one or the other. - // Merge it all to the variableType, so all arrayness is part of the variableType. - variableType.transferArraySizes(arraySizes); - variableType.copyArrayInnerSizes(declaredType.getArraySizes()); - - // samplers accept immediate sampler state - if (variableType.getBasicType() == EbtSampler) { - if (! acceptSamplerState()) - return false; - } - - // post_decls - acceptPostDecls(variableType.getQualifier()); - - // EQUAL assignment_expression - TIntermTyped* expressionNode = nullptr; - if (acceptTokenClass(EHTokAssign)) { - if (typedefDecl) - parseContext.error(idToken.loc, "can't have an initializer", "typedef", ""); - if (! acceptAssignmentExpression(expressionNode)) { - expected("initializer"); - return false; - } - } - - // TODO: things scoped within an annotation need their own name space; - // TODO: non-constant strings are not yet handled. - if (!(variableType.getBasicType() == EbtString && !variableType.getQualifier().isConstant()) && - parseContext.getAnnotationNestingLevel() == 0) { - if (typedefDecl) - parseContext.declareTypedef(idToken.loc, *fullName, variableType); - else if (variableType.getBasicType() == EbtBlock) { - if (expressionNode) - parseContext.error(idToken.loc, "buffer aliasing not yet supported", "block initializer", ""); - parseContext.declareBlock(idToken.loc, variableType, fullName); - parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName); - } else { - if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) { - // this isn't really an individual variable, but a member of the $Global buffer - parseContext.growGlobalUniformBlock(idToken.loc, variableType, *fullName); - } else { - // Declare the variable and add any initializer code to the AST. - // The top-level node is always made into an aggregate, as that's - // historically how the AST has been. - initializers = intermediate.growAggregate(initializers, - parseContext.declareVariable(idToken.loc, *fullName, variableType, expressionNode), - idToken.loc); - } - } - } - } - - // COMMA - if (acceptTokenClass(EHTokComma)) - declarator_list = true; - } - - // The top-level initializer node is a sequence. - if (initializers != nullptr) - initializers->setOperator(EOpSequence); - - // if we have a locally scoped static, it needs a globally scoped initializer - if (declaredType.getQualifier().storage == EvqGlobal && !parseContext.symbolTable.atGlobalLevel()) { - unitNode = intermediate.growAggregate(unitNode, initializers, idToken.loc); - } else { - // Add the initializers' aggregate to the nodeList we were handed. - if (nodeList) - nodeList = intermediate.growAggregate(nodeList, initializers); - else - nodeList = initializers; - } - - // SEMICOLON - if (! acceptTokenClass(EHTokSemicolon)) { - // This may have been a false detection of what appeared to be a declaration, but - // was actually an assignment such as "float = 4", where "float" is an identifier. - // We put the token back to let further parsing happen for cases where that may - // happen. This errors on the side of caution, and mostly triggers the error. - if (peek() == EHTokAssign || peek() == EHTokLeftBracket || peek() == EHTokDot || peek() == EHTokComma) - recedeToken(); - else - expected(";"); - return false; - } - - return true; -} - -// control_declaration -// : fully_specified_type identifier EQUAL expression -// -bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node) -{ - node = nullptr; - TAttributes attributes; - - // fully_specified_type - TType type; - if (! acceptFullySpecifiedType(type, attributes)) - return false; - - if (attributes.size() > 0) - parseContext.warn(token.loc, "attributes don't apply to control declaration", "", ""); - - // filter out type casts - if (peekTokenClass(EHTokLeftParen)) { - recedeToken(); - return false; - } - - // identifier - HlslToken idToken; - if (! acceptIdentifier(idToken)) { - expected("identifier"); - return false; - } - - // EQUAL - TIntermTyped* expressionNode = nullptr; - if (! acceptTokenClass(EHTokAssign)) { - expected("="); - return false; - } - - // expression - if (! acceptExpression(expressionNode)) { - expected("initializer"); - return false; - } - - node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode); - - return true; -} - -// fully_specified_type -// : type_specifier -// | type_qualifier type_specifier -// | type_specifier type_qualifier -// -bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributes& attributes) -{ - TIntermNode* nodeList = nullptr; - return acceptFullySpecifiedType(type, nodeList, attributes); -} -bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributes& attributes, bool forbidDeclarators) -{ - // type_qualifier - TQualifier qualifier; - qualifier.clear(); - if (! acceptPreQualifier(qualifier)) - return false; - TSourceLoc loc = token.loc; - - // type_specifier - if (! acceptType(type, nodeList)) { - // If this is not a type, we may have inadvertently gone down a wrong path - // by parsing "sample", which can be treated like either an identifier or a - // qualifier. Back it out, if we did. - if (qualifier.sample) - recedeToken(); - - return false; - } - - // type_qualifier - if (! acceptPostQualifier(qualifier)) - return false; - - if (type.getBasicType() == EbtBlock) { - // the type was a block, which set some parts of the qualifier - parseContext.mergeQualifiers(type.getQualifier(), qualifier); - - // merge in the attributes - parseContext.transferTypeAttributes(token.loc, attributes, type); - - // further, it can create an anonymous instance of the block - // (cbuffer and tbuffer don't consume the next identifier, and - // should set forbidDeclarators) - if (forbidDeclarators || peek() != EHTokIdentifier) - parseContext.declareBlock(loc, type); - } else { - // Some qualifiers are set when parsing the type. Merge those with - // whatever comes from acceptPreQualifier and acceptPostQualifier. - assert(qualifier.layoutFormat == ElfNone); - - qualifier.layoutFormat = type.getQualifier().layoutFormat; - qualifier.precision = type.getQualifier().precision; - - if (type.getQualifier().storage == EvqOut || - type.getQualifier().storage == EvqBuffer) { - qualifier.storage = type.getQualifier().storage; - qualifier.readonly = type.getQualifier().readonly; - } - - if (type.isBuiltIn()) - qualifier.builtIn = type.getQualifier().builtIn; - - type.getQualifier() = qualifier; - } - - return true; -} - -// type_qualifier -// : qualifier qualifier ... -// -// Zero or more of these, so this can't return false. -// -bool HlslGrammar::acceptPreQualifier(TQualifier& qualifier) -{ - do { - switch (peek()) { - case EHTokStatic: - qualifier.storage = EvqGlobal; - break; - case EHTokExtern: - // TODO: no meaning in glslang? - break; - case EHTokShared: - // TODO: hint - break; - case EHTokGroupShared: - qualifier.storage = EvqShared; - break; - case EHTokUniform: - qualifier.storage = EvqUniform; - break; - case EHTokConst: - qualifier.storage = EvqConst; - break; - case EHTokVolatile: - qualifier.volatil = true; - break; - case EHTokLinear: - qualifier.smooth = true; - break; - case EHTokCentroid: - qualifier.centroid = true; - break; - case EHTokNointerpolation: - qualifier.flat = true; - break; - case EHTokNoperspective: - qualifier.nopersp = true; - break; - case EHTokSample: - qualifier.sample = true; - break; - case EHTokRowMajor: - qualifier.layoutMatrix = ElmColumnMajor; - break; - case EHTokColumnMajor: - qualifier.layoutMatrix = ElmRowMajor; - break; - case EHTokPrecise: - qualifier.noContraction = true; - break; - case EHTokIn: - if (qualifier.storage != EvqUniform) { - qualifier.storage = (qualifier.storage == EvqOut) ? EvqInOut : EvqIn; - } - break; - case EHTokOut: - qualifier.storage = (qualifier.storage == EvqIn) ? EvqInOut : EvqOut; - break; - case EHTokInOut: - qualifier.storage = EvqInOut; - break; - case EHTokLayout: - if (! acceptLayoutQualifierList(qualifier)) - return false; - continue; - case EHTokGloballyCoherent: - qualifier.coherent = true; - break; - case EHTokInline: - // TODO: map this to SPIR-V function control - break; - - // GS geometries: these are specified on stage input variables, and are an error (not verified here) - // for output variables. - case EHTokPoint: - qualifier.storage = EvqIn; - if (!parseContext.handleInputGeometry(token.loc, ElgPoints)) - return false; - break; - case EHTokLine: - qualifier.storage = EvqIn; - if (!parseContext.handleInputGeometry(token.loc, ElgLines)) - return false; - break; - case EHTokTriangle: - qualifier.storage = EvqIn; - if (!parseContext.handleInputGeometry(token.loc, ElgTriangles)) - return false; - break; - case EHTokLineAdj: - qualifier.storage = EvqIn; - if (!parseContext.handleInputGeometry(token.loc, ElgLinesAdjacency)) - return false; - break; - case EHTokTriangleAdj: - qualifier.storage = EvqIn; - if (!parseContext.handleInputGeometry(token.loc, ElgTrianglesAdjacency)) - return false; - break; - - default: - return true; - } - advanceToken(); - } while (true); -} - -// type_qualifier -// : qualifier qualifier ... -// -// Zero or more of these, so this can't return false. -// -bool HlslGrammar::acceptPostQualifier(TQualifier& qualifier) -{ - do { - switch (peek()) { - case EHTokConst: - qualifier.storage = EvqConst; - break; - default: - return true; - } - advanceToken(); - } while (true); -} - -// layout_qualifier_list -// : LAYOUT LEFT_PAREN layout_qualifier COMMA layout_qualifier ... RIGHT_PAREN -// -// layout_qualifier -// : identifier -// | identifier EQUAL expression -// -// Zero or more of these, so this can't return false. -// -bool HlslGrammar::acceptLayoutQualifierList(TQualifier& qualifier) -{ - if (! acceptTokenClass(EHTokLayout)) - return false; - - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) - return false; - - do { - // identifier - HlslToken idToken; - if (! acceptIdentifier(idToken)) - break; - - // EQUAL expression - if (acceptTokenClass(EHTokAssign)) { - TIntermTyped* expr; - if (! acceptConditionalExpression(expr)) { - expected("expression"); - return false; - } - parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string, expr); - } else - parseContext.setLayoutQualifier(idToken.loc, qualifier, *idToken.string); - - // COMMA - if (! acceptTokenClass(EHTokComma)) - break; - } while (true); - - // RIGHT_PAREN - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - return false; - } - - return true; -} - -// template_type -// : FLOAT -// | DOUBLE -// | INT -// | DWORD -// | UINT -// | BOOL -// -bool HlslGrammar::acceptTemplateVecMatBasicType(TBasicType& basicType, - TPrecisionQualifier& precision) -{ - precision = EpqNone; - switch (peek()) { - case EHTokFloat: - basicType = EbtFloat; - break; - case EHTokDouble: - basicType = EbtDouble; - break; - case EHTokInt: - case EHTokDword: - basicType = EbtInt; - break; - case EHTokUint: - basicType = EbtUint; - break; - case EHTokBool: - basicType = EbtBool; - break; - case EHTokHalf: - basicType = parseContext.hlslEnable16BitTypes() ? EbtFloat16 : EbtFloat; - break; - case EHTokMin16float: - case EHTokMin10float: - basicType = parseContext.hlslEnable16BitTypes() ? EbtFloat16 : EbtFloat; - precision = EpqMedium; - break; - case EHTokMin16int: - case EHTokMin12int: - basicType = parseContext.hlslEnable16BitTypes() ? EbtInt16 : EbtInt; - precision = EpqMedium; - break; - case EHTokMin16uint: - basicType = parseContext.hlslEnable16BitTypes() ? EbtUint16 : EbtUint; - precision = EpqMedium; - break; - default: - return false; - } - - advanceToken(); - - return true; -} - -// vector_template_type -// : VECTOR -// | VECTOR LEFT_ANGLE template_type COMMA integer_literal RIGHT_ANGLE -// -bool HlslGrammar::acceptVectorTemplateType(TType& type) -{ - if (! acceptTokenClass(EHTokVector)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) { - // in HLSL, 'vector' alone means float4. - new(&type) TType(EbtFloat, EvqTemporary, 4); - return true; - } - - TBasicType basicType; - TPrecisionQualifier precision; - if (! acceptTemplateVecMatBasicType(basicType, precision)) { - expected("scalar type"); - return false; - } - - // COMMA - if (! acceptTokenClass(EHTokComma)) { - expected(","); - return false; - } - - // integer - if (! peekTokenClass(EHTokIntConstant)) { - expected("literal integer"); - return false; - } - - TIntermTyped* vecSize; - if (! acceptLiteral(vecSize)) - return false; - - const int vecSizeI = vecSize->getAsConstantUnion()->getConstArray()[0].getIConst(); - - new(&type) TType(basicType, EvqTemporary, precision, vecSizeI); - - if (vecSizeI == 1) - type.makeVector(); - - if (!acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - return true; -} - -// matrix_template_type -// : MATRIX -// | MATRIX LEFT_ANGLE template_type COMMA integer_literal COMMA integer_literal RIGHT_ANGLE -// -bool HlslGrammar::acceptMatrixTemplateType(TType& type) -{ - if (! acceptTokenClass(EHTokMatrix)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) { - // in HLSL, 'matrix' alone means float4x4. - new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4); - return true; - } - - TBasicType basicType; - TPrecisionQualifier precision; - if (! acceptTemplateVecMatBasicType(basicType, precision)) { - expected("scalar type"); - return false; - } - - // COMMA - if (! acceptTokenClass(EHTokComma)) { - expected(","); - return false; - } - - // integer rows - if (! peekTokenClass(EHTokIntConstant)) { - expected("literal integer"); - return false; - } - - TIntermTyped* rows; - if (! acceptLiteral(rows)) - return false; - - // COMMA - if (! acceptTokenClass(EHTokComma)) { - expected(","); - return false; - } - - // integer cols - if (! peekTokenClass(EHTokIntConstant)) { - expected("literal integer"); - return false; - } - - TIntermTyped* cols; - if (! acceptLiteral(cols)) - return false; - - new(&type) TType(basicType, EvqTemporary, precision, 0, - rows->getAsConstantUnion()->getConstArray()[0].getIConst(), - cols->getAsConstantUnion()->getConstArray()[0].getIConst()); - - if (!acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - return true; -} - -// layout_geometry -// : LINESTREAM -// | POINTSTREAM -// | TRIANGLESTREAM -// -bool HlslGrammar::acceptOutputPrimitiveGeometry(TLayoutGeometry& geometry) -{ - // read geometry type - const EHlslTokenClass geometryType = peek(); - - switch (geometryType) { - case EHTokPointStream: geometry = ElgPoints; break; - case EHTokLineStream: geometry = ElgLineStrip; break; - case EHTokTriangleStream: geometry = ElgTriangleStrip; break; - default: - return false; // not a layout geometry - } - - advanceToken(); // consume the layout keyword - return true; -} - -// tessellation_decl_type -// : INPUTPATCH -// | OUTPUTPATCH -// -bool HlslGrammar::acceptTessellationDeclType(TBuiltInVariable& patchType) -{ - // read geometry type - const EHlslTokenClass tessType = peek(); - - switch (tessType) { - case EHTokInputPatch: patchType = EbvInputPatch; break; - case EHTokOutputPatch: patchType = EbvOutputPatch; break; - default: - return false; // not a tessellation decl - } - - advanceToken(); // consume the keyword - return true; -} - -// tessellation_patch_template_type -// : tessellation_decl_type LEFT_ANGLE type comma integer_literal RIGHT_ANGLE -// -bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type) -{ - TBuiltInVariable patchType; - - if (! acceptTessellationDeclType(patchType)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) - return false; - - if (! acceptType(type)) { - expected("tessellation patch type"); - return false; - } - - if (! acceptTokenClass(EHTokComma)) - return false; - - // integer size - if (! peekTokenClass(EHTokIntConstant)) { - expected("literal integer"); - return false; - } - - TIntermTyped* size; - if (! acceptLiteral(size)) - return false; - - TArraySizes* arraySizes = new TArraySizes; - arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst()); - type.transferArraySizes(arraySizes); - type.getQualifier().builtIn = patchType; - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - return true; -} - -// stream_out_template_type -// : output_primitive_geometry_type LEFT_ANGLE type RIGHT_ANGLE -// -bool HlslGrammar::acceptStreamOutTemplateType(TType& type, TLayoutGeometry& geometry) -{ - geometry = ElgNone; - - if (! acceptOutputPrimitiveGeometry(geometry)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) - return false; - - if (! acceptType(type)) { - expected("stream output type"); - return false; - } - - type.getQualifier().storage = EvqOut; - type.getQualifier().builtIn = EbvGsOutputStream; - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - return true; -} - -// annotations -// : LEFT_ANGLE declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE -// -bool HlslGrammar::acceptAnnotations(TQualifier&) -{ - if (! acceptTokenClass(EHTokLeftAngle)) - return false; - - // note that we are nesting a name space - parseContext.nestAnnotations(); - - // declaration SEMI_COLON ... declaration SEMICOLON RIGHT_ANGLE - do { - // eat any extra SEMI_COLON; don't know if the grammar calls for this or not - while (acceptTokenClass(EHTokSemicolon)) - ; - - if (acceptTokenClass(EHTokRightAngle)) - break; - - // declaration - TIntermNode* node = nullptr; - if (! acceptDeclaration(node)) { - expected("declaration in annotation"); - return false; - } - } while (true); - - parseContext.unnestAnnotations(); - return true; -} - -// subpass input type -// : SUBPASSINPUT -// | SUBPASSINPUT VECTOR LEFT_ANGLE template_type RIGHT_ANGLE -// | SUBPASSINPUTMS -// | SUBPASSINPUTMS VECTOR LEFT_ANGLE template_type RIGHT_ANGLE -bool HlslGrammar::acceptSubpassInputType(TType& type) -{ - // read subpass type - const EHlslTokenClass subpassInputType = peek(); - - bool multisample; - - switch (subpassInputType) { - case EHTokSubpassInput: multisample = false; break; - case EHTokSubpassInputMS: multisample = true; break; - default: - return false; // not a subpass input declaration - } - - advanceToken(); // consume the sampler type keyword - - TType subpassType(EbtFloat, EvqUniform, 4); // default type is float4 - - if (acceptTokenClass(EHTokLeftAngle)) { - if (! acceptType(subpassType)) { - expected("scalar or vector type"); - return false; - } - - const TBasicType basicRetType = subpassType.getBasicType() ; - - switch (basicRetType) { - case EbtFloat: - case EbtUint: - case EbtInt: - case EbtStruct: - break; - default: - unimplemented("basic type in subpass input"); - return false; - } - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - } - - const TBasicType subpassBasicType = subpassType.isStruct() ? (*subpassType.getStruct())[0].type->getBasicType() - : subpassType.getBasicType(); - - TSampler sampler; - sampler.setSubpass(subpassBasicType, multisample); - - // Remember the declared return type. Function returns false on error. - if (!parseContext.setTextureReturnType(sampler, subpassType, token.loc)) - return false; - - type.shallowCopy(TType(sampler, EvqUniform)); - - return true; -} - -// sampler_type for DX9 compatibility -// : SAMPLER -// | SAMPLER1D -// | SAMPLER2D -// | SAMPLER3D -// | SAMPLERCUBE -bool HlslGrammar::acceptSamplerTypeDX9(TType &type) -{ - // read sampler type - const EHlslTokenClass samplerType = peek(); - - TSamplerDim dim = EsdNone; - TType txType(EbtFloat, EvqUniform, 4); // default type is float4 - - bool isShadow = false; - - switch (samplerType) - { - case EHTokSampler: dim = Esd2D; break; - case EHTokSampler1d: dim = Esd1D; break; - case EHTokSampler2d: dim = Esd2D; break; - case EHTokSampler3d: dim = Esd3D; break; - case EHTokSamplerCube: dim = EsdCube; break; - default: - return false; // not a dx9 sampler declaration - } - - advanceToken(); // consume the sampler type keyword - - TArraySizes *arraySizes = nullptr; // TODO: array - - TSampler sampler; - sampler.set(txType.getBasicType(), dim, false, isShadow, false); - - if (!parseContext.setTextureReturnType(sampler, txType, token.loc)) - return false; - - type.shallowCopy(TType(sampler, EvqUniform, arraySizes)); - type.getQualifier().layoutFormat = ElfNone; - - return true; -} - -// sampler_type -// : SAMPLER -// | SAMPLER1D -// | SAMPLER2D -// | SAMPLER3D -// | SAMPLERCUBE -// | SAMPLERSTATE -// | SAMPLERCOMPARISONSTATE -bool HlslGrammar::acceptSamplerType(TType& type) -{ - // read sampler type - const EHlslTokenClass samplerType = peek(); - - // TODO: for DX9 - // TSamplerDim dim = EsdNone; - - bool isShadow = false; - - switch (samplerType) { - case EHTokSampler: break; - case EHTokSampler1d: /*dim = Esd1D*/; break; - case EHTokSampler2d: /*dim = Esd2D*/; break; - case EHTokSampler3d: /*dim = Esd3D*/; break; - case EHTokSamplerCube: /*dim = EsdCube*/; break; - case EHTokSamplerState: break; - case EHTokSamplerComparisonState: isShadow = true; break; - default: - return false; // not a sampler declaration - } - - advanceToken(); // consume the sampler type keyword - - TArraySizes* arraySizes = nullptr; // TODO: array - - TSampler sampler; - sampler.setPureSampler(isShadow); - - type.shallowCopy(TType(sampler, EvqUniform, arraySizes)); - - return true; -} - -// texture_type -// | BUFFER -// | TEXTURE1D -// | TEXTURE1DARRAY -// | TEXTURE2D -// | TEXTURE2DARRAY -// | TEXTURE3D -// | TEXTURECUBE -// | TEXTURECUBEARRAY -// | TEXTURE2DMS -// | TEXTURE2DMSARRAY -// | RWBUFFER -// | RWTEXTURE1D -// | RWTEXTURE1DARRAY -// | RWTEXTURE2D -// | RWTEXTURE2DARRAY -// | RWTEXTURE3D - -bool HlslGrammar::acceptTextureType(TType& type) -{ - const EHlslTokenClass textureType = peek(); - - TSamplerDim dim = EsdNone; - bool array = false; - bool ms = false; - bool image = false; - bool combined = true; - - switch (textureType) { - case EHTokBuffer: dim = EsdBuffer; combined = false; break; - case EHTokTexture1d: dim = Esd1D; break; - case EHTokTexture1darray: dim = Esd1D; array = true; break; - case EHTokTexture2d: dim = Esd2D; break; - case EHTokTexture2darray: dim = Esd2D; array = true; break; - case EHTokTexture3d: dim = Esd3D; break; - case EHTokTextureCube: dim = EsdCube; break; - case EHTokTextureCubearray: dim = EsdCube; array = true; break; - case EHTokTexture2DMS: dim = Esd2D; ms = true; break; - case EHTokTexture2DMSarray: dim = Esd2D; array = true; ms = true; break; - case EHTokRWBuffer: dim = EsdBuffer; image=true; break; - case EHTokRWTexture1d: dim = Esd1D; array=false; image=true; break; - case EHTokRWTexture1darray: dim = Esd1D; array=true; image=true; break; - case EHTokRWTexture2d: dim = Esd2D; array=false; image=true; break; - case EHTokRWTexture2darray: dim = Esd2D; array=true; image=true; break; - case EHTokRWTexture3d: dim = Esd3D; array=false; image=true; break; - default: - return false; // not a texture declaration - } - - advanceToken(); // consume the texture object keyword - - TType txType(EbtFloat, EvqUniform, 4); // default type is float4 - - TIntermTyped* msCount = nullptr; - - // texture type: required for multisample types and RWBuffer/RWTextures! - if (acceptTokenClass(EHTokLeftAngle)) { - if (! acceptType(txType)) { - expected("scalar or vector type"); - return false; - } - - const TBasicType basicRetType = txType.getBasicType() ; - - switch (basicRetType) { - case EbtFloat: - case EbtUint: - case EbtInt: - case EbtStruct: - break; - default: - unimplemented("basic type in texture"); - return false; - } - - // Buffers can handle small mats if they fit in 4 components - if (dim == EsdBuffer && txType.isMatrix()) { - if ((txType.getMatrixCols() * txType.getMatrixRows()) > 4) { - expected("components < 4 in matrix buffer type"); - return false; - } - - // TODO: except we don't handle it yet... - unimplemented("matrix type in buffer"); - return false; - } - - if (!txType.isScalar() && !txType.isVector() && !txType.isStruct()) { - expected("scalar, vector, or struct type"); - return false; - } - - if (ms && acceptTokenClass(EHTokComma)) { - // read sample count for multisample types, if given - if (! peekTokenClass(EHTokIntConstant)) { - expected("multisample count"); - return false; - } - - if (! acceptLiteral(msCount)) // should never fail, since we just found an integer - return false; - } - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - } else if (ms) { - expected("texture type for multisample"); - return false; - } else if (image) { - expected("type for RWTexture/RWBuffer"); - return false; - } - - TArraySizes* arraySizes = nullptr; - const bool shadow = false; // declared on the sampler - - TSampler sampler; - TLayoutFormat format = ElfNone; - - // Buffer, RWBuffer and RWTexture (images) require a TLayoutFormat. We handle only a limit set. - if (image || dim == EsdBuffer) - format = parseContext.getLayoutFromTxType(token.loc, txType); - - const TBasicType txBasicType = txType.isStruct() ? (*txType.getStruct())[0].type->getBasicType() - : txType.getBasicType(); - - // Non-image Buffers are combined - if (dim == EsdBuffer && !image) { - sampler.set(txType.getBasicType(), dim, array); - } else { - // DX10 textures are separated. TODO: DX9. - if (image) { - sampler.setImage(txBasicType, dim, array, shadow, ms); - } else { - sampler.setTexture(txBasicType, dim, array, shadow, ms); - } - } - - // Remember the declared return type. Function returns false on error. - if (!parseContext.setTextureReturnType(sampler, txType, token.loc)) - return false; - - // Force uncombined, if necessary - if (!combined) - sampler.combined = false; - - type.shallowCopy(TType(sampler, EvqUniform, arraySizes)); - type.getQualifier().layoutFormat = format; - - return true; -} - -// If token is for a type, update 'type' with the type information, -// and return true and advance. -// Otherwise, return false, and don't advance -bool HlslGrammar::acceptType(TType& type) -{ - TIntermNode* nodeList = nullptr; - return acceptType(type, nodeList); -} -bool HlslGrammar::acceptType(TType& type, TIntermNode*& nodeList) -{ - // Basic types for min* types, use native halfs if the option allows them. - bool enable16BitTypes = parseContext.hlslEnable16BitTypes(); - - const TBasicType min16float_bt = enable16BitTypes ? EbtFloat16 : EbtFloat; - const TBasicType min10float_bt = enable16BitTypes ? EbtFloat16 : EbtFloat; - const TBasicType half_bt = enable16BitTypes ? EbtFloat16 : EbtFloat; - const TBasicType min16int_bt = enable16BitTypes ? EbtInt16 : EbtInt; - const TBasicType min12int_bt = enable16BitTypes ? EbtInt16 : EbtInt; - const TBasicType min16uint_bt = enable16BitTypes ? EbtUint16 : EbtUint; - - // Some types might have turned into identifiers. Take the hit for checking - // when this has happened. - if (typeIdentifiers) { - const char* identifierString = getTypeString(peek()); - if (identifierString != nullptr) { - TString name = identifierString; - // if it's an identifier, it's not a type - if (parseContext.symbolTable.find(name) != nullptr) - return false; - } - } - - bool isUnorm = false; - bool isSnorm = false; - - // Accept snorm and unorm. Presently, this is ignored, save for an error check below. - switch (peek()) { - case EHTokUnorm: - isUnorm = true; - advanceToken(); // eat the token - break; - case EHTokSNorm: - isSnorm = true; - advanceToken(); // eat the token - break; - default: - break; - } - - switch (peek()) { - case EHTokVector: - return acceptVectorTemplateType(type); - break; - - case EHTokMatrix: - return acceptMatrixTemplateType(type); - break; - - case EHTokPointStream: // fall through - case EHTokLineStream: // ... - case EHTokTriangleStream: // ... - { - TLayoutGeometry geometry; - if (! acceptStreamOutTemplateType(type, geometry)) - return false; - - if (! parseContext.handleOutputGeometry(token.loc, geometry)) - return false; - - return true; - } - - case EHTokInputPatch: // fall through - case EHTokOutputPatch: // ... - { - if (! acceptTessellationPatchTemplateType(type)) - return false; - - return true; - } - - case EHTokSampler: // fall through - case EHTokSampler1d: // ... - case EHTokSampler2d: // ... - case EHTokSampler3d: // ... - case EHTokSamplerCube: // ... - if (parseContext.hlslDX9Compatible()) - return acceptSamplerTypeDX9(type); - else - return acceptSamplerType(type); - break; - - case EHTokSamplerState: // fall through - case EHTokSamplerComparisonState: // ... - return acceptSamplerType(type); - break; - - case EHTokSubpassInput: // fall through - case EHTokSubpassInputMS: // ... - return acceptSubpassInputType(type); - break; - - case EHTokBuffer: // fall through - case EHTokTexture1d: // ... - case EHTokTexture1darray: // ... - case EHTokTexture2d: // ... - case EHTokTexture2darray: // ... - case EHTokTexture3d: // ... - case EHTokTextureCube: // ... - case EHTokTextureCubearray: // ... - case EHTokTexture2DMS: // ... - case EHTokTexture2DMSarray: // ... - case EHTokRWTexture1d: // ... - case EHTokRWTexture1darray: // ... - case EHTokRWTexture2d: // ... - case EHTokRWTexture2darray: // ... - case EHTokRWTexture3d: // ... - case EHTokRWBuffer: // ... - return acceptTextureType(type); - break; - - case EHTokAppendStructuredBuffer: - case EHTokByteAddressBuffer: - case EHTokConsumeStructuredBuffer: - case EHTokRWByteAddressBuffer: - case EHTokRWStructuredBuffer: - case EHTokStructuredBuffer: - return acceptStructBufferType(type); - break; - - case EHTokTextureBuffer: - return acceptTextureBufferType(type); - break; - - case EHTokConstantBuffer: - return acceptConstantBufferType(type); - - case EHTokClass: - case EHTokStruct: - case EHTokCBuffer: - case EHTokTBuffer: - return acceptStruct(type, nodeList); - - case EHTokIdentifier: - // An identifier could be for a user-defined type. - // Note we cache the symbol table lookup, to save for a later rule - // when this is not a type. - if (parseContext.lookupUserType(*token.string, type) != nullptr) { - advanceToken(); - return true; - } else - return false; - - case EHTokVoid: - new(&type) TType(EbtVoid); - break; - - case EHTokString: - new(&type) TType(EbtString); - break; - - case EHTokFloat: - new(&type) TType(EbtFloat); - break; - case EHTokFloat1: - new(&type) TType(EbtFloat); - type.makeVector(); - break; - case EHTokFloat2: - new(&type) TType(EbtFloat, EvqTemporary, 2); - break; - case EHTokFloat3: - new(&type) TType(EbtFloat, EvqTemporary, 3); - break; - case EHTokFloat4: - new(&type) TType(EbtFloat, EvqTemporary, 4); - break; - - case EHTokDouble: - new(&type) TType(EbtDouble); - break; - case EHTokDouble1: - new(&type) TType(EbtDouble); - type.makeVector(); - break; - case EHTokDouble2: - new(&type) TType(EbtDouble, EvqTemporary, 2); - break; - case EHTokDouble3: - new(&type) TType(EbtDouble, EvqTemporary, 3); - break; - case EHTokDouble4: - new(&type) TType(EbtDouble, EvqTemporary, 4); - break; - - case EHTokInt: - case EHTokDword: - new(&type) TType(EbtInt); - break; - case EHTokInt1: - new(&type) TType(EbtInt); - type.makeVector(); - break; - case EHTokInt2: - new(&type) TType(EbtInt, EvqTemporary, 2); - break; - case EHTokInt3: - new(&type) TType(EbtInt, EvqTemporary, 3); - break; - case EHTokInt4: - new(&type) TType(EbtInt, EvqTemporary, 4); - break; - - case EHTokUint: - new(&type) TType(EbtUint); - break; - case EHTokUint1: - new(&type) TType(EbtUint); - type.makeVector(); - break; - case EHTokUint2: - new(&type) TType(EbtUint, EvqTemporary, 2); - break; - case EHTokUint3: - new(&type) TType(EbtUint, EvqTemporary, 3); - break; - case EHTokUint4: - new(&type) TType(EbtUint, EvqTemporary, 4); - break; - - case EHTokUint64: - new(&type) TType(EbtUint64); - break; - - case EHTokBool: - new(&type) TType(EbtBool); - break; - case EHTokBool1: - new(&type) TType(EbtBool); - type.makeVector(); - break; - case EHTokBool2: - new(&type) TType(EbtBool, EvqTemporary, 2); - break; - case EHTokBool3: - new(&type) TType(EbtBool, EvqTemporary, 3); - break; - case EHTokBool4: - new(&type) TType(EbtBool, EvqTemporary, 4); - break; - - case EHTokHalf: - new(&type) TType(half_bt, EvqTemporary); - break; - case EHTokHalf1: - new(&type) TType(half_bt, EvqTemporary); - type.makeVector(); - break; - case EHTokHalf2: - new(&type) TType(half_bt, EvqTemporary, 2); - break; - case EHTokHalf3: - new(&type) TType(half_bt, EvqTemporary, 3); - break; - case EHTokHalf4: - new(&type) TType(half_bt, EvqTemporary, 4); - break; - - case EHTokMin16float: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium); - break; - case EHTokMin16float1: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium); - type.makeVector(); - break; - case EHTokMin16float2: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 2); - break; - case EHTokMin16float3: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 3); - break; - case EHTokMin16float4: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 4); - break; - - case EHTokMin10float: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium); - break; - case EHTokMin10float1: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium); - type.makeVector(); - break; - case EHTokMin10float2: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 2); - break; - case EHTokMin10float3: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 3); - break; - case EHTokMin10float4: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 4); - break; - - case EHTokMin16int: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium); - break; - case EHTokMin16int1: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium); - type.makeVector(); - break; - case EHTokMin16int2: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 2); - break; - case EHTokMin16int3: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 3); - break; - case EHTokMin16int4: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 4); - break; - - case EHTokMin12int: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium); - break; - case EHTokMin12int1: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium); - type.makeVector(); - break; - case EHTokMin12int2: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 2); - break; - case EHTokMin12int3: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 3); - break; - case EHTokMin12int4: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 4); - break; - - case EHTokMin16uint: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium); - break; - case EHTokMin16uint1: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium); - type.makeVector(); - break; - case EHTokMin16uint2: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 2); - break; - case EHTokMin16uint3: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 3); - break; - case EHTokMin16uint4: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 4); - break; - - case EHTokInt1x1: - new(&type) TType(EbtInt, EvqTemporary, 0, 1, 1); - break; - case EHTokInt1x2: - new(&type) TType(EbtInt, EvqTemporary, 0, 1, 2); - break; - case EHTokInt1x3: - new(&type) TType(EbtInt, EvqTemporary, 0, 1, 3); - break; - case EHTokInt1x4: - new(&type) TType(EbtInt, EvqTemporary, 0, 1, 4); - break; - case EHTokInt2x1: - new(&type) TType(EbtInt, EvqTemporary, 0, 2, 1); - break; - case EHTokInt2x2: - new(&type) TType(EbtInt, EvqTemporary, 0, 2, 2); - break; - case EHTokInt2x3: - new(&type) TType(EbtInt, EvqTemporary, 0, 2, 3); - break; - case EHTokInt2x4: - new(&type) TType(EbtInt, EvqTemporary, 0, 2, 4); - break; - case EHTokInt3x1: - new(&type) TType(EbtInt, EvqTemporary, 0, 3, 1); - break; - case EHTokInt3x2: - new(&type) TType(EbtInt, EvqTemporary, 0, 3, 2); - break; - case EHTokInt3x3: - new(&type) TType(EbtInt, EvqTemporary, 0, 3, 3); - break; - case EHTokInt3x4: - new(&type) TType(EbtInt, EvqTemporary, 0, 3, 4); - break; - case EHTokInt4x1: - new(&type) TType(EbtInt, EvqTemporary, 0, 4, 1); - break; - case EHTokInt4x2: - new(&type) TType(EbtInt, EvqTemporary, 0, 4, 2); - break; - case EHTokInt4x3: - new(&type) TType(EbtInt, EvqTemporary, 0, 4, 3); - break; - case EHTokInt4x4: - new(&type) TType(EbtInt, EvqTemporary, 0, 4, 4); - break; - - case EHTokUint1x1: - new(&type) TType(EbtUint, EvqTemporary, 0, 1, 1); - break; - case EHTokUint1x2: - new(&type) TType(EbtUint, EvqTemporary, 0, 1, 2); - break; - case EHTokUint1x3: - new(&type) TType(EbtUint, EvqTemporary, 0, 1, 3); - break; - case EHTokUint1x4: - new(&type) TType(EbtUint, EvqTemporary, 0, 1, 4); - break; - case EHTokUint2x1: - new(&type) TType(EbtUint, EvqTemporary, 0, 2, 1); - break; - case EHTokUint2x2: - new(&type) TType(EbtUint, EvqTemporary, 0, 2, 2); - break; - case EHTokUint2x3: - new(&type) TType(EbtUint, EvqTemporary, 0, 2, 3); - break; - case EHTokUint2x4: - new(&type) TType(EbtUint, EvqTemporary, 0, 2, 4); - break; - case EHTokUint3x1: - new(&type) TType(EbtUint, EvqTemporary, 0, 3, 1); - break; - case EHTokUint3x2: - new(&type) TType(EbtUint, EvqTemporary, 0, 3, 2); - break; - case EHTokUint3x3: - new(&type) TType(EbtUint, EvqTemporary, 0, 3, 3); - break; - case EHTokUint3x4: - new(&type) TType(EbtUint, EvqTemporary, 0, 3, 4); - break; - case EHTokUint4x1: - new(&type) TType(EbtUint, EvqTemporary, 0, 4, 1); - break; - case EHTokUint4x2: - new(&type) TType(EbtUint, EvqTemporary, 0, 4, 2); - break; - case EHTokUint4x3: - new(&type) TType(EbtUint, EvqTemporary, 0, 4, 3); - break; - case EHTokUint4x4: - new(&type) TType(EbtUint, EvqTemporary, 0, 4, 4); - break; - - case EHTokBool1x1: - new(&type) TType(EbtBool, EvqTemporary, 0, 1, 1); - break; - case EHTokBool1x2: - new(&type) TType(EbtBool, EvqTemporary, 0, 1, 2); - break; - case EHTokBool1x3: - new(&type) TType(EbtBool, EvqTemporary, 0, 1, 3); - break; - case EHTokBool1x4: - new(&type) TType(EbtBool, EvqTemporary, 0, 1, 4); - break; - case EHTokBool2x1: - new(&type) TType(EbtBool, EvqTemporary, 0, 2, 1); - break; - case EHTokBool2x2: - new(&type) TType(EbtBool, EvqTemporary, 0, 2, 2); - break; - case EHTokBool2x3: - new(&type) TType(EbtBool, EvqTemporary, 0, 2, 3); - break; - case EHTokBool2x4: - new(&type) TType(EbtBool, EvqTemporary, 0, 2, 4); - break; - case EHTokBool3x1: - new(&type) TType(EbtBool, EvqTemporary, 0, 3, 1); - break; - case EHTokBool3x2: - new(&type) TType(EbtBool, EvqTemporary, 0, 3, 2); - break; - case EHTokBool3x3: - new(&type) TType(EbtBool, EvqTemporary, 0, 3, 3); - break; - case EHTokBool3x4: - new(&type) TType(EbtBool, EvqTemporary, 0, 3, 4); - break; - case EHTokBool4x1: - new(&type) TType(EbtBool, EvqTemporary, 0, 4, 1); - break; - case EHTokBool4x2: - new(&type) TType(EbtBool, EvqTemporary, 0, 4, 2); - break; - case EHTokBool4x3: - new(&type) TType(EbtBool, EvqTemporary, 0, 4, 3); - break; - case EHTokBool4x4: - new(&type) TType(EbtBool, EvqTemporary, 0, 4, 4); - break; - - case EHTokFloat1x1: - new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 1); - break; - case EHTokFloat1x2: - new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 2); - break; - case EHTokFloat1x3: - new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 3); - break; - case EHTokFloat1x4: - new(&type) TType(EbtFloat, EvqTemporary, 0, 1, 4); - break; - case EHTokFloat2x1: - new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 1); - break; - case EHTokFloat2x2: - new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 2); - break; - case EHTokFloat2x3: - new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 3); - break; - case EHTokFloat2x4: - new(&type) TType(EbtFloat, EvqTemporary, 0, 2, 4); - break; - case EHTokFloat3x1: - new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 1); - break; - case EHTokFloat3x2: - new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 2); - break; - case EHTokFloat3x3: - new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 3); - break; - case EHTokFloat3x4: - new(&type) TType(EbtFloat, EvqTemporary, 0, 3, 4); - break; - case EHTokFloat4x1: - new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 1); - break; - case EHTokFloat4x2: - new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 2); - break; - case EHTokFloat4x3: - new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 3); - break; - case EHTokFloat4x4: - new(&type) TType(EbtFloat, EvqTemporary, 0, 4, 4); - break; - - case EHTokHalf1x1: - new(&type) TType(half_bt, EvqTemporary, 0, 1, 1); - break; - case EHTokHalf1x2: - new(&type) TType(half_bt, EvqTemporary, 0, 1, 2); - break; - case EHTokHalf1x3: - new(&type) TType(half_bt, EvqTemporary, 0, 1, 3); - break; - case EHTokHalf1x4: - new(&type) TType(half_bt, EvqTemporary, 0, 1, 4); - break; - case EHTokHalf2x1: - new(&type) TType(half_bt, EvqTemporary, 0, 2, 1); - break; - case EHTokHalf2x2: - new(&type) TType(half_bt, EvqTemporary, 0, 2, 2); - break; - case EHTokHalf2x3: - new(&type) TType(half_bt, EvqTemporary, 0, 2, 3); - break; - case EHTokHalf2x4: - new(&type) TType(half_bt, EvqTemporary, 0, 2, 4); - break; - case EHTokHalf3x1: - new(&type) TType(half_bt, EvqTemporary, 0, 3, 1); - break; - case EHTokHalf3x2: - new(&type) TType(half_bt, EvqTemporary, 0, 3, 2); - break; - case EHTokHalf3x3: - new(&type) TType(half_bt, EvqTemporary, 0, 3, 3); - break; - case EHTokHalf3x4: - new(&type) TType(half_bt, EvqTemporary, 0, 3, 4); - break; - case EHTokHalf4x1: - new(&type) TType(half_bt, EvqTemporary, 0, 4, 1); - break; - case EHTokHalf4x2: - new(&type) TType(half_bt, EvqTemporary, 0, 4, 2); - break; - case EHTokHalf4x3: - new(&type) TType(half_bt, EvqTemporary, 0, 4, 3); - break; - case EHTokHalf4x4: - new(&type) TType(half_bt, EvqTemporary, 0, 4, 4); - break; - - case EHTokDouble1x1: - new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 1); - break; - case EHTokDouble1x2: - new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 2); - break; - case EHTokDouble1x3: - new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 3); - break; - case EHTokDouble1x4: - new(&type) TType(EbtDouble, EvqTemporary, 0, 1, 4); - break; - case EHTokDouble2x1: - new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 1); - break; - case EHTokDouble2x2: - new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 2); - break; - case EHTokDouble2x3: - new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 3); - break; - case EHTokDouble2x4: - new(&type) TType(EbtDouble, EvqTemporary, 0, 2, 4); - break; - case EHTokDouble3x1: - new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 1); - break; - case EHTokDouble3x2: - new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 2); - break; - case EHTokDouble3x3: - new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 3); - break; - case EHTokDouble3x4: - new(&type) TType(EbtDouble, EvqTemporary, 0, 3, 4); - break; - case EHTokDouble4x1: - new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 1); - break; - case EHTokDouble4x2: - new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 2); - break; - case EHTokDouble4x3: - new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 3); - break; - case EHTokDouble4x4: - new(&type) TType(EbtDouble, EvqTemporary, 0, 4, 4); - break; - - case EHTokMin16float1x1: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 1, 1); - break; - case EHTokMin16float1x2: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 1, 2); - break; - case EHTokMin16float1x3: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 1, 3); - break; - case EHTokMin16float1x4: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 1, 4); - break; - case EHTokMin16float2x1: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 2, 1); - break; - case EHTokMin16float2x2: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 2, 2); - break; - case EHTokMin16float2x3: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 2, 3); - break; - case EHTokMin16float2x4: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 2, 4); - break; - case EHTokMin16float3x1: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 3, 1); - break; - case EHTokMin16float3x2: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 3, 2); - break; - case EHTokMin16float3x3: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 3, 3); - break; - case EHTokMin16float3x4: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 3, 4); - break; - case EHTokMin16float4x1: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 4, 1); - break; - case EHTokMin16float4x2: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 4, 2); - break; - case EHTokMin16float4x3: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 4, 3); - break; - case EHTokMin16float4x4: - new(&type) TType(min16float_bt, EvqTemporary, EpqMedium, 0, 4, 4); - break; - - case EHTokMin10float1x1: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 1, 1); - break; - case EHTokMin10float1x2: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 1, 2); - break; - case EHTokMin10float1x3: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 1, 3); - break; - case EHTokMin10float1x4: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 1, 4); - break; - case EHTokMin10float2x1: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 2, 1); - break; - case EHTokMin10float2x2: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 2, 2); - break; - case EHTokMin10float2x3: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 2, 3); - break; - case EHTokMin10float2x4: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 2, 4); - break; - case EHTokMin10float3x1: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 3, 1); - break; - case EHTokMin10float3x2: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 3, 2); - break; - case EHTokMin10float3x3: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 3, 3); - break; - case EHTokMin10float3x4: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 3, 4); - break; - case EHTokMin10float4x1: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 4, 1); - break; - case EHTokMin10float4x2: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 4, 2); - break; - case EHTokMin10float4x3: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 4, 3); - break; - case EHTokMin10float4x4: - new(&type) TType(min10float_bt, EvqTemporary, EpqMedium, 0, 4, 4); - break; - - case EHTokMin16int1x1: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 1, 1); - break; - case EHTokMin16int1x2: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 1, 2); - break; - case EHTokMin16int1x3: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 1, 3); - break; - case EHTokMin16int1x4: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 1, 4); - break; - case EHTokMin16int2x1: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 2, 1); - break; - case EHTokMin16int2x2: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 2, 2); - break; - case EHTokMin16int2x3: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 2, 3); - break; - case EHTokMin16int2x4: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 2, 4); - break; - case EHTokMin16int3x1: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 3, 1); - break; - case EHTokMin16int3x2: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 3, 2); - break; - case EHTokMin16int3x3: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 3, 3); - break; - case EHTokMin16int3x4: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 3, 4); - break; - case EHTokMin16int4x1: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 4, 1); - break; - case EHTokMin16int4x2: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 4, 2); - break; - case EHTokMin16int4x3: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 4, 3); - break; - case EHTokMin16int4x4: - new(&type) TType(min16int_bt, EvqTemporary, EpqMedium, 0, 4, 4); - break; - - case EHTokMin12int1x1: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 1, 1); - break; - case EHTokMin12int1x2: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 1, 2); - break; - case EHTokMin12int1x3: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 1, 3); - break; - case EHTokMin12int1x4: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 1, 4); - break; - case EHTokMin12int2x1: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 2, 1); - break; - case EHTokMin12int2x2: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 2, 2); - break; - case EHTokMin12int2x3: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 2, 3); - break; - case EHTokMin12int2x4: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 2, 4); - break; - case EHTokMin12int3x1: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 3, 1); - break; - case EHTokMin12int3x2: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 3, 2); - break; - case EHTokMin12int3x3: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 3, 3); - break; - case EHTokMin12int3x4: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 3, 4); - break; - case EHTokMin12int4x1: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 4, 1); - break; - case EHTokMin12int4x2: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 4, 2); - break; - case EHTokMin12int4x3: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 4, 3); - break; - case EHTokMin12int4x4: - new(&type) TType(min12int_bt, EvqTemporary, EpqMedium, 0, 4, 4); - break; - - case EHTokMin16uint1x1: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 1, 1); - break; - case EHTokMin16uint1x2: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 1, 2); - break; - case EHTokMin16uint1x3: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 1, 3); - break; - case EHTokMin16uint1x4: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 1, 4); - break; - case EHTokMin16uint2x1: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 2, 1); - break; - case EHTokMin16uint2x2: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 2, 2); - break; - case EHTokMin16uint2x3: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 2, 3); - break; - case EHTokMin16uint2x4: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 2, 4); - break; - case EHTokMin16uint3x1: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 3, 1); - break; - case EHTokMin16uint3x2: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 3, 2); - break; - case EHTokMin16uint3x3: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 3, 3); - break; - case EHTokMin16uint3x4: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 3, 4); - break; - case EHTokMin16uint4x1: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 4, 1); - break; - case EHTokMin16uint4x2: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 4, 2); - break; - case EHTokMin16uint4x3: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 4, 3); - break; - case EHTokMin16uint4x4: - new(&type) TType(min16uint_bt, EvqTemporary, EpqMedium, 0, 4, 4); - break; - - default: - return false; - } - - advanceToken(); - - if ((isUnorm || isSnorm) && !type.isFloatingDomain()) { - parseContext.error(token.loc, "unorm and snorm only valid in floating point domain", "", ""); - return false; - } - - return true; -} - -// struct -// : struct_type IDENTIFIER post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE -// | struct_type post_decls LEFT_BRACE struct_declaration_list RIGHT_BRACE -// | struct_type IDENTIFIER // use of previously declared struct type -// -// struct_type -// : STRUCT -// | CLASS -// | CBUFFER -// | TBUFFER -// -bool HlslGrammar::acceptStruct(TType& type, TIntermNode*& nodeList) -{ - // This storage qualifier will tell us whether it's an AST - // block type or just a generic structure type. - TStorageQualifier storageQualifier = EvqTemporary; - bool readonly = false; - - if (acceptTokenClass(EHTokCBuffer)) { - // CBUFFER - storageQualifier = EvqUniform; - } else if (acceptTokenClass(EHTokTBuffer)) { - // TBUFFER - storageQualifier = EvqBuffer; - readonly = true; - } else if (! acceptTokenClass(EHTokClass) && ! acceptTokenClass(EHTokStruct)) { - // Neither CLASS nor STRUCT - return false; - } - - // Now known to be one of CBUFFER, TBUFFER, CLASS, or STRUCT - - - // IDENTIFIER. It might also be a keyword which can double as an identifier. - // For example: 'cbuffer ConstantBuffer' or 'struct ConstantBuffer' is legal. - // 'cbuffer int' is also legal, and 'struct int' appears rejected only because - // it attempts to redefine the 'int' type. - const char* idString = getTypeString(peek()); - TString structName = ""; - if (peekTokenClass(EHTokIdentifier) || idString != nullptr) { - if (idString != nullptr) - structName = *idString; - else - structName = *token.string; - advanceToken(); - } - - // post_decls - TQualifier postDeclQualifier; - postDeclQualifier.clear(); - bool postDeclsFound = acceptPostDecls(postDeclQualifier); - - // LEFT_BRACE, or - // struct_type IDENTIFIER - if (! acceptTokenClass(EHTokLeftBrace)) { - if (structName.size() > 0 && !postDeclsFound && parseContext.lookupUserType(structName, type) != nullptr) { - // struct_type IDENTIFIER - return true; - } else { - expected("{"); - return false; - } - } - - - // struct_declaration_list - TTypeList* typeList; - // Save each member function so they can be processed after we have a fully formed 'this'. - TVector functionDeclarators; - - parseContext.pushNamespace(structName); - bool acceptedList = acceptStructDeclarationList(typeList, nodeList, functionDeclarators); - parseContext.popNamespace(); - - if (! acceptedList) { - expected("struct member declarations"); - return false; - } - - // RIGHT_BRACE - if (! acceptTokenClass(EHTokRightBrace)) { - expected("}"); - return false; - } - - // create the user-defined type - if (storageQualifier == EvqTemporary) - new(&type) TType(typeList, structName); - else { - postDeclQualifier.storage = storageQualifier; - postDeclQualifier.readonly = readonly; - new(&type) TType(typeList, structName, postDeclQualifier); // sets EbtBlock - } - - parseContext.declareStruct(token.loc, structName, type); - - // For member functions: now that we know the type of 'this', go back and - // - add their implicit argument with 'this' (not to the mangling, just the argument list) - // - parse the functions, their tokens were saved for deferred parsing (now) - for (int b = 0; b < (int)functionDeclarators.size(); ++b) { - // update signature - if (functionDeclarators[b].function->hasImplicitThis()) - functionDeclarators[b].function->addThisParameter(type, intermediate.implicitThisName); - } - - // All member functions get parsed inside the class/struct namespace and with the - // class/struct members in a symbol-table level. - parseContext.pushNamespace(structName); - parseContext.pushThisScope(type, functionDeclarators); - bool deferredSuccess = true; - for (int b = 0; b < (int)functionDeclarators.size() && deferredSuccess; ++b) { - // parse body - pushTokenStream(functionDeclarators[b].body); - if (! acceptFunctionBody(functionDeclarators[b], nodeList)) - deferredSuccess = false; - popTokenStream(); - } - parseContext.popThisScope(); - parseContext.popNamespace(); - - return deferredSuccess; -} - -// constantbuffer -// : CONSTANTBUFFER LEFT_ANGLE type RIGHT_ANGLE -bool HlslGrammar::acceptConstantBufferType(TType& type) -{ - if (! acceptTokenClass(EHTokConstantBuffer)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) { - expected("left angle bracket"); - return false; - } - - TType templateType; - if (! acceptType(templateType)) { - expected("type"); - return false; - } - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - TQualifier postDeclQualifier; - postDeclQualifier.clear(); - postDeclQualifier.storage = EvqUniform; - - if (templateType.isStruct()) { - // Make a block from the type parsed as the template argument - TTypeList* typeList = templateType.getWritableStruct(); - new(&type) TType(typeList, "", postDeclQualifier); // sets EbtBlock - - type.getQualifier().storage = EvqUniform; - - return true; - } else { - parseContext.error(token.loc, "non-structure type in ConstantBuffer", "", ""); - return false; - } -} - -// texture_buffer -// : TEXTUREBUFFER LEFT_ANGLE type RIGHT_ANGLE -bool HlslGrammar::acceptTextureBufferType(TType& type) -{ - if (! acceptTokenClass(EHTokTextureBuffer)) - return false; - - if (! acceptTokenClass(EHTokLeftAngle)) { - expected("left angle bracket"); - return false; - } - - TType templateType; - if (! acceptType(templateType)) { - expected("type"); - return false; - } - - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - - templateType.getQualifier().storage = EvqBuffer; - templateType.getQualifier().readonly = true; - - TType blockType(templateType.getWritableStruct(), "", templateType.getQualifier()); - - blockType.getQualifier().storage = EvqBuffer; - blockType.getQualifier().readonly = true; - - type.shallowCopy(blockType); - - return true; -} - - -// struct_buffer -// : APPENDSTRUCTUREDBUFFER -// | BYTEADDRESSBUFFER -// | CONSUMESTRUCTUREDBUFFER -// | RWBYTEADDRESSBUFFER -// | RWSTRUCTUREDBUFFER -// | STRUCTUREDBUFFER -bool HlslGrammar::acceptStructBufferType(TType& type) -{ - const EHlslTokenClass structBuffType = peek(); - - // TODO: globallycoherent - bool hasTemplateType = true; - bool readonly = false; - - TStorageQualifier storage = EvqBuffer; - TBuiltInVariable builtinType = EbvNone; - - switch (structBuffType) { - case EHTokAppendStructuredBuffer: - builtinType = EbvAppendConsume; - break; - case EHTokByteAddressBuffer: - hasTemplateType = false; - readonly = true; - builtinType = EbvByteAddressBuffer; - break; - case EHTokConsumeStructuredBuffer: - builtinType = EbvAppendConsume; - break; - case EHTokRWByteAddressBuffer: - hasTemplateType = false; - builtinType = EbvRWByteAddressBuffer; - break; - case EHTokRWStructuredBuffer: - builtinType = EbvRWStructuredBuffer; - break; - case EHTokStructuredBuffer: - builtinType = EbvStructuredBuffer; - readonly = true; - break; - default: - return false; // not a structure buffer type - } - - advanceToken(); // consume the structure keyword - - // type on which this StructedBuffer is templatized. E.g, StructedBuffer ==> MyStruct - TType* templateType = new TType; - - if (hasTemplateType) { - if (! acceptTokenClass(EHTokLeftAngle)) { - expected("left angle bracket"); - return false; - } - - if (! acceptType(*templateType)) { - expected("type"); - return false; - } - if (! acceptTokenClass(EHTokRightAngle)) { - expected("right angle bracket"); - return false; - } - } else { - // byte address buffers have no explicit type. - TType uintType(EbtUint, storage); - templateType->shallowCopy(uintType); - } - - // Create an unsized array out of that type. - // TODO: does this work if it's already an array type? - TArraySizes* unsizedArray = new TArraySizes; - unsizedArray->addInnerSize(UnsizedArraySize); - templateType->transferArraySizes(unsizedArray); - templateType->getQualifier().storage = storage; - - // field name is canonical for all structbuffers - templateType->setFieldName("@data"); - - TTypeList* blockStruct = new TTypeList; - TTypeLoc member = { templateType, token.loc }; - blockStruct->push_back(member); - - // This is the type of the buffer block (SSBO) - TType blockType(blockStruct, "", templateType->getQualifier()); - - blockType.getQualifier().storage = storage; - blockType.getQualifier().readonly = readonly; - blockType.getQualifier().builtIn = builtinType; - - // We may have created an equivalent type before, in which case we should use its - // deep structure. - parseContext.shareStructBufferType(blockType); - - type.shallowCopy(blockType); - - return true; -} - -// struct_declaration_list -// : struct_declaration SEMI_COLON struct_declaration SEMI_COLON ... -// -// struct_declaration -// : attributes fully_specified_type struct_declarator COMMA struct_declarator ... -// | attributes fully_specified_type IDENTIFIER function_parameters post_decls compound_statement // member-function definition -// -// struct_declarator -// : IDENTIFIER post_decls -// | IDENTIFIER array_specifier post_decls -// | IDENTIFIER function_parameters post_decls // member-function prototype -// -bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*& nodeList, - TVector& declarators) -{ - typeList = new TTypeList(); - HlslToken idToken; - - do { - // success on seeing the RIGHT_BRACE coming up - if (peekTokenClass(EHTokRightBrace)) - break; - - // struct_declaration - - // attributes - TAttributes attributes; - acceptAttributes(attributes); - - bool declarator_list = false; - - // fully_specified_type - TType memberType; - if (! acceptFullySpecifiedType(memberType, nodeList, attributes)) { - expected("member type"); - return false; - } - - // merge in the attributes - parseContext.transferTypeAttributes(token.loc, attributes, memberType); - - // struct_declarator COMMA struct_declarator ... - bool functionDefinitionAccepted = false; - do { - if (! acceptIdentifier(idToken)) { - expected("member name"); - return false; - } - - if (peekTokenClass(EHTokLeftParen)) { - // function_parameters - if (!declarator_list) { - declarators.resize(declarators.size() + 1); - // request a token stream for deferred processing - functionDefinitionAccepted = acceptMemberFunctionDefinition(nodeList, memberType, *idToken.string, - declarators.back()); - if (functionDefinitionAccepted) - break; - } - expected("member-function definition"); - return false; - } else { - // add it to the list of members - TTypeLoc member = { new TType(EbtVoid), token.loc }; - member.type->shallowCopy(memberType); - member.type->setFieldName(*idToken.string); - typeList->push_back(member); - - // array_specifier - TArraySizes* arraySizes = nullptr; - acceptArraySpecifier(arraySizes); - if (arraySizes) - typeList->back().type->transferArraySizes(arraySizes); - - acceptPostDecls(member.type->getQualifier()); - - // EQUAL assignment_expression - if (acceptTokenClass(EHTokAssign)) { - parseContext.warn(idToken.loc, "struct-member initializers ignored", "typedef", ""); - TIntermTyped* expressionNode = nullptr; - if (! acceptAssignmentExpression(expressionNode)) { - expected("initializer"); - return false; - } - } - } - // success on seeing the SEMICOLON coming up - if (peekTokenClass(EHTokSemicolon)) - break; - - // COMMA - if (acceptTokenClass(EHTokComma)) - declarator_list = true; - else { - expected(","); - return false; - } - - } while (true); - - // SEMI_COLON - if (! functionDefinitionAccepted && ! acceptTokenClass(EHTokSemicolon)) { - expected(";"); - return false; - } - - } while (true); - - return true; -} - -// member_function_definition -// | function_parameters post_decls compound_statement -// -// Expects type to have EvqGlobal for a static member and -// EvqTemporary for non-static member. -bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType& type, TString& memberName, - TFunctionDeclarator& declarator) -{ - bool accepted = false; - - TString* functionName = &memberName; - parseContext.getFullNamespaceName(functionName); - declarator.function = new TFunction(functionName, type); - if (type.getQualifier().storage == EvqTemporary) - declarator.function->setImplicitThis(); - else - declarator.function->setIllegalImplicitThis(); - - // function_parameters - if (acceptFunctionParameters(*declarator.function)) { - // post_decls - acceptPostDecls(declarator.function->getWritableType().getQualifier()); - - // compound_statement (function body definition) - if (peekTokenClass(EHTokLeftBrace)) { - declarator.loc = token.loc; - declarator.body = new TVector; - accepted = acceptFunctionDefinition(declarator, nodeList, declarator.body); - } - } else - expected("function parameter list"); - - return accepted; -} - -// function_parameters -// : LEFT_PAREN parameter_declaration COMMA parameter_declaration ... RIGHT_PAREN -// | LEFT_PAREN VOID RIGHT_PAREN -// -bool HlslGrammar::acceptFunctionParameters(TFunction& function) -{ - parseContext.beginParameterParsing(function); - - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) - return false; - - // VOID RIGHT_PAREN - if (! acceptTokenClass(EHTokVoid)) { - do { - // parameter_declaration - if (! acceptParameterDeclaration(function)) - break; - - // COMMA - if (! acceptTokenClass(EHTokComma)) - break; - } while (true); - } - - // RIGHT_PAREN - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - return false; - } - - return true; -} - -// default_parameter_declaration -// : EQUAL conditional_expression -// : EQUAL initializer -bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTyped*& node) -{ - node = nullptr; - - // Valid not to have a default_parameter_declaration - if (!acceptTokenClass(EHTokAssign)) - return true; - - if (!acceptConditionalExpression(node)) { - if (!acceptInitializer(node)) - return false; - - // For initializer lists, we have to const-fold into a constructor for the type, so build - // that. - TFunction* constructor = parseContext.makeConstructorCall(token.loc, type); - if (constructor == nullptr) // cannot construct - return false; - - TIntermTyped* arguments = nullptr; - for (int i = 0; i < int(node->getAsAggregate()->getSequence().size()); i++) - parseContext.handleFunctionArgument(constructor, arguments, node->getAsAggregate()->getSequence()[i]->getAsTyped()); - - node = parseContext.handleFunctionCall(token.loc, constructor, node); - } - - if (node == nullptr) - return false; - - // If this is simply a constant, we can use it directly. - if (node->getAsConstantUnion()) - return true; - - // Otherwise, it has to be const-foldable. - TIntermTyped* origNode = node; - - node = intermediate.fold(node->getAsAggregate()); - - if (node != nullptr && origNode != node) - return true; - - parseContext.error(token.loc, "invalid default parameter value", "", ""); - - return false; -} - -// parameter_declaration -// : attributes attributed_declaration -// -// attributed_declaration -// : fully_specified_type post_decls [ = default_parameter_declaration ] -// | fully_specified_type identifier array_specifier post_decls [ = default_parameter_declaration ] -// -bool HlslGrammar::acceptParameterDeclaration(TFunction& function) -{ - // attributes - TAttributes attributes; - acceptAttributes(attributes); - - // fully_specified_type - TType* type = new TType; - if (! acceptFullySpecifiedType(*type, attributes)) - return false; - - // merge in the attributes - parseContext.transferTypeAttributes(token.loc, attributes, *type); - - // identifier - HlslToken idToken; - acceptIdentifier(idToken); - - // array_specifier - TArraySizes* arraySizes = nullptr; - acceptArraySpecifier(arraySizes); - if (arraySizes) { - if (arraySizes->hasUnsized()) { - parseContext.error(token.loc, "function parameter requires array size", "[]", ""); - return false; - } - - type->transferArraySizes(arraySizes); - } - - // post_decls - acceptPostDecls(type->getQualifier()); - - TIntermTyped* defaultValue; - if (!acceptDefaultParameterDeclaration(*type, defaultValue)) - return false; - - parseContext.paramFix(*type); - - // If any prior parameters have default values, all the parameters after that must as well. - if (defaultValue == nullptr && function.getDefaultParamCount() > 0) { - parseContext.error(idToken.loc, "invalid parameter after default value parameters", idToken.string->c_str(), ""); - return false; - } - - TParameter param = { idToken.string, type, defaultValue }; - function.addParameter(param); - - return true; -} - -// Do the work to create the function definition in addition to -// parsing the body (compound_statement). -// -// If 'deferredTokens' are passed in, just get the token stream, -// don't process. -// -bool HlslGrammar::acceptFunctionDefinition(TFunctionDeclarator& declarator, TIntermNode*& nodeList, - TVector* deferredTokens) -{ - parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, false /* not prototype */); - - if (deferredTokens) - return captureBlockTokens(*deferredTokens); - else - return acceptFunctionBody(declarator, nodeList); -} - -bool HlslGrammar::acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList) -{ - // we might get back an entry-point - TIntermNode* entryPointNode = nullptr; - - // This does a pushScope() - TIntermNode* functionNode = parseContext.handleFunctionDefinition(declarator.loc, *declarator.function, - declarator.attributes, entryPointNode); - - // compound_statement - TIntermNode* functionBody = nullptr; - if (! acceptCompoundStatement(functionBody)) - return false; - - // this does a popScope() - parseContext.handleFunctionBody(declarator.loc, *declarator.function, functionBody, functionNode); - - // Hook up the 1 or 2 function definitions. - nodeList = intermediate.growAggregate(nodeList, functionNode); - nodeList = intermediate.growAggregate(nodeList, entryPointNode); - - return true; -} - -// Accept an expression with parenthesis around it, where -// the parenthesis ARE NOT expression parenthesis, but the -// syntactically required ones like in "if ( expression )". -// -// Also accepts a declaration expression; "if (int a = expression)". -// -// Note this one is not set up to be speculative; as it gives -// errors if not found. -// -bool HlslGrammar::acceptParenExpression(TIntermTyped*& expression) -{ - expression = nullptr; - - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) - expected("("); - - bool decl = false; - TIntermNode* declNode = nullptr; - decl = acceptControlDeclaration(declNode); - if (decl) { - if (declNode == nullptr || declNode->getAsTyped() == nullptr) { - expected("initialized declaration"); - return false; - } else - expression = declNode->getAsTyped(); - } else { - // no declaration - if (! acceptExpression(expression)) { - expected("expression"); - return false; - } - } - - // RIGHT_PAREN - if (! acceptTokenClass(EHTokRightParen)) - expected(")"); - - return true; -} - -// The top-level full expression recognizer. -// -// expression -// : assignment_expression COMMA assignment_expression COMMA assignment_expression ... -// -bool HlslGrammar::acceptExpression(TIntermTyped*& node) -{ - node = nullptr; - - // assignment_expression - if (! acceptAssignmentExpression(node)) - return false; - - if (! peekTokenClass(EHTokComma)) - return true; - - do { - // ... COMMA - TSourceLoc loc = token.loc; - advanceToken(); - - // ... assignment_expression - TIntermTyped* rightNode = nullptr; - if (! acceptAssignmentExpression(rightNode)) { - expected("assignment expression"); - return false; - } - - node = intermediate.addComma(node, rightNode, loc); - - if (! peekTokenClass(EHTokComma)) - return true; - } while (true); -} - -// initializer -// : LEFT_BRACE RIGHT_BRACE -// | LEFT_BRACE initializer_list RIGHT_BRACE -// -// initializer_list -// : assignment_expression COMMA assignment_expression COMMA ... -// -bool HlslGrammar::acceptInitializer(TIntermTyped*& node) -{ - // LEFT_BRACE - if (! acceptTokenClass(EHTokLeftBrace)) - return false; - - // RIGHT_BRACE - TSourceLoc loc = token.loc; - if (acceptTokenClass(EHTokRightBrace)) { - // a zero-length initializer list - node = intermediate.makeAggregate(loc); - return true; - } - - // initializer_list - node = nullptr; - do { - // assignment_expression - TIntermTyped* expr; - if (! acceptAssignmentExpression(expr)) { - expected("assignment expression in initializer list"); - return false; - } - - const bool firstNode = (node == nullptr); - - node = intermediate.growAggregate(node, expr, loc); - - // If every sub-node in the list has qualifier EvqConst, the returned node becomes - // EvqConst. Otherwise, it becomes EvqTemporary. That doesn't happen with e.g. - // EvqIn or EvqPosition, since the collection isn't EvqPosition if all the members are. - if (firstNode && expr->getQualifier().storage == EvqConst) - node->getQualifier().storage = EvqConst; - else if (expr->getQualifier().storage != EvqConst) - node->getQualifier().storage = EvqTemporary; - - // COMMA - if (acceptTokenClass(EHTokComma)) { - if (acceptTokenClass(EHTokRightBrace)) // allow trailing comma - return true; - continue; - } - - // RIGHT_BRACE - if (acceptTokenClass(EHTokRightBrace)) - return true; - - expected(", or }"); - return false; - } while (true); -} - -// Accept an assignment expression, where assignment operations -// associate right-to-left. That is, it is implicit, for example -// -// a op (b op (c op d)) -// -// assigment_expression -// : initializer -// | conditional_expression -// | conditional_expression assign_op conditional_expression assign_op conditional_expression ... -// -bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node) -{ - // initializer - if (peekTokenClass(EHTokLeftBrace)) { - if (acceptInitializer(node)) - return true; - - expected("initializer"); - return false; - } - - // conditional_expression - if (! acceptConditionalExpression(node)) - return false; - - // assignment operation? - TOperator assignOp = HlslOpMap::assignment(peek()); - if (assignOp == EOpNull) - return true; - - // assign_op - TSourceLoc loc = token.loc; - advanceToken(); - - // conditional_expression assign_op conditional_expression ... - // Done by recursing this function, which automatically - // gets the right-to-left associativity. - TIntermTyped* rightNode = nullptr; - if (! acceptAssignmentExpression(rightNode)) { - expected("assignment expression"); - return false; - } - - node = parseContext.handleAssign(loc, assignOp, node, rightNode); - node = parseContext.handleLvalue(loc, "assign", node); - - if (node == nullptr) { - parseContext.error(loc, "could not create assignment", "", ""); - return false; - } - - if (! peekTokenClass(EHTokComma)) - return true; - - return true; -} - -// Accept a conditional expression, which associates right-to-left, -// accomplished by the "true" expression calling down to lower -// precedence levels than this level. -// -// conditional_expression -// : binary_expression -// | binary_expression QUESTION expression COLON assignment_expression -// -bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node) -{ - // binary_expression - if (! acceptBinaryExpression(node, PlLogicalOr)) - return false; - - if (! acceptTokenClass(EHTokQuestion)) - return true; - - node = parseContext.convertConditionalExpression(token.loc, node, false); - if (node == nullptr) - return false; - - ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors - - TIntermTyped* trueNode = nullptr; - if (! acceptExpression(trueNode)) { - expected("expression after ?"); - return false; - } - TSourceLoc loc = token.loc; - - if (! acceptTokenClass(EHTokColon)) { - expected(":"); - return false; - } - - TIntermTyped* falseNode = nullptr; - if (! acceptAssignmentExpression(falseNode)) { - expected("expression after :"); - return false; - } - - --parseContext.controlFlowNestingLevel; - - node = intermediate.addSelection(node, trueNode, falseNode, loc); - - return true; -} - -// Accept a binary expression, for binary operations that -// associate left-to-right. This is, it is implicit, for example -// -// ((a op b) op c) op d -// -// binary_expression -// : expression op expression op expression ... -// -// where 'expression' is the next higher level in precedence. -// -bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel) -{ - if (precedenceLevel > PlMul) - return acceptUnaryExpression(node); - - // assignment_expression - if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1))) - return false; - - do { - TOperator op = HlslOpMap::binary(peek()); - PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op); - if (tokenLevel < precedenceLevel) - return true; - - // ... op - TSourceLoc loc = token.loc; - advanceToken(); - - // ... expression - TIntermTyped* rightNode = nullptr; - if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) { - expected("expression"); - return false; - } - - node = intermediate.addBinaryMath(op, node, rightNode, loc); - if (node == nullptr) { - parseContext.error(loc, "Could not perform requested binary operation", "", ""); - return false; - } - } while (true); -} - -// unary_expression -// : (type) unary_expression -// | + unary_expression -// | - unary_expression -// | ! unary_expression -// | ~ unary_expression -// | ++ unary_expression -// | -- unary_expression -// | postfix_expression -// -bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node) -{ - // (type) unary_expression - // Have to look two steps ahead, because this could be, e.g., a - // postfix_expression instead, since that also starts with at "(". - if (acceptTokenClass(EHTokLeftParen)) { - TType castType; - if (acceptType(castType)) { - // recognize any array_specifier as part of the type - TArraySizes* arraySizes = nullptr; - acceptArraySpecifier(arraySizes); - if (arraySizes != nullptr) - castType.transferArraySizes(arraySizes); - TSourceLoc loc = token.loc; - if (acceptTokenClass(EHTokRightParen)) { - // We've matched "(type)" now, get the expression to cast - if (! acceptUnaryExpression(node)) - return false; - - // Hook it up like a constructor - TFunction* constructorFunction = parseContext.makeConstructorCall(loc, castType); - if (constructorFunction == nullptr) { - expected("type that can be constructed"); - return false; - } - TIntermTyped* arguments = nullptr; - parseContext.handleFunctionArgument(constructorFunction, arguments, node); - node = parseContext.handleFunctionCall(loc, constructorFunction, arguments); - - return node != nullptr; - } else { - // This could be a parenthesized constructor, ala (int(3)), and we just accepted - // the '(int' part. We must back up twice. - recedeToken(); - recedeToken(); - - // Note, there are no array constructors like - // (float[2](...)) - if (arraySizes != nullptr) - parseContext.error(loc, "parenthesized array constructor not allowed", "([]())", "", ""); - } - } else { - // This isn't a type cast, but it still started "(", so if it is a - // unary expression, it can only be a postfix_expression, so try that. - // Back it up first. - recedeToken(); - return acceptPostfixExpression(node); - } - } - - // peek for "op unary_expression" - TOperator unaryOp = HlslOpMap::preUnary(peek()); - - // postfix_expression (if no unary operator) - if (unaryOp == EOpNull) - return acceptPostfixExpression(node); - - // op unary_expression - TSourceLoc loc = token.loc; - advanceToken(); - if (! acceptUnaryExpression(node)) - return false; - - // + is a no-op - if (unaryOp == EOpAdd) - return true; - - node = intermediate.addUnaryMath(unaryOp, node, loc); - - // These unary ops require lvalues - if (unaryOp == EOpPreIncrement || unaryOp == EOpPreDecrement) - node = parseContext.handleLvalue(loc, "unary operator", node); - - return node != nullptr; -} - -// postfix_expression -// : LEFT_PAREN expression RIGHT_PAREN -// | literal -// | constructor -// | IDENTIFIER [ COLONCOLON IDENTIFIER [ COLONCOLON IDENTIFIER ... ] ] -// | function_call -// | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET -// | postfix_expression DOT IDENTIFIER -// | postfix_expression DOT IDENTIFIER arguments -// | postfix_expression arguments -// | postfix_expression INC_OP -// | postfix_expression DEC_OP -// -bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node) -{ - // Not implemented as self-recursive: - // The logical "right recursion" is done with a loop at the end - - // idToken will pick up either a variable or a function name in a function call - HlslToken idToken; - - // Find something before the postfix operations, as they can't operate - // on nothing. So, no "return true", they fall through, only "return false". - if (acceptTokenClass(EHTokLeftParen)) { - // LEFT_PAREN expression RIGHT_PAREN - if (! acceptExpression(node)) { - expected("expression"); - return false; - } - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - return false; - } - } else if (acceptLiteral(node)) { - // literal (nothing else to do yet) - } else if (acceptConstructor(node)) { - // constructor (nothing else to do yet) - } else if (acceptIdentifier(idToken)) { - // user-type, namespace name, variable, or function name - TString* fullName = idToken.string; - while (acceptTokenClass(EHTokColonColon)) { - // user-type or namespace name - fullName = NewPoolTString(fullName->c_str()); - fullName->append(parseContext.scopeMangler); - if (acceptIdentifier(idToken)) - fullName->append(*idToken.string); - else { - expected("identifier after ::"); - return false; - } - } - if (! peekTokenClass(EHTokLeftParen)) { - node = parseContext.handleVariable(idToken.loc, fullName); - if (node == nullptr) - return false; - } else if (acceptFunctionCall(idToken.loc, *fullName, node, nullptr)) { - // function_call (nothing else to do yet) - } else { - expected("function call arguments"); - return false; - } - } else { - // nothing found, can't post operate - return false; - } - - // Something was found, chain as many postfix operations as exist. - do { - TSourceLoc loc = token.loc; - TOperator postOp = HlslOpMap::postUnary(peek()); - - // Consume only a valid post-unary operator, otherwise we are done. - switch (postOp) { - case EOpIndexDirectStruct: - case EOpIndexIndirect: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpScoping: - advanceToken(); - break; - default: - return true; - } - - // We have a valid post-unary operator, process it. - switch (postOp) { - case EOpScoping: - case EOpIndexDirectStruct: - { - // DOT IDENTIFIER - // includes swizzles, member variables, and member functions - HlslToken field; - if (! acceptIdentifier(field)) { - expected("swizzle or member"); - return false; - } - - if (peekTokenClass(EHTokLeftParen)) { - // member function - TIntermTyped* thisNode = node; - - // arguments - if (! acceptFunctionCall(field.loc, *field.string, node, thisNode)) { - expected("function parameters"); - return false; - } - } else - node = parseContext.handleDotDereference(field.loc, node, *field.string); - - break; - } - case EOpIndexIndirect: - { - // LEFT_BRACKET integer_expression RIGHT_BRACKET - TIntermTyped* indexNode = nullptr; - if (! acceptExpression(indexNode) || - ! peekTokenClass(EHTokRightBracket)) { - expected("expression followed by ']'"); - return false; - } - advanceToken(); - node = parseContext.handleBracketDereference(indexNode->getLoc(), node, indexNode); - if (node == nullptr) - return false; - break; - } - case EOpPostIncrement: - // INC_OP - // fall through - case EOpPostDecrement: - // DEC_OP - node = intermediate.addUnaryMath(postOp, node, loc); - node = parseContext.handleLvalue(loc, "unary operator", node); - break; - default: - assert(0); - break; - } - } while (true); -} - -// constructor -// : type argument_list -// -bool HlslGrammar::acceptConstructor(TIntermTyped*& node) -{ - // type - TType type; - if (acceptType(type)) { - TFunction* constructorFunction = parseContext.makeConstructorCall(token.loc, type); - if (constructorFunction == nullptr) - return false; - - // arguments - TIntermTyped* arguments = nullptr; - if (! acceptArguments(constructorFunction, arguments)) { - // It's possible this is a type keyword used as an identifier. Put the token back - // for later use. - recedeToken(); - return false; - } - - if (arguments == nullptr) { - expected("one or more arguments"); - return false; - } - - // hook it up - node = parseContext.handleFunctionCall(token.loc, constructorFunction, arguments); - - return node != nullptr; - } - - return false; -} - -// The function_call identifier was already recognized, and passed in as idToken. -// -// function_call -// : [idToken] arguments -// -bool HlslGrammar::acceptFunctionCall(const TSourceLoc& loc, TString& name, TIntermTyped*& node, TIntermTyped* baseObject) -{ - // name - TString* functionName = nullptr; - if (baseObject == nullptr) { - functionName = &name; - } else if (parseContext.isBuiltInMethod(loc, baseObject, name)) { - // Built-in methods are not in the symbol table as methods, but as global functions - // taking an explicit 'this' as the first argument. - functionName = NewPoolTString(BUILTIN_PREFIX); - functionName->append(name); - } else { - if (! baseObject->getType().isStruct()) { - expected("structure"); - return false; - } - functionName = NewPoolTString(""); - functionName->append(baseObject->getType().getTypeName()); - parseContext.addScopeMangler(*functionName); - functionName->append(name); - } - - // function - TFunction* function = new TFunction(functionName, TType(EbtVoid)); - - // arguments - TIntermTyped* arguments = nullptr; - if (baseObject != nullptr) { - // Non-static member functions have an implicit first argument of the base object. - parseContext.handleFunctionArgument(function, arguments, baseObject); - } - if (! acceptArguments(function, arguments)) - return false; - - // call - node = parseContext.handleFunctionCall(loc, function, arguments); - - return node != nullptr; -} - -// arguments -// : LEFT_PAREN expression COMMA expression COMMA ... RIGHT_PAREN -// -// The arguments are pushed onto the 'function' argument list and -// onto the 'arguments' aggregate. -// -bool HlslGrammar::acceptArguments(TFunction* function, TIntermTyped*& arguments) -{ - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) - return false; - - // RIGHT_PAREN - if (acceptTokenClass(EHTokRightParen)) - return true; - - // must now be at least one expression... - do { - // expression - TIntermTyped* arg; - if (! acceptAssignmentExpression(arg)) - return false; - - // hook it up - parseContext.handleFunctionArgument(function, arguments, arg); - - // COMMA - if (! acceptTokenClass(EHTokComma)) - break; - } while (true); - - // RIGHT_PAREN - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - return false; - } - - return true; -} - -bool HlslGrammar::acceptLiteral(TIntermTyped*& node) -{ - switch (token.tokenClass) { - case EHTokIntConstant: - node = intermediate.addConstantUnion(token.i, token.loc, true); - break; - case EHTokUintConstant: - node = intermediate.addConstantUnion(token.u, token.loc, true); - break; - case EHTokFloat16Constant: - node = intermediate.addConstantUnion(token.d, EbtFloat16, token.loc, true); - break; - case EHTokFloatConstant: - node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true); - break; - case EHTokDoubleConstant: - node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true); - break; - case EHTokBoolConstant: - node = intermediate.addConstantUnion(token.b, token.loc, true); - break; - case EHTokStringConstant: - node = intermediate.addConstantUnion(token.string, token.loc, true); - break; - - default: - return false; - } - - advanceToken(); - - return true; -} - -// simple_statement -// : SEMICOLON -// | declaration_statement -// | expression SEMICOLON -// -bool HlslGrammar::acceptSimpleStatement(TIntermNode*& statement) -{ - // SEMICOLON - if (acceptTokenClass(EHTokSemicolon)) - return true; - - // declaration - if (acceptDeclaration(statement)) - return true; - - // expression - TIntermTyped* node; - if (acceptExpression(node)) - statement = node; - else - return false; - - // SEMICOLON (following an expression) - if (acceptTokenClass(EHTokSemicolon)) - return true; - else { - expected(";"); - return false; - } -} - -// compound_statement -// : LEFT_CURLY statement statement ... RIGHT_CURLY -// -bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement) -{ - TIntermAggregate* compoundStatement = nullptr; - - // LEFT_CURLY - if (! acceptTokenClass(EHTokLeftBrace)) - return false; - - // statement statement ... - TIntermNode* statement = nullptr; - while (acceptStatement(statement)) { - TIntermBranch* branch = statement ? statement->getAsBranchNode() : nullptr; - if (branch != nullptr && (branch->getFlowOp() == EOpCase || - branch->getFlowOp() == EOpDefault)) { - // hook up individual subsequences within a switch statement - parseContext.wrapupSwitchSubsequence(compoundStatement, statement); - compoundStatement = nullptr; - } else { - // hook it up to the growing compound statement - compoundStatement = intermediate.growAggregate(compoundStatement, statement); - } - } - if (compoundStatement) - compoundStatement->setOperator(intermediate.getDebugInfo() ? EOpScope : EOpSequence); - - retStatement = compoundStatement; - - // RIGHT_CURLY - return acceptTokenClass(EHTokRightBrace); -} - -bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement) -{ - parseContext.pushScope(); - bool result = acceptStatement(statement); - parseContext.popScope(); - - return result; -} - -bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement) -{ - parseContext.pushScope(); - bool result = acceptCompoundStatement(statement); - parseContext.popScope(); - - return result; -} - -// statement -// : attributes attributed_statement -// -// attributed_statement -// : compound_statement -// | simple_statement -// | selection_statement -// | switch_statement -// | case_label -// | default_label -// | iteration_statement -// | jump_statement -// -bool HlslGrammar::acceptStatement(TIntermNode*& statement) -{ - statement = nullptr; - - // attributes - TAttributes attributes; - acceptAttributes(attributes); - - // attributed_statement - switch (peek()) { - case EHTokLeftBrace: - return acceptScopedCompoundStatement(statement); - - case EHTokIf: - return acceptSelectionStatement(statement, attributes); - - case EHTokSwitch: - return acceptSwitchStatement(statement, attributes); - - case EHTokFor: - case EHTokDo: - case EHTokWhile: - return acceptIterationStatement(statement, attributes); - - case EHTokContinue: - case EHTokBreak: - case EHTokDiscard: - case EHTokReturn: - return acceptJumpStatement(statement); - - case EHTokCase: - return acceptCaseLabel(statement); - case EHTokDefault: - return acceptDefaultLabel(statement); - - case EHTokRightBrace: - // Performance: not strictly necessary, but stops a bunch of hunting early, - // and is how sequences of statements end. - return false; - - default: - return acceptSimpleStatement(statement); - } - - return true; -} - -// attributes -// : [zero or more:] bracketed-attribute -// -// bracketed-attribute: -// : LEFT_BRACKET scoped-attribute RIGHT_BRACKET -// : LEFT_BRACKET LEFT_BRACKET scoped-attribute RIGHT_BRACKET RIGHT_BRACKET -// -// scoped-attribute: -// : attribute -// | namespace COLON COLON attribute -// -// attribute: -// : UNROLL -// | UNROLL LEFT_PAREN literal RIGHT_PAREN -// | FASTOPT -// | ALLOW_UAV_CONDITION -// | BRANCH -// | FLATTEN -// | FORCECASE -// | CALL -// | DOMAIN -// | EARLYDEPTHSTENCIL -// | INSTANCE -// | MAXTESSFACTOR -// | OUTPUTCONTROLPOINTS -// | OUTPUTTOPOLOGY -// | PARTITIONING -// | PATCHCONSTANTFUNC -// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN -// -void HlslGrammar::acceptAttributes(TAttributes& attributes) -{ - // For now, accept the [ XXX(X) ] syntax, but drop all but - // numthreads, which is used to set the CS local size. - // TODO: subset to correct set? Pass on? - do { - HlslToken attributeToken; - - // LEFT_BRACKET? - if (! acceptTokenClass(EHTokLeftBracket)) - return; - // another LEFT_BRACKET? - bool doubleBrackets = false; - if (acceptTokenClass(EHTokLeftBracket)) - doubleBrackets = true; - - // attribute? (could be namespace; will adjust later) - if (!acceptIdentifier(attributeToken)) { - if (!peekTokenClass(EHTokRightBracket)) { - expected("namespace or attribute identifier"); - advanceToken(); - } - } - - TString nameSpace; - if (acceptTokenClass(EHTokColonColon)) { - // namespace COLON COLON - nameSpace = *attributeToken.string; - // attribute - if (!acceptIdentifier(attributeToken)) { - expected("attribute identifier"); - return; - } - } - - TIntermAggregate* expressions = nullptr; - - // (x, ...) - if (acceptTokenClass(EHTokLeftParen)) { - expressions = new TIntermAggregate; - - TIntermTyped* node; - bool expectingExpression = false; - - while (acceptAssignmentExpression(node)) { - expectingExpression = false; - expressions->getSequence().push_back(node); - if (acceptTokenClass(EHTokComma)) - expectingExpression = true; - } - - // 'expressions' is an aggregate with the expressions in it - if (! acceptTokenClass(EHTokRightParen)) - expected(")"); - - // Error for partial or missing expression - if (expectingExpression || expressions->getSequence().empty()) - expected("expression"); - } - - // RIGHT_BRACKET - if (!acceptTokenClass(EHTokRightBracket)) { - expected("]"); - return; - } - // another RIGHT_BRACKET? - if (doubleBrackets && !acceptTokenClass(EHTokRightBracket)) { - expected("]]"); - return; - } - - // Add any values we found into the attribute map. - if (attributeToken.string != nullptr) { - TAttributeType attributeType = parseContext.attributeFromName(nameSpace, *attributeToken.string); - if (attributeType == EatNone) - parseContext.warn(attributeToken.loc, "unrecognized attribute", attributeToken.string->c_str(), ""); - else { - TAttributeArgs attributeArgs = { attributeType, expressions }; - attributes.push_back(attributeArgs); - } - } - } while (true); -} - -// selection_statement -// : IF LEFT_PAREN expression RIGHT_PAREN statement -// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement -// -bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributes& attributes) -{ - TSourceLoc loc = token.loc; - - // IF - if (! acceptTokenClass(EHTokIf)) - return false; - - // so that something declared in the condition is scoped to the lifetimes - // of the then-else statements - parseContext.pushScope(); - - // LEFT_PAREN expression RIGHT_PAREN - TIntermTyped* condition; - if (! acceptParenExpression(condition)) - return false; - condition = parseContext.convertConditionalExpression(loc, condition); - if (condition == nullptr) - return false; - - // create the child statements - TIntermNodePair thenElse = { nullptr, nullptr }; - - ++parseContext.controlFlowNestingLevel; // this only needs to work right if no errors - - // then statement - if (! acceptScopedStatement(thenElse.node1)) { - expected("then statement"); - return false; - } - - // ELSE - if (acceptTokenClass(EHTokElse)) { - // else statement - if (! acceptScopedStatement(thenElse.node2)) { - expected("else statement"); - return false; - } - } - - // Put the pieces together - statement = intermediate.addSelection(condition, thenElse, loc); - parseContext.handleSelectionAttributes(loc, statement->getAsSelectionNode(), attributes); - - parseContext.popScope(); - --parseContext.controlFlowNestingLevel; - - return true; -} - -// switch_statement -// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement -// -bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributes& attributes) -{ - // SWITCH - TSourceLoc loc = token.loc; - - if (! acceptTokenClass(EHTokSwitch)) - return false; - - // LEFT_PAREN expression RIGHT_PAREN - parseContext.pushScope(); - TIntermTyped* switchExpression; - if (! acceptParenExpression(switchExpression)) { - parseContext.popScope(); - return false; - } - - // compound_statement - parseContext.pushSwitchSequence(new TIntermSequence); - - ++parseContext.controlFlowNestingLevel; - bool statementOkay = acceptCompoundStatement(statement); - --parseContext.controlFlowNestingLevel; - - if (statementOkay) - statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr, - attributes); - - parseContext.popSwitchSequence(); - parseContext.popScope(); - - return statementOkay; -} - -// iteration_statement -// : WHILE LEFT_PAREN condition RIGHT_PAREN statement -// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON -// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement -// -// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen. -bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributes& attributes) -{ - TSourceLoc loc = token.loc; - TIntermTyped* condition = nullptr; - - EHlslTokenClass loop = peek(); - assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile); - - // WHILE or DO or FOR - advanceToken(); - - TIntermLoop* loopNode = nullptr; - switch (loop) { - case EHTokWhile: - // so that something declared in the condition is scoped to the lifetime - // of the while sub-statement - parseContext.pushScope(); // this only needs to work right if no errors - parseContext.nestLooping(); - ++parseContext.controlFlowNestingLevel; - - // LEFT_PAREN condition RIGHT_PAREN - if (! acceptParenExpression(condition)) - return false; - condition = parseContext.convertConditionalExpression(loc, condition); - if (condition == nullptr) - return false; - - // statement - if (! acceptScopedStatement(statement)) { - expected("while sub-statement"); - return false; - } - - parseContext.unnestLooping(); - parseContext.popScope(); - --parseContext.controlFlowNestingLevel; - - loopNode = intermediate.addLoop(statement, condition, nullptr, true, loc); - statement = loopNode; - break; - - case EHTokDo: - parseContext.nestLooping(); // this only needs to work right if no errors - ++parseContext.controlFlowNestingLevel; - - // statement - if (! acceptScopedStatement(statement)) { - expected("do sub-statement"); - return false; - } - - // WHILE - if (! acceptTokenClass(EHTokWhile)) { - expected("while"); - return false; - } - - // LEFT_PAREN condition RIGHT_PAREN - if (! acceptParenExpression(condition)) - return false; - condition = parseContext.convertConditionalExpression(loc, condition); - if (condition == nullptr) - return false; - - if (! acceptTokenClass(EHTokSemicolon)) - expected(";"); - - parseContext.unnestLooping(); - --parseContext.controlFlowNestingLevel; - - loopNode = intermediate.addLoop(statement, condition, nullptr, false, loc); - statement = loopNode; - break; - - case EHTokFor: - { - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) - expected("("); - - // so that something declared in the condition is scoped to the lifetime - // of the for sub-statement - parseContext.pushScope(); - - // initializer - TIntermNode* initNode = nullptr; - if (! acceptSimpleStatement(initNode)) - expected("for-loop initializer statement"); - - parseContext.nestLooping(); // this only needs to work right if no errors - ++parseContext.controlFlowNestingLevel; - - // condition SEMI_COLON - acceptExpression(condition); - if (! acceptTokenClass(EHTokSemicolon)) - expected(";"); - if (condition != nullptr) { - condition = parseContext.convertConditionalExpression(loc, condition); - if (condition == nullptr) - return false; - } - - // iterator SEMI_COLON - TIntermTyped* iterator = nullptr; - acceptExpression(iterator); - if (! acceptTokenClass(EHTokRightParen)) - expected(")"); - - // statement - if (! acceptScopedStatement(statement)) { - expected("for sub-statement"); - return false; - } - - statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, loopNode); - - parseContext.popScope(); - parseContext.unnestLooping(); - --parseContext.controlFlowNestingLevel; - - break; - } - - default: - return false; - } - - parseContext.handleLoopAttributes(loc, loopNode, attributes); - return true; -} - -// jump_statement -// : CONTINUE SEMICOLON -// | BREAK SEMICOLON -// | DISCARD SEMICOLON -// | RETURN SEMICOLON -// | RETURN expression SEMICOLON -// -bool HlslGrammar::acceptJumpStatement(TIntermNode*& statement) -{ - EHlslTokenClass jump = peek(); - switch (jump) { - case EHTokContinue: - case EHTokBreak: - case EHTokDiscard: - case EHTokReturn: - advanceToken(); - break; - default: - // not something we handle in this function - return false; - } - - switch (jump) { - case EHTokContinue: - statement = intermediate.addBranch(EOpContinue, token.loc); - if (parseContext.loopNestingLevel == 0) { - expected("loop"); - return false; - } - break; - case EHTokBreak: - statement = intermediate.addBranch(EOpBreak, token.loc); - if (parseContext.loopNestingLevel == 0 && parseContext.switchSequenceStack.size() == 0) { - expected("loop or switch"); - return false; - } - break; - case EHTokDiscard: - statement = intermediate.addBranch(EOpKill, token.loc); - break; - - case EHTokReturn: - { - // expression - TIntermTyped* node; - if (acceptExpression(node)) { - // hook it up - statement = parseContext.handleReturnValue(token.loc, node); - } else - statement = intermediate.addBranch(EOpReturn, token.loc); - break; - } - - default: - assert(0); - return false; - } - - // SEMICOLON - if (! acceptTokenClass(EHTokSemicolon)) - expected(";"); - - return true; -} - -// case_label -// : CASE expression COLON -// -bool HlslGrammar::acceptCaseLabel(TIntermNode*& statement) -{ - TSourceLoc loc = token.loc; - if (! acceptTokenClass(EHTokCase)) - return false; - - TIntermTyped* expression; - if (! acceptExpression(expression)) { - expected("case expression"); - return false; - } - - if (! acceptTokenClass(EHTokColon)) { - expected(":"); - return false; - } - - statement = parseContext.intermediate.addBranch(EOpCase, expression, loc); - - return true; -} - -// default_label -// : DEFAULT COLON -// -bool HlslGrammar::acceptDefaultLabel(TIntermNode*& statement) -{ - TSourceLoc loc = token.loc; - if (! acceptTokenClass(EHTokDefault)) - return false; - - if (! acceptTokenClass(EHTokColon)) { - expected(":"); - return false; - } - - statement = parseContext.intermediate.addBranch(EOpDefault, loc); - - return true; -} - -// array_specifier -// : LEFT_BRACKET integer_expression RGHT_BRACKET ... // optional -// : LEFT_BRACKET RGHT_BRACKET // optional -// -void HlslGrammar::acceptArraySpecifier(TArraySizes*& arraySizes) -{ - arraySizes = nullptr; - - // Early-out if there aren't any array dimensions - if (!peekTokenClass(EHTokLeftBracket)) - return; - - // If we get here, we have at least one array dimension. This will track the sizes we find. - arraySizes = new TArraySizes; - - // Collect each array dimension. - while (acceptTokenClass(EHTokLeftBracket)) { - TSourceLoc loc = token.loc; - TIntermTyped* sizeExpr = nullptr; - - // Array sizing expression is optional. If omitted, array will be later sized by initializer list. - const bool hasArraySize = acceptAssignmentExpression(sizeExpr); - - if (! acceptTokenClass(EHTokRightBracket)) { - expected("]"); - return; - } - - if (hasArraySize) { - TArraySize arraySize; - parseContext.arraySizeCheck(loc, sizeExpr, arraySize); - arraySizes->addInnerSize(arraySize); - } else { - arraySizes->addInnerSize(0); // sized by initializers. - } - } -} - -// post_decls -// : COLON semantic // optional -// COLON PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN // optional -// COLON REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN // optional -// COLON LAYOUT layout_qualifier_list -// annotations // optional -// -// Return true if any tokens were accepted. That is, -// false can be returned on successfully recognizing nothing, -// not necessarily meaning bad syntax. -// -bool HlslGrammar::acceptPostDecls(TQualifier& qualifier) -{ - bool found = false; - - do { - // COLON - if (acceptTokenClass(EHTokColon)) { - found = true; - HlslToken idToken; - if (peekTokenClass(EHTokLayout)) - acceptLayoutQualifierList(qualifier); - else if (acceptTokenClass(EHTokPackOffset)) { - // PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) { - expected("("); - return false; - } - HlslToken locationToken; - if (! acceptIdentifier(locationToken)) { - expected("c[subcomponent][.component]"); - return false; - } - HlslToken componentToken; - if (acceptTokenClass(EHTokDot)) { - if (! acceptIdentifier(componentToken)) { - expected("component"); - return false; - } - } - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - break; - } - parseContext.handlePackOffset(locationToken.loc, qualifier, *locationToken.string, componentToken.string); - } else if (! acceptIdentifier(idToken)) { - expected("layout, semantic, packoffset, or register"); - return false; - } else if (*idToken.string == "register") { - // REGISTER LEFT_PAREN [shader_profile,] Type#[subcomp]opt (COMMA SPACEN)opt RIGHT_PAREN - // LEFT_PAREN - if (! acceptTokenClass(EHTokLeftParen)) { - expected("("); - return false; - } - HlslToken registerDesc; // for Type# - HlslToken profile; - if (! acceptIdentifier(registerDesc)) { - expected("register number description"); - return false; - } - if (registerDesc.string->size() > 1 && !isdigit((*registerDesc.string)[1]) && - acceptTokenClass(EHTokComma)) { - // Then we didn't really see the registerDesc yet, it was - // actually the profile. Adjust... - profile = registerDesc; - if (! acceptIdentifier(registerDesc)) { - expected("register number description"); - return false; - } - } - int subComponent = 0; - if (acceptTokenClass(EHTokLeftBracket)) { - // LEFT_BRACKET subcomponent RIGHT_BRACKET - if (! peekTokenClass(EHTokIntConstant)) { - expected("literal integer"); - return false; - } - subComponent = token.i; - advanceToken(); - if (! acceptTokenClass(EHTokRightBracket)) { - expected("]"); - break; - } - } - // (COMMA SPACEN)opt - HlslToken spaceDesc; - if (acceptTokenClass(EHTokComma)) { - if (! acceptIdentifier(spaceDesc)) { - expected ("space identifier"); - return false; - } - } - // RIGHT_PAREN - if (! acceptTokenClass(EHTokRightParen)) { - expected(")"); - break; - } - parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string); - } else { - // semantic, in idToken.string - TString semanticUpperCase = *idToken.string; - std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper); - parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(semanticUpperCase.c_str()), semanticUpperCase); - } - } else if (peekTokenClass(EHTokLeftAngle)) { - found = true; - acceptAnnotations(qualifier); - } else - break; - - } while (true); - - return found; -} - -// -// Get the stream of tokens from the scanner, but skip all syntactic/semantic -// processing. -// -bool HlslGrammar::captureBlockTokens(TVector& tokens) -{ - if (! peekTokenClass(EHTokLeftBrace)) - return false; - - int braceCount = 0; - - do { - switch (peek()) { - case EHTokLeftBrace: - ++braceCount; - break; - case EHTokRightBrace: - --braceCount; - break; - case EHTokNone: - // End of input before balance { } is bad... - return false; - default: - break; - } - - tokens.push_back(token); - advanceToken(); - } while (braceCount > 0); - - return true; -} - -// Return a string for just the types that can also be declared as an identifier. -const char* HlslGrammar::getTypeString(EHlslTokenClass tokenClass) const -{ - switch (tokenClass) { - case EHTokSample: return "sample"; - case EHTokHalf: return "half"; - case EHTokHalf1x1: return "half1x1"; - case EHTokHalf1x2: return "half1x2"; - case EHTokHalf1x3: return "half1x3"; - case EHTokHalf1x4: return "half1x4"; - case EHTokHalf2x1: return "half2x1"; - case EHTokHalf2x2: return "half2x2"; - case EHTokHalf2x3: return "half2x3"; - case EHTokHalf2x4: return "half2x4"; - case EHTokHalf3x1: return "half3x1"; - case EHTokHalf3x2: return "half3x2"; - case EHTokHalf3x3: return "half3x3"; - case EHTokHalf3x4: return "half3x4"; - case EHTokHalf4x1: return "half4x1"; - case EHTokHalf4x2: return "half4x2"; - case EHTokHalf4x3: return "half4x3"; - case EHTokHalf4x4: return "half4x4"; - case EHTokBool: return "bool"; - case EHTokFloat: return "float"; - case EHTokDouble: return "double"; - case EHTokInt: return "int"; - case EHTokUint: return "uint"; - case EHTokMin16float: return "min16float"; - case EHTokMin10float: return "min10float"; - case EHTokMin16int: return "min16int"; - case EHTokMin12int: return "min12int"; - case EHTokConstantBuffer: return "ConstantBuffer"; - case EHTokLayout: return "layout"; - default: - return nullptr; - } -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/HLSL/hlslGrammar.h b/3rdparty/glslang/glslang/HLSL/hlslGrammar.h deleted file mode 100644 index cfe294bc..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslGrammar.h +++ /dev/null @@ -1,144 +0,0 @@ -// -// Copyright (C) 2016-2018 Google, Inc. -// Copyright (C) 2016 LunarG, Inc. -// Copyright (C) 2023 Mobica Limited. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef HLSLGRAMMAR_H_ -#define HLSLGRAMMAR_H_ - -#include "hlslParseHelper.h" -#include "hlslOpMap.h" -#include "hlslTokenStream.h" - -namespace glslang { - - class TFunctionDeclarator; - - // Should just be the grammar aspect of HLSL. - // Described in more detail in hlslGrammar.cpp. - - class HlslGrammar : public HlslTokenStream { - public: - HlslGrammar(HlslScanContext& scanner, HlslParseContext& parseContext) - : HlslTokenStream(scanner), parseContext(parseContext), intermediate(parseContext.intermediate), - typeIdentifiers(false), unitNode(nullptr) { } - virtual ~HlslGrammar() { } - - bool parse(); - - protected: - HlslGrammar(); - HlslGrammar& operator=(const HlslGrammar&); - - void expected(const char*); - void unimplemented(const char*); - bool acceptIdentifier(HlslToken&); - bool acceptCompilationUnit(); - bool acceptDeclarationList(TIntermNode*&); - bool acceptDeclaration(TIntermNode*&); - bool acceptControlDeclaration(TIntermNode*& node); - bool acceptSamplerDeclarationDX9(TType&); - bool acceptSamplerState(); - bool acceptFullySpecifiedType(TType&, const TAttributes&); - bool acceptFullySpecifiedType(TType&, TIntermNode*& nodeList, const TAttributes&, bool forbidDeclarators = false); - bool acceptPreQualifier(TQualifier&); - bool acceptPostQualifier(TQualifier&); - bool acceptLayoutQualifierList(TQualifier&); - bool acceptType(TType&); - bool acceptType(TType&, TIntermNode*& nodeList); - bool acceptTemplateVecMatBasicType(TBasicType&, TPrecisionQualifier&); - bool acceptVectorTemplateType(TType&); - bool acceptMatrixTemplateType(TType&); - bool acceptTessellationDeclType(TBuiltInVariable&); - bool acceptTessellationPatchTemplateType(TType&); - bool acceptStreamOutTemplateType(TType&, TLayoutGeometry&); - bool acceptOutputPrimitiveGeometry(TLayoutGeometry&); - bool acceptAnnotations(TQualifier&); - bool acceptSamplerTypeDX9(TType &); - bool acceptSamplerType(TType&); - bool acceptTextureType(TType&); - bool acceptSubpassInputType(TType&); - bool acceptStructBufferType(TType&); - bool acceptTextureBufferType(TType&); - bool acceptConstantBufferType(TType&); - bool acceptStruct(TType&, TIntermNode*& nodeList); - bool acceptStructDeclarationList(TTypeList*&, TIntermNode*& nodeList, TVector&); - bool acceptMemberFunctionDefinition(TIntermNode*& nodeList, const TType&, TString& memberName, - TFunctionDeclarator&); - bool acceptFunctionParameters(TFunction&); - bool acceptParameterDeclaration(TFunction&); - bool acceptFunctionDefinition(TFunctionDeclarator&, TIntermNode*& nodeList, TVector* deferredTokens); - bool acceptFunctionBody(TFunctionDeclarator& declarator, TIntermNode*& nodeList); - bool acceptParenExpression(TIntermTyped*&); - bool acceptExpression(TIntermTyped*&); - bool acceptInitializer(TIntermTyped*&); - bool acceptAssignmentExpression(TIntermTyped*&); - bool acceptConditionalExpression(TIntermTyped*&); - bool acceptBinaryExpression(TIntermTyped*&, PrecedenceLevel); - bool acceptUnaryExpression(TIntermTyped*&); - bool acceptPostfixExpression(TIntermTyped*&); - bool acceptConstructor(TIntermTyped*&); - bool acceptFunctionCall(const TSourceLoc&, TString& name, TIntermTyped*&, TIntermTyped* objectBase); - bool acceptArguments(TFunction*, TIntermTyped*&); - bool acceptLiteral(TIntermTyped*&); - bool acceptSimpleStatement(TIntermNode*&); - bool acceptCompoundStatement(TIntermNode*&); - bool acceptScopedStatement(TIntermNode*&); - bool acceptScopedCompoundStatement(TIntermNode*&); - bool acceptStatement(TIntermNode*&); - bool acceptNestedStatement(TIntermNode*&); - void acceptAttributes(TAttributes&); - bool acceptSelectionStatement(TIntermNode*&, const TAttributes&); - bool acceptSwitchStatement(TIntermNode*&, const TAttributes&); - bool acceptIterationStatement(TIntermNode*&, const TAttributes&); - bool acceptJumpStatement(TIntermNode*&); - bool acceptCaseLabel(TIntermNode*&); - bool acceptDefaultLabel(TIntermNode*&); - void acceptArraySpecifier(TArraySizes*&); - bool acceptPostDecls(TQualifier&); - bool acceptDefaultParameterDeclaration(const TType&, TIntermTyped*&); - - bool captureBlockTokens(TVector& tokens); - const char* getTypeString(EHlslTokenClass tokenClass) const; - - HlslParseContext& parseContext; // state of parsing and helper functions for building the intermediate - TIntermediate& intermediate; // the final product, the intermediate representation, includes the AST - bool typeIdentifiers; // shader uses some types as identifiers - TIntermNode* unitNode; - }; - -} // end namespace glslang - -#endif // HLSLGRAMMAR_H_ diff --git a/3rdparty/glslang/glslang/HLSL/hlslOpMap.cpp b/3rdparty/glslang/glslang/HLSL/hlslOpMap.cpp deleted file mode 100644 index ebe6fbd9..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslOpMap.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// Map from physical token form (e.g. '-') to logical operator -// form (e.g., binary subtract or unary negate). - -#include "hlslOpMap.h" - -namespace glslang { - -// Map parsing tokens that could be assignments into assignment operators. -TOperator HlslOpMap::assignment(EHlslTokenClass op) -{ - switch (op) { - case EHTokAssign: return EOpAssign; - case EHTokMulAssign: return EOpMulAssign; - case EHTokDivAssign: return EOpDivAssign; - case EHTokAddAssign: return EOpAddAssign; - case EHTokModAssign: return EOpModAssign; - case EHTokLeftAssign: return EOpLeftShiftAssign; - case EHTokRightAssign: return EOpRightShiftAssign; - case EHTokAndAssign: return EOpAndAssign; - case EHTokXorAssign: return EOpExclusiveOrAssign; - case EHTokOrAssign: return EOpInclusiveOrAssign; - case EHTokSubAssign: return EOpSubAssign; - - default: - return EOpNull; - } -} - -// Map parsing tokens that could be binary operations into binary operators. -TOperator HlslOpMap::binary(EHlslTokenClass op) -{ - switch (op) { - case EHTokPlus: return EOpAdd; - case EHTokDash: return EOpSub; - case EHTokStar: return EOpMul; - case EHTokSlash: return EOpDiv; - case EHTokPercent: return EOpMod; - case EHTokRightOp: return EOpRightShift; - case EHTokLeftOp: return EOpLeftShift; - case EHTokAmpersand: return EOpAnd; - case EHTokVerticalBar: return EOpInclusiveOr; - case EHTokCaret: return EOpExclusiveOr; - case EHTokEqOp: return EOpEqual; - case EHTokNeOp: return EOpNotEqual; - case EHTokLeftAngle: return EOpLessThan; - case EHTokRightAngle: return EOpGreaterThan; - case EHTokLeOp: return EOpLessThanEqual; - case EHTokGeOp: return EOpGreaterThanEqual; - case EHTokOrOp: return EOpLogicalOr; - case EHTokXorOp: return EOpLogicalXor; - case EHTokAndOp: return EOpLogicalAnd; - - default: - return EOpNull; - } -} - -// Map parsing tokens that could be unary operations into unary operators. -// These are just the ones that can appear in front of its operand. -TOperator HlslOpMap::preUnary(EHlslTokenClass op) -{ - switch (op) { - case EHTokPlus: return EOpAdd; // means no-op, but still a unary op was present - case EHTokDash: return EOpNegative; - case EHTokBang: return EOpLogicalNot; - case EHTokTilde: return EOpBitwiseNot; - - case EHTokIncOp: return EOpPreIncrement; - case EHTokDecOp: return EOpPreDecrement; - - default: return EOpNull; // means not a pre-unary op - } -} - -// Map parsing tokens that could be unary operations into unary operators. -// These are just the ones that can appear behind its operand. -TOperator HlslOpMap::postUnary(EHlslTokenClass op) -{ - switch (op) { - case EHTokDot: return EOpIndexDirectStruct; - case EHTokLeftBracket: return EOpIndexIndirect; - - case EHTokIncOp: return EOpPostIncrement; - case EHTokDecOp: return EOpPostDecrement; - - case EHTokColonColon: return EOpScoping; - - default: return EOpNull; // means not a post-unary op - } -} - -// Map operators into their level of precedence. -PrecedenceLevel HlslOpMap::precedenceLevel(TOperator op) -{ - switch (op) { - case EOpLogicalOr: - return PlLogicalOr; - case EOpLogicalXor: - return PlLogicalXor; - case EOpLogicalAnd: - return PlLogicalAnd; - - case EOpInclusiveOr: - return PlBitwiseOr; - case EOpExclusiveOr: - return PlBitwiseXor; - case EOpAnd: - return PlBitwiseAnd; - - case EOpEqual: - case EOpNotEqual: - return PlEquality; - - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - return PlRelational; - - case EOpRightShift: - case EOpLeftShift: - return PlShift; - - case EOpAdd: - case EOpSub: - return PlAdd; - - case EOpMul: - case EOpDiv: - case EOpMod: - return PlMul; - - default: - return PlBad; - } -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/HLSL/hlslOpMap.h b/3rdparty/glslang/glslang/HLSL/hlslOpMap.h deleted file mode 100644 index 4e783f3f..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslOpMap.h +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef HLSLOPMAP_H_ -#define HLSLOPMAP_H_ - -#include "hlslScanContext.h" - -namespace glslang { - - enum PrecedenceLevel { - PlBad, - PlLogicalOr, - PlLogicalXor, - PlLogicalAnd, - PlBitwiseOr, - PlBitwiseXor, - PlBitwiseAnd, - PlEquality, - PlRelational, - PlShift, - PlAdd, - PlMul - }; - - class HlslOpMap { - public: - static TOperator assignment(EHlslTokenClass op); - static TOperator binary(EHlslTokenClass op); - static TOperator preUnary(EHlslTokenClass op); - static TOperator postUnary(EHlslTokenClass op); - static PrecedenceLevel precedenceLevel(TOperator); - }; - -} // end namespace glslang - -#endif // HLSLOPMAP_H_ diff --git a/3rdparty/glslang/glslang/HLSL/hlslParseHelper.cpp b/3rdparty/glslang/glslang/HLSL/hlslParseHelper.cpp deleted file mode 100644 index b0fb5f46..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslParseHelper.cpp +++ /dev/null @@ -1,10287 +0,0 @@ -// -// Copyright (C) 2017-2018 Google, Inc. -// Copyright (C) 2017 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "hlslParseHelper.h" -#include "hlslScanContext.h" -#include "hlslGrammar.h" -#include "hlslAttributes.h" - -#include "../Include/Common.h" -#include "../MachineIndependent/Scan.h" -#include "../MachineIndependent/preprocessor/PpContext.h" - -#include "../OSDependent/osinclude.h" - -#include -#include -#include -#include -#include - -namespace glslang { - -HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, - int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, - TInfoSink& infoSink, - const TString sourceEntryPointName, - bool forwardCompatible, EShMessages messages) : - TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, - forwardCompatible, messages, &sourceEntryPointName), - annotationNestingLevel(0), - inputPatch(nullptr), - nextInLocation(0), nextOutLocation(0), - entryPointFunction(nullptr), - entryPointFunctionBody(nullptr), - gsStreamOutput(nullptr), - clipDistanceOutput(nullptr), - cullDistanceOutput(nullptr), - clipDistanceInput(nullptr), - cullDistanceInput(nullptr), - parsingEntrypointParameters(false) -{ - globalUniformDefaults.clear(); - globalUniformDefaults.layoutMatrix = ElmRowMajor; - globalUniformDefaults.layoutPacking = ElpStd140; - - globalBufferDefaults.clear(); - globalBufferDefaults.layoutMatrix = ElmRowMajor; - globalBufferDefaults.layoutPacking = ElpStd430; - - globalInputDefaults.clear(); - globalOutputDefaults.clear(); - - clipSemanticNSizeIn.fill(0); - cullSemanticNSizeIn.fill(0); - clipSemanticNSizeOut.fill(0); - cullSemanticNSizeOut.fill(0); - - // "Shaders in the transform - // feedback capturing mode have an initial global default of - // layout(xfb_buffer = 0) out;" - if (language == EShLangVertex || - language == EShLangTessControl || - language == EShLangTessEvaluation || - language == EShLangGeometry) - globalOutputDefaults.layoutXfbBuffer = 0; - - if (language == EShLangGeometry) - globalOutputDefaults.layoutStream = 0; -} - -HlslParseContext::~HlslParseContext() -{ -} - -void HlslParseContext::initializeExtensionBehavior() -{ - TParseContextBase::initializeExtensionBehavior(); - - // HLSL allows #line by default. - extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhEnable; -} - -void HlslParseContext::setLimits(const TBuiltInResource& r) -{ - resources = r; - intermediate.setLimits(resources); -} - -// -// Parse an array of strings using the parser in HlslRules. -// -// Returns true for successful acceptance of the shader, false if any errors. -// -bool HlslParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner& input, bool versionWillBeError) -{ - currentScanner = &input; - ppContext.setInput(input, versionWillBeError); - - HlslScanContext scanContext(*this, ppContext); - HlslGrammar grammar(scanContext, *this); - if (!grammar.parse()) { - // Print a message formated such that if you click on the message it will take you right to - // the line through most UIs. - const glslang::TSourceLoc& sourceLoc = input.getSourceLoc(); - infoSink.info << sourceLoc.getFilenameStr() << "(" << sourceLoc.line << "): error at column " << sourceLoc.column - << ", HLSL parsing failed.\n"; - ++numErrors; - return false; - } - - finish(); - - return numErrors == 0; -} - -// -// Return true if this l-value node should be converted in some manner. -// For instance: turning a load aggregate into a store in an l-value. -// -bool HlslParseContext::shouldConvertLValue(const TIntermNode* node) const -{ - if (node == nullptr || node->getAsTyped() == nullptr) - return false; - - const TIntermAggregate* lhsAsAggregate = node->getAsAggregate(); - const TIntermBinary* lhsAsBinary = node->getAsBinaryNode(); - - // If it's a swizzled/indexed aggregate, look at the left node instead. - if (lhsAsBinary != nullptr && - (lhsAsBinary->getOp() == EOpVectorSwizzle || lhsAsBinary->getOp() == EOpIndexDirect)) - lhsAsAggregate = lhsAsBinary->getLeft()->getAsAggregate(); - if (lhsAsAggregate != nullptr && lhsAsAggregate->getOp() == EOpImageLoad) - return true; - - return false; -} - -void HlslParseContext::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, - TTypeList* newTypeList) -{ - newTypeList = nullptr; - correctUniform(memberType.getQualifier()); - if (memberType.isStruct()) { - auto it = ioTypeMap.find(memberType.getStruct()); - if (it != ioTypeMap.end() && it->second.uniform) - newTypeList = it->second.uniform; - } - TParseContextBase::growGlobalUniformBlock(loc, memberType, memberName, newTypeList); -} - -// -// Return a TLayoutFormat corresponding to the given texture type. -// -TLayoutFormat HlslParseContext::getLayoutFromTxType(const TSourceLoc& loc, const TType& txType) -{ - if (txType.isStruct()) { - // TODO: implement. - error(loc, "unimplemented: structure type in image or buffer", "", ""); - return ElfNone; - } - - const int components = txType.getVectorSize(); - const TBasicType txBasicType = txType.getBasicType(); - - const auto selectFormat = [this,&components](TLayoutFormat v1, TLayoutFormat v2, TLayoutFormat v4) -> TLayoutFormat { - if (intermediate.getNoStorageFormat()) - return ElfNone; - - return components == 1 ? v1 : - components == 2 ? v2 : v4; - }; - - switch (txBasicType) { - case EbtFloat: return selectFormat(ElfR32f, ElfRg32f, ElfRgba32f); - case EbtInt: return selectFormat(ElfR32i, ElfRg32i, ElfRgba32i); - case EbtUint: return selectFormat(ElfR32ui, ElfRg32ui, ElfRgba32ui); - default: - error(loc, "unknown basic type in image format", "", ""); - return ElfNone; - } -} - -// -// Both test and if necessary, spit out an error, to see if the node is really -// an l-value that can be operated on this way. -// -// Returns true if there was an error. -// -bool HlslParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) -{ - if (shouldConvertLValue(node)) { - // if we're writing to a texture, it must be an RW form. - - TIntermAggregate* lhsAsAggregate = node->getAsAggregate(); - TIntermTyped* object = lhsAsAggregate->getSequence()[0]->getAsTyped(); - - if (!object->getType().getSampler().isImage()) { - error(loc, "operator[] on a non-RW texture must be an r-value", "", ""); - return true; - } - } - - // We tolerate samplers as l-values, even though they are nominally - // illegal, because we expect a later optimization to eliminate them. - if (node->getType().getBasicType() == EbtSampler) { - intermediate.setNeedsLegalization(); - return false; - } - - // Let the base class check errors - return TParseContextBase::lValueErrorCheck(loc, op, node); -} - -// -// This function handles l-value conversions and verifications. It uses, but is not synonymous -// with lValueErrorCheck. That function accepts an l-value directly, while this one must be -// given the surrounding tree - e.g, with an assignment, so we can convert the assign into a -// series of other image operations. -// -// Most things are passed through unmodified, except for error checking. -// -TIntermTyped* HlslParseContext::handleLvalue(const TSourceLoc& loc, const char* op, TIntermTyped*& node) -{ - if (node == nullptr) - return nullptr; - - TIntermBinary* nodeAsBinary = node->getAsBinaryNode(); - TIntermUnary* nodeAsUnary = node->getAsUnaryNode(); - TIntermAggregate* sequence = nullptr; - - TIntermTyped* lhs = nodeAsUnary ? nodeAsUnary->getOperand() : - nodeAsBinary ? nodeAsBinary->getLeft() : - nullptr; - - // Early bail out if there is no conversion to apply - if (!shouldConvertLValue(lhs)) { - if (lhs != nullptr) - if (lValueErrorCheck(loc, op, lhs)) - return nullptr; - return node; - } - - // *** If we get here, we're going to apply some conversion to an l-value. - - // Helper to create a load. - const auto makeLoad = [&](TIntermSymbol* rhsTmp, TIntermTyped* object, TIntermTyped* coord, const TType& derefType) { - TIntermAggregate* loadOp = new TIntermAggregate(EOpImageLoad); - loadOp->setLoc(loc); - loadOp->getSequence().push_back(object); - loadOp->getSequence().push_back(intermediate.addSymbol(*coord->getAsSymbolNode())); - loadOp->setType(derefType); - - sequence = intermediate.growAggregate(sequence, - intermediate.addAssign(EOpAssign, rhsTmp, loadOp, loc), - loc); - }; - - // Helper to create a store. - const auto makeStore = [&](TIntermTyped* object, TIntermTyped* coord, TIntermSymbol* rhsTmp) { - TIntermAggregate* storeOp = new TIntermAggregate(EOpImageStore); - storeOp->getSequence().push_back(object); - storeOp->getSequence().push_back(coord); - storeOp->getSequence().push_back(intermediate.addSymbol(*rhsTmp)); - storeOp->setLoc(loc); - storeOp->setType(TType(EbtVoid)); - - sequence = intermediate.growAggregate(sequence, storeOp); - }; - - // Helper to create an assign. - const auto makeBinary = [&](TOperator op, TIntermTyped* lhs, TIntermTyped* rhs) { - sequence = intermediate.growAggregate(sequence, - intermediate.addBinaryNode(op, lhs, rhs, loc, lhs->getType()), - loc); - }; - - // Helper to complete sequence by adding trailing variable, so we evaluate to the right value. - const auto finishSequence = [&](TIntermSymbol* rhsTmp, const TType& derefType) -> TIntermAggregate* { - // Add a trailing use of the temp, so the sequence returns the proper value. - sequence = intermediate.growAggregate(sequence, intermediate.addSymbol(*rhsTmp)); - sequence->setOperator(EOpSequence); - sequence->setLoc(loc); - sequence->setType(derefType); - - return sequence; - }; - - // Helper to add unary op - const auto makeUnary = [&](TOperator op, TIntermSymbol* rhsTmp) { - sequence = intermediate.growAggregate(sequence, - intermediate.addUnaryNode(op, intermediate.addSymbol(*rhsTmp), loc, - rhsTmp->getType()), - loc); - }; - - // Return true if swizzle or index writes all components of the given variable. - const auto writesAllComponents = [&](TIntermSymbol* var, TIntermBinary* swizzle) -> bool { - if (swizzle == nullptr) // not a swizzle or index - return true; - - // Track which components are being set. - std::array compIsSet; - compIsSet.fill(false); - - const TIntermConstantUnion* asConst = swizzle->getRight()->getAsConstantUnion(); - const TIntermAggregate* asAggregate = swizzle->getRight()->getAsAggregate(); - - // This could be either a direct index, or a swizzle. - if (asConst) { - compIsSet[asConst->getConstArray()[0].getIConst()] = true; - } else if (asAggregate) { - const TIntermSequence& seq = asAggregate->getSequence(); - for (int comp=0; compgetAsConstantUnion()->getConstArray()[0].getIConst()] = true; - } else { - assert(0); - } - - // Return true if all components are being set by the index or swizzle - return std::all_of(compIsSet.begin(), compIsSet.begin() + var->getType().getVectorSize(), - [](bool isSet) { return isSet; } ); - }; - - // Create swizzle matching input swizzle - const auto addSwizzle = [&](TIntermSymbol* var, TIntermBinary* swizzle) -> TIntermTyped* { - if (swizzle) - return intermediate.addBinaryNode(swizzle->getOp(), var, swizzle->getRight(), loc, swizzle->getType()); - else - return var; - }; - - TIntermBinary* lhsAsBinary = lhs->getAsBinaryNode(); - TIntermAggregate* lhsAsAggregate = lhs->getAsAggregate(); - bool lhsIsSwizzle = false; - - // If it's a swizzled L-value, remember the swizzle, and use the LHS. - if (lhsAsBinary != nullptr && (lhsAsBinary->getOp() == EOpVectorSwizzle || lhsAsBinary->getOp() == EOpIndexDirect)) { - lhsAsAggregate = lhsAsBinary->getLeft()->getAsAggregate(); - lhsIsSwizzle = true; - } - - TIntermTyped* object = lhsAsAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* coord = lhsAsAggregate->getSequence()[1]->getAsTyped(); - - const TSampler& texSampler = object->getType().getSampler(); - - TType objDerefType; - getTextureReturnType(texSampler, objDerefType); - - if (nodeAsBinary) { - TIntermTyped* rhs = nodeAsBinary->getRight(); - const TOperator assignOp = nodeAsBinary->getOp(); - - bool isModifyOp = false; - - switch (assignOp) { - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - case EOpModAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - case EOpLeftShiftAssign: - case EOpRightShiftAssign: - isModifyOp = true; - // fall through... - case EOpAssign: - { - // Since this is an lvalue, we'll convert an image load to a sequence like this - // (to still provide the value): - // OpSequence - // OpImageStore(object, lhs, rhs) - // rhs - // But if it's not a simple symbol RHS (say, a fn call), we don't want to duplicate the RHS, - // so we'll convert instead to this: - // OpSequence - // rhsTmp = rhs - // OpImageStore(object, coord, rhsTmp) - // rhsTmp - // If this is a read-modify-write op, like +=, we issue: - // OpSequence - // coordtmp = load's param1 - // rhsTmp = OpImageLoad(object, coordTmp) - // rhsTmp op= rhs - // OpImageStore(object, coordTmp, rhsTmp) - // rhsTmp - // - // If the lvalue is swizzled, we apply that when writing the temp variable, like so: - // ... - // rhsTmp.some_swizzle = ... - // For partial writes, an error is generated. - - TIntermSymbol* rhsTmp = rhs->getAsSymbolNode(); - TIntermTyped* coordTmp = coord; - - if (rhsTmp == nullptr || isModifyOp || lhsIsSwizzle) { - rhsTmp = makeInternalVariableNode(loc, "storeTemp", objDerefType); - - // Partial updates not yet supported - if (!writesAllComponents(rhsTmp, lhsAsBinary)) { - error(loc, "unimplemented: partial image updates", "", ""); - } - - // Assign storeTemp = rhs - if (isModifyOp) { - // We have to make a temp var for the coordinate, to avoid evaluating it twice. - coordTmp = makeInternalVariableNode(loc, "coordTemp", coord->getType()); - makeBinary(EOpAssign, coordTmp, coord); // coordtmp = load[param1] - makeLoad(rhsTmp, object, coordTmp, objDerefType); // rhsTmp = OpImageLoad(object, coordTmp) - } - - // rhsTmp op= rhs. - makeBinary(assignOp, addSwizzle(intermediate.addSymbol(*rhsTmp), lhsAsBinary), rhs); - } - - makeStore(object, coordTmp, rhsTmp); // add a store - return finishSequence(rhsTmp, objDerefType); // return rhsTmp from sequence - } - - default: - break; - } - } - - if (nodeAsUnary) { - const TOperator assignOp = nodeAsUnary->getOp(); - - switch (assignOp) { - case EOpPreIncrement: - case EOpPreDecrement: - { - // We turn this into: - // OpSequence - // coordtmp = load's param1 - // rhsTmp = OpImageLoad(object, coordTmp) - // rhsTmp op - // OpImageStore(object, coordTmp, rhsTmp) - // rhsTmp - - TIntermSymbol* rhsTmp = makeInternalVariableNode(loc, "storeTemp", objDerefType); - TIntermTyped* coordTmp = makeInternalVariableNode(loc, "coordTemp", coord->getType()); - - makeBinary(EOpAssign, coordTmp, coord); // coordtmp = load[param1] - makeLoad(rhsTmp, object, coordTmp, objDerefType); // rhsTmp = OpImageLoad(object, coordTmp) - makeUnary(assignOp, rhsTmp); // op rhsTmp - makeStore(object, coordTmp, rhsTmp); // OpImageStore(object, coordTmp, rhsTmp) - return finishSequence(rhsTmp, objDerefType); // return rhsTmp from sequence - } - - case EOpPostIncrement: - case EOpPostDecrement: - { - // We turn this into: - // OpSequence - // coordtmp = load's param1 - // rhsTmp1 = OpImageLoad(object, coordTmp) - // rhsTmp2 = rhsTmp1 - // rhsTmp2 op - // OpImageStore(object, coordTmp, rhsTmp2) - // rhsTmp1 (pre-op value) - TIntermSymbol* rhsTmp1 = makeInternalVariableNode(loc, "storeTempPre", objDerefType); - TIntermSymbol* rhsTmp2 = makeInternalVariableNode(loc, "storeTempPost", objDerefType); - TIntermTyped* coordTmp = makeInternalVariableNode(loc, "coordTemp", coord->getType()); - - makeBinary(EOpAssign, coordTmp, coord); // coordtmp = load[param1] - makeLoad(rhsTmp1, object, coordTmp, objDerefType); // rhsTmp1 = OpImageLoad(object, coordTmp) - makeBinary(EOpAssign, rhsTmp2, rhsTmp1); // rhsTmp2 = rhsTmp1 - makeUnary(assignOp, rhsTmp2); // rhsTmp op - makeStore(object, coordTmp, rhsTmp2); // OpImageStore(object, coordTmp, rhsTmp2) - return finishSequence(rhsTmp1, objDerefType); // return rhsTmp from sequence - } - - default: - break; - } - } - - if (lhs) - if (lValueErrorCheck(loc, op, lhs)) - return nullptr; - - return node; -} - -void HlslParseContext::handlePragma(const TSourceLoc& loc, const TVector& tokens) -{ - if (pragmaCallback) - pragmaCallback(loc.line, tokens); - - if (tokens.size() == 0) - return; - - // These pragmas are case insensitive in HLSL, so we'll compare in lower case. - TVector lowerTokens = tokens; - - for (auto it = lowerTokens.begin(); it != lowerTokens.end(); ++it) - std::transform(it->begin(), it->end(), it->begin(), ::tolower); - - // Handle pack_matrix - if (tokens.size() == 4 && lowerTokens[0] == "pack_matrix" && tokens[1] == "(" && tokens[3] == ")") { - // Note that HLSL semantic order is Mrc, not Mcr like SPIR-V, so we reverse the sense. - // Row major becomes column major and vice versa. - - if (lowerTokens[2] == "row_major") { - globalUniformDefaults.layoutMatrix = globalBufferDefaults.layoutMatrix = ElmColumnMajor; - } else if (lowerTokens[2] == "column_major") { - globalUniformDefaults.layoutMatrix = globalBufferDefaults.layoutMatrix = ElmRowMajor; - } else { - // unknown majorness strings are treated as (HLSL column major)==(SPIR-V row major) - warn(loc, "unknown pack_matrix pragma value", tokens[2].c_str(), ""); - globalUniformDefaults.layoutMatrix = globalBufferDefaults.layoutMatrix = ElmRowMajor; - } - return; - } - - // Handle once - if (lowerTokens[0] == "once") { - warn(loc, "not implemented", "#pragma once", ""); - return; - } -} - -// -// Look at a '.' matrix selector string and change it into components -// for a matrix. There are two types: -// -// _21 second row, first column (one based) -// _m21 third row, second column (zero based) -// -// Returns true if there is no error. -// -bool HlslParseContext::parseMatrixSwizzleSelector(const TSourceLoc& loc, const TString& fields, int cols, int rows, - TSwizzleSelectors& components) -{ - int startPos[MaxSwizzleSelectors]; - int numComps = 0; - TString compString = fields; - - // Find where each component starts, - // recording the first character position after the '_'. - for (size_t c = 0; c < compString.size(); ++c) { - if (compString[c] == '_') { - if (numComps >= MaxSwizzleSelectors) { - error(loc, "matrix component swizzle has too many components", compString.c_str(), ""); - return false; - } - if (c > compString.size() - 3 || - ((compString[c+1] == 'm' || compString[c+1] == 'M') && c > compString.size() - 4)) { - error(loc, "matrix component swizzle missing", compString.c_str(), ""); - return false; - } - startPos[numComps++] = (int)c + 1; - } - } - - // Process each component - for (int i = 0; i < numComps; ++i) { - int pos = startPos[i]; - int bias = -1; - if (compString[pos] == 'm' || compString[pos] == 'M') { - bias = 0; - ++pos; - } - TMatrixSelector comp; - comp.coord1 = compString[pos+0] - '0' + bias; - comp.coord2 = compString[pos+1] - '0' + bias; - if (comp.coord1 < 0 || comp.coord1 >= cols) { - error(loc, "matrix row component out of range", compString.c_str(), ""); - return false; - } - if (comp.coord2 < 0 || comp.coord2 >= rows) { - error(loc, "matrix column component out of range", compString.c_str(), ""); - return false; - } - components.push_back(comp); - } - - return true; -} - -// If the 'comps' express a column of a matrix, -// return the column. Column means the first coords all match. -// -// Otherwise, return -1. -// -int HlslParseContext::getMatrixComponentsColumn(int rows, const TSwizzleSelectors& selector) -{ - int col = -1; - - // right number of comps? - if (selector.size() != rows) - return -1; - - // all comps in the same column? - // rows in order? - col = selector[0].coord1; - for (int i = 0; i < rows; ++i) { - if (col != selector[i].coord1) - return -1; - if (i != selector[i].coord2) - return -1; - } - - return col; -} - -// -// Handle seeing a variable identifier in the grammar. -// -TIntermTyped* HlslParseContext::handleVariable(const TSourceLoc& loc, const TString* string) -{ - int thisDepth; - TSymbol* symbol = symbolTable.find(*string, thisDepth); - if (symbol && symbol->getAsVariable() && symbol->getAsVariable()->isUserType()) { - error(loc, "expected symbol, not user-defined type", string->c_str(), ""); - return nullptr; - } - - const TVariable* variable = nullptr; - const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : nullptr; - TIntermTyped* node = nullptr; - if (anon) { - // It was a member of an anonymous container, which could be a 'this' structure. - - // Create a subtree for its dereference. - if (thisDepth > 0) { - variable = getImplicitThis(thisDepth); - if (variable == nullptr) - error(loc, "cannot access member variables (static member function?)", "this", ""); - } - if (variable == nullptr) - variable = anon->getAnonContainer().getAsVariable(); - - TIntermTyped* container = intermediate.addSymbol(*variable, loc); - TIntermTyped* constNode = intermediate.addConstantUnion(anon->getMemberNumber(), loc); - node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc); - - node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type); - if (node->getType().hiddenMember()) - error(loc, "member of nameless block was not redeclared", string->c_str(), ""); - } else { - // Not a member of an anonymous container. - - // The symbol table search was done in the lexical phase. - // See if it was a variable. - variable = symbol ? symbol->getAsVariable() : nullptr; - if (variable) { - if ((variable->getType().getBasicType() == EbtBlock || - variable->getType().getBasicType() == EbtStruct) && variable->getType().getStruct() == nullptr) { - error(loc, "cannot be used (maybe an instance name is needed)", string->c_str(), ""); - variable = nullptr; - } - } else { - if (symbol) - error(loc, "variable name expected", string->c_str(), ""); - } - - // Recovery, if it wasn't found or was not a variable. - if (variable == nullptr) { - error(loc, "unknown variable", string->c_str(), ""); - variable = new TVariable(string, TType(EbtVoid)); - } - - if (variable->getType().getQualifier().isFrontEndConstant()) - node = intermediate.addConstantUnion(variable->getConstArray(), variable->getType(), loc); - else - node = intermediate.addSymbol(*variable, loc); - } - - if (variable->getType().getQualifier().isIo()) - intermediate.addIoAccessed(*string); - - return node; -} - -// -// Handle operator[] on any objects it applies to. Currently: -// Textures -// Buffers -// -TIntermTyped* HlslParseContext::handleBracketOperator(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index) -{ - // handle r-value operator[] on textures and images. l-values will be processed later. - if (base->getType().getBasicType() == EbtSampler && !base->isArray()) { - const TSampler& sampler = base->getType().getSampler(); - if (sampler.isImage() || sampler.isTexture()) { - if (! mipsOperatorMipArg.empty() && mipsOperatorMipArg.back().mipLevel == nullptr) { - // The first operator[] to a .mips[] sequence is the mip level. We'll remember it. - mipsOperatorMipArg.back().mipLevel = index; - return base; // next [] index is to the same base. - } else { - TIntermAggregate* load = new TIntermAggregate(sampler.isImage() ? EOpImageLoad : EOpTextureFetch); - - TType sampReturnType; - getTextureReturnType(sampler, sampReturnType); - - load->setType(sampReturnType); - load->setLoc(loc); - load->getSequence().push_back(base); - load->getSequence().push_back(index); - - // Textures need a MIP. If we saw one go by, use it. Otherwise, use zero. - if (sampler.isTexture()) { - if (! mipsOperatorMipArg.empty()) { - load->getSequence().push_back(mipsOperatorMipArg.back().mipLevel); - mipsOperatorMipArg.pop_back(); - } else { - load->getSequence().push_back(intermediate.addConstantUnion(0, loc, true)); - } - } - - return load; - } - } - } - - // Handle operator[] on structured buffers: this indexes into the array element of the buffer. - // indexStructBufferContent returns nullptr if it isn't a structuredbuffer (SSBO). - TIntermTyped* sbArray = indexStructBufferContent(loc, base); - if (sbArray != nullptr) { - // Now we'll apply the [] index to that array - const TOperator idxOp = (index->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect; - - TIntermTyped* element = intermediate.addIndex(idxOp, sbArray, index, loc); - const TType derefType(sbArray->getType(), 0); - element->setType(derefType); - return element; - } - - return nullptr; -} - -// -// Cast index value to a uint if it isn't already (for operator[], load indexes, etc) -TIntermTyped* HlslParseContext::makeIntegerIndex(TIntermTyped* index) -{ - const TBasicType indexBasicType = index->getType().getBasicType(); - const int vecSize = index->getType().getVectorSize(); - - // We can use int types directly as the index - if (indexBasicType == EbtInt || indexBasicType == EbtUint || - indexBasicType == EbtInt64 || indexBasicType == EbtUint64) - return index; - - // Cast index to unsigned integer if it isn't one. - return intermediate.addConversion(EOpConstructUint, TType(EbtUint, EvqTemporary, vecSize), index); -} - -// -// Handle seeing a base[index] dereference in the grammar. -// -TIntermTyped* HlslParseContext::handleBracketDereference(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index) -{ - index = makeIntegerIndex(index); - - if (index == nullptr) { - error(loc, " unknown index type ", "", ""); - return nullptr; - } - - TIntermTyped* result = handleBracketOperator(loc, base, index); - - if (result != nullptr) - return result; // it was handled as an operator[] - - bool flattened = false; - int indexValue = 0; - if (index->getQualifier().isFrontEndConstant()) - indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst(); - - variableCheck(base); - if (! base->isArray() && ! base->isMatrix() && ! base->isVector()) { - if (base->getAsSymbolNode()) - error(loc, " left of '[' is not of type array, matrix, or vector ", - base->getAsSymbolNode()->getName().c_str(), ""); - else - error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", ""); - } else if (base->getType().getQualifier().isFrontEndConstant() && - index->getQualifier().isFrontEndConstant()) { - // both base and index are front-end constants - checkIndex(loc, base->getType(), indexValue); - return intermediate.foldDereference(base, indexValue, loc); - } else { - // at least one of base and index is variable... - - if (index->getQualifier().isFrontEndConstant()) - checkIndex(loc, base->getType(), indexValue); - - if (base->getType().isScalarOrVec1()) - result = base; - else if (base->getAsSymbolNode() && wasFlattened(base)) { - if (index->getQualifier().storage != EvqConst) - error(loc, "Invalid variable index to flattened array", base->getAsSymbolNode()->getName().c_str(), ""); - - result = flattenAccess(base, indexValue); - flattened = (result != base); - } else { - if (index->getQualifier().isFrontEndConstant()) { - if (base->getType().isUnsizedArray()) - base->getWritableType().updateImplicitArraySize(indexValue + 1); - else - checkIndex(loc, base->getType(), indexValue); - result = intermediate.addIndex(EOpIndexDirect, base, index, loc); - } else - result = intermediate.addIndex(EOpIndexIndirect, base, index, loc); - } - } - - if (result == nullptr) { - // Insert dummy error-recovery result - result = intermediate.addConstantUnion(0.0, EbtFloat, loc); - } else { - // If the array reference was flattened, it has the correct type. E.g, if it was - // a uniform array, it was flattened INTO a set of scalar uniforms, not scalar temps. - // In that case, we preserve the qualifiers. - if (!flattened) { - // Insert valid dereferenced result - TType newType(base->getType(), 0); // dereferenced type - if (base->getType().getQualifier().storage == EvqConst && index->getQualifier().storage == EvqConst) - newType.getQualifier().storage = EvqConst; - else - newType.getQualifier().storage = EvqTemporary; - result->setType(newType); - } - } - - return result; -} - -// Handle seeing a binary node with a math operation. -TIntermTyped* HlslParseContext::handleBinaryMath(const TSourceLoc& loc, const char* str, TOperator op, - TIntermTyped* left, TIntermTyped* right) -{ - TIntermTyped* result = intermediate.addBinaryMath(op, left, right, loc); - if (result == nullptr) - binaryOpError(loc, str, left->getCompleteString(), right->getCompleteString()); - - return result; -} - -// Handle seeing a unary node with a math operation. -TIntermTyped* HlslParseContext::handleUnaryMath(const TSourceLoc& loc, const char* str, TOperator op, - TIntermTyped* childNode) -{ - TIntermTyped* result = intermediate.addUnaryMath(op, childNode, loc); - - if (result) - return result; - else - unaryOpError(loc, str, childNode->getCompleteString()); - - return childNode; -} -// -// Return true if the name is a struct buffer method -// -bool HlslParseContext::isStructBufferMethod(const TString& name) const -{ - return - name == "GetDimensions" || - name == "Load" || - name == "Load2" || - name == "Load3" || - name == "Load4" || - name == "Store" || - name == "Store2" || - name == "Store3" || - name == "Store4" || - name == "InterlockedAdd" || - name == "InterlockedAnd" || - name == "InterlockedCompareExchange" || - name == "InterlockedCompareStore" || - name == "InterlockedExchange" || - name == "InterlockedMax" || - name == "InterlockedMin" || - name == "InterlockedOr" || - name == "InterlockedXor" || - name == "IncrementCounter" || - name == "DecrementCounter" || - name == "Append" || - name == "Consume"; -} - -// -// Handle seeing a base.field dereference in the grammar, where 'field' is a -// swizzle or member variable. -// -TIntermTyped* HlslParseContext::handleDotDereference(const TSourceLoc& loc, TIntermTyped* base, const TString& field) -{ - variableCheck(base); - - if (base->isArray()) { - error(loc, "cannot apply to an array:", ".", field.c_str()); - return base; - } - - TIntermTyped* result = base; - - if (base->getType().getBasicType() == EbtSampler) { - // Handle .mips[mipid][pos] operation on textures - const TSampler& sampler = base->getType().getSampler(); - if (sampler.isTexture() && field == "mips") { - // Push a null to signify that we expect a mip level under operator[] next. - mipsOperatorMipArg.push_back(tMipsOperatorData(loc, nullptr)); - // Keep 'result' pointing to 'base', since we expect an operator[] to go by next. - } else { - if (field == "mips") - error(loc, "unexpected texture type for .mips[][] operator:", - base->getType().getCompleteString().c_str(), ""); - else - error(loc, "unexpected operator on texture type:", field.c_str(), - base->getType().getCompleteString().c_str()); - } - } else if (base->isVector() || base->isScalar()) { - TSwizzleSelectors selectors; - parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); - - if (base->isScalar()) { - if (selectors.size() == 1) - return result; - else { - TType type(base->getBasicType(), EvqTemporary, selectors.size()); - return addConstructor(loc, base, type); - } - } - if (base->getVectorSize() == 1) { - TType scalarType(base->getBasicType(), EvqTemporary, 1); - if (selectors.size() == 1) - return addConstructor(loc, base, scalarType); - else { - TType vectorType(base->getBasicType(), EvqTemporary, selectors.size()); - return addConstructor(loc, addConstructor(loc, base, scalarType), vectorType); - } - } - - if (base->getType().getQualifier().isFrontEndConstant()) - result = intermediate.foldSwizzle(base, selectors, loc); - else { - if (selectors.size() == 1) { - TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc); - result = intermediate.addIndex(EOpIndexDirect, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary)); - } else { - TIntermTyped* index = intermediate.addSwizzle(selectors, loc); - result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, - selectors.size())); - } - } - } else if (base->isMatrix()) { - TSwizzleSelectors selectors; - if (! parseMatrixSwizzleSelector(loc, field, base->getMatrixCols(), base->getMatrixRows(), selectors)) - return result; - - if (selectors.size() == 1) { - // Representable by m[c][r] - if (base->getType().getQualifier().isFrontEndConstant()) { - result = intermediate.foldDereference(base, selectors[0].coord1, loc); - result = intermediate.foldDereference(result, selectors[0].coord2, loc); - } else { - result = intermediate.addIndex(EOpIndexDirect, base, - intermediate.addConstantUnion(selectors[0].coord1, loc), - loc); - TType dereferencedCol(base->getType(), 0); - result->setType(dereferencedCol); - result = intermediate.addIndex(EOpIndexDirect, result, - intermediate.addConstantUnion(selectors[0].coord2, loc), - loc); - TType dereferenced(dereferencedCol, 0); - result->setType(dereferenced); - } - } else { - int column = getMatrixComponentsColumn(base->getMatrixRows(), selectors); - if (column >= 0) { - // Representable by m[c] - if (base->getType().getQualifier().isFrontEndConstant()) - result = intermediate.foldDereference(base, column, loc); - else { - result = intermediate.addIndex(EOpIndexDirect, base, intermediate.addConstantUnion(column, loc), - loc); - TType dereferenced(base->getType(), 0); - result->setType(dereferenced); - } - } else { - // general case, not a column, not a single component - TIntermTyped* index = intermediate.addSwizzle(selectors, loc); - result = intermediate.addIndex(EOpMatrixSwizzle, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, - selectors.size())); - } - } - } else if (base->getBasicType() == EbtStruct || base->getBasicType() == EbtBlock) { - const TTypeList* fields = base->getType().getStruct(); - bool fieldFound = false; - int member; - for (member = 0; member < (int)fields->size(); ++member) { - if ((*fields)[member].type->getFieldName() == field) { - fieldFound = true; - break; - } - } - if (fieldFound) { - if (base->getAsSymbolNode() && wasFlattened(base)) { - result = flattenAccess(base, member); - } else { - if (base->getType().getQualifier().storage == EvqConst) - result = intermediate.foldDereference(base, member, loc); - else { - TIntermTyped* index = intermediate.addConstantUnion(member, loc); - result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc); - result->setType(*(*fields)[member].type); - } - } - } else - error(loc, "no such field in structure", field.c_str(), ""); - } else - error(loc, "does not apply to this type:", field.c_str(), base->getType().getCompleteString().c_str()); - - return result; -} - -// -// Return true if the field should be treated as a built-in method. -// Return false otherwise. -// -bool HlslParseContext::isBuiltInMethod(const TSourceLoc&, TIntermTyped* base, const TString& field) -{ - if (base == nullptr) - return false; - - variableCheck(base); - - if (base->getType().getBasicType() == EbtSampler) { - return true; - } else if (isStructBufferType(base->getType()) && isStructBufferMethod(field)) { - return true; - } else if (field == "Append" || - field == "RestartStrip") { - // We cannot check the type here: it may be sanitized if we're not compiling a geometry shader, but - // the code is around in the shader source. - return true; - } else - return false; -} - -// Independently establish a built-in that is a member of a structure. -// 'arraySizes' are what's desired for the independent built-in, whatever -// the higher-level source/expression of them was. -void HlslParseContext::splitBuiltIn(const TString& baseName, const TType& memberType, const TArraySizes* arraySizes, - const TQualifier& outerQualifier) -{ - // Because of arrays of structs, we might be asked more than once, - // but the arraySizes passed in should have captured the whole thing - // the first time. - // However, clip/cull rely on multiple updates. - if (!isClipOrCullDistance(memberType)) - if (splitBuiltIns.find(tInterstageIoData(memberType.getQualifier().builtIn, outerQualifier.storage)) != - splitBuiltIns.end()) - return; - - TVariable* ioVar = makeInternalVariable(baseName + "." + memberType.getFieldName(), memberType); - - if (arraySizes != nullptr && !memberType.isArray()) - ioVar->getWritableType().copyArraySizes(*arraySizes); - - splitBuiltIns[tInterstageIoData(memberType.getQualifier().builtIn, outerQualifier.storage)] = ioVar; - if (!isClipOrCullDistance(ioVar->getType())) - trackLinkage(*ioVar); - - // Merge qualifier from the user structure - mergeQualifiers(ioVar->getWritableType().getQualifier(), outerQualifier); - - // Fix the builtin type if needed (e.g, some types require fixed array sizes, no matter how the - // shader declared them). This is done after mergeQualifiers(), in case fixBuiltInIoType looks - // at the qualifier to determine e.g, in or out qualifications. - fixBuiltInIoType(ioVar->getWritableType()); - - // But, not location, we're losing that - ioVar->getWritableType().getQualifier().layoutLocation = TQualifier::layoutLocationEnd; -} - -// Split a type into -// 1. a struct of non-I/O members -// 2. a collection of independent I/O variables -void HlslParseContext::split(const TVariable& variable) -{ - // Create a new variable: - const TType& clonedType = *variable.getType().clone(); - const TType& splitType = split(clonedType, variable.getName(), clonedType.getQualifier()); - splitNonIoVars[variable.getUniqueId()] = makeInternalVariable(variable.getName(), splitType); -} - -// Recursive implementation of split(). -// Returns reference to the modified type. -const TType& HlslParseContext::split(const TType& type, const TString& name, const TQualifier& outerQualifier) -{ - if (type.isStruct()) { - TTypeList* userStructure = type.getWritableStruct(); - for (auto ioType = userStructure->begin(); ioType != userStructure->end(); ) { - if (ioType->type->isBuiltIn()) { - // move out the built-in - splitBuiltIn(name, *ioType->type, type.getArraySizes(), outerQualifier); - ioType = userStructure->erase(ioType); - } else { - split(*ioType->type, name + "." + ioType->type->getFieldName(), outerQualifier); - ++ioType; - } - } - } - - return type; -} - -// Is this an aggregate that should be flattened? -// Can be applied to intermediate levels of type in a hierarchy. -// Some things like flattening uniform arrays are only about the top level -// of the aggregate, triggered on 'topLevel'. -bool HlslParseContext::shouldFlatten(const TType& type, TStorageQualifier qualifier, bool topLevel) const -{ - switch (qualifier) { - case EvqVaryingIn: - case EvqVaryingOut: - return type.isStruct() || type.isArray(); - case EvqUniform: - return (type.isArray() && intermediate.getFlattenUniformArrays() && topLevel) || - (type.isStruct() && type.containsOpaque()); - default: - return false; - }; -} - -// Top level variable flattening: construct data -void HlslParseContext::flatten(const TVariable& variable, bool linkage, bool arrayed) -{ - const TType& type = variable.getType(); - - // If it's a standalone built-in, there is nothing to flatten - if (type.isBuiltIn() && !type.isStruct()) - return; - - - auto entry = flattenMap.insert(std::make_pair(variable.getUniqueId(), - TFlattenData(type.getQualifier().layoutBinding, - type.getQualifier().layoutLocation))); - - if (type.isStruct() && type.getStruct()->size()==0) - return; - // if flattening arrayed io struct, array each member of dereferenced type - if (arrayed) { - const TType dereferencedType(type, 0); - flatten(variable, dereferencedType, entry.first->second, variable.getName(), linkage, - type.getQualifier(), type.getArraySizes()); - } else { - flatten(variable, type, entry.first->second, variable.getName(), linkage, - type.getQualifier(), nullptr); - } -} - -// Recursively flatten the given variable at the provided type, building the flattenData as we go. -// -// This is mutually recursive with flattenStruct and flattenArray. -// We are going to flatten an arbitrarily nested composite structure into a linear sequence of -// members, and later on, we want to turn a path through the tree structure into a final -// location in this linear sequence. -// -// If the tree was N-ary, that can be directly calculated. However, we are dealing with -// arbitrary numbers - perhaps a struct of 7 members containing an array of 3. Thus, we must -// build a data structure to allow the sequence of bracket and dot operators on arrays and -// structs to arrive at the proper member. -// -// To avoid storing a tree with pointers, we are going to flatten the tree into a vector of integers. -// The leaves are the indexes into the flattened member array. -// Each level will have the next location for the Nth item stored sequentially, so for instance: -// -// struct { float2 a[2]; int b; float4 c[3] }; -// -// This will produce the following flattened tree: -// Pos: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 -// (3, 7, 8, 5, 6, 0, 1, 2, 11, 12, 13, 3, 4, 5} -// -// Given a reference to mystruct.c[1], the access chain is (2,1), so we traverse: -// (0+2) = 8 --> (8+1) = 12 --> 12 = 4 -// -// so the 4th flattened member in traversal order is ours. -// -int HlslParseContext::flatten(const TVariable& variable, const TType& type, - TFlattenData& flattenData, TString name, bool linkage, - const TQualifier& outerQualifier, - const TArraySizes* builtInArraySizes) -{ - // If something is an arrayed struct, the array flattener will recursively call flatten() - // to then flatten the struct, so this is an "if else": we don't do both. - if (type.isArray()) - return flattenArray(variable, type, flattenData, name, linkage, outerQualifier); - else if (type.isStruct()) - return flattenStruct(variable, type, flattenData, name, linkage, outerQualifier, builtInArraySizes); - else { - assert(0); // should never happen - return -1; - } -} - -// Add a single flattened member to the flattened data being tracked for the composite -// Returns true for the final flattening level. -int HlslParseContext::addFlattenedMember(const TVariable& variable, const TType& type, TFlattenData& flattenData, - const TString& memberName, bool linkage, - const TQualifier& outerQualifier, - const TArraySizes* builtInArraySizes) -{ - if (!shouldFlatten(type, outerQualifier.storage, false)) { - // This is as far as we flatten. Insert the variable. - TVariable* memberVariable = makeInternalVariable(memberName, type); - mergeQualifiers(memberVariable->getWritableType().getQualifier(), variable.getType().getQualifier()); - - if (flattenData.nextBinding != TQualifier::layoutBindingEnd) - memberVariable->getWritableType().getQualifier().layoutBinding = flattenData.nextBinding++; - - if (memberVariable->getType().isBuiltIn()) { - // inherited locations are nonsensical for built-ins (TODO: what if semantic had a number) - memberVariable->getWritableType().getQualifier().layoutLocation = TQualifier::layoutLocationEnd; - } else { - // inherited locations must be auto bumped, not replicated - if (flattenData.nextLocation != TQualifier::layoutLocationEnd) { - memberVariable->getWritableType().getQualifier().layoutLocation = flattenData.nextLocation; - flattenData.nextLocation += intermediate.computeTypeLocationSize(memberVariable->getType(), language); - nextOutLocation = std::max(nextOutLocation, flattenData.nextLocation); - } - } - - // Only propagate arraysizes here for arrayed io - if (variable.getType().getQualifier().isArrayedIo(language) && builtInArraySizes != nullptr) - memberVariable->getWritableType().copyArraySizes(*builtInArraySizes); - - flattenData.offsets.push_back(static_cast(flattenData.members.size())); - flattenData.members.push_back(memberVariable); - - if (linkage) - trackLinkage(*memberVariable); - - return static_cast(flattenData.offsets.size()) - 1; // location of the member reference - } else { - // Further recursion required - return flatten(variable, type, flattenData, memberName, linkage, outerQualifier, builtInArraySizes); - } -} - -// Figure out the mapping between an aggregate's top members and an -// equivalent set of individual variables. -// -// Assumes shouldFlatten() or equivalent was called first. -int HlslParseContext::flattenStruct(const TVariable& variable, const TType& type, - TFlattenData& flattenData, TString name, bool linkage, - const TQualifier& outerQualifier, - const TArraySizes* builtInArraySizes) -{ - assert(type.isStruct()); - - auto members = *type.getStruct(); - - // Reserve space for this tree level. - int start = static_cast(flattenData.offsets.size()); - int pos = start; - flattenData.offsets.resize(int(pos + members.size()), -1); - - for (int member = 0; member < (int)members.size(); ++member) { - TType& dereferencedType = *members[member].type; - if (dereferencedType.isBuiltIn()) - splitBuiltIn(variable.getName(), dereferencedType, builtInArraySizes, outerQualifier); - else { - const int mpos = addFlattenedMember(variable, dereferencedType, flattenData, - name + "." + dereferencedType.getFieldName(), - linkage, outerQualifier, - builtInArraySizes == nullptr && dereferencedType.isArray() - ? dereferencedType.getArraySizes() - : builtInArraySizes); - flattenData.offsets[pos++] = mpos; - } - } - - return start; -} - -// Figure out mapping between an array's members and an -// equivalent set of individual variables. -// -// Assumes shouldFlatten() or equivalent was called first. -int HlslParseContext::flattenArray(const TVariable& variable, const TType& type, - TFlattenData& flattenData, TString name, bool linkage, - const TQualifier& outerQualifier) -{ - assert(type.isSizedArray()); - - const int size = type.getOuterArraySize(); - const TType dereferencedType(type, 0); - - if (name.empty()) - name = variable.getName(); - - // Reserve space for this tree level. - int start = static_cast(flattenData.offsets.size()); - int pos = start; - flattenData.offsets.resize(int(pos + size), -1); - - for (int element=0; element < size; ++element) { - char elementNumBuf[20]; // sufficient for MAXINT - snprintf(elementNumBuf, sizeof(elementNumBuf)-1, "[%d]", element); - const int mpos = addFlattenedMember(variable, dereferencedType, flattenData, - name + elementNumBuf, linkage, outerQualifier, - type.getArraySizes()); - - flattenData.offsets[pos++] = mpos; - } - - return start; -} - -// Return true if we have flattened this node. -bool HlslParseContext::wasFlattened(const TIntermTyped* node) const -{ - return node != nullptr && node->getAsSymbolNode() != nullptr && - wasFlattened(node->getAsSymbolNode()->getId()); -} - -// Return true if we have split this structure -bool HlslParseContext::wasSplit(const TIntermTyped* node) const -{ - return node != nullptr && node->getAsSymbolNode() != nullptr && - wasSplit(node->getAsSymbolNode()->getId()); -} - -// Turn an access into an aggregate that was flattened to instead be -// an access to the individual variable the member was flattened to. -// Assumes wasFlattened() or equivalent was called first. -TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member) -{ - const TType dereferencedType(base->getType(), member); // dereferenced type - const TIntermSymbol& symbolNode = *base->getAsSymbolNode(); - TIntermTyped* flattened = flattenAccess(symbolNode.getId(), member, base->getQualifier().storage, - dereferencedType, symbolNode.getFlattenSubset()); - - return flattened ? flattened : base; -} -TIntermTyped* HlslParseContext::flattenAccess(long long uniqueId, int member, TStorageQualifier outerStorage, - const TType& dereferencedType, int subset) -{ - const auto flattenData = flattenMap.find(uniqueId); - - if (flattenData == flattenMap.end()) - return nullptr; - - // Calculate new cumulative offset from the packed tree - int newSubset = flattenData->second.offsets[subset >= 0 ? subset + member : member]; - - TIntermSymbol* subsetSymbol; - if (!shouldFlatten(dereferencedType, outerStorage, false)) { - // Finished flattening: create symbol for variable - member = flattenData->second.offsets[newSubset]; - const TVariable* memberVariable = flattenData->second.members[member]; - subsetSymbol = intermediate.addSymbol(*memberVariable); - subsetSymbol->setFlattenSubset(-1); - } else { - - // If this is not the final flattening, accumulate the position and return - // an object of the partially dereferenced type. - subsetSymbol = new TIntermSymbol(uniqueId, "flattenShadow", dereferencedType); - subsetSymbol->setFlattenSubset(newSubset); - } - - return subsetSymbol; -} - -// For finding where the first leaf is in a subtree of a multi-level aggregate -// that is just getting a subset assigned. Follows the same logic as flattenAccess, -// but logically going down the "left-most" tree branch each step of the way. -// -// Returns the offset into the first leaf of the subset. -int HlslParseContext::findSubtreeOffset(const TIntermNode& node) const -{ - const TIntermSymbol* sym = node.getAsSymbolNode(); - if (sym == nullptr) - return 0; - if (!sym->isArray() && !sym->isStruct()) - return 0; - int subset = sym->getFlattenSubset(); - if (subset == -1) - return 0; - - // Getting this far means a partial aggregate is identified by the flatten subset. - // Find the first leaf of the subset. - - const auto flattenData = flattenMap.find(sym->getId()); - if (flattenData == flattenMap.end()) - return 0; - - return findSubtreeOffset(sym->getType(), subset, flattenData->second.offsets); - - do { - subset = flattenData->second.offsets[subset]; - } while (true); -} -// Recursively do the desent -int HlslParseContext::findSubtreeOffset(const TType& type, int subset, const TVector& offsets) const -{ - if (!type.isArray() && !type.isStruct()) - return offsets[subset]; - TType derefType(type, 0); - return findSubtreeOffset(derefType, offsets[subset], offsets); -}; - -// Find and return the split IO TVariable for id, or nullptr if none. -TVariable* HlslParseContext::getSplitNonIoVar(long long id) const -{ - const auto splitNonIoVar = splitNonIoVars.find(id); - if (splitNonIoVar == splitNonIoVars.end()) - return nullptr; - - return splitNonIoVar->second; -} - -// Pass through to base class after remembering built-in mappings. -void HlslParseContext::trackLinkage(TSymbol& symbol) -{ - TBuiltInVariable biType = symbol.getType().getQualifier().builtIn; - - if (biType != EbvNone) - builtInTessLinkageSymbols[biType] = symbol.clone(); - - TParseContextBase::trackLinkage(symbol); -} - - -// Returns true if the built-in is a clip or cull distance variable. -bool HlslParseContext::isClipOrCullDistance(TBuiltInVariable builtIn) -{ - return builtIn == EbvClipDistance || builtIn == EbvCullDistance; -} - -// Some types require fixed array sizes in SPIR-V, but can be scalars or -// arrays of sizes SPIR-V doesn't allow. For example, tessellation factors. -// This creates the right size. A conversion is performed when the internal -// type is copied to or from the external type. This corrects the externally -// facing input or output type to abide downstream semantics. -void HlslParseContext::fixBuiltInIoType(TType& type) -{ - int requiredArraySize = 0; - int requiredVectorSize = 0; - - switch (type.getQualifier().builtIn) { - case EbvTessLevelOuter: requiredArraySize = 4; break; - case EbvTessLevelInner: requiredArraySize = 2; break; - - case EbvSampleMask: - { - // Promote scalar to array of size 1. Leave existing arrays alone. - if (!type.isArray()) - requiredArraySize = 1; - break; - } - - case EbvWorkGroupId: requiredVectorSize = 3; break; - case EbvGlobalInvocationId: requiredVectorSize = 3; break; - case EbvLocalInvocationId: requiredVectorSize = 3; break; - case EbvTessCoord: requiredVectorSize = 3; break; - - default: - if (isClipOrCullDistance(type)) { - const int loc = type.getQualifier().layoutLocation; - - if (type.getQualifier().builtIn == EbvClipDistance) { - if (type.getQualifier().storage == EvqVaryingIn) - clipSemanticNSizeIn[loc] = type.getVectorSize(); - else - clipSemanticNSizeOut[loc] = type.getVectorSize(); - } else { - if (type.getQualifier().storage == EvqVaryingIn) - cullSemanticNSizeIn[loc] = type.getVectorSize(); - else - cullSemanticNSizeOut[loc] = type.getVectorSize(); - } - } - - return; - } - - // Alter or set vector size as needed. - if (requiredVectorSize > 0) { - TType newType(type.getBasicType(), type.getQualifier().storage, requiredVectorSize); - newType.getQualifier() = type.getQualifier(); - - type.shallowCopy(newType); - } - - // Alter or set array size as needed. - if (requiredArraySize > 0) { - if (!type.isArray() || type.getOuterArraySize() != requiredArraySize) { - TArraySizes* arraySizes = new TArraySizes; - arraySizes->addInnerSize(requiredArraySize); - type.transferArraySizes(arraySizes); - } - } -} - -// Variables that correspond to the user-interface in and out of a stage -// (not the built-in interface) are -// - assigned locations -// - registered as a linkage node (part of the stage's external interface). -// Assumes it is called in the order in which locations should be assigned. -void HlslParseContext::assignToInterface(TVariable& variable) -{ - const auto assignLocation = [&](TVariable& variable) { - TType& type = variable.getWritableType(); - if (!type.isStruct() || type.getStruct()->size() > 0) { - TQualifier& qualifier = type.getQualifier(); - if (qualifier.storage == EvqVaryingIn || qualifier.storage == EvqVaryingOut) { - if (qualifier.builtIn == EbvNone && !qualifier.hasLocation()) { - // Strip off the outer array dimension for those having an extra one. - int size; - if (type.isArray() && qualifier.isArrayedIo(language)) { - TType elementType(type, 0); - size = intermediate.computeTypeLocationSize(elementType, language); - } else - size = intermediate.computeTypeLocationSize(type, language); - - if (qualifier.storage == EvqVaryingIn) { - variable.getWritableType().getQualifier().layoutLocation = nextInLocation; - nextInLocation += size; - } else { - variable.getWritableType().getQualifier().layoutLocation = nextOutLocation; - nextOutLocation += size; - } - } - trackLinkage(variable); - } - } - }; - - if (wasFlattened(variable.getUniqueId())) { - auto& memberList = flattenMap[variable.getUniqueId()].members; - for (auto member = memberList.begin(); member != memberList.end(); ++member) - assignLocation(**member); - } else if (wasSplit(variable.getUniqueId())) { - TVariable* splitIoVar = getSplitNonIoVar(variable.getUniqueId()); - assignLocation(*splitIoVar); - } else { - assignLocation(variable); - } -} - -// -// Handle seeing a function declarator in the grammar. This is the precursor -// to recognizing a function prototype or function definition. -// -void HlslParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunction& function, bool prototype) -{ - // - // Multiple declarations of the same function name are allowed. - // - // If this is a definition, the definition production code will check for redefinitions - // (we don't know at this point if it's a definition or not). - // - bool builtIn; - TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn); - const TFunction* prevDec = symbol ? symbol->getAsFunction() : nullptr; - - if (prototype) { - // All built-in functions are defined, even though they don't have a body. - // Count their prototype as a definition instead. - if (symbolTable.atBuiltInLevel()) - function.setDefined(); - else { - if (prevDec && ! builtIn) - symbol->getAsFunction()->setPrototyped(); // need a writable one, but like having prevDec as a const - function.setPrototyped(); - } - } - - // This insert won't actually insert it if it's a duplicate signature, but it will still check for - // other forms of name collisions. - if (! symbolTable.insert(function)) - error(loc, "function name is redeclaration of existing name", function.getName().c_str(), ""); -} - -// For struct buffers with counters, we must pass the counter buffer as hidden parameter. -// This adds the hidden parameter to the parameter list in 'paramNodes' if needed. -// Otherwise, it's a no-op -void HlslParseContext::addStructBufferHiddenCounterParam(const TSourceLoc& loc, TParameter& param, - TIntermAggregate*& paramNodes) -{ - if (! hasStructBuffCounter(*param.type)) - return; - - const TString counterBlockName(intermediate.addCounterBufferName(*param.name)); - - TType counterType; - counterBufferType(loc, counterType); - TVariable *variable = makeInternalVariable(counterBlockName, counterType); - - if (! symbolTable.insert(*variable)) - error(loc, "redefinition", variable->getName().c_str(), ""); - - paramNodes = intermediate.growAggregate(paramNodes, - intermediate.addSymbol(*variable, loc), - loc); -} - -// -// Handle seeing the function prototype in front of a function definition in the grammar. -// The body is handled after this function returns. -// -// Returns an aggregate of parameter-symbol nodes. -// -TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function, - const TAttributes& attributes, - TIntermNode*& entryPointTree) -{ - currentCaller = function.getMangledName(); - TSymbol* symbol = symbolTable.find(function.getMangledName()); - TFunction* prevDec = symbol ? symbol->getAsFunction() : nullptr; - - if (prevDec == nullptr) - error(loc, "can't find function", function.getName().c_str(), ""); - // Note: 'prevDec' could be 'function' if this is the first time we've seen function - // as it would have just been put in the symbol table. Otherwise, we're looking up - // an earlier occurrence. - - if (prevDec && prevDec->isDefined()) { - // Then this function already has a body. - error(loc, "function already has a body", function.getName().c_str(), ""); - } - if (prevDec && ! prevDec->isDefined()) { - prevDec->setDefined(); - - // Remember the return type for later checking for RETURN statements. - currentFunctionType = &(prevDec->getType()); - } else - currentFunctionType = new TType(EbtVoid); - functionReturnsValue = false; - - // Entry points need different I/O and other handling, transform it so the - // rest of this function doesn't care. - entryPointTree = transformEntryPoint(loc, function, attributes); - - // - // New symbol table scope for body of function plus its arguments - // - pushScope(); - - // - // Insert parameters into the symbol table. - // If the parameter has no name, it's not an error, just don't insert it - // (could be used for unused args). - // - // Also, accumulate the list of parameters into the AST, so lower level code - // knows where to find parameters. - // - TIntermAggregate* paramNodes = new TIntermAggregate; - for (int i = 0; i < function.getParamCount(); i++) { - TParameter& param = function[i]; - if (param.name != nullptr) { - TVariable *variable = new TVariable(param.name, *param.type); - - if (i == 0 && function.hasImplicitThis()) { - // Anonymous 'this' members are already in a symbol-table level, - // and we need to know what function parameter to map them to. - symbolTable.makeInternalVariable(*variable); - pushImplicitThis(variable); - } - - // Insert the parameters with name in the symbol table. - if (! symbolTable.insert(*variable)) - error(loc, "redefinition", variable->getName().c_str(), ""); - - // Add parameters to the AST list. - if (shouldFlatten(variable->getType(), variable->getType().getQualifier().storage, true)) { - // Expand the AST parameter nodes (but not the name mangling or symbol table view) - // for structures that need to be flattened. - flatten(*variable, false); - const TTypeList* structure = variable->getType().getStruct(); - for (int mem = 0; mem < (int)structure->size(); ++mem) { - paramNodes = intermediate.growAggregate(paramNodes, - flattenAccess(variable->getUniqueId(), mem, - variable->getType().getQualifier().storage, - *(*structure)[mem].type), - loc); - } - } else { - // Add the parameter to the AST - paramNodes = intermediate.growAggregate(paramNodes, - intermediate.addSymbol(*variable, loc), - loc); - } - - // Add hidden AST parameter for struct buffer counters, if needed. - addStructBufferHiddenCounterParam(loc, param, paramNodes); - } else - paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); - } - if (function.hasIllegalImplicitThis()) - pushImplicitThis(nullptr); - - intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc); - loopNestingLevel = 0; - controlFlowNestingLevel = 0; - postEntryPointReturn = false; - - return paramNodes; -} - -// Handle all [attrib] attribute for the shader entry point -void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const TAttributes& attributes) -{ - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - switch (it->name) { - case EatNumThreads: - { - const TIntermSequence& sequence = it->args->getSequence(); - for (int lid = 0; lid < int(sequence.size()); ++lid) - intermediate.setLocalSize(lid, sequence[lid]->getAsConstantUnion()->getConstArray()[0].getIConst()); - break; - } - case EatInstance: - { - int invocations; - - if (!it->getInt(invocations)) { - error(loc, "invalid instance", "", ""); - } else { - if (!intermediate.setInvocations(invocations)) - error(loc, "cannot change previously set instance attribute", "", ""); - } - break; - } - case EatMaxVertexCount: - { - int maxVertexCount; - - if (! it->getInt(maxVertexCount)) { - error(loc, "invalid maxvertexcount", "", ""); - } else { - if (! intermediate.setVertices(maxVertexCount)) - error(loc, "cannot change previously set maxvertexcount attribute", "", ""); - } - break; - } - case EatPatchConstantFunc: - { - TString pcfName; - if (! it->getString(pcfName, 0, false)) { - error(loc, "invalid patch constant function", "", ""); - } else { - patchConstantFunctionName = pcfName; - } - break; - } - case EatDomain: - { - // Handle [domain("...")] - TString domainStr; - if (! it->getString(domainStr)) { - error(loc, "invalid domain", "", ""); - } else { - TLayoutGeometry domain = ElgNone; - - if (domainStr == "tri") { - domain = ElgTriangles; - } else if (domainStr == "quad") { - domain = ElgQuads; - } else if (domainStr == "isoline") { - domain = ElgIsolines; - } else { - error(loc, "unsupported domain type", domainStr.c_str(), ""); - } - - if (language == EShLangTessEvaluation) { - if (! intermediate.setInputPrimitive(domain)) - error(loc, "cannot change previously set domain", TQualifier::getGeometryString(domain), ""); - } else { - if (! intermediate.setOutputPrimitive(domain)) - error(loc, "cannot change previously set domain", TQualifier::getGeometryString(domain), ""); - } - } - break; - } - case EatOutputTopology: - { - // Handle [outputtopology("...")] - TString topologyStr; - if (! it->getString(topologyStr)) { - error(loc, "invalid outputtopology", "", ""); - } else { - TVertexOrder vertexOrder = EvoNone; - TLayoutGeometry primitive = ElgNone; - - if (topologyStr == "point") { - intermediate.setPointMode(); - } else if (topologyStr == "line") { - primitive = ElgIsolines; - } else if (topologyStr == "triangle_cw") { - vertexOrder = EvoCw; - primitive = ElgTriangles; - } else if (topologyStr == "triangle_ccw") { - vertexOrder = EvoCcw; - primitive = ElgTriangles; - } else { - error(loc, "unsupported outputtopology type", topologyStr.c_str(), ""); - } - - if (vertexOrder != EvoNone) { - if (! intermediate.setVertexOrder(vertexOrder)) { - error(loc, "cannot change previously set outputtopology", - TQualifier::getVertexOrderString(vertexOrder), ""); - } - } - if (primitive != ElgNone) - intermediate.setOutputPrimitive(primitive); - } - break; - } - case EatPartitioning: - { - // Handle [partitioning("...")] - TString partitionStr; - if (! it->getString(partitionStr)) { - error(loc, "invalid partitioning", "", ""); - } else { - TVertexSpacing partitioning = EvsNone; - - if (partitionStr == "integer") { - partitioning = EvsEqual; - } else if (partitionStr == "fractional_even") { - partitioning = EvsFractionalEven; - } else if (partitionStr == "fractional_odd") { - partitioning = EvsFractionalOdd; - //} else if (partition == "pow2") { // TODO: currently nothing to map this to. - } else { - error(loc, "unsupported partitioning type", partitionStr.c_str(), ""); - } - - if (! intermediate.setVertexSpacing(partitioning)) - error(loc, "cannot change previously set partitioning", - TQualifier::getVertexSpacingString(partitioning), ""); - } - break; - } - case EatOutputControlPoints: - { - // Handle [outputcontrolpoints("...")] - int ctrlPoints; - if (! it->getInt(ctrlPoints)) { - error(loc, "invalid outputcontrolpoints", "", ""); - } else { - if (! intermediate.setVertices(ctrlPoints)) { - error(loc, "cannot change previously set outputcontrolpoints attribute", "", ""); - } - } - break; - } - case EatEarlyDepthStencil: - intermediate.setEarlyFragmentTests(); - break; - case EatBuiltIn: - case EatLocation: - // tolerate these because of dual use of entrypoint and type attributes - break; - default: - warn(loc, "attribute does not apply to entry point", "", ""); - break; - } - } -} - -// Update the given type with any type-like attribute information in the -// attributes. -void HlslParseContext::transferTypeAttributes(const TSourceLoc& loc, const TAttributes& attributes, TType& type, - bool allowEntry) -{ - if (attributes.size() == 0) - return; - - int value; - TString builtInString; - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - switch (it->name) { - case EatLocation: - // location - if (it->getInt(value)) - type.getQualifier().layoutLocation = value; - else - error(loc, "needs a literal integer", "location", ""); - break; - case EatBinding: - // binding - if (it->getInt(value)) { - type.getQualifier().layoutBinding = value; - type.getQualifier().layoutSet = 0; - } else - error(loc, "needs a literal integer", "binding", ""); - // set - if (it->getInt(value, 1)) - type.getQualifier().layoutSet = value; - break; - case EatGlobalBinding: - // global cbuffer binding - if (it->getInt(value)) - globalUniformBinding = value; - else - error(loc, "needs a literal integer", "global binding", ""); - // global cbuffer set - if (it->getInt(value, 1)) - globalUniformSet = value; - break; - case EatInputAttachment: - // input attachment - if (it->getInt(value)) - type.getQualifier().layoutAttachment = value; - else - error(loc, "needs a literal integer", "input attachment", ""); - break; - case EatBuiltIn: - // PointSize built-in - if (it->getString(builtInString, 0, false)) { - if (builtInString == "PointSize") - type.getQualifier().builtIn = EbvPointSize; - } - break; - case EatPushConstant: - // push_constant - type.getQualifier().layoutPushConstant = true; - break; - case EatConstantId: - // specialization constant - if (type.getQualifier().storage != EvqConst) { - error(loc, "needs a const type", "constant_id", ""); - break; - } - if (it->getInt(value)) { - TSourceLoc loc; - loc.init(); - setSpecConstantId(loc, type.getQualifier(), value); - } - break; - - // image formats - case EatFormatRgba32f: type.getQualifier().layoutFormat = ElfRgba32f; break; - case EatFormatRgba16f: type.getQualifier().layoutFormat = ElfRgba16f; break; - case EatFormatR32f: type.getQualifier().layoutFormat = ElfR32f; break; - case EatFormatRgba8: type.getQualifier().layoutFormat = ElfRgba8; break; - case EatFormatRgba8Snorm: type.getQualifier().layoutFormat = ElfRgba8Snorm; break; - case EatFormatRg32f: type.getQualifier().layoutFormat = ElfRg32f; break; - case EatFormatRg16f: type.getQualifier().layoutFormat = ElfRg16f; break; - case EatFormatR11fG11fB10f: type.getQualifier().layoutFormat = ElfR11fG11fB10f; break; - case EatFormatR16f: type.getQualifier().layoutFormat = ElfR16f; break; - case EatFormatRgba16: type.getQualifier().layoutFormat = ElfRgba16; break; - case EatFormatRgb10A2: type.getQualifier().layoutFormat = ElfRgb10A2; break; - case EatFormatRg16: type.getQualifier().layoutFormat = ElfRg16; break; - case EatFormatRg8: type.getQualifier().layoutFormat = ElfRg8; break; - case EatFormatR16: type.getQualifier().layoutFormat = ElfR16; break; - case EatFormatR8: type.getQualifier().layoutFormat = ElfR8; break; - case EatFormatRgba16Snorm: type.getQualifier().layoutFormat = ElfRgba16Snorm; break; - case EatFormatRg16Snorm: type.getQualifier().layoutFormat = ElfRg16Snorm; break; - case EatFormatRg8Snorm: type.getQualifier().layoutFormat = ElfRg8Snorm; break; - case EatFormatR16Snorm: type.getQualifier().layoutFormat = ElfR16Snorm; break; - case EatFormatR8Snorm: type.getQualifier().layoutFormat = ElfR8Snorm; break; - case EatFormatRgba32i: type.getQualifier().layoutFormat = ElfRgba32i; break; - case EatFormatRgba16i: type.getQualifier().layoutFormat = ElfRgba16i; break; - case EatFormatRgba8i: type.getQualifier().layoutFormat = ElfRgba8i; break; - case EatFormatR32i: type.getQualifier().layoutFormat = ElfR32i; break; - case EatFormatRg32i: type.getQualifier().layoutFormat = ElfRg32i; break; - case EatFormatRg16i: type.getQualifier().layoutFormat = ElfRg16i; break; - case EatFormatRg8i: type.getQualifier().layoutFormat = ElfRg8i; break; - case EatFormatR16i: type.getQualifier().layoutFormat = ElfR16i; break; - case EatFormatR8i: type.getQualifier().layoutFormat = ElfR8i; break; - case EatFormatRgba32ui: type.getQualifier().layoutFormat = ElfRgba32ui; break; - case EatFormatRgba16ui: type.getQualifier().layoutFormat = ElfRgba16ui; break; - case EatFormatRgba8ui: type.getQualifier().layoutFormat = ElfRgba8ui; break; - case EatFormatR32ui: type.getQualifier().layoutFormat = ElfR32ui; break; - case EatFormatRgb10a2ui: type.getQualifier().layoutFormat = ElfRgb10a2ui; break; - case EatFormatRg32ui: type.getQualifier().layoutFormat = ElfRg32ui; break; - case EatFormatRg16ui: type.getQualifier().layoutFormat = ElfRg16ui; break; - case EatFormatRg8ui: type.getQualifier().layoutFormat = ElfRg8ui; break; - case EatFormatR16ui: type.getQualifier().layoutFormat = ElfR16ui; break; - case EatFormatR8ui: type.getQualifier().layoutFormat = ElfR8ui; break; - case EatFormatUnknown: type.getQualifier().layoutFormat = ElfNone; break; - - case EatNonWritable: type.getQualifier().readonly = true; break; - case EatNonReadable: type.getQualifier().writeonly = true; break; - - default: - if (! allowEntry) - warn(loc, "attribute does not apply to a type", "", ""); - break; - } - } -} - -// -// Do all special handling for the entry point, including wrapping -// the shader's entry point with the official entry point that will call it. -// -// The following: -// -// retType shaderEntryPoint(args...) // shader declared entry point -// { body } -// -// Becomes -// -// out retType ret; -// in iargs...; -// out oargs ...; -// -// void shaderEntryPoint() // synthesized, but official, entry point -// { -// args = iargs...; -// ret = @shaderEntryPoint(args...); -// oargs = args...; -// } -// retType @shaderEntryPoint(args...) -// { body } -// -// The symbol table will still map the original entry point name to the -// the modified function and its new name: -// -// symbol table: shaderEntryPoint -> @shaderEntryPoint -// -// Returns nullptr if no entry-point tree was built, otherwise, returns -// a subtree that creates the entry point. -// -TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunction& userFunction, - const TAttributes& attributes) -{ - // Return true if this is a tessellation patch constant function input to a domain shader. - const auto isDsPcfInput = [this](const TType& type) { - return language == EShLangTessEvaluation && - type.contains([](const TType* t) { - return t->getQualifier().builtIn == EbvTessLevelOuter || - t->getQualifier().builtIn == EbvTessLevelInner; - }); - }; - - // if we aren't in the entry point, fix the IO as such and exit - if (! isEntrypointName(userFunction.getName())) { - remapNonEntryPointIO(userFunction); - return nullptr; - } - - entryPointFunction = &userFunction; // needed in finish() - - // Handle entry point attributes - handleEntryPointAttributes(loc, attributes); - - // entry point logic... - - // Move parameters and return value to shader in/out - TVariable* entryPointOutput; // gets created in remapEntryPointIO - TVector inputs; - TVector outputs; - remapEntryPointIO(userFunction, entryPointOutput, inputs, outputs); - - // Further this return/in/out transform by flattening, splitting, and assigning locations - const auto makeVariableInOut = [&](TVariable& variable) { - if (variable.getType().isStruct()) { - bool arrayed = variable.getType().getQualifier().isArrayedIo(language); - flatten(variable, false /* don't track linkage here, it will be tracked in assignToInterface() */, arrayed); - } - // TODO: flatten arrays too - // TODO: flatten everything in I/O - // TODO: replace all split with flatten, make all paths can create flattened I/O, then split code can be removed - - // For clip and cull distance, multiple output variables potentially get merged - // into one in assignClipCullDistance. That code in assignClipCullDistance - // handles the interface logic, so we avoid it here in that case. - if (!isClipOrCullDistance(variable.getType())) - assignToInterface(variable); - }; - if (entryPointOutput != nullptr) - makeVariableInOut(*entryPointOutput); - for (auto it = inputs.begin(); it != inputs.end(); ++it) - if (!isDsPcfInput((*it)->getType())) // wait until the end for PCF input (see comment below) - makeVariableInOut(*(*it)); - for (auto it = outputs.begin(); it != outputs.end(); ++it) - makeVariableInOut(*(*it)); - - // In the domain shader, PCF input must be at the end of the linkage. That's because in the - // hull shader there is no ordering: the output comes from the separate PCF, which does not - // participate in the argument list. That is always put at the end of the HS linkage, so the - // input side of the DS must match. The argument may be in any position in the DS argument list - // however, so this ensures the linkage is built in the correct order regardless of argument order. - if (language == EShLangTessEvaluation) { - for (auto it = inputs.begin(); it != inputs.end(); ++it) - if (isDsPcfInput((*it)->getType())) - makeVariableInOut(*(*it)); - } - - // Add uniform parameters to the $Global uniform block. - TVector opaque_uniforms; - for (int i = 0; i < userFunction.getParamCount(); i++) { - TType& paramType = *userFunction[i].type; - TString& paramName = *userFunction[i].name; - if (paramType.getQualifier().storage == EvqUniform) { - if (!paramType.containsOpaque()) { - // Add it to the global uniform block. - growGlobalUniformBlock(loc, paramType, paramName); - } else { - // Declare it as a separate variable. - TVariable *var = makeInternalVariable(paramName.c_str(), paramType); - opaque_uniforms.push_back(var); - } - } - } - - // Synthesize the call - - pushScope(); // matches the one in handleFunctionBody() - - // new signature - TType voidType(EbtVoid); - TFunction synthEntryPoint(&userFunction.getName(), voidType); - TIntermAggregate* synthParams = new TIntermAggregate(); - intermediate.setAggregateOperator(synthParams, EOpParameters, voidType, loc); - intermediate.setEntryPointMangledName(synthEntryPoint.getMangledName().c_str()); - intermediate.incrementEntryPointCount(); - TFunction callee(&userFunction.getName(), voidType); // call based on old name, which is still in the symbol table - - // change original name - userFunction.addPrefix("@"); // change the name in the function, but not in the symbol table - - // Copy inputs (shader-in -> calling arg), while building up the call node - TVector argVars; - TIntermAggregate* synthBody = new TIntermAggregate(); - auto inputIt = inputs.begin(); - auto opaqueUniformIt = opaque_uniforms.begin(); - TIntermTyped* callingArgs = nullptr; - - for (int i = 0; i < userFunction.getParamCount(); i++) { - TParameter& param = userFunction[i]; - argVars.push_back(makeInternalVariable(*param.name, *param.type)); - argVars.back()->getWritableType().getQualifier().makeTemporary(); - - // Track the input patch, which is the only non-builtin supported by hull shader PCF. - if (param.getDeclaredBuiltIn() == EbvInputPatch) - inputPatch = argVars.back(); - - TIntermSymbol* arg = intermediate.addSymbol(*argVars.back()); - handleFunctionArgument(&callee, callingArgs, arg); - if (param.type->getQualifier().isParamInput()) { - TIntermTyped* input = intermediate.addSymbol(**inputIt); - if (input->getType().getQualifier().builtIn == EbvFragCoord && intermediate.getDxPositionW()) { - // Replace FragCoord W with reciprocal - auto pos_xyz = handleDotDereference(loc, input, "xyz"); - auto pos_w = handleDotDereference(loc, input, "w"); - auto one = intermediate.addConstantUnion(1.0, EbtFloat, loc); - auto recip_w = intermediate.addBinaryMath(EOpDiv, one, pos_w, loc); - TIntermAggregate* dst = new TIntermAggregate(EOpConstructVec4); - dst->getSequence().push_back(pos_xyz); - dst->getSequence().push_back(recip_w); - dst->setType(TType(EbtFloat, EvqTemporary, 4)); - dst->setLoc(loc); - input = dst; - } - intermediate.growAggregate(synthBody, handleAssign(loc, EOpAssign, arg, input)); - inputIt++; - } - if (param.type->getQualifier().storage == EvqUniform) { - if (!param.type->containsOpaque()) { - // Look it up in the $Global uniform block. - intermediate.growAggregate(synthBody, handleAssign(loc, EOpAssign, arg, - handleVariable(loc, param.name))); - } else { - intermediate.growAggregate(synthBody, handleAssign(loc, EOpAssign, arg, - intermediate.addSymbol(**opaqueUniformIt))); - ++opaqueUniformIt; - } - } - } - - // Call - currentCaller = synthEntryPoint.getMangledName(); - TIntermTyped* callReturn = handleFunctionCall(loc, &callee, callingArgs); - currentCaller = userFunction.getMangledName(); - - // Return value - if (entryPointOutput) { - TIntermTyped* returnAssign; - - // For hull shaders, the wrapped entry point return value is written to - // an array element as indexed by invocation ID, which we might have to make up. - // This is required to match SPIR-V semantics. - if (language == EShLangTessControl) { - TIntermSymbol* invocationIdSym = findTessLinkageSymbol(EbvInvocationId); - - // If there is no user declared invocation ID, we must make one. - if (invocationIdSym == nullptr) { - TType invocationIdType(EbtUint, EvqIn, 1); - TString* invocationIdName = NewPoolTString("InvocationId"); - invocationIdType.getQualifier().builtIn = EbvInvocationId; - - TVariable* variable = makeInternalVariable(*invocationIdName, invocationIdType); - - globalQualifierFix(loc, variable->getWritableType().getQualifier()); - trackLinkage(*variable); - - invocationIdSym = intermediate.addSymbol(*variable); - } - - TIntermTyped* element = intermediate.addIndex(EOpIndexIndirect, intermediate.addSymbol(*entryPointOutput), - invocationIdSym, loc); - - // Set the type of the array element being dereferenced - const TType derefElementType(entryPointOutput->getType(), 0); - element->setType(derefElementType); - - returnAssign = handleAssign(loc, EOpAssign, element, callReturn); - } else { - returnAssign = handleAssign(loc, EOpAssign, intermediate.addSymbol(*entryPointOutput), callReturn); - } - intermediate.growAggregate(synthBody, returnAssign); - } else - intermediate.growAggregate(synthBody, callReturn); - - // Output copies - auto outputIt = outputs.begin(); - for (int i = 0; i < userFunction.getParamCount(); i++) { - TParameter& param = userFunction[i]; - - // GS outputs are via emit, so we do not copy them here. - if (param.type->getQualifier().isParamOutput()) { - if (param.getDeclaredBuiltIn() == EbvGsOutputStream) { - // GS output stream does not assign outputs here: it's the Append() method - // which writes to the output, probably multiple times separated by Emit. - // We merely remember the output to use, here. - gsStreamOutput = *outputIt; - } else { - intermediate.growAggregate(synthBody, handleAssign(loc, EOpAssign, - intermediate.addSymbol(**outputIt), - intermediate.addSymbol(*argVars[i]))); - } - - outputIt++; - } - } - - // Put the pieces together to form a full function subtree - // for the synthesized entry point. - synthBody->setOperator(EOpSequence); - TIntermNode* synthFunctionDef = synthParams; - handleFunctionBody(loc, synthEntryPoint, synthBody, synthFunctionDef); - - entryPointFunctionBody = synthBody; - - return synthFunctionDef; -} - -void HlslParseContext::handleFunctionBody(const TSourceLoc& loc, TFunction& function, TIntermNode* functionBody, - TIntermNode*& node) -{ - node = intermediate.growAggregate(node, functionBody); - intermediate.setAggregateOperator(node, EOpFunction, function.getType(), loc); - node->getAsAggregate()->setName(function.getMangledName().c_str()); - - popScope(); - if (function.hasImplicitThis()) - popImplicitThis(); - - if (function.getType().getBasicType() != EbtVoid && ! functionReturnsValue) - error(loc, "function does not return a value:", "", function.getName().c_str()); -} - -// AST I/O is done through shader globals declared in the 'in' or 'out' -// storage class. An HLSL entry point has a return value, input parameters -// and output parameters. These need to get remapped to the AST I/O. -void HlslParseContext::remapEntryPointIO(TFunction& function, TVariable*& returnValue, - TVector& inputs, TVector& outputs) -{ - // We might have in input structure type with no decorations that caused it - // to look like an input type, yet it has (e.g.) interpolation types that - // must be modified that turn it into an input type. - // Hence, a missing ioTypeMap for 'input' might need to be synthesized. - const auto synthesizeEditedInput = [this](TType& type) { - // True if a type needs to be 'flat' - const auto needsFlat = [](const TType& type) { - return type.containsBasicType(EbtInt) || - type.containsBasicType(EbtUint) || - type.containsBasicType(EbtInt64) || - type.containsBasicType(EbtUint64) || - type.containsBasicType(EbtBool) || - type.containsBasicType(EbtDouble); - }; - - if (language == EShLangFragment && needsFlat(type)) { - if (type.isStruct()) { - TTypeList* finalList = nullptr; - auto it = ioTypeMap.find(type.getStruct()); - if (it == ioTypeMap.end() || it->second.input == nullptr) { - // Getting here means we have no input struct, but we need one. - auto list = new TTypeList; - for (auto member = type.getStruct()->begin(); member != type.getStruct()->end(); ++member) { - TType* newType = new TType; - newType->shallowCopy(*member->type); - TTypeLoc typeLoc = { newType, member->loc }; - list->push_back(typeLoc); - } - // install the new input type - if (it == ioTypeMap.end()) { - tIoKinds newLists = { list, nullptr, nullptr }; - ioTypeMap[type.getStruct()] = newLists; - } else - it->second.input = list; - finalList = list; - } else - finalList = it->second.input; - // edit for 'flat' - for (auto member = finalList->begin(); member != finalList->end(); ++member) { - if (needsFlat(*member->type)) { - member->type->getQualifier().clearInterpolation(); - member->type->getQualifier().flat = true; - } - } - } else { - type.getQualifier().clearInterpolation(); - type.getQualifier().flat = true; - } - } - }; - - // Do the actual work to make a type be a shader input or output variable, - // and clear the original to be non-IO (for use as a normal function parameter/return). - const auto makeIoVariable = [this](const char* name, TType& type, TStorageQualifier storage) -> TVariable* { - TVariable* ioVariable = makeInternalVariable(name, type); - clearUniformInputOutput(type.getQualifier()); - if (type.isStruct()) { - auto newLists = ioTypeMap.find(ioVariable->getType().getStruct()); - if (newLists != ioTypeMap.end()) { - if (storage == EvqVaryingIn && newLists->second.input) - ioVariable->getWritableType().setStruct(newLists->second.input); - else if (storage == EvqVaryingOut && newLists->second.output) - ioVariable->getWritableType().setStruct(newLists->second.output); - } - } - if (storage == EvqVaryingIn) { - correctInput(ioVariable->getWritableType().getQualifier()); - if (language == EShLangTessEvaluation) - if (!ioVariable->getType().isArray()) - ioVariable->getWritableType().getQualifier().patch = true; - } else { - correctOutput(ioVariable->getWritableType().getQualifier()); - } - ioVariable->getWritableType().getQualifier().storage = storage; - - fixBuiltInIoType(ioVariable->getWritableType()); - - return ioVariable; - }; - - // return value is actually a shader-scoped output (out) - if (function.getType().getBasicType() == EbtVoid) { - returnValue = nullptr; - } else { - if (language == EShLangTessControl) { - // tessellation evaluation in HLSL writes a per-ctrl-pt value, but it needs to be an - // array in SPIR-V semantics. We'll write to it indexed by invocation ID. - - returnValue = makeIoVariable("@entryPointOutput", function.getWritableType(), EvqVaryingOut); - - TType outputType; - outputType.shallowCopy(function.getType()); - - // vertices has necessarily already been set when handling entry point attributes. - TArraySizes* arraySizes = new TArraySizes; - arraySizes->addInnerSize(intermediate.getVertices()); - outputType.transferArraySizes(arraySizes); - - clearUniformInputOutput(function.getWritableType().getQualifier()); - returnValue = makeIoVariable("@entryPointOutput", outputType, EvqVaryingOut); - } else { - returnValue = makeIoVariable("@entryPointOutput", function.getWritableType(), EvqVaryingOut); - } - } - - // parameters are actually shader-scoped inputs and outputs (in or out) - for (int i = 0; i < function.getParamCount(); i++) { - TType& paramType = *function[i].type; - if (paramType.getQualifier().isParamInput()) { - synthesizeEditedInput(paramType); - TVariable* argAsGlobal = makeIoVariable(function[i].name->c_str(), paramType, EvqVaryingIn); - inputs.push_back(argAsGlobal); - } - if (paramType.getQualifier().isParamOutput()) { - TVariable* argAsGlobal = makeIoVariable(function[i].name->c_str(), paramType, EvqVaryingOut); - outputs.push_back(argAsGlobal); - } - } -} - -// An HLSL function that looks like an entry point, but is not, -// declares entry point IO built-ins, but these have to be undone. -void HlslParseContext::remapNonEntryPointIO(TFunction& function) -{ - // return value - if (function.getType().getBasicType() != EbtVoid) - clearUniformInputOutput(function.getWritableType().getQualifier()); - - // parameters. - // References to structuredbuffer types are left unmodified - for (int i = 0; i < function.getParamCount(); i++) - if (!isReference(*function[i].type)) - clearUniformInputOutput(function[i].type->getQualifier()); -} - -TIntermNode* HlslParseContext::handleDeclare(const TSourceLoc& loc, TIntermTyped* var) -{ - return intermediate.addUnaryNode(EOpDeclare, var, loc, TType(EbtVoid)); -} - -// Handle function returns, including type conversions to the function return type -// if necessary. -TIntermNode* HlslParseContext::handleReturnValue(const TSourceLoc& loc, TIntermTyped* value) -{ - functionReturnsValue = true; - - if (currentFunctionType->getBasicType() == EbtVoid) { - error(loc, "void function cannot return a value", "return", ""); - return intermediate.addBranch(EOpReturn, loc); - } else if (*currentFunctionType != value->getType()) { - value = intermediate.addConversion(EOpReturn, *currentFunctionType, value); - if (value && *currentFunctionType != value->getType()) - value = intermediate.addUniShapeConversion(EOpReturn, *currentFunctionType, value); - if (value == nullptr || *currentFunctionType != value->getType()) { - error(loc, "type does not match, or is not convertible to, the function's return type", "return", ""); - return value; - } - } - - return intermediate.addBranch(EOpReturn, value, loc); -} - -void HlslParseContext::handleFunctionArgument(TFunction* function, - TIntermTyped*& arguments, TIntermTyped* newArg) -{ - TParameter param = { nullptr, new TType, nullptr }; - param.type->shallowCopy(newArg->getType()); - - function->addParameter(param); - if (arguments) - arguments = intermediate.growAggregate(arguments, newArg); - else - arguments = newArg; -} - -// FragCoord may require special loading: we can optionally reciprocate W. -TIntermTyped* HlslParseContext::assignFromFragCoord(const TSourceLoc& loc, TOperator op, - TIntermTyped* left, TIntermTyped* right) -{ - // If we are not asked for reciprocal W, use a plain old assign. - if (!intermediate.getDxPositionW()) - return intermediate.addAssign(op, left, right, loc); - - // If we get here, we should reciprocate W. - TIntermAggregate* assignList = nullptr; - - // If this is a complex rvalue, we don't want to dereference it many times. Create a temporary. - TVariable* rhsTempVar = nullptr; - rhsTempVar = makeInternalVariable("@fragcoord", right->getType()); - rhsTempVar->getWritableType().getQualifier().makeTemporary(); - - { - TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc); - assignList = intermediate.growAggregate(assignList, - intermediate.addAssign(EOpAssign, rhsTempSym, right, loc), loc); - } - - // tmp.w = 1.0 / tmp.w - { - const int W = 3; - - TIntermTyped* tempSymL = intermediate.addSymbol(*rhsTempVar, loc); - TIntermTyped* tempSymR = intermediate.addSymbol(*rhsTempVar, loc); - TIntermTyped* index = intermediate.addConstantUnion(W, loc); - - TIntermTyped* lhsElement = intermediate.addIndex(EOpIndexDirect, tempSymL, index, loc); - TIntermTyped* rhsElement = intermediate.addIndex(EOpIndexDirect, tempSymR, index, loc); - - const TType derefType(right->getType(), 0); - - lhsElement->setType(derefType); - rhsElement->setType(derefType); - - auto one = intermediate.addConstantUnion(1.0, EbtFloat, loc); - auto recip_w = intermediate.addBinaryMath(EOpDiv, one, rhsElement, loc); - - assignList = intermediate.growAggregate(assignList, intermediate.addAssign(EOpAssign, lhsElement, recip_w, loc)); - } - - // Assign the rhs temp (now with W reciprocal) to the final output - { - TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc); - assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, left, rhsTempSym, loc)); - } - - assert(assignList != nullptr); - assignList->setOperator(EOpSequence); - - return assignList; -} - -// Position may require special handling: we can optionally invert Y. -// See: https://github.com/KhronosGroup/glslang/issues/1173 -// https://github.com/KhronosGroup/glslang/issues/494 -TIntermTyped* HlslParseContext::assignPosition(const TSourceLoc& loc, TOperator op, - TIntermTyped* left, TIntermTyped* right) -{ - // If we are not asked for Y inversion, use a plain old assign. - if (!intermediate.getInvertY()) - return intermediate.addAssign(op, left, right, loc); - - // If we get here, we should invert Y. - TIntermAggregate* assignList = nullptr; - - // If this is a complex rvalue, we don't want to dereference it many times. Create a temporary. - TVariable* rhsTempVar = nullptr; - rhsTempVar = makeInternalVariable("@position", right->getType()); - rhsTempVar->getWritableType().getQualifier().makeTemporary(); - - { - TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc); - assignList = intermediate.growAggregate(assignList, - intermediate.addAssign(EOpAssign, rhsTempSym, right, loc), loc); - } - - // pos.y = -pos.y - { - const int Y = 1; - - TIntermTyped* tempSymL = intermediate.addSymbol(*rhsTempVar, loc); - TIntermTyped* tempSymR = intermediate.addSymbol(*rhsTempVar, loc); - TIntermTyped* index = intermediate.addConstantUnion(Y, loc); - - TIntermTyped* lhsElement = intermediate.addIndex(EOpIndexDirect, tempSymL, index, loc); - TIntermTyped* rhsElement = intermediate.addIndex(EOpIndexDirect, tempSymR, index, loc); - - const TType derefType(right->getType(), 0); - - lhsElement->setType(derefType); - rhsElement->setType(derefType); - - TIntermTyped* yNeg = intermediate.addUnaryMath(EOpNegative, rhsElement, loc); - - assignList = intermediate.growAggregate(assignList, intermediate.addAssign(EOpAssign, lhsElement, yNeg, loc)); - } - - // Assign the rhs temp (now with Y inversion) to the final output - { - TIntermTyped* rhsTempSym = intermediate.addSymbol(*rhsTempVar, loc); - assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, left, rhsTempSym, loc)); - } - - assert(assignList != nullptr); - assignList->setOperator(EOpSequence); - - return assignList; -} - -// Clip and cull distance require special handling due to a semantic mismatch. In HLSL, -// these can be float scalar, float vector, or arrays of float scalar or float vector. -// In SPIR-V, they are arrays of scalar floats in all cases. We must copy individual components -// (e.g, both x and y components of a float2) out into the destination float array. -// -// The values are assigned to sequential members of the output array. The inner dimension -// is vector components. The outer dimension is array elements. -TIntermAggregate* HlslParseContext::assignClipCullDistance(const TSourceLoc& loc, TOperator op, int semanticId, - TIntermTyped* left, TIntermTyped* right) -{ - switch (language) { - case EShLangFragment: - case EShLangVertex: - case EShLangGeometry: - break; - default: - error(loc, "unimplemented: clip/cull not currently implemented for this stage", "", ""); - return nullptr; - } - - TVariable** clipCullVar = nullptr; - - // Figure out if we are assigning to, or from, clip or cull distance. - const bool isOutput = isClipOrCullDistance(left->getType()); - - // This is the rvalue or lvalue holding the clip or cull distance. - TIntermTyped* clipCullNode = isOutput ? left : right; - // This is the value going into or out of the clip or cull distance. - TIntermTyped* internalNode = isOutput ? right : left; - - const TBuiltInVariable builtInType = clipCullNode->getQualifier().builtIn; - - decltype(clipSemanticNSizeIn)* semanticNSize = nullptr; - - // Refer to either the clip or the cull distance, depending on semantic. - switch (builtInType) { - case EbvClipDistance: - clipCullVar = isOutput ? &clipDistanceOutput : &clipDistanceInput; - semanticNSize = isOutput ? &clipSemanticNSizeOut : &clipSemanticNSizeIn; - break; - case EbvCullDistance: - clipCullVar = isOutput ? &cullDistanceOutput : &cullDistanceInput; - semanticNSize = isOutput ? &cullSemanticNSizeOut : &cullSemanticNSizeIn; - break; - - // called invalidly: we expected a clip or a cull distance. - // static compile time problem: should not happen. - default: assert(0); return nullptr; - } - - // This is the offset in the destination array of a given semantic's data - std::array semanticOffset; - - // Calculate offset of variable of semantic N in destination array - int arrayLoc = 0; - int vecItems = 0; - - for (int x = 0; x < maxClipCullRegs; ++x) { - // See if we overflowed the vec4 packing - if ((vecItems + (*semanticNSize)[x]) > 4) { - arrayLoc = (arrayLoc + 3) & (~0x3); // round up to next multiple of 4 - vecItems = 0; - } - - semanticOffset[x] = arrayLoc; - vecItems += (*semanticNSize)[x]; - arrayLoc += (*semanticNSize)[x]; - } - - - // It can have up to 2 array dimensions (in the case of geometry shader inputs) - const TArraySizes* const internalArraySizes = internalNode->getType().getArraySizes(); - const int internalArrayDims = internalNode->getType().isArray() ? internalArraySizes->getNumDims() : 0; - // vector sizes: - const int internalVectorSize = internalNode->getType().getVectorSize(); - // array sizes, or 1 if it's not an array: - const int internalInnerArraySize = (internalArrayDims > 0 ? internalArraySizes->getDimSize(internalArrayDims-1) : 1); - const int internalOuterArraySize = (internalArrayDims > 1 ? internalArraySizes->getDimSize(0) : 1); - - // The created type may be an array of arrays, e.g, for geometry shader inputs. - const bool isImplicitlyArrayed = (language == EShLangGeometry && !isOutput); - - // If we haven't created the output already, create it now. - if (*clipCullVar == nullptr) { - // ClipDistance and CullDistance are handled specially in the entry point input/output copy - // algorithm, because they may need to be unpacked from components of vectors (or a scalar) - // into a float array, or vice versa. Here, we make the array the right size and type, - // which depends on the incoming data, which has several potential dimensions: - // * Semantic ID - // * vector size - // * array size - // Of those, semantic ID and array size cannot appear simultaneously. - // - // Also to note: for implicitly arrayed forms (e.g, geometry shader inputs), we need to create two - // array dimensions. The shader's declaration may have one or two array dimensions. One is always - // the geometry's dimension. - - const bool useInnerSize = internalArrayDims > 1 || !isImplicitlyArrayed; - - const int requiredInnerArraySize = arrayLoc * (useInnerSize ? internalInnerArraySize : 1); - const int requiredOuterArraySize = (internalArrayDims > 0) ? internalArraySizes->getDimSize(0) : 1; - - TType clipCullType(EbtFloat, clipCullNode->getType().getQualifier().storage, 1); - clipCullType.getQualifier() = clipCullNode->getType().getQualifier(); - - // Create required array dimension - TArraySizes* arraySizes = new TArraySizes; - if (isImplicitlyArrayed) - arraySizes->addInnerSize(requiredOuterArraySize); - arraySizes->addInnerSize(requiredInnerArraySize); - clipCullType.transferArraySizes(arraySizes); - - // Obtain symbol name: we'll use that for the symbol we introduce. - TIntermSymbol* sym = clipCullNode->getAsSymbolNode(); - assert(sym != nullptr); - - // We are moving the semantic ID from the layout location, so it is no longer needed or - // desired there. - clipCullType.getQualifier().layoutLocation = TQualifier::layoutLocationEnd; - - // Create variable and track its linkage - *clipCullVar = makeInternalVariable(sym->getName().c_str(), clipCullType); - - trackLinkage(**clipCullVar); - } - - // Create symbol for the clip or cull variable. - TIntermSymbol* clipCullSym = intermediate.addSymbol(**clipCullVar); - - // vector sizes: - const int clipCullVectorSize = clipCullSym->getType().getVectorSize(); - - // array sizes, or 1 if it's not an array: - const TArraySizes* const clipCullArraySizes = clipCullSym->getType().getArraySizes(); - const int clipCullOuterArraySize = isImplicitlyArrayed ? clipCullArraySizes->getDimSize(0) : 1; - const int clipCullInnerArraySize = clipCullArraySizes->getDimSize(isImplicitlyArrayed ? 1 : 0); - - // clipCullSym has got to be an array of scalar floats, per SPIR-V semantics. - // fixBuiltInIoType() should have handled that upstream. - assert(clipCullSym->getType().isArray()); - assert(clipCullSym->getType().getVectorSize() == 1); - assert(clipCullSym->getType().getBasicType() == EbtFloat); - - // We may be creating multiple sub-assignments. This is an aggregate to hold them. - // TODO: it would be possible to be clever sometimes and avoid the sequence node if not needed. - TIntermAggregate* assignList = nullptr; - - // Holds individual component assignments as we make them. - TIntermTyped* clipCullAssign = nullptr; - - // If the types are homomorphic, use a simple assign. No need to mess about with - // individual components. - if (clipCullSym->getType().isArray() == internalNode->getType().isArray() && - clipCullInnerArraySize == internalInnerArraySize && - clipCullOuterArraySize == internalOuterArraySize && - clipCullVectorSize == internalVectorSize) { - - if (isOutput) - clipCullAssign = intermediate.addAssign(op, clipCullSym, internalNode, loc); - else - clipCullAssign = intermediate.addAssign(op, internalNode, clipCullSym, loc); - - assignList = intermediate.growAggregate(assignList, clipCullAssign); - assignList->setOperator(EOpSequence); - - return assignList; - } - - // We are going to copy each component of the internal (per array element if indicated) to sequential - // array elements of the clipCullSym. This tracks the lhs element we're writing to as we go along. - // We may be starting in the middle - e.g, for a non-zero semantic ID calculated above. - int clipCullInnerArrayPos = semanticOffset[semanticId]; - int clipCullOuterArrayPos = 0; - - // Lambda to add an index to a node, set the type of the result, and return the new node. - const auto addIndex = [this, &loc](TIntermTyped* node, int pos) -> TIntermTyped* { - const TType derefType(node->getType(), 0); - node = intermediate.addIndex(EOpIndexDirect, node, intermediate.addConstantUnion(pos, loc), loc); - node->setType(derefType); - return node; - }; - - // Loop through every component of every element of the internal, and copy to or from the matching external. - for (int internalOuterArrayPos = 0; internalOuterArrayPos < internalOuterArraySize; ++internalOuterArrayPos) { - for (int internalInnerArrayPos = 0; internalInnerArrayPos < internalInnerArraySize; ++internalInnerArrayPos) { - for (int internalComponent = 0; internalComponent < internalVectorSize; ++internalComponent) { - // clip/cull array member to read from / write to: - TIntermTyped* clipCullMember = clipCullSym; - - // If implicitly arrayed, there is an outer array dimension involved - if (isImplicitlyArrayed) - clipCullMember = addIndex(clipCullMember, clipCullOuterArrayPos); - - // Index into proper array position for clip cull member - clipCullMember = addIndex(clipCullMember, clipCullInnerArrayPos++); - - // if needed, start over with next outer array slice. - if (isImplicitlyArrayed && clipCullInnerArrayPos >= clipCullInnerArraySize) { - clipCullInnerArrayPos = semanticOffset[semanticId]; - ++clipCullOuterArrayPos; - } - - // internal member to read from / write to: - TIntermTyped* internalMember = internalNode; - - // If internal node has outer array dimension, index appropriately. - if (internalArrayDims > 1) - internalMember = addIndex(internalMember, internalOuterArrayPos); - - // If internal node has inner array dimension, index appropriately. - if (internalArrayDims > 0) - internalMember = addIndex(internalMember, internalInnerArrayPos); - - // If internal node is a vector, extract the component of interest. - if (internalNode->getType().isVector()) - internalMember = addIndex(internalMember, internalComponent); - - // Create an assignment: output from internal to clip cull, or input from clip cull to internal. - if (isOutput) - clipCullAssign = intermediate.addAssign(op, clipCullMember, internalMember, loc); - else - clipCullAssign = intermediate.addAssign(op, internalMember, clipCullMember, loc); - - // Track assignment in the sequence. - assignList = intermediate.growAggregate(assignList, clipCullAssign); - } - } - } - - assert(assignList != nullptr); - assignList->setOperator(EOpSequence); - - return assignList; -} - -// Some simple source assignments need to be flattened to a sequence -// of AST assignments. Catch these and flatten, otherwise, pass through -// to intermediate.addAssign(). -// -// Also, assignment to matrix swizzles requires multiple component assignments, -// intercept those as well. -TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op, TIntermTyped* left, - TIntermTyped* right) -{ - if (left == nullptr || right == nullptr) - return nullptr; - - // writing to opaques will require fixing transforms - if (left->getType().containsOpaque()) - intermediate.setNeedsLegalization(); - - if (left->getAsOperator() && left->getAsOperator()->getOp() == EOpMatrixSwizzle) - return handleAssignToMatrixSwizzle(loc, op, left, right); - - // Return true if the given node is an index operation into a split variable. - const auto indexesSplit = [this](const TIntermTyped* node) -> bool { - const TIntermBinary* binaryNode = node->getAsBinaryNode(); - - if (binaryNode == nullptr) - return false; - - return (binaryNode->getOp() == EOpIndexDirect || binaryNode->getOp() == EOpIndexIndirect) && - wasSplit(binaryNode->getLeft()); - }; - - // Return symbol if node is symbol or index ref - const auto getSymbol = [](const TIntermTyped* node) -> const TIntermSymbol* { - const TIntermSymbol* symbolNode = node->getAsSymbolNode(); - if (symbolNode != nullptr) - return symbolNode; - - const TIntermBinary* binaryNode = node->getAsBinaryNode(); - if (binaryNode != nullptr && (binaryNode->getOp() == EOpIndexDirect || binaryNode->getOp() == EOpIndexIndirect)) - return binaryNode->getLeft()->getAsSymbolNode(); - - return nullptr; - }; - - // Return true if this stage assigns clip position with potentially inverted Y - const auto assignsClipPos = [this](const TIntermTyped* node) -> bool { - return node->getType().getQualifier().builtIn == EbvPosition && - (language == EShLangVertex || language == EShLangGeometry || language == EShLangTessEvaluation); - }; - - const TIntermSymbol* leftSymbol = getSymbol(left); - const TIntermSymbol* rightSymbol = getSymbol(right); - - const bool isSplitLeft = wasSplit(left) || indexesSplit(left); - const bool isSplitRight = wasSplit(right) || indexesSplit(right); - - const bool isFlattenLeft = wasFlattened(leftSymbol); - const bool isFlattenRight = wasFlattened(rightSymbol); - - // OK to do a single assign if neither side is split or flattened. Otherwise, - // fall through to a member-wise copy. - if (!isFlattenLeft && !isFlattenRight && !isSplitLeft && !isSplitRight) { - // Clip and cull distance requires more processing. See comment above assignClipCullDistance. - if (isClipOrCullDistance(left->getType()) || isClipOrCullDistance(right->getType())) { - const bool isOutput = isClipOrCullDistance(left->getType()); - - const int semanticId = (isOutput ? left : right)->getType().getQualifier().layoutLocation; - return assignClipCullDistance(loc, op, semanticId, left, right); - } else if (assignsClipPos(left)) { - // Position can require special handling: see comment above assignPosition - return assignPosition(loc, op, left, right); - } else if (left->getQualifier().builtIn == EbvSampleMask) { - // Certain builtins are required to be arrayed outputs in SPIR-V, but may internally be scalars - // in the shader. Copy the scalar RHS into the LHS array element zero, if that happens. - if (left->isArray() && !right->isArray()) { - const TType derefType(left->getType(), 0); - left = intermediate.addIndex(EOpIndexDirect, left, intermediate.addConstantUnion(0, loc), loc); - left->setType(derefType); - // Fall through to add assign. - } - } - - return intermediate.addAssign(op, left, right, loc); - } - - TIntermAggregate* assignList = nullptr; - const TVector* leftVariables = nullptr; - const TVector* rightVariables = nullptr; - - // A temporary to store the right node's value, so we don't keep indirecting into it - // if it's not a simple symbol. - TVariable* rhsTempVar = nullptr; - - // If the RHS is a simple symbol node, we'll copy it for each member. - TIntermSymbol* cloneSymNode = nullptr; - - int memberCount = 0; - - // Track how many items there are to copy. - if (left->getType().isStruct()) - memberCount = (int)left->getType().getStruct()->size(); - if (left->getType().isArray()) - memberCount = left->getType().getCumulativeArraySize(); - - if (isFlattenLeft) - leftVariables = &flattenMap.find(leftSymbol->getId())->second.members; - - if (isFlattenRight) { - rightVariables = &flattenMap.find(rightSymbol->getId())->second.members; - } else { - // The RHS is not flattened. There are several cases: - // 1. 1 item to copy: Use the RHS directly. - // 2. >1 item, simple symbol RHS: we'll create a new TIntermSymbol node for each, but no assign to temp. - // 3. >1 item, complex RHS: assign it to a new temp variable, and create a TIntermSymbol for each member. - - if (memberCount <= 1) { - // case 1: we'll use the symbol directly below. Nothing to do. - } else { - if (right->getAsSymbolNode() != nullptr) { - // case 2: we'll copy the symbol per iteration below. - cloneSymNode = right->getAsSymbolNode(); - } else { - // case 3: assign to a temp, and indirect into that. - rhsTempVar = makeInternalVariable("flattenTemp", right->getType()); - rhsTempVar->getWritableType().getQualifier().makeTemporary(); - TIntermTyped* noFlattenRHS = intermediate.addSymbol(*rhsTempVar, loc); - - // Add this to the aggregate being built. - assignList = intermediate.growAggregate(assignList, - intermediate.addAssign(op, noFlattenRHS, right, loc), loc); - } - } - } - - // When dealing with split arrayed structures of built-ins, the arrayness is moved to the extracted built-in - // variables, which is awkward when copying between split and unsplit structures. This variable tracks - // array indirections so they can be percolated from outer structs to inner variables. - std::vector arrayElement; - - TStorageQualifier leftStorage = left->getType().getQualifier().storage; - TStorageQualifier rightStorage = right->getType().getQualifier().storage; - - int leftOffsetStart = findSubtreeOffset(*left); - int rightOffsetStart = findSubtreeOffset(*right); - int leftOffset = leftOffsetStart; - int rightOffset = rightOffsetStart; - - const auto getMember = [&](bool isLeft, const TType& type, int member, TIntermTyped* splitNode, int splitMember, - bool flattened) - -> TIntermTyped * { - const bool split = isLeft ? isSplitLeft : isSplitRight; - - TIntermTyped* subTree; - const TType derefType(type, member); - const TVariable* builtInVar = nullptr; - if ((flattened || split) && derefType.isBuiltIn()) { - auto splitPair = splitBuiltIns.find(HlslParseContext::tInterstageIoData( - derefType.getQualifier().builtIn, - isLeft ? leftStorage : rightStorage)); - if (splitPair != splitBuiltIns.end()) - builtInVar = splitPair->second; - } - if (builtInVar != nullptr) { - // copy from interstage IO built-in if needed - subTree = intermediate.addSymbol(*builtInVar); - - if (subTree->getType().isArray()) { - // Arrayness of builtIn symbols isn't handled by the normal recursion: - // it's been extracted and moved to the built-in. - if (!arrayElement.empty()) { - const TType splitDerefType(subTree->getType(), arrayElement.back()); - subTree = intermediate.addIndex(EOpIndexDirect, subTree, - intermediate.addConstantUnion(arrayElement.back(), loc), loc); - subTree->setType(splitDerefType); - } else if (splitNode->getAsOperator() != nullptr && (splitNode->getAsOperator()->getOp() == EOpIndexIndirect)) { - // This might also be a stage with arrayed outputs, in which case there's an index - // operation we should transfer to the output builtin. - - const TType splitDerefType(subTree->getType(), 0); - subTree = intermediate.addIndex(splitNode->getAsOperator()->getOp(), subTree, - splitNode->getAsBinaryNode()->getRight(), loc); - subTree->setType(splitDerefType); - } - } - } else if (flattened && !shouldFlatten(derefType, isLeft ? leftStorage : rightStorage, false)) { - if (isLeft) { - // offset will cycle through variables for arrayed io - if (leftOffset >= static_cast(leftVariables->size())) - leftOffset = leftOffsetStart; - subTree = intermediate.addSymbol(*(*leftVariables)[leftOffset++]); - } else { - // offset will cycle through variables for arrayed io - if (rightOffset >= static_cast(rightVariables->size())) - rightOffset = rightOffsetStart; - subTree = intermediate.addSymbol(*(*rightVariables)[rightOffset++]); - } - - // arrayed io - if (subTree->getType().isArray()) { - if (!arrayElement.empty()) { - const TType derefType(subTree->getType(), arrayElement.front()); - subTree = intermediate.addIndex(EOpIndexDirect, subTree, - intermediate.addConstantUnion(arrayElement.front(), loc), loc); - subTree->setType(derefType); - } else { - // There's an index operation we should transfer to the output builtin. - assert(splitNode->getAsOperator() != nullptr && - splitNode->getAsOperator()->getOp() == EOpIndexIndirect); - const TType splitDerefType(subTree->getType(), 0); - subTree = intermediate.addIndex(splitNode->getAsOperator()->getOp(), subTree, - splitNode->getAsBinaryNode()->getRight(), loc); - subTree->setType(splitDerefType); - } - } - } else { - // Index operator if it's an aggregate, else EOpNull - const TOperator accessOp = type.isArray() ? EOpIndexDirect - : type.isStruct() ? EOpIndexDirectStruct - : EOpNull; - if (accessOp == EOpNull) { - subTree = splitNode; - } else { - subTree = intermediate.addIndex(accessOp, splitNode, intermediate.addConstantUnion(splitMember, loc), - loc); - const TType splitDerefType(splitNode->getType(), splitMember); - subTree->setType(splitDerefType); - } - } - - return subTree; - }; - - // Use the proper RHS node: a new symbol from a TVariable, copy - // of an TIntermSymbol node, or sometimes the right node directly. - right = rhsTempVar != nullptr ? intermediate.addSymbol(*rhsTempVar, loc) : - cloneSymNode != nullptr ? intermediate.addSymbol(*cloneSymNode) : - right; - - // Cannot use auto here, because this is recursive, and auto can't work out the type without seeing the - // whole thing. So, we'll resort to an explicit type via std::function. - const std::function - traverse = [&](TIntermTyped* left, TIntermTyped* right, TIntermTyped* splitLeft, TIntermTyped* splitRight, - bool topLevel) -> void { - // If we get here, we are assigning to or from a whole array or struct that must be - // flattened, so have to do member-by-member assignment: - - bool shouldFlattenSubsetLeft = isFlattenLeft && shouldFlatten(left->getType(), leftStorage, topLevel); - bool shouldFlattenSubsetRight = isFlattenRight && shouldFlatten(right->getType(), rightStorage, topLevel); - - if ((left->getType().isArray() || right->getType().isArray()) && - (shouldFlattenSubsetLeft || isSplitLeft || - shouldFlattenSubsetRight || isSplitRight)) { - const int elementsL = left->getType().isArray() ? left->getType().getOuterArraySize() : 1; - const int elementsR = right->getType().isArray() ? right->getType().getOuterArraySize() : 1; - - // The arrays might not be the same size, - // e.g., if the size has been forced for EbvTessLevelInner/Outer. - const int elementsToCopy = std::min(elementsL, elementsR); - - // array case - for (int element = 0; element < elementsToCopy; ++element) { - arrayElement.push_back(element); - - // Add a new AST symbol node if we have a temp variable holding a complex RHS. - TIntermTyped* subLeft = getMember(true, left->getType(), element, left, element, - shouldFlattenSubsetLeft); - TIntermTyped* subRight = getMember(false, right->getType(), element, right, element, - shouldFlattenSubsetRight); - - TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left->getType(), element, splitLeft, - element, shouldFlattenSubsetLeft) - : subLeft; - TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), element, splitRight, - element, shouldFlattenSubsetRight) - : subRight; - - traverse(subLeft, subRight, subSplitLeft, subSplitRight, false); - - arrayElement.pop_back(); - } - } else if (left->getType().isStruct() && (shouldFlattenSubsetLeft || isSplitLeft || - shouldFlattenSubsetRight || isSplitRight)) { - // struct case - const auto& membersL = *left->getType().getStruct(); - const auto& membersR = *right->getType().getStruct(); - - // These track the members in the split structures corresponding to the same in the unsplit structures, - // which we traverse in parallel. - int memberL = 0; - int memberR = 0; - - // Handle empty structure assignment - if (int(membersL.size()) == 0 && int(membersR.size()) == 0) - assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, left, right, loc), loc); - - for (int member = 0; member < int(membersL.size()); ++member) { - const TType& typeL = *membersL[member].type; - const TType& typeR = *membersR[member].type; - - TIntermTyped* subLeft = getMember(true, left->getType(), member, left, member, - shouldFlattenSubsetLeft); - TIntermTyped* subRight = getMember(false, right->getType(), member, right, member, - shouldFlattenSubsetRight); - - // If there is no splitting, use the same values to avoid inefficiency. - TIntermTyped* subSplitLeft = isSplitLeft ? getMember(true, left->getType(), member, splitLeft, - memberL, shouldFlattenSubsetLeft) - : subLeft; - TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right->getType(), member, splitRight, - memberR, shouldFlattenSubsetRight) - : subRight; - - if (isClipOrCullDistance(subSplitLeft->getType()) || isClipOrCullDistance(subSplitRight->getType())) { - // Clip and cull distance built-in assignment is complex in its own right, and is handled in - // a separate function dedicated to that task. See comment above assignClipCullDistance; - - const bool isOutput = isClipOrCullDistance(subSplitLeft->getType()); - - // Since all clip/cull semantics boil down to the same built-in type, we need to get the - // semantic ID from the dereferenced type's layout location, to avoid an N-1 mapping. - const TType derefType((isOutput ? left : right)->getType(), member); - const int semanticId = derefType.getQualifier().layoutLocation; - - TIntermAggregate* clipCullAssign = assignClipCullDistance(loc, op, semanticId, - subSplitLeft, subSplitRight); - - assignList = intermediate.growAggregate(assignList, clipCullAssign, loc); - } else if (subSplitRight->getType().getQualifier().builtIn == EbvFragCoord) { - // FragCoord can require special handling: see comment above assignFromFragCoord - TIntermTyped* fragCoordAssign = assignFromFragCoord(loc, op, subSplitLeft, subSplitRight); - assignList = intermediate.growAggregate(assignList, fragCoordAssign, loc); - } else if (assignsClipPos(subSplitLeft)) { - // Position can require special handling: see comment above assignPosition - TIntermTyped* positionAssign = assignPosition(loc, op, subSplitLeft, subSplitRight); - assignList = intermediate.growAggregate(assignList, positionAssign, loc); - } else if (!shouldFlattenSubsetLeft && !shouldFlattenSubsetRight && - !typeL.containsBuiltIn() && !typeR.containsBuiltIn()) { - // If this is the final flattening (no nested types below to flatten) - // we'll copy the member, else recurse into the type hierarchy. - // However, if splitting the struct, that means we can copy a whole - // subtree here IFF it does not itself contain any interstage built-in - // IO variables, so we only have to recurse into it if there's something - // for splitting to do. That can save a lot of AST verbosity for - // a bunch of memberwise copies. - - assignList = intermediate.growAggregate(assignList, - intermediate.addAssign(op, subSplitLeft, subSplitRight, loc), - loc); - } else { - traverse(subLeft, subRight, subSplitLeft, subSplitRight, false); - } - - memberL += (typeL.isBuiltIn() ? 0 : 1); - memberR += (typeR.isBuiltIn() ? 0 : 1); - } - } else { - // Member copy - assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, left, right, loc), loc); - } - - }; - - TIntermTyped* splitLeft = left; - TIntermTyped* splitRight = right; - - // If either left or right was a split structure, we must read or write it, but still have to - // parallel-recurse through the unsplit structure to identify the built-in IO vars. - // The left can be either a symbol, or an index into a symbol (e.g, array reference) - if (isSplitLeft) { - if (indexesSplit(left)) { - // Index case: Refer to the indexed symbol, if the left is an index operator. - const TIntermSymbol* symNode = left->getAsBinaryNode()->getLeft()->getAsSymbolNode(); - - TIntermTyped* splitLeftNonIo = intermediate.addSymbol(*getSplitNonIoVar(symNode->getId()), loc); - - splitLeft = intermediate.addIndex(left->getAsBinaryNode()->getOp(), splitLeftNonIo, - left->getAsBinaryNode()->getRight(), loc); - - const TType derefType(splitLeftNonIo->getType(), 0); - splitLeft->setType(derefType); - } else { - // Symbol case: otherwise, if not indexed, we have the symbol directly. - const TIntermSymbol* symNode = left->getAsSymbolNode(); - splitLeft = intermediate.addSymbol(*getSplitNonIoVar(symNode->getId()), loc); - } - } - - if (isSplitRight) - splitRight = intermediate.addSymbol(*getSplitNonIoVar(right->getAsSymbolNode()->getId()), loc); - - // This makes the whole assignment, recursing through subtypes as needed. - traverse(left, right, splitLeft, splitRight, true); - - assert(assignList != nullptr); - assignList->setOperator(EOpSequence); - - return assignList; -} - -// An assignment to matrix swizzle must be decomposed into individual assignments. -// These must be selected component-wise from the RHS and stored component-wise -// into the LHS. -TIntermTyped* HlslParseContext::handleAssignToMatrixSwizzle(const TSourceLoc& loc, TOperator op, TIntermTyped* left, - TIntermTyped* right) -{ - assert(left->getAsOperator() && left->getAsOperator()->getOp() == EOpMatrixSwizzle); - - if (op != EOpAssign) - error(loc, "only simple assignment to non-simple matrix swizzle is supported", "assign", ""); - - // isolate the matrix and swizzle nodes - TIntermTyped* matrix = left->getAsBinaryNode()->getLeft()->getAsTyped(); - const TIntermSequence& swizzle = left->getAsBinaryNode()->getRight()->getAsAggregate()->getSequence(); - - // if the RHS isn't already a simple vector, let's store into one - TIntermSymbol* vector = right->getAsSymbolNode(); - TIntermTyped* vectorAssign = nullptr; - if (vector == nullptr) { - // create a new intermediate vector variable to assign to - TType vectorType(matrix->getBasicType(), EvqTemporary, matrix->getQualifier().precision, (int)swizzle.size()/2); - vector = intermediate.addSymbol(*makeInternalVariable("intermVec", vectorType), loc); - - // assign the right to the new vector - vectorAssign = handleAssign(loc, op, vector, right); - } - - // Assign the vector components to the matrix components. - // Store this as a sequence, so a single aggregate node represents this - // entire operation. - TIntermAggregate* result = intermediate.makeAggregate(vectorAssign); - TType columnType(matrix->getType(), 0); - TType componentType(columnType, 0); - TType indexType(EbtInt); - for (int i = 0; i < (int)swizzle.size(); i += 2) { - // the right component, single index into the RHS vector - TIntermTyped* rightComp = intermediate.addIndex(EOpIndexDirect, vector, - intermediate.addConstantUnion(i/2, loc), loc); - - // the left component, double index into the LHS matrix - TIntermTyped* leftComp = intermediate.addIndex(EOpIndexDirect, matrix, - intermediate.addConstantUnion(swizzle[i]->getAsConstantUnion()->getConstArray(), - indexType, loc), - loc); - leftComp->setType(columnType); - leftComp = intermediate.addIndex(EOpIndexDirect, leftComp, - intermediate.addConstantUnion(swizzle[i+1]->getAsConstantUnion()->getConstArray(), - indexType, loc), - loc); - leftComp->setType(componentType); - - // Add the assignment to the aggregate - result = intermediate.growAggregate(result, intermediate.addAssign(op, leftComp, rightComp, loc)); - } - - result->setOp(EOpSequence); - - return result; -} - -// -// HLSL atomic operations have slightly different arguments than -// GLSL/AST/SPIRV. The semantics are converted below in decomposeIntrinsic. -// This provides the post-decomposition equivalent opcode. -// -TOperator HlslParseContext::mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage) -{ - switch (op) { - case EOpInterlockedAdd: return isImage ? EOpImageAtomicAdd : EOpAtomicAdd; - case EOpInterlockedAnd: return isImage ? EOpImageAtomicAnd : EOpAtomicAnd; - case EOpInterlockedCompareExchange: return isImage ? EOpImageAtomicCompSwap : EOpAtomicCompSwap; - case EOpInterlockedMax: return isImage ? EOpImageAtomicMax : EOpAtomicMax; - case EOpInterlockedMin: return isImage ? EOpImageAtomicMin : EOpAtomicMin; - case EOpInterlockedOr: return isImage ? EOpImageAtomicOr : EOpAtomicOr; - case EOpInterlockedXor: return isImage ? EOpImageAtomicXor : EOpAtomicXor; - case EOpInterlockedExchange: return isImage ? EOpImageAtomicExchange : EOpAtomicExchange; - case EOpInterlockedCompareStore: // TODO: ... - default: - error(loc, "unknown atomic operation", "unknown op", ""); - return EOpNull; - } -} - -// -// Create a combined sampler/texture from separate sampler and texture. -// -TIntermAggregate* HlslParseContext::handleSamplerTextureCombine(const TSourceLoc& loc, TIntermTyped* argTex, - TIntermTyped* argSampler) -{ - TIntermAggregate* txcombine = new TIntermAggregate(EOpConstructTextureSampler); - - txcombine->getSequence().push_back(argTex); - txcombine->getSequence().push_back(argSampler); - - TSampler samplerType = argTex->getType().getSampler(); - samplerType.combined = true; - - // TODO: - // This block exists until the spec no longer requires shadow modes on texture objects. - // It can be deleted after that, along with the shadowTextureVariant member. - { - const bool shadowMode = argSampler->getType().getSampler().shadow; - - TIntermSymbol* texSymbol = argTex->getAsSymbolNode(); - - if (texSymbol == nullptr) - texSymbol = argTex->getAsBinaryNode()->getLeft()->getAsSymbolNode(); - - if (texSymbol == nullptr) { - error(loc, "unable to find texture symbol", "", ""); - return nullptr; - } - - // This forces the texture's shadow state to be the sampler's - // shadow state. This depends on downstream optimization to - // DCE one variant in [shadow, nonshadow] if both are present, - // or the SPIR-V module would be invalid. - long long newId = texSymbol->getId(); - - // Check to see if this texture has been given a shadow mode already. - // If so, look up the one we already have. - const auto textureShadowEntry = textureShadowVariant.find(texSymbol->getId()); - - if (textureShadowEntry != textureShadowVariant.end()) - newId = textureShadowEntry->second->get(shadowMode); - else - textureShadowVariant[texSymbol->getId()] = NewPoolObject(tShadowTextureSymbols(), 1); - - // Sometimes we have to create another symbol (if this texture has been seen before, - // and we haven't created the form for this shadow mode). - if (newId == -1) { - TType texType; - texType.shallowCopy(argTex->getType()); - texType.getSampler().shadow = shadowMode; // set appropriate shadow mode. - globalQualifierFix(loc, texType.getQualifier()); - - TVariable* newTexture = makeInternalVariable(texSymbol->getName(), texType); - - trackLinkage(*newTexture); - - newId = newTexture->getUniqueId(); - } - - assert(newId != -1); - - if (textureShadowVariant.find(newId) == textureShadowVariant.end()) - textureShadowVariant[newId] = textureShadowVariant[texSymbol->getId()]; - - textureShadowVariant[newId]->set(shadowMode, newId); - - // Remember this shadow mode in the texture and the merged type. - argTex->getWritableType().getSampler().shadow = shadowMode; - samplerType.shadow = shadowMode; - - texSymbol->switchId(newId); - } - - txcombine->setType(TType(samplerType, EvqTemporary)); - txcombine->setLoc(loc); - - return txcombine; -} - -// Return true if this a buffer type that has an associated counter buffer. -bool HlslParseContext::hasStructBuffCounter(const TType& type) const -{ - switch (type.getQualifier().declaredBuiltIn) { - case EbvAppendConsume: // fall through... - case EbvRWStructuredBuffer: // ... - return true; - default: - return false; // the other structuredbuffer types do not have a counter. - } -} - -void HlslParseContext::counterBufferType(const TSourceLoc& loc, TType& type) -{ - // Counter type - TType* counterType = new TType(EbtUint, EvqBuffer); - counterType->setFieldName(intermediate.implicitCounterName); - - TTypeList* blockStruct = new TTypeList; - TTypeLoc member = { counterType, loc }; - blockStruct->push_back(member); - - TType blockType(blockStruct, "", counterType->getQualifier()); - blockType.getQualifier().storage = EvqBuffer; - - type.shallowCopy(blockType); - shareStructBufferType(type); -} - -// declare counter for a structured buffer type -void HlslParseContext::declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name) -{ - // Bail out if not a struct buffer - if (! isStructBufferType(bufferType)) - return; - - if (! hasStructBuffCounter(bufferType)) - return; - - TType blockType; - counterBufferType(loc, blockType); - - TString* blockName = NewPoolTString(intermediate.addCounterBufferName(name).c_str()); - - // Counter buffer is not yet in use - structBufferCounter[*blockName] = false; - - shareStructBufferType(blockType); - declareBlock(loc, blockType, blockName); -} - -// return the counter that goes with a given structuredbuffer -TIntermTyped* HlslParseContext::getStructBufferCounter(const TSourceLoc& loc, TIntermTyped* buffer) -{ - // Bail out if not a struct buffer - if (buffer == nullptr || ! isStructBufferType(buffer->getType())) - return nullptr; - - const TString counterBlockName(intermediate.addCounterBufferName(buffer->getAsSymbolNode()->getName())); - - // Mark the counter as being used - structBufferCounter[counterBlockName] = true; - - TIntermTyped* counterVar = handleVariable(loc, &counterBlockName); // find the block structure - TIntermTyped* index = intermediate.addConstantUnion(0, loc); // index to counter inside block struct - - TIntermTyped* counterMember = intermediate.addIndex(EOpIndexDirectStruct, counterVar, index, loc); - counterMember->setType(TType(EbtUint)); - return counterMember; -} - -// -// Decompose structure buffer methods into AST -// -void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TIntermTyped*& node, TIntermNode* arguments) -{ - if (node == nullptr || node->getAsOperator() == nullptr || arguments == nullptr) - return; - - const TOperator op = node->getAsOperator()->getOp(); - TIntermAggregate* argAggregate = arguments->getAsAggregate(); - - // Buffer is the object upon which method is called, so always arg 0 - TIntermTyped* bufferObj = nullptr; - - // The parameters can be an aggregate, or just a the object as a symbol if there are no fn params. - if (argAggregate) { - if (argAggregate->getSequence().empty()) - return; - if (argAggregate->getSequence()[0]) - bufferObj = argAggregate->getSequence()[0]->getAsTyped(); - } else { - bufferObj = arguments->getAsSymbolNode(); - } - - if (bufferObj == nullptr || bufferObj->getAsSymbolNode() == nullptr) - return; - - // Some methods require a hidden internal counter, obtained via getStructBufferCounter(). - // This lambda adds something to it and returns the old value. - const auto incDecCounter = [&](int incval) -> TIntermTyped* { - TIntermTyped* incrementValue = intermediate.addConstantUnion(static_cast(incval), loc, true); - TIntermTyped* counter = getStructBufferCounter(loc, bufferObj); // obtain the counter member - - if (counter == nullptr) - return nullptr; - - TIntermAggregate* counterIncrement = new TIntermAggregate(EOpAtomicAdd); - counterIncrement->setType(TType(EbtUint, EvqTemporary)); - counterIncrement->setLoc(loc); - counterIncrement->getSequence().push_back(counter); - counterIncrement->getSequence().push_back(incrementValue); - - return counterIncrement; - }; - - // Index to obtain the runtime sized array out of the buffer. - TIntermTyped* argArray = indexStructBufferContent(loc, bufferObj); - if (argArray == nullptr) - return; // It might not be a struct buffer method. - - switch (op) { - case EOpMethodLoad: - { - TIntermTyped* argIndex = makeIntegerIndex(argAggregate->getSequence()[1]->getAsTyped()); // index - - const TType& bufferType = bufferObj->getType(); - - const TBuiltInVariable builtInType = bufferType.getQualifier().declaredBuiltIn; - - // Byte address buffers index in bytes (only multiples of 4 permitted... not so much a byte address - // buffer then, but that's what it calls itself. - const bool isByteAddressBuffer = (builtInType == EbvByteAddressBuffer || - builtInType == EbvRWByteAddressBuffer); - - - if (isByteAddressBuffer) - argIndex = intermediate.addBinaryNode(EOpRightShift, argIndex, - intermediate.addConstantUnion(2, loc, true), - loc, TType(EbtInt)); - - // Index into the array to find the item being loaded. - const TOperator idxOp = (argIndex->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect; - - node = intermediate.addIndex(idxOp, argArray, argIndex, loc); - - const TType derefType(argArray->getType(), 0); - node->setType(derefType); - } - - break; - - case EOpMethodLoad2: - case EOpMethodLoad3: - case EOpMethodLoad4: - { - TIntermTyped* argIndex = makeIntegerIndex(argAggregate->getSequence()[1]->getAsTyped()); // index - - TOperator constructOp = EOpNull; - int size = 0; - - switch (op) { - case EOpMethodLoad2: size = 2; constructOp = EOpConstructVec2; break; - case EOpMethodLoad3: size = 3; constructOp = EOpConstructVec3; break; - case EOpMethodLoad4: size = 4; constructOp = EOpConstructVec4; break; - default: assert(0); - } - - TIntermTyped* body = nullptr; - - // First, we'll store the address in a variable to avoid multiple shifts - // (we must convert the byte address to an item address) - TIntermTyped* byteAddrIdx = intermediate.addBinaryNode(EOpRightShift, argIndex, - intermediate.addConstantUnion(2, loc, true), - loc, TType(EbtInt)); - - TVariable* byteAddrSym = makeInternalVariable("byteAddrTemp", TType(EbtInt, EvqTemporary)); - TIntermTyped* byteAddrIdxVar = intermediate.addSymbol(*byteAddrSym, loc); - - body = intermediate.growAggregate(body, intermediate.addAssign(EOpAssign, byteAddrIdxVar, byteAddrIdx, loc)); - - TIntermTyped* vec = nullptr; - - // These are only valid on (rw)byteaddressbuffers, so we can always perform the >>2 - // address conversion. - for (int idx=0; idxgetQualifier().storage == EvqConst) ? EOpIndexDirect - : EOpIndexIndirect; - - TIntermTyped* indexVal = intermediate.addIndex(idxOp, argArray, offsetIdx, loc); - - TType derefType(argArray->getType(), 0); - derefType.getQualifier().makeTemporary(); - indexVal->setType(derefType); - - vec = intermediate.growAggregate(vec, indexVal); - } - - vec->setType(TType(argArray->getBasicType(), EvqTemporary, size)); - vec->getAsAggregate()->setOperator(constructOp); - - body = intermediate.growAggregate(body, vec); - body->setType(vec->getType()); - body->getAsAggregate()->setOperator(EOpSequence); - - node = body; - } - - break; - - case EOpMethodStore: - case EOpMethodStore2: - case EOpMethodStore3: - case EOpMethodStore4: - { - TIntermTyped* argIndex = makeIntegerIndex(argAggregate->getSequence()[1]->getAsTyped()); // index - TIntermTyped* argValue = argAggregate->getSequence()[2]->getAsTyped(); // value - - // Index into the array to find the item being loaded. - // Byte address buffers index in bytes (only multiples of 4 permitted... not so much a byte address - // buffer then, but that's what it calls itself). - - int size = 0; - - switch (op) { - case EOpMethodStore: size = 1; break; - case EOpMethodStore2: size = 2; break; - case EOpMethodStore3: size = 3; break; - case EOpMethodStore4: size = 4; break; - default: assert(0); - } - - TIntermAggregate* body = nullptr; - - // First, we'll store the address in a variable to avoid multiple shifts - // (we must convert the byte address to an item address) - TIntermTyped* byteAddrIdx = intermediate.addBinaryNode(EOpRightShift, argIndex, - intermediate.addConstantUnion(2, loc, true), loc, TType(EbtInt)); - - TVariable* byteAddrSym = makeInternalVariable("byteAddrTemp", TType(EbtInt, EvqTemporary)); - TIntermTyped* byteAddrIdxVar = intermediate.addSymbol(*byteAddrSym, loc); - - body = intermediate.growAggregate(body, intermediate.addAssign(EOpAssign, byteAddrIdxVar, byteAddrIdx, loc)); - - for (int idx=0; idxgetQualifier().storage == EvqConst) ? EOpIndexDirect - : EOpIndexIndirect; - - TIntermTyped* lValue = intermediate.addIndex(idxOp, argArray, offsetIdx, loc); - const TType derefType(argArray->getType(), 0); - lValue->setType(derefType); - - TIntermTyped* rValue; - if (size == 1) { - rValue = argValue; - } else { - rValue = intermediate.addIndex(EOpIndexDirect, argValue, idxConst, loc); - const TType indexType(argValue->getType(), 0); - rValue->setType(indexType); - } - - TIntermTyped* assign = intermediate.addAssign(EOpAssign, lValue, rValue, loc); - - body = intermediate.growAggregate(body, assign); - } - - body->setOperator(EOpSequence); - node = body; - } - - break; - - case EOpMethodGetDimensions: - { - const int numArgs = (int)argAggregate->getSequence().size(); - TIntermTyped* argNumItems = argAggregate->getSequence()[1]->getAsTyped(); // out num items - TIntermTyped* argStride = numArgs > 2 ? argAggregate->getSequence()[2]->getAsTyped() : nullptr; // out stride - - TIntermAggregate* body = nullptr; - - // Length output: - if (argArray->getType().isSizedArray()) { - const int length = argArray->getType().getOuterArraySize(); - TIntermTyped* assign = intermediate.addAssign(EOpAssign, argNumItems, - intermediate.addConstantUnion(length, loc, true), loc); - body = intermediate.growAggregate(body, assign, loc); - } else { - TIntermTyped* lengthCall = intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, argArray, - argNumItems->getType()); - TIntermTyped* assign = intermediate.addAssign(EOpAssign, argNumItems, lengthCall, loc); - body = intermediate.growAggregate(body, assign, loc); - } - - // Stride output: - if (argStride != nullptr) { - int size; - int stride; - intermediate.getMemberAlignment(argArray->getType(), size, stride, argArray->getType().getQualifier().layoutPacking, - argArray->getType().getQualifier().layoutMatrix == ElmRowMajor); - - TIntermTyped* assign = intermediate.addAssign(EOpAssign, argStride, - intermediate.addConstantUnion(stride, loc, true), loc); - - body = intermediate.growAggregate(body, assign); - } - - body->setOperator(EOpSequence); - node = body; - } - - break; - - case EOpInterlockedAdd: - case EOpInterlockedAnd: - case EOpInterlockedExchange: - case EOpInterlockedMax: - case EOpInterlockedMin: - case EOpInterlockedOr: - case EOpInterlockedXor: - case EOpInterlockedCompareExchange: - case EOpInterlockedCompareStore: - { - // We'll replace the first argument with the block dereference, and let - // downstream decomposition handle the rest. - - TIntermSequence& sequence = argAggregate->getSequence(); - - TIntermTyped* argIndex = makeIntegerIndex(sequence[1]->getAsTyped()); // index - argIndex = intermediate.addBinaryNode(EOpRightShift, argIndex, intermediate.addConstantUnion(2, loc, true), - loc, TType(EbtInt)); - - const TOperator idxOp = (argIndex->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect; - TIntermTyped* element = intermediate.addIndex(idxOp, argArray, argIndex, loc); - - const TType derefType(argArray->getType(), 0); - element->setType(derefType); - - // Replace the numeric byte offset parameter with array reference. - sequence[1] = element; - sequence.erase(sequence.begin(), sequence.begin()+1); - } - break; - - case EOpMethodIncrementCounter: - { - node = incDecCounter(1); - break; - } - - case EOpMethodDecrementCounter: - { - TIntermTyped* preIncValue = incDecCounter(-1); // result is original value - node = intermediate.addBinaryNode(EOpAdd, preIncValue, intermediate.addConstantUnion(-1, loc, true), loc, - preIncValue->getType()); - break; - } - - case EOpMethodAppend: - { - TIntermTyped* oldCounter = incDecCounter(1); - - TIntermTyped* lValue = intermediate.addIndex(EOpIndexIndirect, argArray, oldCounter, loc); - TIntermTyped* rValue = argAggregate->getSequence()[1]->getAsTyped(); - - const TType derefType(argArray->getType(), 0); - lValue->setType(derefType); - - node = intermediate.addAssign(EOpAssign, lValue, rValue, loc); - - break; - } - - case EOpMethodConsume: - { - TIntermTyped* oldCounter = incDecCounter(-1); - - TIntermTyped* newCounter = intermediate.addBinaryNode(EOpAdd, oldCounter, - intermediate.addConstantUnion(-1, loc, true), loc, - oldCounter->getType()); - - node = intermediate.addIndex(EOpIndexIndirect, argArray, newCounter, loc); - - const TType derefType(argArray->getType(), 0); - node->setType(derefType); - - break; - } - - default: - break; // most pass through unchanged - } -} - -// Create array of standard sample positions for given sample count. -// TODO: remove when a real method to query sample pos exists in SPIR-V. -TIntermConstantUnion* HlslParseContext::getSamplePosArray(int count) -{ - struct tSamplePos { float x, y; }; - - static const tSamplePos pos1[] = { - { 0.0/16.0, 0.0/16.0 }, - }; - - // standard sample positions for 2, 4, 8, and 16 samples. - static const tSamplePos pos2[] = { - { 4.0/16.0, 4.0/16.0 }, {-4.0/16.0, -4.0/16.0 }, - }; - - static const tSamplePos pos4[] = { - {-2.0/16.0, -6.0/16.0 }, { 6.0/16.0, -2.0/16.0 }, {-6.0/16.0, 2.0/16.0 }, { 2.0/16.0, 6.0/16.0 }, - }; - - static const tSamplePos pos8[] = { - { 1.0/16.0, -3.0/16.0 }, {-1.0/16.0, 3.0/16.0 }, { 5.0/16.0, 1.0/16.0 }, {-3.0/16.0, -5.0/16.0 }, - {-5.0/16.0, 5.0/16.0 }, {-7.0/16.0, -1.0/16.0 }, { 3.0/16.0, 7.0/16.0 }, { 7.0/16.0, -7.0/16.0 }, - }; - - static const tSamplePos pos16[] = { - { 1.0/16.0, 1.0/16.0 }, {-1.0/16.0, -3.0/16.0 }, {-3.0/16.0, 2.0/16.0 }, { 4.0/16.0, -1.0/16.0 }, - {-5.0/16.0, -2.0/16.0 }, { 2.0/16.0, 5.0/16.0 }, { 5.0/16.0, 3.0/16.0 }, { 3.0/16.0, -5.0/16.0 }, - {-2.0/16.0, 6.0/16.0 }, { 0.0/16.0, -7.0/16.0 }, {-4.0/16.0, -6.0/16.0 }, {-6.0/16.0, 4.0/16.0 }, - {-8.0/16.0, 0.0/16.0 }, { 7.0/16.0, -4.0/16.0 }, { 6.0/16.0, 7.0/16.0 }, {-7.0/16.0, -8.0/16.0 }, - }; - - const tSamplePos* sampleLoc = nullptr; - int numSamples = count; - - switch (count) { - case 2: sampleLoc = pos2; break; - case 4: sampleLoc = pos4; break; - case 8: sampleLoc = pos8; break; - case 16: sampleLoc = pos16; break; - default: - sampleLoc = pos1; - numSamples = 1; - } - - TConstUnionArray* values = new TConstUnionArray(numSamples*2); - - for (int pos=0; posaddInnerSize(numSamples); - retType.transferArraySizes(arraySizes); - } - - return new TIntermConstantUnion(*values, retType); -} - -// -// Decompose DX9 and DX10 sample intrinsics & object methods into AST -// -void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermTyped*& node, TIntermNode* arguments) -{ - if (node == nullptr || !node->getAsOperator()) - return; - - // Sampler return must always be a vec4, but we can construct a shorter vector or a structure from it. - const auto convertReturn = [&loc, &node, this](TIntermTyped* result, const TSampler& sampler) -> TIntermTyped* { - result->setType(TType(node->getType().getBasicType(), EvqTemporary, node->getVectorSize())); - - TIntermTyped* convertedResult = nullptr; - - TType retType; - getTextureReturnType(sampler, retType); - - if (retType.isStruct()) { - // For type convenience, conversionAggregate points to the convertedResult (we know it's an aggregate here) - TIntermAggregate* conversionAggregate = new TIntermAggregate; - convertedResult = conversionAggregate; - - // Convert vector output to return structure. We will need a temp symbol to copy the results to. - TVariable* structVar = makeInternalVariable("@sampleStructTemp", retType); - - // We also need a temp symbol to hold the result of the texture. We don't want to re-fetch the - // sample each time we'll index into the result, so we'll copy to this, and index into the copy. - TVariable* sampleShadow = makeInternalVariable("@sampleResultShadow", result->getType()); - - // Initial copy from texture to our sample result shadow. - TIntermTyped* shadowCopy = intermediate.addAssign(EOpAssign, intermediate.addSymbol(*sampleShadow, loc), - result, loc); - - conversionAggregate->getSequence().push_back(shadowCopy); - - unsigned vec4Pos = 0; - - for (unsigned m = 0; m < unsigned(retType.getStruct()->size()); ++m) { - const TType memberType(retType, m); // dereferenced type of the member we're about to assign. - - // Check for bad struct members. This should have been caught upstream. Complain, because - // wwe don't know what to do with it. This algorithm could be generalized to handle - // other things, e.g, sub-structures, but HLSL doesn't allow them. - if (!memberType.isVector() && !memberType.isScalar()) { - error(loc, "expected: scalar or vector type in texture structure", "", ""); - return nullptr; - } - - // Index into the struct variable to find the member to assign. - TIntermTyped* structMember = intermediate.addIndex(EOpIndexDirectStruct, - intermediate.addSymbol(*structVar, loc), - intermediate.addConstantUnion(m, loc), loc); - - structMember->setType(memberType); - - // Assign each component of (possible) vector in struct member. - for (int component = 0; component < memberType.getVectorSize(); ++component) { - TIntermTyped* vec4Member = intermediate.addIndex(EOpIndexDirect, - intermediate.addSymbol(*sampleShadow, loc), - intermediate.addConstantUnion(vec4Pos++, loc), loc); - vec4Member->setType(TType(memberType.getBasicType(), EvqTemporary, 1)); - - TIntermTyped* memberAssign = nullptr; - - if (memberType.isVector()) { - // Vector member: we need to create an access chain to the vector component. - - TIntermTyped* structVecComponent = intermediate.addIndex(EOpIndexDirect, structMember, - intermediate.addConstantUnion(component, loc), loc); - - memberAssign = intermediate.addAssign(EOpAssign, structVecComponent, vec4Member, loc); - } else { - // Scalar member: we can assign to it directly. - memberAssign = intermediate.addAssign(EOpAssign, structMember, vec4Member, loc); - } - - - conversionAggregate->getSequence().push_back(memberAssign); - } - } - - // Add completed variable so the expression results in the whole struct value we just built. - conversionAggregate->getSequence().push_back(intermediate.addSymbol(*structVar, loc)); - - // Make it a sequence. - intermediate.setAggregateOperator(conversionAggregate, EOpSequence, retType, loc); - } else { - // vector clamp the output if template vector type is smaller than sample result. - if (retType.getVectorSize() < node->getVectorSize()) { - // Too many components. Construct shorter vector from it. - const TOperator op = intermediate.mapTypeToConstructorOp(retType); - - convertedResult = constructBuiltIn(retType, op, result, loc, false); - } else { - // Enough components. Use directly. - convertedResult = result; - } - } - - convertedResult->setLoc(loc); - return convertedResult; - }; - - const TOperator op = node->getAsOperator()->getOp(); - const TIntermAggregate* argAggregate = arguments ? arguments->getAsAggregate() : nullptr; - - // Bail out if not a sampler method. - // Note though this is odd to do before checking the op, because the op - // could be something that takes the arguments, and the function in question - // takes the result of the op. So, this is not the final word. - if (arguments != nullptr) { - if (argAggregate == nullptr) { - if (arguments->getAsTyped()->getBasicType() != EbtSampler) - return; - } else { - if (argAggregate->getSequence().size() == 0 || - argAggregate->getSequence()[0] == nullptr || - argAggregate->getSequence()[0]->getAsTyped()->getBasicType() != EbtSampler) - return; - } - } - - switch (op) { - // **** DX9 intrinsics: **** - case EOpTexture: - { - // Texture with ddx & ddy is really gradient form in HLSL - if (argAggregate->getSequence().size() == 4) - node->getAsAggregate()->setOperator(EOpTextureGrad); - - break; - } - case EOpTextureLod: //is almost EOpTextureBias (only args & operations are different) - { - TIntermTyped *argSamp = argAggregate->getSequence()[0]->getAsTyped(); // sampler - TIntermTyped *argCoord = argAggregate->getSequence()[1]->getAsTyped(); // coord - - assert(argCoord->getVectorSize() == 4); - TIntermTyped *w = intermediate.addConstantUnion(3, loc, true); - TIntermTyped *argLod = intermediate.addIndex(EOpIndexDirect, argCoord, w, loc); - - TOperator constructOp = EOpNull; - const TSampler &sampler = argSamp->getType().getSampler(); - int coordSize = 0; - - switch (sampler.dim) - { - case Esd1D: constructOp = EOpConstructFloat; coordSize = 1; break; // 1D - case Esd2D: constructOp = EOpConstructVec2; coordSize = 2; break; // 2D - case Esd3D: constructOp = EOpConstructVec3; coordSize = 3; break; // 3D - case EsdCube: constructOp = EOpConstructVec3; coordSize = 3; break; // also 3D - default: - error(loc, "unhandled DX9 texture LoD dimension", "", ""); - break; - } - - TIntermAggregate *constructCoord = new TIntermAggregate(constructOp); - constructCoord->getSequence().push_back(argCoord); - constructCoord->setLoc(loc); - constructCoord->setType(TType(argCoord->getBasicType(), EvqTemporary, coordSize)); - - TIntermAggregate *tex = new TIntermAggregate(EOpTextureLod); - tex->getSequence().push_back(argSamp); // sampler - tex->getSequence().push_back(constructCoord); // coordinate - tex->getSequence().push_back(argLod); // lod - - node = convertReturn(tex, sampler); - - break; - } - - case EOpTextureBias: - { - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); // sampler - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); // coord - - // HLSL puts bias in W component of coordinate. We extract it and add it to - // the argument list, instead - TIntermTyped* w = intermediate.addConstantUnion(3, loc, true); - TIntermTyped* bias = intermediate.addIndex(EOpIndexDirect, arg1, w, loc); - - TOperator constructOp = EOpNull; - const TSampler& sampler = arg0->getType().getSampler(); - - switch (sampler.dim) { - case Esd1D: constructOp = EOpConstructFloat; break; // 1D - case Esd2D: constructOp = EOpConstructVec2; break; // 2D - case Esd3D: constructOp = EOpConstructVec3; break; // 3D - case EsdCube: constructOp = EOpConstructVec3; break; // also 3D - default: - error(loc, "unhandled DX9 texture bias dimension", "", ""); - break; - } - - TIntermAggregate* constructCoord = new TIntermAggregate(constructOp); - constructCoord->getSequence().push_back(arg1); - constructCoord->setLoc(loc); - - // The input vector should never be less than 2, since there's always a bias. - // The max is for safety, and should be a no-op. - constructCoord->setType(TType(arg1->getBasicType(), EvqTemporary, std::max(arg1->getVectorSize() - 1, 0))); - - TIntermAggregate* tex = new TIntermAggregate(EOpTexture); - tex->getSequence().push_back(arg0); // sampler - tex->getSequence().push_back(constructCoord); // coordinate - tex->getSequence().push_back(bias); // bias - - node = convertReturn(tex, sampler); - - break; - } - - // **** DX10 methods: **** - case EOpMethodSample: // fall through - case EOpMethodSampleBias: // ... - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - TIntermTyped* argBias = nullptr; - TIntermTyped* argOffset = nullptr; - const TSampler& sampler = argTex->getType().getSampler(); - - int nextArg = 3; - - if (op == EOpMethodSampleBias) // SampleBias has a bias arg - argBias = argAggregate->getSequence()[nextArg++]->getAsTyped(); - - TOperator textureOp = EOpTexture; - - if ((int)argAggregate->getSequence().size() == (nextArg+1)) { // last parameter is offset form - textureOp = EOpTextureOffset; - argOffset = argAggregate->getSequence()[nextArg++]->getAsTyped(); - } - - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - - TIntermAggregate* txsample = new TIntermAggregate(textureOp); - txsample->getSequence().push_back(txcombine); - txsample->getSequence().push_back(argCoord); - - if (argOffset != nullptr) - txsample->getSequence().push_back(argOffset); - - if (argBias != nullptr) - txsample->getSequence().push_back(argBias); - - node = convertReturn(txsample, sampler); - - break; - } - - case EOpMethodSampleGrad: // ... - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - TIntermTyped* argDDX = argAggregate->getSequence()[3]->getAsTyped(); - TIntermTyped* argDDY = argAggregate->getSequence()[4]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - const TSampler& sampler = argTex->getType().getSampler(); - - TOperator textureOp = EOpTextureGrad; - - if (argAggregate->getSequence().size() == 6) { // last parameter is offset form - textureOp = EOpTextureGradOffset; - argOffset = argAggregate->getSequence()[5]->getAsTyped(); - } - - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - - TIntermAggregate* txsample = new TIntermAggregate(textureOp); - txsample->getSequence().push_back(txcombine); - txsample->getSequence().push_back(argCoord); - txsample->getSequence().push_back(argDDX); - txsample->getSequence().push_back(argDDY); - - if (argOffset != nullptr) - txsample->getSequence().push_back(argOffset); - - node = convertReturn(txsample, sampler); - - break; - } - - case EOpMethodGetDimensions: - { - // AST returns a vector of results, which we break apart component-wise into - // separate values to assign to the HLSL method's outputs, ala: - // tx . GetDimensions(width, height); - // float2 sizeQueryTemp = EOpTextureQuerySize - // width = sizeQueryTemp.X; - // height = sizeQueryTemp.Y; - - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - const TType& texType = argTex->getType(); - - assert(texType.getBasicType() == EbtSampler); - - const TSampler& sampler = texType.getSampler(); - const TSamplerDim dim = sampler.dim; - const bool isImage = sampler.isImage(); - const bool isMs = sampler.isMultiSample(); - const int numArgs = (int)argAggregate->getSequence().size(); - - int numDims = 0; - - switch (dim) { - case Esd1D: numDims = 1; break; // W - case Esd2D: numDims = 2; break; // W, H - case Esd3D: numDims = 3; break; // W, H, D - case EsdCube: numDims = 2; break; // W, H (cube) - case EsdBuffer: numDims = 1; break; // W (buffers) - case EsdRect: numDims = 2; break; // W, H (rect) - default: - error(loc, "unhandled DX10 MethodGet dimension", "", ""); - break; - } - - // Arrayed adds another dimension for the number of array elements - if (sampler.isArrayed()) - ++numDims; - - // Establish whether the method itself is querying mip levels. This can be false even - // if the underlying query requires a MIP level, due to the available HLSL method overloads. - const bool mipQuery = (numArgs > (numDims + 1 + (isMs ? 1 : 0))); - - // Establish whether we must use the LOD form of query (even if the method did not supply a mip level to query). - // True if: - // 1. 1D/2D/3D/Cube AND multisample==0 AND NOT image (those can be sent to the non-LOD query) - // or, - // 2. There is a LOD (because the non-LOD query cannot be used in that case, per spec) - const bool mipRequired = - ((dim == Esd1D || dim == Esd2D || dim == Esd3D || dim == EsdCube) && !isMs && !isImage) || // 1... - mipQuery; // 2... - - // AST assumes integer return. Will be converted to float if required. - TIntermAggregate* sizeQuery = new TIntermAggregate(isImage ? EOpImageQuerySize : EOpTextureQuerySize); - sizeQuery->getSequence().push_back(argTex); - - // If we're building an LOD query, add the LOD. - if (mipRequired) { - // If the base HLSL query had no MIP level given, use level 0. - TIntermTyped* queryLod = mipQuery ? argAggregate->getSequence()[1]->getAsTyped() : - intermediate.addConstantUnion(0, loc, true); - sizeQuery->getSequence().push_back(queryLod); - } - - sizeQuery->setType(TType(EbtUint, EvqTemporary, numDims)); - sizeQuery->setLoc(loc); - - // Return value from size query - TVariable* tempArg = makeInternalVariable("sizeQueryTemp", sizeQuery->getType()); - tempArg->getWritableType().getQualifier().makeTemporary(); - TIntermTyped* sizeQueryAssign = intermediate.addAssign(EOpAssign, - intermediate.addSymbol(*tempArg, loc), - sizeQuery, loc); - - // Compound statement for assigning outputs - TIntermAggregate* compoundStatement = intermediate.makeAggregate(sizeQueryAssign, loc); - // Index of first output parameter - const int outParamBase = mipQuery ? 2 : 1; - - for (int compNum = 0; compNum < numDims; ++compNum) { - TIntermTyped* indexedOut = nullptr; - TIntermSymbol* sizeQueryReturn = intermediate.addSymbol(*tempArg, loc); - - if (numDims > 1) { - TIntermTyped* component = intermediate.addConstantUnion(compNum, loc, true); - indexedOut = intermediate.addIndex(EOpIndexDirect, sizeQueryReturn, component, loc); - indexedOut->setType(TType(EbtUint, EvqTemporary, 1)); - indexedOut->setLoc(loc); - } else { - indexedOut = sizeQueryReturn; - } - - TIntermTyped* outParam = argAggregate->getSequence()[outParamBase + compNum]->getAsTyped(); - TIntermTyped* compAssign = intermediate.addAssign(EOpAssign, outParam, indexedOut, loc); - - compoundStatement = intermediate.growAggregate(compoundStatement, compAssign); - } - - // handle mip level parameter - if (mipQuery) { - TIntermTyped* outParam = argAggregate->getSequence()[outParamBase + numDims]->getAsTyped(); - - TIntermAggregate* levelsQuery = new TIntermAggregate(EOpTextureQueryLevels); - levelsQuery->getSequence().push_back(argTex); - levelsQuery->setType(TType(EbtUint, EvqTemporary, 1)); - levelsQuery->setLoc(loc); - - TIntermTyped* compAssign = intermediate.addAssign(EOpAssign, outParam, levelsQuery, loc); - compoundStatement = intermediate.growAggregate(compoundStatement, compAssign); - } - - // 2DMS formats query # samples, which needs a different query op - if (sampler.isMultiSample()) { - TIntermTyped* outParam = argAggregate->getSequence()[outParamBase + numDims]->getAsTyped(); - - TIntermAggregate* samplesQuery = new TIntermAggregate(EOpImageQuerySamples); - samplesQuery->getSequence().push_back(argTex); - samplesQuery->setType(TType(EbtUint, EvqTemporary, 1)); - samplesQuery->setLoc(loc); - - TIntermTyped* compAssign = intermediate.addAssign(EOpAssign, outParam, samplesQuery, loc); - compoundStatement = intermediate.growAggregate(compoundStatement, compAssign); - } - - compoundStatement->setOperator(EOpSequence); - compoundStatement->setLoc(loc); - compoundStatement->setType(TType(EbtVoid)); - - node = compoundStatement; - - break; - } - - case EOpMethodSampleCmp: // fall through... - case EOpMethodSampleCmpLevelZero: - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - TIntermTyped* argCmpVal = argAggregate->getSequence()[3]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - - // Sampler argument should be a sampler. - if (argSamp->getType().getBasicType() != EbtSampler) { - error(loc, "expected: sampler type", "", ""); - return; - } - - // Sampler should be a SamplerComparisonState - if (! argSamp->getType().getSampler().isShadow()) { - error(loc, "expected: SamplerComparisonState", "", ""); - return; - } - - // optional offset value - if (argAggregate->getSequence().size() > 4) - argOffset = argAggregate->getSequence()[4]->getAsTyped(); - - const int coordDimWithCmpVal = argCoord->getType().getVectorSize() + 1; // +1 for cmp - - // AST wants comparison value as one of the texture coordinates - TOperator constructOp = EOpNull; - switch (coordDimWithCmpVal) { - // 1D can't happen: there's always at least 1 coordinate dimension + 1 cmp val - case 2: constructOp = EOpConstructVec2; break; - case 3: constructOp = EOpConstructVec3; break; - case 4: constructOp = EOpConstructVec4; break; - case 5: constructOp = EOpConstructVec4; break; // cubeArrayShadow, cmp value is separate arg. - default: - error(loc, "unhandled DX10 MethodSample dimension", "", ""); - break; - } - - TIntermAggregate* coordWithCmp = new TIntermAggregate(constructOp); - coordWithCmp->getSequence().push_back(argCoord); - if (coordDimWithCmpVal != 5) // cube array shadow is special. - coordWithCmp->getSequence().push_back(argCmpVal); - coordWithCmp->setLoc(loc); - coordWithCmp->setType(TType(argCoord->getBasicType(), EvqTemporary, std::min(coordDimWithCmpVal, 4))); - - TOperator textureOp = (op == EOpMethodSampleCmpLevelZero ? EOpTextureLod : EOpTexture); - if (argOffset != nullptr) - textureOp = (op == EOpMethodSampleCmpLevelZero ? EOpTextureLodOffset : EOpTextureOffset); - - // Create combined sampler & texture op - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - TIntermAggregate* txsample = new TIntermAggregate(textureOp); - txsample->getSequence().push_back(txcombine); - txsample->getSequence().push_back(coordWithCmp); - - if (coordDimWithCmpVal == 5) // cube array shadow is special: cmp val follows coord. - txsample->getSequence().push_back(argCmpVal); - - // the LevelZero form uses 0 as an explicit LOD - if (op == EOpMethodSampleCmpLevelZero) - txsample->getSequence().push_back(intermediate.addConstantUnion(0.0, EbtFloat, loc, true)); - - // Add offset if present - if (argOffset != nullptr) - txsample->getSequence().push_back(argOffset); - - txsample->setType(node->getType()); - txsample->setLoc(loc); - node = txsample; - - break; - } - - case EOpMethodLoad: - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - TIntermTyped* lodComponent = nullptr; - TIntermTyped* coordSwizzle = nullptr; - - const TSampler& sampler = argTex->getType().getSampler(); - const bool isMS = sampler.isMultiSample(); - const bool isBuffer = sampler.dim == EsdBuffer; - const bool isImage = sampler.isImage(); - const TBasicType coordBaseType = argCoord->getType().getBasicType(); - - // Last component of coordinate is the mip level, for non-MS. we separate them here: - if (isMS || isBuffer || isImage) { - // MS, Buffer, and Image have no LOD - coordSwizzle = argCoord; - } else { - // Extract coordinate - int swizzleSize = argCoord->getType().getVectorSize() - (isMS ? 0 : 1); - TSwizzleSelectors coordFields; - for (int i = 0; i < swizzleSize; ++i) - coordFields.push_back(i); - TIntermTyped* coordIdx = intermediate.addSwizzle(coordFields, loc); - coordSwizzle = intermediate.addIndex(EOpVectorSwizzle, argCoord, coordIdx, loc); - coordSwizzle->setType(TType(coordBaseType, EvqTemporary, coordFields.size())); - - // Extract LOD - TIntermTyped* lodIdx = intermediate.addConstantUnion(coordFields.size(), loc, true); - lodComponent = intermediate.addIndex(EOpIndexDirect, argCoord, lodIdx, loc); - lodComponent->setType(TType(coordBaseType, EvqTemporary, 1)); - } - - const int numArgs = (int)argAggregate->getSequence().size(); - const bool hasOffset = ((!isMS && numArgs == 3) || (isMS && numArgs == 4)); - - // Create texel fetch - const TOperator fetchOp = (isImage ? EOpImageLoad : - hasOffset ? EOpTextureFetchOffset : - EOpTextureFetch); - TIntermAggregate* txfetch = new TIntermAggregate(fetchOp); - - // Build up the fetch - txfetch->getSequence().push_back(argTex); - txfetch->getSequence().push_back(coordSwizzle); - - if (isMS) { - // add 2DMS sample index - TIntermTyped* argSampleIdx = argAggregate->getSequence()[2]->getAsTyped(); - txfetch->getSequence().push_back(argSampleIdx); - } else if (isBuffer) { - // Nothing else to do for buffers. - } else if (isImage) { - // Nothing else to do for images. - } else { - // 2DMS and buffer have no LOD, but everything else does. - txfetch->getSequence().push_back(lodComponent); - } - - // Obtain offset arg, if there is one. - if (hasOffset) { - const int offsetPos = (isMS ? 3 : 2); - argOffset = argAggregate->getSequence()[offsetPos]->getAsTyped(); - txfetch->getSequence().push_back(argOffset); - } - - node = convertReturn(txfetch, sampler); - - break; - } - - case EOpMethodSampleLevel: - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - TIntermTyped* argLod = argAggregate->getSequence()[3]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - const TSampler& sampler = argTex->getType().getSampler(); - - const int numArgs = (int)argAggregate->getSequence().size(); - - if (numArgs == 5) // offset, if present - argOffset = argAggregate->getSequence()[4]->getAsTyped(); - - const TOperator textureOp = (argOffset == nullptr ? EOpTextureLod : EOpTextureLodOffset); - TIntermAggregate* txsample = new TIntermAggregate(textureOp); - - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - - txsample->getSequence().push_back(txcombine); - txsample->getSequence().push_back(argCoord); - txsample->getSequence().push_back(argLod); - - if (argOffset != nullptr) - txsample->getSequence().push_back(argOffset); - - node = convertReturn(txsample, sampler); - - break; - } - - case EOpMethodGather: - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - - // Offset is optional - if (argAggregate->getSequence().size() > 3) - argOffset = argAggregate->getSequence()[3]->getAsTyped(); - - const TOperator textureOp = (argOffset == nullptr ? EOpTextureGather : EOpTextureGatherOffset); - TIntermAggregate* txgather = new TIntermAggregate(textureOp); - - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - - txgather->getSequence().push_back(txcombine); - txgather->getSequence().push_back(argCoord); - // Offset if not given is implicitly channel 0 (red) - - if (argOffset != nullptr) - txgather->getSequence().push_back(argOffset); - - txgather->setType(node->getType()); - txgather->setLoc(loc); - node = txgather; - - break; - } - - case EOpMethodGatherRed: // fall through... - case EOpMethodGatherGreen: // ... - case EOpMethodGatherBlue: // ... - case EOpMethodGatherAlpha: // ... - case EOpMethodGatherCmpRed: // ... - case EOpMethodGatherCmpGreen: // ... - case EOpMethodGatherCmpBlue: // ... - case EOpMethodGatherCmpAlpha: // ... - { - int channel = 0; // the channel we are gathering - int cmpValues = 0; // 1 if there is a compare value (handier than a bool below) - - switch (op) { - case EOpMethodGatherCmpRed: cmpValues = 1; // fall through - case EOpMethodGatherRed: channel = 0; break; - case EOpMethodGatherCmpGreen: cmpValues = 1; // fall through - case EOpMethodGatherGreen: channel = 1; break; - case EOpMethodGatherCmpBlue: cmpValues = 1; // fall through - case EOpMethodGatherBlue: channel = 2; break; - case EOpMethodGatherCmpAlpha: cmpValues = 1; // fall through - case EOpMethodGatherAlpha: channel = 3; break; - default: assert(0); break; - } - - // For now, we have nothing to map the component-wise comparison forms - // to, because neither GLSL nor SPIR-V has such an opcode. Issue an - // unimplemented error instead. Most of the machinery is here if that - // should ever become available. However, red can be passed through - // to OpImageDrefGather. G/B/A cannot, because that opcode does not - // accept a component. - if (cmpValues != 0 && op != EOpMethodGatherCmpRed) { - error(loc, "unimplemented: component-level gather compare", "", ""); - return; - } - - int arg = 0; - - TIntermTyped* argTex = argAggregate->getSequence()[arg++]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[arg++]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[arg++]->getAsTyped(); - TIntermTyped* argOffset = nullptr; - TIntermTyped* argOffsets[4] = { nullptr, nullptr, nullptr, nullptr }; - // TIntermTyped* argStatus = nullptr; // TODO: residency - TIntermTyped* argCmp = nullptr; - - const TSamplerDim dim = argTex->getType().getSampler().dim; - - const int argSize = (int)argAggregate->getSequence().size(); - bool hasStatus = (argSize == (5+cmpValues) || argSize == (8+cmpValues)); - bool hasOffset1 = false; - bool hasOffset4 = false; - - // Sampler argument should be a sampler. - if (argSamp->getType().getBasicType() != EbtSampler) { - error(loc, "expected: sampler type", "", ""); - return; - } - - // Cmp forms require SamplerComparisonState - if (cmpValues > 0 && ! argSamp->getType().getSampler().isShadow()) { - error(loc, "expected: SamplerComparisonState", "", ""); - return; - } - - // Only 2D forms can have offsets. Discover if we have 0, 1 or 4 offsets. - if (dim == Esd2D) { - hasOffset1 = (argSize == (4+cmpValues) || argSize == (5+cmpValues)); - hasOffset4 = (argSize == (7+cmpValues) || argSize == (8+cmpValues)); - } - - assert(!(hasOffset1 && hasOffset4)); - - TOperator textureOp = EOpTextureGather; - - // Compare forms have compare value - if (cmpValues != 0) - argCmp = argOffset = argAggregate->getSequence()[arg++]->getAsTyped(); - - // Some forms have single offset - if (hasOffset1) { - textureOp = EOpTextureGatherOffset; // single offset form - argOffset = argAggregate->getSequence()[arg++]->getAsTyped(); - } - - // Some forms have 4 gather offsets - if (hasOffset4) { - textureOp = EOpTextureGatherOffsets; // note plural, for 4 offset form - for (int offsetNum = 0; offsetNum < 4; ++offsetNum) - argOffsets[offsetNum] = argAggregate->getSequence()[arg++]->getAsTyped(); - } - - // Residency status - if (hasStatus) { - // argStatus = argAggregate->getSequence()[arg++]->getAsTyped(); - error(loc, "unimplemented: residency status", "", ""); - return; - } - - TIntermAggregate* txgather = new TIntermAggregate(textureOp); - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - - TIntermTyped* argChannel = intermediate.addConstantUnion(channel, loc, true); - - txgather->getSequence().push_back(txcombine); - txgather->getSequence().push_back(argCoord); - - // AST wants an array of 4 offsets, where HLSL has separate args. Here - // we construct an array from the separate args. - if (hasOffset4) { - TType arrayType(EbtInt, EvqTemporary, 2); - TArraySizes* arraySizes = new TArraySizes; - arraySizes->addInnerSize(4); - arrayType.transferArraySizes(arraySizes); - - TIntermAggregate* initList = new TIntermAggregate(EOpNull); - - for (int offsetNum = 0; offsetNum < 4; ++offsetNum) - initList->getSequence().push_back(argOffsets[offsetNum]); - - argOffset = addConstructor(loc, initList, arrayType); - } - - // Add comparison value if we have one - if (argCmp != nullptr) - txgather->getSequence().push_back(argCmp); - - // Add offset (either 1, or an array of 4) if we have one - if (argOffset != nullptr) - txgather->getSequence().push_back(argOffset); - - // Add channel value if the sampler is not shadow - if (! argSamp->getType().getSampler().isShadow()) - txgather->getSequence().push_back(argChannel); - - txgather->setType(node->getType()); - txgather->setLoc(loc); - node = txgather; - - break; - } - - case EOpMethodCalculateLevelOfDetail: - case EOpMethodCalculateLevelOfDetailUnclamped: - { - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSamp = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* argCoord = argAggregate->getSequence()[2]->getAsTyped(); - - TIntermAggregate* txquerylod = new TIntermAggregate(EOpTextureQueryLod); - - TIntermAggregate* txcombine = handleSamplerTextureCombine(loc, argTex, argSamp); - txquerylod->getSequence().push_back(txcombine); - txquerylod->getSequence().push_back(argCoord); - - TIntermTyped* lodComponent = intermediate.addConstantUnion( - op == EOpMethodCalculateLevelOfDetail ? 0 : 1, - loc, true); - TIntermTyped* lodComponentIdx = intermediate.addIndex(EOpIndexDirect, txquerylod, lodComponent, loc); - lodComponentIdx->setType(TType(EbtFloat, EvqTemporary, 1)); - node = lodComponentIdx; - - break; - } - - case EOpMethodGetSamplePosition: - { - // TODO: this entire decomposition exists because there is not yet a way to query - // the sample position directly through SPIR-V. Instead, we return fixed sample - // positions for common cases. *** If the sample positions are set differently, - // this will be wrong. *** - - TIntermTyped* argTex = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* argSampIdx = argAggregate->getSequence()[1]->getAsTyped(); - - TIntermAggregate* samplesQuery = new TIntermAggregate(EOpImageQuerySamples); - samplesQuery->getSequence().push_back(argTex); - samplesQuery->setType(TType(EbtUint, EvqTemporary, 1)); - samplesQuery->setLoc(loc); - - TIntermAggregate* compoundStatement = nullptr; - - TVariable* outSampleCount = makeInternalVariable("@sampleCount", TType(EbtUint)); - outSampleCount->getWritableType().getQualifier().makeTemporary(); - TIntermTyped* compAssign = intermediate.addAssign(EOpAssign, intermediate.addSymbol(*outSampleCount, loc), - samplesQuery, loc); - compoundStatement = intermediate.growAggregate(compoundStatement, compAssign); - - TIntermTyped* idxtest[4]; - - // Create tests against 2, 4, 8, and 16 sample values - int count = 0; - for (int val = 2; val <= 16; val *= 2) - idxtest[count++] = - intermediate.addBinaryNode(EOpEqual, - intermediate.addSymbol(*outSampleCount, loc), - intermediate.addConstantUnion(val, loc), - loc, TType(EbtBool)); - - const TOperator idxOp = (argSampIdx->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect; - - // Create index ops into position arrays given sample index. - // TODO: should it be clamped? - TIntermTyped* index[4]; - count = 0; - for (int val = 2; val <= 16; val *= 2) { - index[count] = intermediate.addIndex(idxOp, getSamplePosArray(val), argSampIdx, loc); - index[count++]->setType(TType(EbtFloat, EvqTemporary, 2)); - } - - // Create expression as: - // (sampleCount == 2) ? pos2[idx] : - // (sampleCount == 4) ? pos4[idx] : - // (sampleCount == 8) ? pos8[idx] : - // (sampleCount == 16) ? pos16[idx] : float2(0,0); - TIntermTyped* test = - intermediate.addSelection(idxtest[0], index[0], - intermediate.addSelection(idxtest[1], index[1], - intermediate.addSelection(idxtest[2], index[2], - intermediate.addSelection(idxtest[3], index[3], - getSamplePosArray(1), loc), loc), loc), loc); - - compoundStatement = intermediate.growAggregate(compoundStatement, test); - compoundStatement->setOperator(EOpSequence); - compoundStatement->setLoc(loc); - compoundStatement->setType(TType(EbtFloat, EvqTemporary, 2)); - - node = compoundStatement; - - break; - } - - case EOpSubpassLoad: - { - const TIntermTyped* argSubpass = - argAggregate ? argAggregate->getSequence()[0]->getAsTyped() : - arguments->getAsTyped(); - - const TSampler& sampler = argSubpass->getType().getSampler(); - - // subpass load: the multisample form is overloaded. Here, we convert that to - // the EOpSubpassLoadMS opcode. - if (argAggregate != nullptr && argAggregate->getSequence().size() > 1) - node->getAsOperator()->setOp(EOpSubpassLoadMS); - - node = convertReturn(node, sampler); - - break; - } - - - default: - break; // most pass through unchanged - } -} - -// -// Decompose geometry shader methods -// -void HlslParseContext::decomposeGeometryMethods(const TSourceLoc& loc, TIntermTyped*& node, TIntermNode* arguments) -{ - if (node == nullptr || !node->getAsOperator()) - return; - - const TOperator op = node->getAsOperator()->getOp(); - const TIntermAggregate* argAggregate = arguments ? arguments->getAsAggregate() : nullptr; - - switch (op) { - case EOpMethodAppend: - if (argAggregate) { - // Don't emit these for non-GS stage, since we won't have the gsStreamOutput symbol. - if (language != EShLangGeometry) { - node = nullptr; - return; - } - - TIntermAggregate* sequence = nullptr; - TIntermAggregate* emit = new TIntermAggregate(EOpEmitVertex); - - emit->setLoc(loc); - emit->setType(TType(EbtVoid)); - - TIntermTyped* data = argAggregate->getSequence()[1]->getAsTyped(); - - // This will be patched in finalization during finalizeAppendMethods() - sequence = intermediate.growAggregate(sequence, data, loc); - sequence = intermediate.growAggregate(sequence, emit); - - sequence->setOperator(EOpSequence); - sequence->setLoc(loc); - sequence->setType(TType(EbtVoid)); - - gsAppends.push_back({sequence, loc}); - - node = sequence; - } - break; - - case EOpMethodRestartStrip: - { - // Don't emit these for non-GS stage, since we won't have the gsStreamOutput symbol. - if (language != EShLangGeometry) { - node = nullptr; - return; - } - - TIntermAggregate* cut = new TIntermAggregate(EOpEndPrimitive); - cut->setLoc(loc); - cut->setType(TType(EbtVoid)); - node = cut; - } - break; - - default: - break; // most pass through unchanged - } -} - -// -// Optionally decompose intrinsics to AST opcodes. -// -void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*& node, TIntermNode* arguments) -{ - // Helper to find image data for image atomics: - // OpImageLoad(image[idx]) - // We take the image load apart and add its params to the atomic op aggregate node - const auto imageAtomicParams = [this, &loc, &node](TIntermAggregate* atomic, TIntermTyped* load) { - TIntermAggregate* loadOp = load->getAsAggregate(); - if (loadOp == nullptr) { - error(loc, "unknown image type in atomic operation", "", ""); - node = nullptr; - return; - } - - atomic->getSequence().push_back(loadOp->getSequence()[0]); - atomic->getSequence().push_back(loadOp->getSequence()[1]); - }; - - // Return true if this is an imageLoad, which we will change to an image atomic. - const auto isImageParam = [](TIntermTyped* image) -> bool { - TIntermAggregate* imageAggregate = image->getAsAggregate(); - return imageAggregate != nullptr && imageAggregate->getOp() == EOpImageLoad; - }; - - const auto lookupBuiltinVariable = [&](const char* name, TBuiltInVariable builtin, TType& type) -> TIntermTyped* { - TSymbol* symbol = symbolTable.find(name); - if (nullptr == symbol) { - type.getQualifier().builtIn = builtin; - - TVariable* variable = new TVariable(NewPoolTString(name), type); - - symbolTable.insert(*variable); - - symbol = symbolTable.find(name); - assert(symbol && "Inserted symbol could not be found!"); - } - - return intermediate.addSymbol(*(symbol->getAsVariable()), loc); - }; - - // HLSL intrinsics can be pass through to native AST opcodes, or decomposed here to existing AST - // opcodes for compatibility with existing software stacks. - static const bool decomposeHlslIntrinsics = true; - - if (!decomposeHlslIntrinsics || !node || !node->getAsOperator()) - return; - - const TIntermAggregate* argAggregate = arguments ? arguments->getAsAggregate() : nullptr; - TIntermUnary* fnUnary = node->getAsUnaryNode(); - const TOperator op = node->getAsOperator()->getOp(); - - switch (op) { - case EOpGenMul: - { - // mul(a,b) -> MatrixTimesMatrix, MatrixTimesVector, MatrixTimesScalar, VectorTimesScalar, Dot, Mul - // Since we are treating HLSL rows like GLSL columns (the first matrix indirection), - // we must reverse the operand order here. Hence, arg0 gets sequence[1], etc. - TIntermTyped* arg0 = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* arg1 = argAggregate->getSequence()[0]->getAsTyped(); - - if (arg0->isVector() && arg1->isVector()) { // vec * vec - node->getAsAggregate()->setOperator(EOpDot); - } else { - node = handleBinaryMath(loc, "mul", EOpMul, arg0, arg1); - } - - break; - } - - case EOpRcp: - { - // rcp(a) -> 1 / a - TIntermTyped* arg0 = fnUnary->getOperand(); - TBasicType type0 = arg0->getBasicType(); - TIntermTyped* one = intermediate.addConstantUnion(1, type0, loc, true); - node = handleBinaryMath(loc, "rcp", EOpDiv, one, arg0); - - break; - } - - case EOpAny: // fall through - case EOpAll: - { - TIntermTyped* typedArg = arguments->getAsTyped(); - - // HLSL allows float/etc types here, and the SPIR-V opcode requires a bool. - // We'll convert here. Note that for efficiency, we could add a smarter - // decomposition for some type cases, e.g, maybe by decomposing a dot product. - if (typedArg->getType().getBasicType() != EbtBool) { - const TType boolType(EbtBool, EvqTemporary, - typedArg->getVectorSize(), - typedArg->getMatrixCols(), - typedArg->getMatrixRows(), - typedArg->isVector()); - - typedArg = intermediate.addConversion(EOpConstructBool, boolType, typedArg); - node->getAsUnaryNode()->setOperand(typedArg); - } - - break; - } - - case EOpSaturate: - { - // saturate(a) -> clamp(a,0,1) - TIntermTyped* arg0 = fnUnary->getOperand(); - TBasicType type0 = arg0->getBasicType(); - TIntermAggregate* clamp = new TIntermAggregate(EOpClamp); - - clamp->getSequence().push_back(arg0); - clamp->getSequence().push_back(intermediate.addConstantUnion(0, type0, loc, true)); - clamp->getSequence().push_back(intermediate.addConstantUnion(1, type0, loc, true)); - clamp->setLoc(loc); - clamp->setType(node->getType()); - clamp->getWritableType().getQualifier().makeTemporary(); - node = clamp; - - break; - } - - case EOpSinCos: - { - // sincos(a,b,c) -> b = sin(a), c = cos(a) - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* arg2 = argAggregate->getSequence()[2]->getAsTyped(); - - TIntermTyped* sinStatement = handleUnaryMath(loc, "sin", EOpSin, arg0); - TIntermTyped* cosStatement = handleUnaryMath(loc, "cos", EOpCos, arg0); - TIntermTyped* sinAssign = intermediate.addAssign(EOpAssign, arg1, sinStatement, loc); - TIntermTyped* cosAssign = intermediate.addAssign(EOpAssign, arg2, cosStatement, loc); - - TIntermAggregate* compoundStatement = intermediate.makeAggregate(sinAssign, loc); - compoundStatement = intermediate.growAggregate(compoundStatement, cosAssign); - compoundStatement->setOperator(EOpSequence); - compoundStatement->setLoc(loc); - compoundStatement->setType(TType(EbtVoid)); - - node = compoundStatement; - - break; - } - - case EOpClip: - { - // clip(a) -> if (any(a<0)) discard; - TIntermTyped* arg0 = fnUnary->getOperand(); - TBasicType type0 = arg0->getBasicType(); - TIntermTyped* compareNode = nullptr; - - // For non-scalars: per experiment with FXC compiler, discard if any component < 0. - if (!arg0->isScalar()) { - // component-wise compare: a < 0 - TIntermAggregate* less = new TIntermAggregate(EOpLessThan); - less->getSequence().push_back(arg0); - less->setLoc(loc); - - // make vec or mat of bool matching dimensions of input - less->setType(TType(EbtBool, EvqTemporary, - arg0->getType().getVectorSize(), - arg0->getType().getMatrixCols(), - arg0->getType().getMatrixRows(), - arg0->getType().isVector())); - - // calculate # of components for comparison const - const int constComponentCount = - std::max(arg0->getType().getVectorSize(), 1) * - std::max(arg0->getType().getMatrixCols(), 1) * - std::max(arg0->getType().getMatrixRows(), 1); - - TConstUnion zero; - if (arg0->getType().isIntegerDomain()) - zero.setDConst(0); - else - zero.setDConst(0.0); - TConstUnionArray zeros(constComponentCount, zero); - - less->getSequence().push_back(intermediate.addConstantUnion(zeros, arg0->getType(), loc, true)); - - compareNode = intermediate.addBuiltInFunctionCall(loc, EOpAny, true, less, TType(EbtBool)); - } else { - TIntermTyped* zero; - if (arg0->getType().isIntegerDomain()) - zero = intermediate.addConstantUnion(0, loc, true); - else - zero = intermediate.addConstantUnion(0.0, type0, loc, true); - compareNode = handleBinaryMath(loc, "clip", EOpLessThan, arg0, zero); - } - - TIntermBranch* killNode = intermediate.addBranch(EOpKill, loc); - - node = new TIntermSelection(compareNode, killNode, nullptr); - node->setLoc(loc); - - break; - } - - case EOpLog10: - { - // log10(a) -> log2(a) * 0.301029995663981 (== 1/log2(10)) - TIntermTyped* arg0 = fnUnary->getOperand(); - TIntermTyped* log2 = handleUnaryMath(loc, "log2", EOpLog2, arg0); - TIntermTyped* base = intermediate.addConstantUnion(0.301029995663981f, EbtFloat, loc, true); - - node = handleBinaryMath(loc, "mul", EOpMul, log2, base); - - break; - } - - case EOpDst: - { - // dest.x = 1; - // dest.y = src0.y * src1.y; - // dest.z = src0.z; - // dest.w = src1.w; - - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); - - TIntermTyped* y = intermediate.addConstantUnion(1, loc, true); - TIntermTyped* z = intermediate.addConstantUnion(2, loc, true); - TIntermTyped* w = intermediate.addConstantUnion(3, loc, true); - - TIntermTyped* src0y = intermediate.addIndex(EOpIndexDirect, arg0, y, loc); - TIntermTyped* src1y = intermediate.addIndex(EOpIndexDirect, arg1, y, loc); - TIntermTyped* src0z = intermediate.addIndex(EOpIndexDirect, arg0, z, loc); - TIntermTyped* src1w = intermediate.addIndex(EOpIndexDirect, arg1, w, loc); - - TIntermAggregate* dst = new TIntermAggregate(EOpConstructVec4); - - dst->getSequence().push_back(intermediate.addConstantUnion(1.0, EbtFloat, loc, true)); - dst->getSequence().push_back(handleBinaryMath(loc, "mul", EOpMul, src0y, src1y)); - dst->getSequence().push_back(src0z); - dst->getSequence().push_back(src1w); - dst->setType(TType(EbtFloat, EvqTemporary, 4)); - dst->setLoc(loc); - node = dst; - - break; - } - - case EOpInterlockedAdd: // optional last argument (if present) is assigned from return value - case EOpInterlockedMin: // ... - case EOpInterlockedMax: // ... - case EOpInterlockedAnd: // ... - case EOpInterlockedOr: // ... - case EOpInterlockedXor: // ... - case EOpInterlockedExchange: // always has output arg - { - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); // dest - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); // value - TIntermTyped* arg2 = nullptr; - - if (argAggregate->getSequence().size() > 2) - arg2 = argAggregate->getSequence()[2]->getAsTyped(); - - const bool isImage = isImageParam(arg0); - const TOperator atomicOp = mapAtomicOp(loc, op, isImage); - TIntermAggregate* atomic = new TIntermAggregate(atomicOp); - atomic->setType(arg0->getType()); - atomic->getWritableType().getQualifier().makeTemporary(); - atomic->setLoc(loc); - - if (isImage) { - // orig_value = imageAtomicOp(image, loc, data) - imageAtomicParams(atomic, arg0); - atomic->getSequence().push_back(arg1); - - if (argAggregate->getSequence().size() > 2) { - node = intermediate.addAssign(EOpAssign, arg2, atomic, loc); - } else { - node = atomic; // no assignment needed, as there was no out var. - } - } else { - // Normal memory variable: - // arg0 = mem, arg1 = data, arg2(optional,out) = orig_value - if (argAggregate->getSequence().size() > 2) { - // optional output param is present. return value goes to arg2. - atomic->getSequence().push_back(arg0); - atomic->getSequence().push_back(arg1); - - node = intermediate.addAssign(EOpAssign, arg2, atomic, loc); - } else { - // Set the matching operator. Since output is absent, this is all we need to do. - node->getAsAggregate()->setOperator(atomicOp); - node->setType(atomic->getType()); - } - } - - break; - } - - case EOpInterlockedCompareExchange: - { - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); // dest - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); // cmp - TIntermTyped* arg2 = argAggregate->getSequence()[2]->getAsTyped(); // value - TIntermTyped* arg3 = argAggregate->getSequence()[3]->getAsTyped(); // orig - - const bool isImage = isImageParam(arg0); - TIntermAggregate* atomic = new TIntermAggregate(mapAtomicOp(loc, op, isImage)); - atomic->setLoc(loc); - atomic->setType(arg2->getType()); - atomic->getWritableType().getQualifier().makeTemporary(); - - if (isImage) { - imageAtomicParams(atomic, arg0); - } else { - atomic->getSequence().push_back(arg0); - } - - atomic->getSequence().push_back(arg1); - atomic->getSequence().push_back(arg2); - node = intermediate.addAssign(EOpAssign, arg3, atomic, loc); - - break; - } - - case EOpEvaluateAttributeSnapped: - { - // SPIR-V InterpolateAtOffset uses float vec2 offset in pixels - // HLSL uses int2 offset on a 16x16 grid in [-8..7] on x & y: - // iU = (iU<<28)>>28 - // fU = ((float)iU)/16 - // Targets might handle this natively, in which case they can disable - // decompositions. - - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); // value - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); // offset - - TIntermTyped* i28 = intermediate.addConstantUnion(28, loc, true); - TIntermTyped* iU = handleBinaryMath(loc, ">>", EOpRightShift, - handleBinaryMath(loc, "<<", EOpLeftShift, arg1, i28), - i28); - - TIntermTyped* recip16 = intermediate.addConstantUnion((1.0/16.0), EbtFloat, loc, true); - TIntermTyped* floatOffset = handleBinaryMath(loc, "mul", EOpMul, - intermediate.addConversion(EOpConstructFloat, - TType(EbtFloat, EvqTemporary, 2), iU), - recip16); - - TIntermAggregate* interp = new TIntermAggregate(EOpInterpolateAtOffset); - interp->getSequence().push_back(arg0); - interp->getSequence().push_back(floatOffset); - interp->setLoc(loc); - interp->setType(arg0->getType()); - interp->getWritableType().getQualifier().makeTemporary(); - - node = interp; - - break; - } - - case EOpLit: - { - TIntermTyped* n_dot_l = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* n_dot_h = argAggregate->getSequence()[1]->getAsTyped(); - TIntermTyped* m = argAggregate->getSequence()[2]->getAsTyped(); - - TIntermAggregate* dst = new TIntermAggregate(EOpConstructVec4); - - // Ambient - dst->getSequence().push_back(intermediate.addConstantUnion(1.0, EbtFloat, loc, true)); - - // Diffuse: - TIntermTyped* zero = intermediate.addConstantUnion(0.0, EbtFloat, loc, true); - TIntermAggregate* diffuse = new TIntermAggregate(EOpMax); - diffuse->getSequence().push_back(n_dot_l); - diffuse->getSequence().push_back(zero); - diffuse->setLoc(loc); - diffuse->setType(TType(EbtFloat)); - dst->getSequence().push_back(diffuse); - - // Specular: - TIntermAggregate* min_ndot = new TIntermAggregate(EOpMin); - min_ndot->getSequence().push_back(n_dot_l); - min_ndot->getSequence().push_back(n_dot_h); - min_ndot->setLoc(loc); - min_ndot->setType(TType(EbtFloat)); - - TIntermTyped* compare = handleBinaryMath(loc, "<", EOpLessThan, min_ndot, zero); - TIntermTyped* n_dot_h_m = handleBinaryMath(loc, "mul", EOpMul, n_dot_h, m); // n_dot_h * m - - dst->getSequence().push_back(intermediate.addSelection(compare, zero, n_dot_h_m, loc)); - - // One: - dst->getSequence().push_back(intermediate.addConstantUnion(1.0, EbtFloat, loc, true)); - - dst->setLoc(loc); - dst->setType(TType(EbtFloat, EvqTemporary, 4)); - node = dst; - break; - } - - case EOpAsDouble: - { - // asdouble accepts two 32 bit ints. we can use EOpUint64BitsToDouble, but must - // first construct a uint64. - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); - - if (arg0->getType().isVector()) { // TODO: ... - error(loc, "double2 conversion not implemented", "asdouble", ""); - break; - } - - TIntermAggregate* uint64 = new TIntermAggregate(EOpConstructUVec2); - - uint64->getSequence().push_back(arg0); - uint64->getSequence().push_back(arg1); - uint64->setType(TType(EbtUint, EvqTemporary, 2)); // convert 2 uints to a uint2 - uint64->setLoc(loc); - - // bitcast uint2 to a double - TIntermTyped* convert = new TIntermUnary(EOpUint64BitsToDouble); - convert->getAsUnaryNode()->setOperand(uint64); - convert->setLoc(loc); - convert->setType(TType(EbtDouble, EvqTemporary)); - node = convert; - - break; - } - - case EOpF16tof32: - { - // input uvecN with low 16 bits of each component holding a float16. convert to float32. - TIntermTyped* argValue = node->getAsUnaryNode()->getOperand(); - TIntermTyped* zero = intermediate.addConstantUnion(0, loc, true); - const int vecSize = argValue->getType().getVectorSize(); - - TOperator constructOp = EOpNull; - switch (vecSize) { - case 1: constructOp = EOpNull; break; // direct use, no construct needed - case 2: constructOp = EOpConstructVec2; break; - case 3: constructOp = EOpConstructVec3; break; - case 4: constructOp = EOpConstructVec4; break; - default: assert(0); break; - } - - // For scalar case, we don't need to construct another type. - TIntermAggregate* result = (vecSize > 1) ? new TIntermAggregate(constructOp) : nullptr; - - if (result) { - result->setType(TType(EbtFloat, EvqTemporary, vecSize)); - result->setLoc(loc); - } - - for (int idx = 0; idx < vecSize; ++idx) { - TIntermTyped* idxConst = intermediate.addConstantUnion(idx, loc, true); - TIntermTyped* component = argValue->getType().isVector() ? - intermediate.addIndex(EOpIndexDirect, argValue, idxConst, loc) : argValue; - - if (component != argValue) - component->setType(TType(argValue->getBasicType(), EvqTemporary)); - - TIntermTyped* unpackOp = new TIntermUnary(EOpUnpackHalf2x16); - unpackOp->setType(TType(EbtFloat, EvqTemporary, 2)); - unpackOp->getAsUnaryNode()->setOperand(component); - unpackOp->setLoc(loc); - - TIntermTyped* lowOrder = intermediate.addIndex(EOpIndexDirect, unpackOp, zero, loc); - - if (result != nullptr) { - result->getSequence().push_back(lowOrder); - node = result; - } else { - node = lowOrder; - } - } - - break; - } - - case EOpF32tof16: - { - // input floatN converted to 16 bit float in low order bits of each component of uintN - TIntermTyped* argValue = node->getAsUnaryNode()->getOperand(); - - TIntermTyped* zero = intermediate.addConstantUnion(0.0, EbtFloat, loc, true); - const int vecSize = argValue->getType().getVectorSize(); - - TOperator constructOp = EOpNull; - switch (vecSize) { - case 1: constructOp = EOpNull; break; // direct use, no construct needed - case 2: constructOp = EOpConstructUVec2; break; - case 3: constructOp = EOpConstructUVec3; break; - case 4: constructOp = EOpConstructUVec4; break; - default: assert(0); break; - } - - // For scalar case, we don't need to construct another type. - TIntermAggregate* result = (vecSize > 1) ? new TIntermAggregate(constructOp) : nullptr; - - if (result) { - result->setType(TType(EbtUint, EvqTemporary, vecSize)); - result->setLoc(loc); - } - - for (int idx = 0; idx < vecSize; ++idx) { - TIntermTyped* idxConst = intermediate.addConstantUnion(idx, loc, true); - TIntermTyped* component = argValue->getType().isVector() ? - intermediate.addIndex(EOpIndexDirect, argValue, idxConst, loc) : argValue; - - if (component != argValue) - component->setType(TType(argValue->getBasicType(), EvqTemporary)); - - TIntermAggregate* vec2ComponentAndZero = new TIntermAggregate(EOpConstructVec2); - vec2ComponentAndZero->getSequence().push_back(component); - vec2ComponentAndZero->getSequence().push_back(zero); - vec2ComponentAndZero->setType(TType(EbtFloat, EvqTemporary, 2)); - vec2ComponentAndZero->setLoc(loc); - - TIntermTyped* packOp = new TIntermUnary(EOpPackHalf2x16); - packOp->getAsUnaryNode()->setOperand(vec2ComponentAndZero); - packOp->setLoc(loc); - packOp->setType(TType(EbtUint, EvqTemporary)); - - if (result != nullptr) { - result->getSequence().push_back(packOp); - node = result; - } else { - node = packOp; - } - } - - break; - } - - case EOpD3DCOLORtoUBYTE4: - { - // ivec4 ( x.zyxw * 255.001953 ); - TIntermTyped* arg0 = node->getAsUnaryNode()->getOperand(); - TSwizzleSelectors selectors; - selectors.push_back(2); - selectors.push_back(1); - selectors.push_back(0); - selectors.push_back(3); - TIntermTyped* swizzleIdx = intermediate.addSwizzle(selectors, loc); - TIntermTyped* swizzled = intermediate.addIndex(EOpVectorSwizzle, arg0, swizzleIdx, loc); - swizzled->setType(arg0->getType()); - swizzled->getWritableType().getQualifier().makeTemporary(); - - TIntermTyped* conversion = intermediate.addConstantUnion(255.001953f, EbtFloat, loc, true); - TIntermTyped* rangeConverted = handleBinaryMath(loc, "mul", EOpMul, conversion, swizzled); - rangeConverted->setType(arg0->getType()); - rangeConverted->getWritableType().getQualifier().makeTemporary(); - - node = intermediate.addConversion(EOpConstructInt, TType(EbtInt, EvqTemporary, 4), rangeConverted); - node->setLoc(loc); - node->setType(TType(EbtInt, EvqTemporary, 4)); - break; - } - - case EOpIsFinite: - { - // Since OPIsFinite in SPIR-V is only supported with the Kernel capability, we translate - // it to !isnan && !isinf - - TIntermTyped* arg0 = node->getAsUnaryNode()->getOperand(); - - // We'll make a temporary in case the RHS is cmoplex - TVariable* tempArg = makeInternalVariable("@finitetmp", arg0->getType()); - tempArg->getWritableType().getQualifier().makeTemporary(); - - TIntermTyped* tmpArgAssign = intermediate.addAssign(EOpAssign, - intermediate.addSymbol(*tempArg, loc), - arg0, loc); - - TIntermAggregate* compoundStatement = intermediate.makeAggregate(tmpArgAssign, loc); - - const TType boolType(EbtBool, EvqTemporary, arg0->getVectorSize(), arg0->getMatrixCols(), - arg0->getMatrixRows()); - - TIntermTyped* isnan = handleUnaryMath(loc, "isnan", EOpIsNan, intermediate.addSymbol(*tempArg, loc)); - isnan->setType(boolType); - - TIntermTyped* notnan = handleUnaryMath(loc, "!", EOpLogicalNot, isnan); - notnan->setType(boolType); - - TIntermTyped* isinf = handleUnaryMath(loc, "isinf", EOpIsInf, intermediate.addSymbol(*tempArg, loc)); - isinf->setType(boolType); - - TIntermTyped* notinf = handleUnaryMath(loc, "!", EOpLogicalNot, isinf); - notinf->setType(boolType); - - TIntermTyped* andNode = handleBinaryMath(loc, "and", EOpLogicalAnd, notnan, notinf); - andNode->setType(boolType); - - compoundStatement = intermediate.growAggregate(compoundStatement, andNode); - compoundStatement->setOperator(EOpSequence); - compoundStatement->setLoc(loc); - compoundStatement->setType(boolType); - - node = compoundStatement; - - break; - } - case EOpWaveGetLaneCount: - { - // Mapped to gl_SubgroupSize builtin (We preprend @ to the symbol - // so that it inhabits the symbol table, but has a user-invalid name - // in-case some source HLSL defined the symbol also). - TType type(EbtUint, EvqVaryingIn); - node = lookupBuiltinVariable("@gl_SubgroupSize", EbvSubgroupSize2, type); - break; - } - case EOpWaveGetLaneIndex: - { - // Mapped to gl_SubgroupInvocationID builtin (We preprend @ to the - // symbol so that it inhabits the symbol table, but has a - // user-invalid name in-case some source HLSL defined the symbol - // also). - TType type(EbtUint, EvqVaryingIn); - node = lookupBuiltinVariable("@gl_SubgroupInvocationID", EbvSubgroupInvocation2, type); - break; - } - case EOpWaveActiveCountBits: - { - // Mapped to subgroupBallotBitCount(subgroupBallot()) builtin - - // uvec4 type. - TType uvec4Type(EbtUint, EvqTemporary, 4); - - // Get the uvec4 return from subgroupBallot(). - TIntermTyped* res = intermediate.addBuiltInFunctionCall(loc, - EOpSubgroupBallot, true, arguments, uvec4Type); - - // uint type. - TType uintType(EbtUint, EvqTemporary); - - node = intermediate.addBuiltInFunctionCall(loc, - EOpSubgroupBallotBitCount, true, res, uintType); - - break; - } - case EOpWavePrefixCountBits: - { - // Mapped to subgroupBallotExclusiveBitCount(subgroupBallot()) - // builtin - - // uvec4 type. - TType uvec4Type(EbtUint, EvqTemporary, 4); - - // Get the uvec4 return from subgroupBallot(). - TIntermTyped* res = intermediate.addBuiltInFunctionCall(loc, - EOpSubgroupBallot, true, arguments, uvec4Type); - - // uint type. - TType uintType(EbtUint, EvqTemporary); - - node = intermediate.addBuiltInFunctionCall(loc, - EOpSubgroupBallotExclusiveBitCount, true, res, uintType); - - break; - } - - default: - break; // most pass through unchanged - } -} - -// -// Handle seeing function call syntax in the grammar, which could be any of -// - .length() method -// - constructor -// - a call to a built-in function mapped to an operator -// - a call to a built-in function that will remain a function call (e.g., texturing) -// - user function -// - subroutine call (not implemented yet) -// -TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermTyped* arguments) -{ - TIntermTyped* result = nullptr; - - TOperator op = function->getBuiltInOp(); - if (op != EOpNull) { - // - // Then this should be a constructor. - // Don't go through the symbol table for constructors. - // Their parameters will be verified algorithmically. - // - TType type(EbtVoid); // use this to get the type back - if (! constructorError(loc, arguments, *function, op, type)) { - // - // It's a constructor, of type 'type'. - // - result = handleConstructor(loc, arguments, type); - if (result == nullptr) { - error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), ""); - return nullptr; - } - } - } else { - // - // Find it in the symbol table. - // - const TFunction* fnCandidate = nullptr; - bool builtIn = false; - int thisDepth = 0; - - // For mat mul, the situation is unusual: we have to compare vector sizes to mat row or col sizes, - // and clamp the opposite arg. Since that's complex, we farm it off to a separate method. - // It doesn't naturally fall out of processing an argument at a time in isolation. - if (function->getName() == "mul") - addGenMulArgumentConversion(loc, *function, arguments); - - TIntermAggregate* aggregate = arguments ? arguments->getAsAggregate() : nullptr; - - // TODO: this needs improvement: there's no way at present to look up a signature in - // the symbol table for an arbitrary type. This is a temporary hack until that ability exists. - // It will have false positives, since it doesn't check arg counts or types. - if (arguments) { - // Check if first argument is struct buffer type. It may be an aggregate or a symbol, so we - // look for either case. - - TIntermTyped* arg0 = nullptr; - - if (aggregate && aggregate->getSequence().size() > 0 && aggregate->getSequence()[0]) - arg0 = aggregate->getSequence()[0]->getAsTyped(); - else if (arguments->getAsSymbolNode()) - arg0 = arguments->getAsSymbolNode(); - - if (arg0 != nullptr && isStructBufferType(arg0->getType())) { - static const int methodPrefixSize = sizeof(BUILTIN_PREFIX)-1; - - if (function->getName().length() > methodPrefixSize && - isStructBufferMethod(function->getName().substr(methodPrefixSize))) { - const TString mangle = function->getName() + "("; - TSymbol* symbol = symbolTable.find(mangle, &builtIn); - - if (symbol) - fnCandidate = symbol->getAsFunction(); - } - } - } - - if (fnCandidate == nullptr) - fnCandidate = findFunction(loc, *function, builtIn, thisDepth, arguments); - - if (fnCandidate) { - // This is a declared function that might map to - // - a built-in operator, - // - a built-in function not mapped to an operator, or - // - a user function. - - // turn an implicit member-function resolution into an explicit call - TString callerName; - if (thisDepth == 0) - callerName = fnCandidate->getMangledName(); - else { - // get the explicit (full) name of the function - callerName = currentTypePrefix[currentTypePrefix.size() - thisDepth]; - callerName += fnCandidate->getMangledName(); - // insert the implicit calling argument - pushFrontArguments(intermediate.addSymbol(*getImplicitThis(thisDepth)), arguments); - } - - // Convert 'in' arguments, so that types match. - // However, skip those that need expansion, that is covered next. - if (arguments) - addInputArgumentConversions(*fnCandidate, arguments); - - // Expand arguments. Some arguments must physically expand to a different set - // than what the shader declared and passes. - if (arguments && !builtIn) - expandArguments(loc, *fnCandidate, arguments); - - // Expansion may have changed the form of arguments - aggregate = arguments ? arguments->getAsAggregate() : nullptr; - - op = fnCandidate->getBuiltInOp(); - if (builtIn && op != EOpNull) { - // SM 4.0 and above guarantees roundEven semantics for round() - if (!hlslDX9Compatible() && op == EOpRound) - op = EOpRoundEven; - - // A function call mapped to a built-in operation. - result = intermediate.addBuiltInFunctionCall(loc, op, fnCandidate->getParamCount() == 1, arguments, - fnCandidate->getType()); - if (result == nullptr) { - error(arguments->getLoc(), " wrong operand type", "Internal Error", - "built in unary operator function. Type: %s", - static_cast(arguments)->getCompleteString().c_str()); - } else if (result->getAsOperator()) { - builtInOpCheck(loc, *fnCandidate, *result->getAsOperator()); - } - } else { - // This is a function call not mapped to built-in operator. - // It could still be a built-in function, but only if PureOperatorBuiltins == false. - result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc); - TIntermAggregate* call = result->getAsAggregate(); - call->setName(callerName); - - // this is how we know whether the given function is a built-in function or a user-defined function - // if builtIn == false, it's a userDefined -> could be an overloaded built-in function also - // if builtIn == true, it's definitely a built-in function with EOpNull - if (! builtIn) { - call->setUserDefined(); - intermediate.addToCallGraph(infoSink, currentCaller, callerName); - } - } - - // for decompositions, since we want to operate on the function node, not the aggregate holding - // output conversions. - const TIntermTyped* fnNode = result; - - decomposeStructBufferMethods(loc, result, arguments); // HLSL->AST struct buffer method decompositions - decomposeIntrinsic(loc, result, arguments); // HLSL->AST intrinsic decompositions - decomposeSampleMethods(loc, result, arguments); // HLSL->AST sample method decompositions - decomposeGeometryMethods(loc, result, arguments); // HLSL->AST geometry method decompositions - - // Create the qualifier list, carried in the AST for the call. - // Because some arguments expand to multiple arguments, the qualifier list will - // be longer than the formal parameter list. - if (result == fnNode && result->getAsAggregate()) { - TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList(); - for (int i = 0; i < fnCandidate->getParamCount(); ++i) { - TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage; - if (hasStructBuffCounter(*(*fnCandidate)[i].type)) { - // add buffer and counter buffer argument qualifier - qualifierList.push_back(qual); - qualifierList.push_back(qual); - } else if (shouldFlatten(*(*fnCandidate)[i].type, (*fnCandidate)[i].type->getQualifier().storage, - true)) { - // add structure member expansion - for (int memb = 0; memb < (int)(*fnCandidate)[i].type->getStruct()->size(); ++memb) - qualifierList.push_back(qual); - } else { - // Normal 1:1 case - qualifierList.push_back(qual); - } - } - } - - // Convert 'out' arguments. If it was a constant folded built-in, it won't be an aggregate anymore. - // Built-ins with a single argument aren't called with an aggregate, but they also don't have an output. - // Also, build the qualifier list for user function calls, which are always called with an aggregate. - // We don't do this is if there has been a decomposition, which will have added its own conversions - // for output parameters. - if (result == fnNode && result->getAsAggregate()) - result = addOutputArgumentConversions(*fnCandidate, *result->getAsOperator()); - } - } - - // generic error recovery - // TODO: simplification: localize all the error recoveries that look like this, and taking type into account to - // reduce cascades - if (result == nullptr) - result = intermediate.addConstantUnion(0.0, EbtFloat, loc); - - return result; -} - -// An initial argument list is difficult: it can be null, or a single node, -// or an aggregate if more than one argument. Add one to the front, maintaining -// this lack of uniformity. -void HlslParseContext::pushFrontArguments(TIntermTyped* front, TIntermTyped*& arguments) -{ - if (arguments == nullptr) - arguments = front; - else if (arguments->getAsAggregate() != nullptr) - arguments->getAsAggregate()->getSequence().insert(arguments->getAsAggregate()->getSequence().begin(), front); - else - arguments = intermediate.growAggregate(front, arguments); -} - -// -// HLSL allows mismatched dimensions on vec*mat, mat*vec, vec*vec, and mat*mat. This is a -// situation not well suited to resolution in intrinsic selection, but we can do so here, since we -// can look at both arguments insert explicit shape changes if required. -// -void HlslParseContext::addGenMulArgumentConversion(const TSourceLoc& loc, TFunction& call, TIntermTyped*& args) -{ - TIntermAggregate* argAggregate = args ? args->getAsAggregate() : nullptr; - - if (argAggregate == nullptr || argAggregate->getSequence().size() != 2) { - // It really ought to have two arguments. - error(loc, "expected: mul arguments", "", ""); - return; - } - - TIntermTyped* arg0 = argAggregate->getSequence()[0]->getAsTyped(); - TIntermTyped* arg1 = argAggregate->getSequence()[1]->getAsTyped(); - - if (arg0->isVector() && arg1->isVector()) { - // For: - // vec * vec: it's handled during intrinsic selection, so while we could do it here, - // we can also ignore it, which is easier. - } else if (arg0->isVector() && arg1->isMatrix()) { - // vec * mat: we clamp the vec if the mat col is smaller, else clamp the mat col. - if (arg0->getVectorSize() < arg1->getMatrixCols()) { - // vec is smaller, so truncate larger mat dimension - const TType truncType(arg1->getBasicType(), arg1->getQualifier().storage, arg1->getQualifier().precision, - 0, arg0->getVectorSize(), arg1->getMatrixRows()); - arg1 = addConstructor(loc, arg1, truncType); - } else if (arg0->getVectorSize() > arg1->getMatrixCols()) { - // vec is larger, so truncate vec to mat size - const TType truncType(arg0->getBasicType(), arg0->getQualifier().storage, arg0->getQualifier().precision, - arg1->getMatrixCols()); - arg0 = addConstructor(loc, arg0, truncType); - } - } else if (arg0->isMatrix() && arg1->isVector()) { - // mat * vec: we clamp the vec if the mat col is smaller, else clamp the mat col. - if (arg1->getVectorSize() < arg0->getMatrixRows()) { - // vec is smaller, so truncate larger mat dimension - const TType truncType(arg0->getBasicType(), arg0->getQualifier().storage, arg0->getQualifier().precision, - 0, arg0->getMatrixCols(), arg1->getVectorSize()); - arg0 = addConstructor(loc, arg0, truncType); - } else if (arg1->getVectorSize() > arg0->getMatrixRows()) { - // vec is larger, so truncate vec to mat size - const TType truncType(arg1->getBasicType(), arg1->getQualifier().storage, arg1->getQualifier().precision, - arg0->getMatrixRows()); - arg1 = addConstructor(loc, arg1, truncType); - } - } else if (arg0->isMatrix() && arg1->isMatrix()) { - // mat * mat: we clamp the smaller inner dimension to match the other matrix size. - // Remember, HLSL Mrc = GLSL/SPIRV Mcr. - if (arg0->getMatrixRows() > arg1->getMatrixCols()) { - const TType truncType(arg0->getBasicType(), arg0->getQualifier().storage, arg0->getQualifier().precision, - 0, arg0->getMatrixCols(), arg1->getMatrixCols()); - arg0 = addConstructor(loc, arg0, truncType); - } else if (arg0->getMatrixRows() < arg1->getMatrixCols()) { - const TType truncType(arg1->getBasicType(), arg1->getQualifier().storage, arg1->getQualifier().precision, - 0, arg0->getMatrixRows(), arg1->getMatrixRows()); - arg1 = addConstructor(loc, arg1, truncType); - } - } else { - // It's something with scalars: we'll just leave it alone. Function selection will handle it - // downstream. - } - - // Warn if we altered one of the arguments - if (arg0 != argAggregate->getSequence()[0] || arg1 != argAggregate->getSequence()[1]) - warn(loc, "mul() matrix size mismatch", "", ""); - - // Put arguments back. (They might be unchanged, in which case this is harmless). - argAggregate->getSequence()[0] = arg0; - argAggregate->getSequence()[1] = arg1; - - call[0].type = &arg0->getWritableType(); - call[1].type = &arg1->getWritableType(); -} - -// -// Add any needed implicit conversions for function-call arguments to input parameters. -// -void HlslParseContext::addInputArgumentConversions(const TFunction& function, TIntermTyped*& arguments) -{ - TIntermAggregate* aggregate = arguments->getAsAggregate(); - - // Replace a single argument with a single argument. - const auto setArg = [&](int paramNum, TIntermTyped* arg) { - if (function.getParamCount() == 1) - arguments = arg; - else { - if (aggregate == nullptr) - arguments = arg; - else - aggregate->getSequence()[paramNum] = arg; - } - }; - - // Process each argument's conversion - for (int param = 0; param < function.getParamCount(); ++param) { - if (! function[param].type->getQualifier().isParamInput()) - continue; - - // At this early point there is a slight ambiguity between whether an aggregate 'arguments' - // is the single argument itself or its children are the arguments. Only one argument - // means take 'arguments' itself as the one argument. - TIntermTyped* arg = function.getParamCount() == 1 - ? arguments->getAsTyped() - : (aggregate ? - aggregate->getSequence()[param]->getAsTyped() : - arguments->getAsTyped()); - if (*function[param].type != arg->getType()) { - // In-qualified arguments just need an extra node added above the argument to - // convert to the correct type. - TIntermTyped* convArg = intermediate.addConversion(EOpFunctionCall, *function[param].type, arg); - if (convArg != nullptr) - convArg = intermediate.addUniShapeConversion(EOpFunctionCall, *function[param].type, convArg); - if (convArg != nullptr) - setArg(param, convArg); - else - error(arg->getLoc(), "cannot convert input argument, argument", "", "%d", param); - } else { - if (wasFlattened(arg)) { - // If both formal and calling arg are to be flattened, leave that to argument - // expansion, not conversion. - if (!shouldFlatten(*function[param].type, function[param].type->getQualifier().storage, true)) { - // Will make a two-level subtree. - // The deepest will copy member-by-member to build the structure to pass. - // The level above that will be a two-operand EOpComma sequence that follows the copy by the - // object itself. - TVariable* internalAggregate = makeInternalVariable("aggShadow", *function[param].type); - internalAggregate->getWritableType().getQualifier().makeTemporary(); - TIntermSymbol* internalSymbolNode = new TIntermSymbol(internalAggregate->getUniqueId(), - internalAggregate->getName(), - internalAggregate->getType()); - internalSymbolNode->setLoc(arg->getLoc()); - // This makes the deepest level, the member-wise copy - TIntermAggregate* assignAgg = handleAssign(arg->getLoc(), EOpAssign, - internalSymbolNode, arg)->getAsAggregate(); - - // Now, pair that with the resulting aggregate. - assignAgg = intermediate.growAggregate(assignAgg, internalSymbolNode, arg->getLoc()); - assignAgg->setOperator(EOpComma); - assignAgg->setType(internalAggregate->getType()); - setArg(param, assignAgg); - } - } - } - } -} - -// -// Add any needed implicit expansion of calling arguments from what the shader listed to what's -// internally needed for the AST (given the constraints downstream). -// -void HlslParseContext::expandArguments(const TSourceLoc& loc, const TFunction& function, TIntermTyped*& arguments) -{ - TIntermAggregate* aggregate = arguments->getAsAggregate(); - int functionParamNumberOffset = 0; - - // Replace a single argument with a single argument. - const auto setArg = [&](int paramNum, TIntermTyped* arg) { - if (function.getParamCount() + functionParamNumberOffset == 1) - arguments = arg; - else { - if (aggregate == nullptr) - arguments = arg; - else - aggregate->getSequence()[paramNum] = arg; - } - }; - - // Replace a single argument with a list of arguments - const auto setArgList = [&](int paramNum, const TVector& args) { - if (args.size() == 1) - setArg(paramNum, args.front()); - else if (args.size() > 1) { - if (function.getParamCount() + functionParamNumberOffset == 1) { - arguments = intermediate.makeAggregate(args.front()); - std::for_each(args.begin() + 1, args.end(), - [&](TIntermTyped* arg) { - arguments = intermediate.growAggregate(arguments, arg); - }); - } else { - auto it = aggregate->getSequence().erase(aggregate->getSequence().begin() + paramNum); - aggregate->getSequence().insert(it, args.begin(), args.end()); - } - functionParamNumberOffset += (int)(args.size() - 1); - } - }; - - // Process each argument's conversion - for (int param = 0; param < function.getParamCount(); ++param) { - // At this early point there is a slight ambiguity between whether an aggregate 'arguments' - // is the single argument itself or its children are the arguments. Only one argument - // means take 'arguments' itself as the one argument. - TIntermTyped* arg = function.getParamCount() == 1 - ? arguments->getAsTyped() - : (aggregate ? - aggregate->getSequence()[param + functionParamNumberOffset]->getAsTyped() : - arguments->getAsTyped()); - - if (wasFlattened(arg) && shouldFlatten(*function[param].type, function[param].type->getQualifier().storage, true)) { - // Need to pass the structure members instead of the structure. - TVector memberArgs; - for (int memb = 0; memb < (int)arg->getType().getStruct()->size(); ++memb) - memberArgs.push_back(flattenAccess(arg, memb)); - setArgList(param + functionParamNumberOffset, memberArgs); - } - } - - // TODO: if we need both hidden counter args (below) and struct expansion (above) - // the two algorithms need to be merged: Each assumes the list starts out 1:1 between - // parameters and arguments. - - // If any argument is a pass-by-reference struct buffer with an associated counter - // buffer, we have to add another hidden parameter for that counter. - if (aggregate) - addStructBuffArguments(loc, aggregate); -} - -// -// Add any needed implicit output conversions for function-call arguments. This -// can require a new tree topology, complicated further by whether the function -// has a return value. -// -// Returns a node of a subtree that evaluates to the return value of the function. -// -TIntermTyped* HlslParseContext::addOutputArgumentConversions(const TFunction& function, TIntermOperator& intermNode) -{ - assert (intermNode.getAsAggregate() != nullptr || intermNode.getAsUnaryNode() != nullptr); - - const TSourceLoc& loc = intermNode.getLoc(); - - TIntermSequence argSequence; // temp sequence for unary node args - - if (intermNode.getAsUnaryNode()) - argSequence.push_back(intermNode.getAsUnaryNode()->getOperand()); - - TIntermSequence& arguments = argSequence.empty() ? intermNode.getAsAggregate()->getSequence() : argSequence; - - const auto needsConversion = [&](int argNum) { - return function[argNum].type->getQualifier().isParamOutput() && - (*function[argNum].type != arguments[argNum]->getAsTyped()->getType() || - shouldConvertLValue(arguments[argNum]) || - wasFlattened(arguments[argNum]->getAsTyped())); - }; - - // Will there be any output conversions? - bool outputConversions = false; - for (int i = 0; i < function.getParamCount(); ++i) { - if (needsConversion(i)) { - outputConversions = true; - break; - } - } - - if (! outputConversions) - return &intermNode; - - // Setup for the new tree, if needed: - // - // Output conversions need a different tree topology. - // Out-qualified arguments need a temporary of the correct type, with the call - // followed by an assignment of the temporary to the original argument: - // void: function(arg, ...) -> ( function(tempArg, ...), arg = tempArg, ...) - // ret = function(arg, ...) -> ret = (tempRet = function(tempArg, ...), arg = tempArg, ..., tempRet) - // Where the "tempArg" type needs no conversion as an argument, but will convert on assignment. - TIntermTyped* conversionTree = nullptr; - TVariable* tempRet = nullptr; - if (intermNode.getBasicType() != EbtVoid) { - // do the "tempRet = function(...), " bit from above - tempRet = makeInternalVariable("tempReturn", intermNode.getType()); - TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, loc); - conversionTree = intermediate.addAssign(EOpAssign, tempRetNode, &intermNode, loc); - } else - conversionTree = &intermNode; - - conversionTree = intermediate.makeAggregate(conversionTree); - - // Process each argument's conversion - for (int i = 0; i < function.getParamCount(); ++i) { - if (needsConversion(i)) { - // Out-qualified arguments needing conversion need to use the topology setup above. - // Do the " ...(tempArg, ...), arg = tempArg" bit from above. - - // Make a temporary for what the function expects the argument to look like. - TVariable* tempArg = makeInternalVariable("tempArg", *function[i].type); - tempArg->getWritableType().getQualifier().makeTemporary(); - TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, loc); - - // This makes the deepest level, the member-wise copy - TIntermTyped* tempAssign = handleAssign(arguments[i]->getLoc(), EOpAssign, arguments[i]->getAsTyped(), - tempArgNode); - tempAssign = handleLvalue(arguments[i]->getLoc(), "assign", tempAssign); - conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc()); - - // replace the argument with another node for the same tempArg variable - arguments[i] = intermediate.addSymbol(*tempArg, loc); - } - } - - // Finalize the tree topology (see bigger comment above). - if (tempRet) { - // do the "..., tempRet" bit from above - TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, loc); - conversionTree = intermediate.growAggregate(conversionTree, tempRetNode, loc); - } - - conversionTree = intermediate.setAggregateOperator(conversionTree, EOpComma, intermNode.getType(), loc); - - return conversionTree; -} - -// -// Add any needed "hidden" counter buffer arguments for function calls. -// -// Modifies the 'aggregate' argument if needed. Otherwise, is no-op. -// -void HlslParseContext::addStructBuffArguments(const TSourceLoc& loc, TIntermAggregate*& aggregate) -{ - // See if there are any SB types with counters. - const bool hasStructBuffArg = - std::any_of(aggregate->getSequence().begin(), - aggregate->getSequence().end(), - [this](const TIntermNode* node) { - return (node && node->getAsTyped() != nullptr) && hasStructBuffCounter(node->getAsTyped()->getType()); - }); - - // Nothing to do, if we didn't find one. - if (! hasStructBuffArg) - return; - - TIntermSequence argsWithCounterBuffers; - - for (int param = 0; param < int(aggregate->getSequence().size()); ++param) { - argsWithCounterBuffers.push_back(aggregate->getSequence()[param]); - - if (hasStructBuffCounter(aggregate->getSequence()[param]->getAsTyped()->getType())) { - const TIntermSymbol* blockSym = aggregate->getSequence()[param]->getAsSymbolNode(); - if (blockSym != nullptr) { - TType counterType; - counterBufferType(loc, counterType); - - const TString counterBlockName(intermediate.addCounterBufferName(blockSym->getName())); - - TVariable* variable = makeInternalVariable(counterBlockName, counterType); - - // Mark this buffer's counter block as being in use - structBufferCounter[counterBlockName] = true; - - TIntermSymbol* sym = intermediate.addSymbol(*variable, loc); - argsWithCounterBuffers.push_back(sym); - } - } - } - - // Swap with the temp list we've built up. - aggregate->getSequence().swap(argsWithCounterBuffers); -} - - -// -// Do additional checking of built-in function calls that is not caught -// by normal semantic checks on argument type, extension tagging, etc. -// -// Assumes there has been a semantically correct match to a built-in function prototype. -// -void HlslParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermOperator& callNode) -{ - // Set up convenience accessors to the argument(s). There is almost always - // multiple arguments for the cases below, but when there might be one, - // check the unaryArg first. - const TIntermSequence* argp = nullptr; // confusing to use [] syntax on a pointer, so this is to help get a reference - const TIntermTyped* unaryArg = nullptr; - const TIntermTyped* arg0 = nullptr; - if (callNode.getAsAggregate()) { - argp = &callNode.getAsAggregate()->getSequence(); - if (argp->size() > 0) - arg0 = (*argp)[0]->getAsTyped(); - } else { - assert(callNode.getAsUnaryNode()); - unaryArg = callNode.getAsUnaryNode()->getOperand(); - arg0 = unaryArg; - } - const TIntermSequence& aggArgs = *argp; // only valid when unaryArg is nullptr - - switch (callNode.getOp()) { - case EOpTextureGather: - case EOpTextureGatherOffset: - case EOpTextureGatherOffsets: - { - // Figure out which variants are allowed by what extensions, - // and what arguments must be constant for which situations. - - TString featureString = fnCandidate.getName() + "(...)"; - const char* feature = featureString.c_str(); - int compArg = -1; // track which argument, if any, is the constant component argument - switch (callNode.getOp()) { - case EOpTextureGather: - // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5, - // otherwise, need GL_ARB_texture_gather. - if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || - fnCandidate[0].type->getSampler().shadow) { - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 2; - } - break; - case EOpTextureGatherOffset: - // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - break; - case EOpTextureGatherOffsets: - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - break; - default: - break; - } - - if (compArg > 0 && compArg < fnCandidate.getParamCount()) { - if (aggArgs[compArg]->getAsConstantUnion()) { - int value = aggArgs[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (value < 0 || value > 3) - error(loc, "must be 0, 1, 2, or 3:", feature, "component argument"); - } else - error(loc, "must be a compile-time constant:", feature, "component argument"); - } - - break; - } - - case EOpTextureOffset: - case EOpTextureFetchOffset: - case EOpTextureProjOffset: - case EOpTextureLodOffset: - case EOpTextureProjLodOffset: - case EOpTextureGradOffset: - case EOpTextureProjGradOffset: - { - // Handle texture-offset limits checking - // Pick which argument has to hold constant offsets - int arg = -1; - switch (callNode.getOp()) { - case EOpTextureOffset: arg = 2; break; - case EOpTextureFetchOffset: arg = (arg0->getType().getSampler().dim != EsdRect) ? 3 : 2; break; - case EOpTextureProjOffset: arg = 2; break; - case EOpTextureLodOffset: arg = 3; break; - case EOpTextureProjLodOffset: arg = 3; break; - case EOpTextureGradOffset: arg = 4; break; - case EOpTextureProjGradOffset: arg = 4; break; - default: - assert(0); - break; - } - - if (arg > 0) { - if (aggArgs[arg]->getAsConstantUnion() == nullptr) - error(loc, "argument must be compile-time constant", "texel offset", ""); - else { - const TType& type = aggArgs[arg]->getAsTyped()->getType(); - for (int c = 0; c < type.getVectorSize(); ++c) { - int offset = aggArgs[arg]->getAsConstantUnion()->getConstArray()[c].getIConst(); - if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset) - error(loc, "value is out of range:", "texel offset", - "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); - } - } - } - - break; - } - - case EOpTextureQuerySamples: - case EOpImageQuerySamples: - break; - - case EOpImageAtomicAdd: - case EOpImageAtomicMin: - case EOpImageAtomicMax: - case EOpImageAtomicAnd: - case EOpImageAtomicOr: - case EOpImageAtomicXor: - case EOpImageAtomicExchange: - case EOpImageAtomicCompSwap: - break; - - case EOpInterpolateAtCentroid: - case EOpInterpolateAtSample: - case EOpInterpolateAtOffset: - // TODO(greg-lunarg): Re-enable this check. It currently gives false errors for builtins - // defined and passed as members of a struct. In this case the storage class is showing to be - // Function. See glslang #2584 - - // Make sure the first argument is an interpolant, or an array element of an interpolant - // if (arg0->getType().getQualifier().storage != EvqVaryingIn) { - // It might still be an array element. - // - // We could check more, but the semantics of the first argument are already met; the - // only way to turn an array into a float/vec* is array dereference and swizzle. - // - // ES and desktop 4.3 and earlier: swizzles may not be used - // desktop 4.4 and later: swizzles may be used - // const TIntermTyped* base = TIntermediate::findLValueBase(arg0, true); - // if (base == nullptr || base->getType().getQualifier().storage != EvqVaryingIn) - // error(loc, "first argument must be an interpolant, or interpolant-array element", - // fnCandidate.getName().c_str(), ""); - // } - break; - - default: - break; - } -} - -// -// Handle seeing something in a grammar production that can be done by calling -// a constructor. -// -// The constructor still must be "handled" by handleFunctionCall(), which will -// then call handleConstructor(). -// -TFunction* HlslParseContext::makeConstructorCall(const TSourceLoc& loc, const TType& type) -{ - TOperator op = intermediate.mapTypeToConstructorOp(type); - - if (op == EOpNull) { - error(loc, "cannot construct this type", type.getBasicString(), ""); - return nullptr; - } - - TString empty(""); - - return new TFunction(&empty, type, op); -} - -// -// Handle seeing a "COLON semantic" at the end of a type declaration, -// by updating the type according to the semantic. -// -void HlslParseContext::handleSemantic(TSourceLoc loc, TQualifier& qualifier, TBuiltInVariable builtIn, - const TString& upperCase) -{ - // Parse and return semantic number. If limit is 0, it will be ignored. Otherwise, if the parsed - // semantic number is >= limit, errorMsg is issued and 0 is returned. - // TODO: it would be nicer if limit and errorMsg had default parameters, but some compilers don't yet - // accept those in lambda functions. - const auto getSemanticNumber = [this, loc](const TString& semantic, unsigned int limit, const char* errorMsg) -> unsigned int { - size_t pos = semantic.find_last_not_of("0123456789"); - if (pos == std::string::npos) - return 0u; - - unsigned int semanticNum = (unsigned int)atoi(semantic.c_str() + pos + 1); - - if (limit != 0 && semanticNum >= limit) { - error(loc, errorMsg, semantic.c_str(), ""); - return 0u; - } - - return semanticNum; - }; - - if (builtIn == EbvNone && hlslDX9Compatible()) { - if (language == EShLangVertex) { - if (qualifier.isParamOutput()) { - if (upperCase == "POSITION") { - builtIn = EbvPosition; - } - if (upperCase == "PSIZE") { - builtIn = EbvPointSize; - } - } - } else if (language == EShLangFragment) { - if (qualifier.isParamInput() && upperCase == "VPOS") { - builtIn = EbvFragCoord; - } - if (qualifier.isParamOutput()) { - if (upperCase.compare(0, 5, "COLOR") == 0) { - qualifier.layoutLocation = getSemanticNumber(upperCase, 0, nullptr); - nextOutLocation = std::max(nextOutLocation, qualifier.layoutLocation + 1u); - } - if (upperCase == "DEPTH") { - builtIn = EbvFragDepth; - } - } - } - } - - switch(builtIn) { - case EbvNone: - // Get location numbers from fragment outputs, instead of - // auto-assigning them. - if (language == EShLangFragment && upperCase.compare(0, 9, "SV_TARGET") == 0) { - qualifier.layoutLocation = getSemanticNumber(upperCase, 0, nullptr); - nextOutLocation = std::max(nextOutLocation, qualifier.layoutLocation + 1u); - } else if (upperCase.compare(0, 15, "SV_CLIPDISTANCE") == 0) { - builtIn = EbvClipDistance; - qualifier.layoutLocation = getSemanticNumber(upperCase, maxClipCullRegs, "invalid clip semantic"); - } else if (upperCase.compare(0, 15, "SV_CULLDISTANCE") == 0) { - builtIn = EbvCullDistance; - qualifier.layoutLocation = getSemanticNumber(upperCase, maxClipCullRegs, "invalid cull semantic"); - } - break; - case EbvPosition: - // adjust for stage in/out - if (language == EShLangFragment) - builtIn = EbvFragCoord; - break; - case EbvFragStencilRef: - error(loc, "unimplemented; need ARB_shader_stencil_export", "SV_STENCILREF", ""); - break; - case EbvTessLevelInner: - case EbvTessLevelOuter: - qualifier.patch = true; - break; - default: - break; - } - - if (qualifier.builtIn == EbvNone) - qualifier.builtIn = builtIn; - qualifier.semanticName = intermediate.addSemanticName(upperCase); -} - -// -// Handle seeing something like "PACKOFFSET LEFT_PAREN c[Subcomponent][.component] RIGHT_PAREN" -// -// 'location' has the "c[Subcomponent]" part. -// 'component' points to the "component" part, or nullptr if not present. -// -void HlslParseContext::handlePackOffset(const TSourceLoc& loc, TQualifier& qualifier, const glslang::TString& location, - const glslang::TString* component) -{ - if (location.size() == 0 || location[0] != 'c') { - error(loc, "expected 'c'", "packoffset", ""); - return; - } - if (location.size() == 1) - return; - if (! isdigit(location[1])) { - error(loc, "expected number after 'c'", "packoffset", ""); - return; - } - - qualifier.layoutOffset = 16 * atoi(location.substr(1, location.size()).c_str()); - if (component != nullptr) { - int componentOffset = 0; - switch ((*component)[0]) { - case 'x': componentOffset = 0; break; - case 'y': componentOffset = 4; break; - case 'z': componentOffset = 8; break; - case 'w': componentOffset = 12; break; - default: - componentOffset = -1; - break; - } - if (componentOffset < 0 || component->size() > 1) { - error(loc, "expected {x, y, z, w} for component", "packoffset", ""); - return; - } - qualifier.layoutOffset += componentOffset; - } -} - -// -// Handle seeing something like "REGISTER LEFT_PAREN [shader_profile,] Type# RIGHT_PAREN" -// -// 'profile' points to the shader_profile part, or nullptr if not present. -// 'desc' is the type# part. -// -void HlslParseContext::handleRegister(const TSourceLoc& loc, TQualifier& qualifier, const glslang::TString* profile, - const glslang::TString& desc, int subComponent, const glslang::TString* spaceDesc) -{ - if (profile != nullptr) - warn(loc, "ignoring shader_profile", "register", ""); - - if (desc.size() < 1) { - error(loc, "expected register type", "register", ""); - return; - } - - int regNumber = 0; - if (desc.size() > 1) { - if (isdigit(desc[1])) - regNumber = atoi(desc.substr(1, desc.size()).c_str()); - else { - error(loc, "expected register number after register type", "register", ""); - return; - } - } - - // more information about register types see - // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-variable-register - const std::vector& resourceInfo = intermediate.getResourceSetBinding(); - switch (std::tolower(desc[0])) { - case 'c': - // c register is the register slot in the global const buffer - // each slot is a vector of 4 32 bit components - qualifier.layoutOffset = regNumber * 4 * 4; - break; - // const buffer register slot - case 'b': - // textrues and structured buffers - case 't': - // samplers - case 's': - // uav resources - case 'u': - // if nothing else has set the binding, do so now - // (other mechanisms override this one) - if (!qualifier.hasBinding()) - qualifier.layoutBinding = regNumber + subComponent; - - // This handles per-register layout sets numbers. For the global mode which sets - // every symbol to the same value, see setLinkageLayoutSets(). - if ((resourceInfo.size() % 3) == 0) { - // Apply per-symbol resource set and binding. - for (auto it = resourceInfo.cbegin(); it != resourceInfo.cend(); it = it + 3) { - if (strcmp(desc.c_str(), it[0].c_str()) == 0) { - qualifier.layoutSet = atoi(it[1].c_str()); - qualifier.layoutBinding = atoi(it[2].c_str()) + subComponent; - break; - } - } - } - break; - default: - warn(loc, "ignoring unrecognized register type", "register", "%c", desc[0]); - break; - } - - // space - unsigned int setNumber; - const auto crackSpace = [&]() -> bool { - const int spaceLen = 5; - if (spaceDesc->size() < spaceLen + 1) - return false; - if (spaceDesc->compare(0, spaceLen, "space") != 0) - return false; - if (! isdigit((*spaceDesc)[spaceLen])) - return false; - setNumber = atoi(spaceDesc->substr(spaceLen, spaceDesc->size()).c_str()); - return true; - }; - - // if nothing else has set the set, do so now - // (other mechanisms override this one) - if (spaceDesc && !qualifier.hasSet()) { - if (! crackSpace()) { - error(loc, "expected spaceN", "register", ""); - return; - } - qualifier.layoutSet = setNumber; - } -} - -// Convert to a scalar boolean, or if not allowed by HLSL semantics, -// report an error and return nullptr. -TIntermTyped* HlslParseContext::convertConditionalExpression(const TSourceLoc& loc, TIntermTyped* condition, - bool mustBeScalar) -{ - if (mustBeScalar && !condition->getType().isScalarOrVec1()) { - error(loc, "requires a scalar", "conditional expression", ""); - return nullptr; - } - - return intermediate.addConversion(EOpConstructBool, TType(EbtBool, EvqTemporary, condition->getVectorSize()), - condition); -} - -// -// Same error message for all places assignments don't work. -// -void HlslParseContext::assignError(const TSourceLoc& loc, const char* op, TString left, TString right) -{ - error(loc, "", op, "cannot convert from '%s' to '%s'", - right.c_str(), left.c_str()); -} - -// -// Same error message for all places unary operations don't work. -// -void HlslParseContext::unaryOpError(const TSourceLoc& loc, const char* op, TString operand) -{ - error(loc, " wrong operand type", op, - "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)", - op, operand.c_str()); -} - -// -// Same error message for all binary operations don't work. -// -void HlslParseContext::binaryOpError(const TSourceLoc& loc, const char* op, TString left, TString right) -{ - error(loc, " wrong operand types:", op, - "no operation '%s' exists that takes a left-hand operand of type '%s' and " - "a right operand of type '%s' (or there is no acceptable conversion)", - op, left.c_str(), right.c_str()); -} - -// -// A basic type of EbtVoid is a key that the name string was seen in the source, but -// it was not found as a variable in the symbol table. If so, give the error -// message and insert a dummy variable in the symbol table to prevent future errors. -// -void HlslParseContext::variableCheck(TIntermTyped*& nodePtr) -{ - TIntermSymbol* symbol = nodePtr->getAsSymbolNode(); - if (! symbol) - return; - - if (symbol->getType().getBasicType() == EbtVoid) { - error(symbol->getLoc(), "undeclared identifier", symbol->getName().c_str(), ""); - - // Add to symbol table to prevent future error messages on the same name - if (symbol->getName().size() > 0) { - TVariable* fakeVariable = new TVariable(&symbol->getName(), TType(EbtFloat)); - symbolTable.insert(*fakeVariable); - - // substitute a symbol node for this new variable - nodePtr = intermediate.addSymbol(*fakeVariable, symbol->getLoc()); - } - } -} - -// -// Both test, and if necessary spit out an error, to see if the node is really -// a constant. -// -void HlslParseContext::constantValueCheck(TIntermTyped* node, const char* token) -{ - if (node->getQualifier().storage != EvqConst) - error(node->getLoc(), "constant expression required", token, ""); -} - -// -// Both test, and if necessary spit out an error, to see if the node is really -// an integer. -// -void HlslParseContext::integerCheck(const TIntermTyped* node, const char* token) -{ - if ((node->getBasicType() == EbtInt || node->getBasicType() == EbtUint) && node->isScalar()) - return; - - error(node->getLoc(), "scalar integer expression required", token, ""); -} - -// -// Both test, and if necessary spit out an error, to see if we are currently -// globally scoped. -// -void HlslParseContext::globalCheck(const TSourceLoc& loc, const char* token) -{ - if (! symbolTable.atGlobalLevel()) - error(loc, "not allowed in nested scope", token, ""); -} - -bool HlslParseContext::builtInName(const TString& /*identifier*/) -{ - return false; -} - -// -// Make sure there is enough data and not too many arguments provided to the -// constructor to build something of the type of the constructor. Also returns -// the type of the constructor. -// -// Returns true if there was an error in construction. -// -bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, TFunction& function, - TOperator op, TType& type) -{ - type.shallowCopy(function.getType()); - - bool constructingMatrix = false; - switch (op) { - case EOpConstructTextureSampler: - error(loc, "unhandled texture constructor", "constructor", ""); - return true; - case EOpConstructMat2x2: - case EOpConstructMat2x3: - case EOpConstructMat2x4: - case EOpConstructMat3x2: - case EOpConstructMat3x3: - case EOpConstructMat3x4: - case EOpConstructMat4x2: - case EOpConstructMat4x3: - case EOpConstructMat4x4: - case EOpConstructDMat2x2: - case EOpConstructDMat2x3: - case EOpConstructDMat2x4: - case EOpConstructDMat3x2: - case EOpConstructDMat3x3: - case EOpConstructDMat3x4: - case EOpConstructDMat4x2: - case EOpConstructDMat4x3: - case EOpConstructDMat4x4: - case EOpConstructIMat2x2: - case EOpConstructIMat2x3: - case EOpConstructIMat2x4: - case EOpConstructIMat3x2: - case EOpConstructIMat3x3: - case EOpConstructIMat3x4: - case EOpConstructIMat4x2: - case EOpConstructIMat4x3: - case EOpConstructIMat4x4: - case EOpConstructUMat2x2: - case EOpConstructUMat2x3: - case EOpConstructUMat2x4: - case EOpConstructUMat3x2: - case EOpConstructUMat3x3: - case EOpConstructUMat3x4: - case EOpConstructUMat4x2: - case EOpConstructUMat4x3: - case EOpConstructUMat4x4: - case EOpConstructBMat2x2: - case EOpConstructBMat2x3: - case EOpConstructBMat2x4: - case EOpConstructBMat3x2: - case EOpConstructBMat3x3: - case EOpConstructBMat3x4: - case EOpConstructBMat4x2: - case EOpConstructBMat4x3: - case EOpConstructBMat4x4: - constructingMatrix = true; - break; - default: - break; - } - - // - // Walk the arguments for first-pass checks and collection of information. - // - - int size = 0; - bool constType = true; - bool full = false; - bool overFull = false; - bool matrixInMatrix = false; - bool arrayArg = false; - for (int arg = 0; arg < function.getParamCount(); ++arg) { - if (function[arg].type->isArray()) { - if (function[arg].type->isUnsizedArray()) { - // Can't construct from an unsized array. - error(loc, "array argument must be sized", "constructor", ""); - return true; - } - arrayArg = true; - } - if (constructingMatrix && function[arg].type->isMatrix()) - matrixInMatrix = true; - - // 'full' will go to true when enough args have been seen. If we loop - // again, there is an extra argument. - if (full) { - // For vectors and matrices, it's okay to have too many components - // available, but not okay to have unused arguments. - overFull = true; - } - - size += function[arg].type->computeNumComponents(); - if (op != EOpConstructStruct && ! type.isArray() && size >= type.computeNumComponents()) - full = true; - - if (function[arg].type->getQualifier().storage != EvqConst) - constType = false; - } - - if (constType) - type.getQualifier().storage = EvqConst; - - if (type.isArray()) { - if (function.getParamCount() == 0) { - error(loc, "array constructor must have at least one argument", "constructor", ""); - return true; - } - - if (type.isUnsizedArray()) { - // auto adapt the constructor type to the number of arguments - type.changeOuterArraySize(function.getParamCount()); - } else if (type.getOuterArraySize() != function.getParamCount() && type.computeNumComponents() > size) { - error(loc, "array constructor needs one argument per array element", "constructor", ""); - return true; - } - - if (type.isArrayOfArrays()) { - // Types have to match, but we're still making the type. - // Finish making the type, and the comparison is done later - // when checking for conversion. - TArraySizes& arraySizes = *type.getArraySizes(); - - // At least the dimensionalities have to match. - if (! function[0].type->isArray() || - arraySizes.getNumDims() != function[0].type->getArraySizes()->getNumDims() + 1) { - error(loc, "array constructor argument not correct type to construct array element", "constructor", ""); - return true; - } - - if (arraySizes.isInnerUnsized()) { - // "Arrays of arrays ..., and the size for any dimension is optional" - // That means we need to adopt (from the first argument) the other array sizes into the type. - for (int d = 1; d < arraySizes.getNumDims(); ++d) { - if (arraySizes.getDimSize(d) == UnsizedArraySize) { - arraySizes.setDimSize(d, function[0].type->getArraySizes()->getDimSize(d - 1)); - } - } - } - } - } - - // Some array -> array type casts are okay - if (arrayArg && function.getParamCount() == 1 && op != EOpConstructStruct && type.isArray() && - !type.isArrayOfArrays() && !function[0].type->isArrayOfArrays() && - type.getVectorSize() >= 1 && function[0].type->getVectorSize() >= 1) - return false; - - if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) { - error(loc, "constructing non-array constituent from array argument", "constructor", ""); - return true; - } - - if (matrixInMatrix && ! type.isArray()) { - return false; - } - - if (overFull) { - error(loc, "too many arguments", "constructor", ""); - return true; - } - - if (op == EOpConstructStruct && ! type.isArray()) { - if (isScalarConstructor(node)) - return false; - - // Self-type construction: e.g, we can construct a struct from a single identically typed object. - if (function.getParamCount() == 1 && type == *function[0].type) - return false; - - if ((int)type.getStruct()->size() != function.getParamCount()) { - error(loc, "Number of constructor parameters does not match the number of structure fields", "constructor", ""); - return true; - } - } - - if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) || - (op == EOpConstructStruct && size < type.computeNumComponents())) { - error(loc, "not enough data provided for construction", "constructor", ""); - return true; - } - - return false; -} - -// See if 'node', in the context of constructing aggregates, is a scalar argument -// to a constructor. -// -bool HlslParseContext::isScalarConstructor(const TIntermNode* node) -{ - // Obviously, it must be a scalar, but an aggregate node might not be fully - // completed yet: holding a sequence of initializers under an aggregate - // would not yet be typed, so don't check it's type. This corresponds to - // the aggregate operator also not being set yet. (An aggregate operation - // that legitimately yields a scalar will have a getOp() of that operator, - // not EOpNull.) - - return node->getAsTyped() != nullptr && - node->getAsTyped()->isScalar() && - (node->getAsAggregate() == nullptr || node->getAsAggregate()->getOp() != EOpNull); -} - -// Checks to see if a void variable has been declared and raise an error message for such a case -// -// returns true in case of an error -// -bool HlslParseContext::voidErrorCheck(const TSourceLoc& loc, const TString& identifier, const TBasicType basicType) -{ - if (basicType == EbtVoid) { - error(loc, "illegal use of type 'void'", identifier.c_str(), ""); - return true; - } - - return false; -} - -// -// Fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level. -// -void HlslParseContext::globalQualifierFix(const TSourceLoc&, TQualifier& qualifier) -{ - // move from parameter/unknown qualifiers to pipeline in/out qualifiers - switch (qualifier.storage) { - case EvqIn: - qualifier.storage = EvqVaryingIn; - break; - case EvqOut: - qualifier.storage = EvqVaryingOut; - break; - default: - break; - } -} - -// -// Merge characteristics of the 'src' qualifier into the 'dst'. -// -void HlslParseContext::mergeQualifiers(TQualifier& dst, const TQualifier& src) -{ - // Storage qualification - if (dst.storage == EvqTemporary || dst.storage == EvqGlobal) - dst.storage = src.storage; - else if ((dst.storage == EvqIn && src.storage == EvqOut) || - (dst.storage == EvqOut && src.storage == EvqIn)) - dst.storage = EvqInOut; - else if ((dst.storage == EvqIn && src.storage == EvqConst) || - (dst.storage == EvqConst && src.storage == EvqIn)) - dst.storage = EvqConstReadOnly; - - // Layout qualifiers - mergeObjectLayoutQualifiers(dst, src, false); - - // individual qualifiers -#define MERGE_SINGLETON(field) dst.field |= src.field; - MERGE_SINGLETON(invariant); - MERGE_SINGLETON(noContraction); - MERGE_SINGLETON(centroid); - MERGE_SINGLETON(smooth); - MERGE_SINGLETON(flat); - MERGE_SINGLETON(nopersp); - MERGE_SINGLETON(patch); - MERGE_SINGLETON(sample); - MERGE_SINGLETON(coherent); - MERGE_SINGLETON(volatil); - MERGE_SINGLETON(restrict); - MERGE_SINGLETON(readonly); - MERGE_SINGLETON(writeonly); - MERGE_SINGLETON(specConstant); - MERGE_SINGLETON(nonUniform); -} - -// used to flatten the sampler type space into a single dimension -// correlates with the declaration of defaultSamplerPrecision[] -int HlslParseContext::computeSamplerTypeIndex(TSampler& sampler) -{ - int arrayIndex = sampler.arrayed ? 1 : 0; - int shadowIndex = sampler.shadow ? 1 : 0; - int externalIndex = sampler.external ? 1 : 0; - - return EsdNumDims * - (EbtNumTypes * (2 * (2 * arrayIndex + shadowIndex) + externalIndex) + sampler.type) + sampler.dim; -} - -// -// Do size checking for an array type's size. -// -void HlslParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TArraySize& sizePair) -{ - bool isConst = false; - sizePair.size = 1; - sizePair.node = nullptr; - - TIntermConstantUnion* constant = expr->getAsConstantUnion(); - if (constant) { - // handle true (non-specialization) constant - sizePair.size = constant->getConstArray()[0].getIConst(); - isConst = true; - } else { - // see if it's a specialization constant instead - if (expr->getQualifier().isSpecConstant()) { - isConst = true; - sizePair.node = expr; - TIntermSymbol* symbol = expr->getAsSymbolNode(); - if (symbol && symbol->getConstArray().size() > 0) - sizePair.size = symbol->getConstArray()[0].getIConst(); - } - } - - if (! isConst || (expr->getBasicType() != EbtInt && expr->getBasicType() != EbtUint)) { - error(loc, "array size must be a constant integer expression", "", ""); - return; - } - - if (sizePair.size <= 0) { - error(loc, "array size must be a positive integer", "", ""); - return; - } -} - -// -// Require array to be completely sized -// -void HlslParseContext::arraySizeRequiredCheck(const TSourceLoc& loc, const TArraySizes& arraySizes) -{ - if (arraySizes.hasUnsized()) - error(loc, "array size required", "", ""); -} - -void HlslParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& type) -{ - const TTypeList& structure = *type.getStruct(); - for (int m = 0; m < (int)structure.size(); ++m) { - const TType& member = *structure[m].type; - if (member.isArray()) - arraySizeRequiredCheck(structure[m].loc, *member.getArraySizes()); - } -} - -// -// Do all the semantic checking for declaring or redeclaring an array, with and -// without a size, and make the right changes to the symbol table. -// -void HlslParseContext::declareArray(const TSourceLoc& loc, const TString& identifier, const TType& type, - TSymbol*& symbol, bool track) -{ - if (symbol == nullptr) { - bool currentScope; - symbol = symbolTable.find(identifier, nullptr, ¤tScope); - - if (symbol && builtInName(identifier) && ! symbolTable.atBuiltInLevel()) { - // bad shader (errors already reported) trying to redeclare a built-in name as an array - return; - } - if (symbol == nullptr || ! currentScope) { - // - // Successfully process a new definition. - // (Redeclarations have to take place at the same scope; otherwise they are hiding declarations) - // - symbol = new TVariable(&identifier, type); - symbolTable.insert(*symbol); - if (track && symbolTable.atGlobalLevel()) - trackLinkage(*symbol); - - return; - } - if (symbol->getAsAnonMember()) { - error(loc, "cannot redeclare a user-block member array", identifier.c_str(), ""); - symbol = nullptr; - return; - } - } - - // - // Process a redeclaration. - // - - if (symbol == nullptr) { - error(loc, "array variable name expected", identifier.c_str(), ""); - return; - } - - // redeclareBuiltinVariable() should have already done the copyUp() - TType& existingType = symbol->getWritableType(); - - if (existingType.isSizedArray()) { - // be more lenient for input arrays to geometry shaders and tessellation control outputs, - // where the redeclaration is the same size - return; - } - - existingType.updateArraySizes(type); -} - -// -// Enforce non-initializer type/qualifier rules. -// -void HlslParseContext::fixConstInit(const TSourceLoc& loc, const TString& identifier, TType& type, - TIntermTyped*& initializer) -{ - // - // Make the qualifier make sense, given that there is an initializer. - // - if (initializer == nullptr) { - if (type.getQualifier().storage == EvqConst || - type.getQualifier().storage == EvqConstReadOnly) { - initializer = intermediate.makeAggregate(loc); - warn(loc, "variable with qualifier 'const' not initialized; zero initializing", identifier.c_str(), ""); - } - } -} - -// -// See if the identifier is a built-in symbol that can be redeclared, and if so, -// copy the symbol table's read-only built-in variable to the current -// global level, where it can be modified based on the passed in type. -// -// Returns nullptr if no redeclaration took place; meaning a normal declaration still -// needs to occur for it, not necessarily an error. -// -// Returns a redeclared and type-modified variable if a redeclared occurred. -// -TSymbol* HlslParseContext::redeclareBuiltinVariable(const TSourceLoc& /*loc*/, const TString& identifier, - const TQualifier& /*qualifier*/, - const TShaderQualifiers& /*publicType*/) -{ - if (! builtInName(identifier) || symbolTable.atBuiltInLevel() || ! symbolTable.atGlobalLevel()) - return nullptr; - - return nullptr; -} - -// -// Generate index to the array element in a structure buffer (SSBO) -// -TIntermTyped* HlslParseContext::indexStructBufferContent(const TSourceLoc& loc, TIntermTyped* buffer) const -{ - // Bail out if not a struct buffer - if (buffer == nullptr || ! isStructBufferType(buffer->getType())) - return nullptr; - - // Runtime sized array is always the last element. - const TTypeList* bufferStruct = buffer->getType().getStruct(); - TIntermTyped* arrayPosition = intermediate.addConstantUnion(unsigned(bufferStruct->size()-1), loc); - - TIntermTyped* argArray = intermediate.addIndex(EOpIndexDirectStruct, buffer, arrayPosition, loc); - argArray->setType(*(*bufferStruct)[bufferStruct->size()-1].type); - - return argArray; -} - -// -// IFF type is a structuredbuffer/byteaddressbuffer type, return the content -// (template) type. E.g, StructuredBuffer -> MyType. Else return nullptr. -// -TType* HlslParseContext::getStructBufferContentType(const TType& type) const -{ - if (type.getBasicType() != EbtBlock || type.getQualifier().storage != EvqBuffer) - return nullptr; - - const int memberCount = (int)type.getStruct()->size(); - assert(memberCount > 0); - - TType* contentType = (*type.getStruct())[memberCount-1].type; - - return contentType->isUnsizedArray() ? contentType : nullptr; -} - -// -// If an existing struct buffer has a sharable type, then share it. -// -void HlslParseContext::shareStructBufferType(TType& type) -{ - // PackOffset must be equivalent to share types on a per-member basis. - // Note: cannot use auto type due to recursion. Thus, this is a std::function. - const std::function - compareQualifiers = [&](TType& lhs, TType& rhs) -> bool { - if (lhs.getQualifier().layoutOffset != rhs.getQualifier().layoutOffset) - return false; - - if (lhs.isStruct() != rhs.isStruct()) - return false; - - if (lhs.getQualifier().builtIn != rhs.getQualifier().builtIn) - return false; - - if (lhs.isStruct() && rhs.isStruct()) { - if (lhs.getStruct()->size() != rhs.getStruct()->size()) - return false; - - for (int i = 0; i < int(lhs.getStruct()->size()); ++i) - if (!compareQualifiers(*(*lhs.getStruct())[i].type, *(*rhs.getStruct())[i].type)) - return false; - } - - return true; - }; - - // We need to compare certain qualifiers in addition to the type. - const auto typeEqual = [compareQualifiers](TType& lhs, TType& rhs) -> bool { - if (lhs.getQualifier().readonly != rhs.getQualifier().readonly) - return false; - - // If both are structures, recursively look for packOffset equality - // as well as type equality. - return compareQualifiers(lhs, rhs) && lhs == rhs; - }; - - // This is an exhaustive O(N) search, but real world shaders have - // only a small number of these. - for (int idx = 0; idx < int(structBufferTypes.size()); ++idx) { - // If the deep structure matches, modulo qualifiers, use it - if (typeEqual(*structBufferTypes[idx], type)) { - type.shallowCopy(*structBufferTypes[idx]); - return; - } - } - - // Otherwise, remember it: - TType* typeCopy = new TType; - typeCopy->shallowCopy(type); - structBufferTypes.push_back(typeCopy); -} - -void HlslParseContext::paramFix(TType& type) -{ - switch (type.getQualifier().storage) { - case EvqConst: - type.getQualifier().storage = EvqConstReadOnly; - break; - case EvqGlobal: - case EvqTemporary: - type.getQualifier().storage = EvqIn; - break; - case EvqBuffer: - { - // SSBO parameter. These do not go through the declareBlock path since they are fn parameters. - correctUniform(type.getQualifier()); - TQualifier bufferQualifier = globalBufferDefaults; - mergeObjectLayoutQualifiers(bufferQualifier, type.getQualifier(), true); - bufferQualifier.storage = type.getQualifier().storage; - bufferQualifier.readonly = type.getQualifier().readonly; - bufferQualifier.coherent = type.getQualifier().coherent; - bufferQualifier.declaredBuiltIn = type.getQualifier().declaredBuiltIn; - type.getQualifier() = bufferQualifier; - break; - } - default: - break; - } -} - -void HlslParseContext::specializationCheck(const TSourceLoc& loc, const TType& type, const char* op) -{ - if (type.containsSpecializationSize()) - error(loc, "can't use with types containing arrays sized with a specialization constant", op, ""); -} - -// -// Layout qualifier stuff. -// - -// Put the id's layout qualification into the public type, for qualifiers not having a number set. -// This is before we know any type information for error checking. -void HlslParseContext::setLayoutQualifier(const TSourceLoc& loc, TQualifier& qualifier, TString& id) -{ - std::transform(id.begin(), id.end(), id.begin(), ::tolower); - - if (id == TQualifier::getLayoutMatrixString(ElmColumnMajor)) { - qualifier.layoutMatrix = ElmRowMajor; - return; - } - if (id == TQualifier::getLayoutMatrixString(ElmRowMajor)) { - qualifier.layoutMatrix = ElmColumnMajor; - return; - } - if (id == "push_constant") { - requireVulkan(loc, "push_constant"); - qualifier.layoutPushConstant = true; - return; - } - if (language == EShLangGeometry || language == EShLangTessEvaluation) { - if (id == TQualifier::getGeometryString(ElgTriangles)) { - // publicType.shaderQualifiers.geometry = ElgTriangles; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (language == EShLangGeometry) { - if (id == TQualifier::getGeometryString(ElgPoints)) { - // publicType.shaderQualifiers.geometry = ElgPoints; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgLineStrip)) { - // publicType.shaderQualifiers.geometry = ElgLineStrip; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgLines)) { - // publicType.shaderQualifiers.geometry = ElgLines; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgLinesAdjacency)) { - // publicType.shaderQualifiers.geometry = ElgLinesAdjacency; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgTrianglesAdjacency)) { - // publicType.shaderQualifiers.geometry = ElgTrianglesAdjacency; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgTriangleStrip)) { - // publicType.shaderQualifiers.geometry = ElgTriangleStrip; - warn(loc, "ignored", id.c_str(), ""); - return; - } - } else { - assert(language == EShLangTessEvaluation); - - // input primitive - if (id == TQualifier::getGeometryString(ElgTriangles)) { - // publicType.shaderQualifiers.geometry = ElgTriangles; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgQuads)) { - // publicType.shaderQualifiers.geometry = ElgQuads; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getGeometryString(ElgIsolines)) { - // publicType.shaderQualifiers.geometry = ElgIsolines; - warn(loc, "ignored", id.c_str(), ""); - return; - } - - // vertex spacing - if (id == TQualifier::getVertexSpacingString(EvsEqual)) { - // publicType.shaderQualifiers.spacing = EvsEqual; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getVertexSpacingString(EvsFractionalEven)) { - // publicType.shaderQualifiers.spacing = EvsFractionalEven; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getVertexSpacingString(EvsFractionalOdd)) { - // publicType.shaderQualifiers.spacing = EvsFractionalOdd; - warn(loc, "ignored", id.c_str(), ""); - return; - } - - // triangle order - if (id == TQualifier::getVertexOrderString(EvoCw)) { - // publicType.shaderQualifiers.order = EvoCw; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == TQualifier::getVertexOrderString(EvoCcw)) { - // publicType.shaderQualifiers.order = EvoCcw; - warn(loc, "ignored", id.c_str(), ""); - return; - } - - // point mode - if (id == "point_mode") { - // publicType.shaderQualifiers.pointMode = true; - warn(loc, "ignored", id.c_str(), ""); - return; - } - } - } - if (language == EShLangFragment) { - if (id == "origin_upper_left") { - // publicType.shaderQualifiers.originUpperLeft = true; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "pixel_center_integer") { - // publicType.shaderQualifiers.pixelCenterInteger = true; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "early_fragment_tests") { - // publicType.shaderQualifiers.earlyFragmentTests = true; - warn(loc, "ignored", id.c_str(), ""); - return; - } - for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth + 1)) { - if (id == TQualifier::getLayoutDepthString(depth)) { - // publicType.shaderQualifiers.layoutDepth = depth; - warn(loc, "ignored", id.c_str(), ""); - return; - } - } - if (id.compare(0, 13, "blend_support") == 0) { - bool found = false; - for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) { - if (id == TQualifier::getBlendEquationString(be)) { - requireExtensions(loc, 1, &E_GL_KHR_blend_equation_advanced, "blend equation"); - intermediate.addBlendEquation(be); - // publicType.shaderQualifiers.blendEquation = true; - warn(loc, "ignored", id.c_str(), ""); - found = true; - break; - } - } - if (! found) - error(loc, "unknown blend equation", "blend_support", ""); - return; - } - } - error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), ""); -} - -// Put the id's layout qualifier value into the public type, for qualifiers having a number set. -// This is before we know any type information for error checking. -void HlslParseContext::setLayoutQualifier(const TSourceLoc& loc, TQualifier& qualifier, TString& id, - const TIntermTyped* node) -{ - const char* feature = "layout-id value"; - // const char* nonLiteralFeature = "non-literal layout-id value"; - - integerCheck(node, feature); - const TIntermConstantUnion* constUnion = node->getAsConstantUnion(); - int value = 0; - if (constUnion) { - value = constUnion->getConstArray()[0].getIConst(); - } - - std::transform(id.begin(), id.end(), id.begin(), ::tolower); - - if (id == "offset") { - qualifier.layoutOffset = value; - return; - } else if (id == "align") { - // "The specified alignment must be a power of 2, or a compile-time error results." - if (! IsPow2(value)) - error(loc, "must be a power of 2", "align", ""); - else - qualifier.layoutAlign = value; - return; - } else if (id == "location") { - if ((unsigned int)value >= TQualifier::layoutLocationEnd) - error(loc, "location is too large", id.c_str(), ""); - else - qualifier.layoutLocation = value; - return; - } else if (id == "set") { - if ((unsigned int)value >= TQualifier::layoutSetEnd) - error(loc, "set is too large", id.c_str(), ""); - else - qualifier.layoutSet = value; - return; - } else if (id == "binding") { - if ((unsigned int)value >= TQualifier::layoutBindingEnd) - error(loc, "binding is too large", id.c_str(), ""); - else - qualifier.layoutBinding = value; - return; - } else if (id == "component") { - if ((unsigned)value >= TQualifier::layoutComponentEnd) - error(loc, "component is too large", id.c_str(), ""); - else - qualifier.layoutComponent = value; - return; - } else if (id.compare(0, 4, "xfb_") == 0) { - // "Any shader making any static use (after preprocessing) of any of these - // *xfb_* qualifiers will cause the shader to be in a transform feedback - // capturing mode and hence responsible for describing the transform feedback - // setup." - intermediate.setXfbMode(); - if (id == "xfb_buffer") { - // "It is a compile-time error to specify an *xfb_buffer* that is greater than - // the implementation-dependent constant gl_MaxTransformFeedbackBuffers." - if (value >= resources.maxTransformFeedbackBuffers) - error(loc, "buffer is too large:", id.c_str(), "gl_MaxTransformFeedbackBuffers is %d", - resources.maxTransformFeedbackBuffers); - if (value >= (int)TQualifier::layoutXfbBufferEnd) - error(loc, "buffer is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbBufferEnd - 1); - else - qualifier.layoutXfbBuffer = value; - return; - } else if (id == "xfb_offset") { - if (value >= (int)TQualifier::layoutXfbOffsetEnd) - error(loc, "offset is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbOffsetEnd - 1); - else - qualifier.layoutXfbOffset = value; - return; - } else if (id == "xfb_stride") { - // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the - // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents." - if (value > 4 * resources.maxTransformFeedbackInterleavedComponents) - error(loc, "1/4 stride is too large:", id.c_str(), "gl_MaxTransformFeedbackInterleavedComponents is %d", - resources.maxTransformFeedbackInterleavedComponents); - else if (value >= (int)TQualifier::layoutXfbStrideEnd) - error(loc, "stride is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbStrideEnd - 1); - if (value < (int)TQualifier::layoutXfbStrideEnd) - qualifier.layoutXfbStride = value; - return; - } - } - - if (id == "input_attachment_index") { - requireVulkan(loc, "input_attachment_index"); - if (value >= (int)TQualifier::layoutAttachmentEnd) - error(loc, "attachment index is too large", id.c_str(), ""); - else - qualifier.layoutAttachment = value; - return; - } - if (id == "constant_id") { - setSpecConstantId(loc, qualifier, value); - return; - } - - switch (language) { - case EShLangVertex: - break; - - case EShLangTessControl: - if (id == "vertices") { - if (value == 0) - error(loc, "must be greater than 0", "vertices", ""); - else - // publicType.shaderQualifiers.vertices = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - break; - - case EShLangTessEvaluation: - break; - - case EShLangGeometry: - if (id == "invocations") { - if (value == 0) - error(loc, "must be at least 1", "invocations", ""); - else - // publicType.shaderQualifiers.invocations = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "max_vertices") { - // publicType.shaderQualifiers.vertices = value; - warn(loc, "ignored", id.c_str(), ""); - if (value > resources.maxGeometryOutputVertices) - error(loc, "too large, must be less than gl_MaxGeometryOutputVertices", "max_vertices", ""); - return; - } - if (id == "stream") { - qualifier.layoutStream = value; - return; - } - break; - - case EShLangFragment: - if (id == "index") { - qualifier.layoutIndex = value; - return; - } - break; - - case EShLangCompute: - if (id.compare(0, 11, "local_size_") == 0) { - if (id == "local_size_x") { - // publicType.shaderQualifiers.localSize[0] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "local_size_y") { - // publicType.shaderQualifiers.localSize[1] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "local_size_z") { - // publicType.shaderQualifiers.localSize[2] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (spvVersion.spv != 0) { - if (id == "local_size_x_id") { - // publicType.shaderQualifiers.localSizeSpecId[0] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "local_size_y_id") { - // publicType.shaderQualifiers.localSizeSpecId[1] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - if (id == "local_size_z_id") { - // publicType.shaderQualifiers.localSizeSpecId[2] = value; - warn(loc, "ignored", id.c_str(), ""); - return; - } - } - } - break; - - default: - break; - } - - error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), ""); -} - -void HlslParseContext::setSpecConstantId(const TSourceLoc& loc, TQualifier& qualifier, int value) -{ - if (value >= (int)TQualifier::layoutSpecConstantIdEnd) { - error(loc, "specialization-constant id is too large", "constant_id", ""); - } else { - qualifier.layoutSpecConstantId = value; - qualifier.specConstant = true; - if (! intermediate.addUsedConstantId(value)) - error(loc, "specialization-constant id already used", "constant_id", ""); - } - return; -} - -// Merge any layout qualifier information from src into dst, leaving everything else in dst alone -// -// "More than one layout qualifier may appear in a single declaration. -// Additionally, the same layout-qualifier-name can occur multiple times -// within a layout qualifier or across multiple layout qualifiers in the -// same declaration. When the same layout-qualifier-name occurs -// multiple times, in a single declaration, the last occurrence overrides -// the former occurrence(s). Further, if such a layout-qualifier-name -// will effect subsequent declarations or other observable behavior, it -// is only the last occurrence that will have any effect, behaving as if -// the earlier occurrence(s) within the declaration are not present. -// This is also true for overriding layout-qualifier-names, where one -// overrides the other (e.g., row_major vs. column_major); only the last -// occurrence has any effect." -// -void HlslParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifier& src, bool inheritOnly) -{ - if (src.hasMatrix()) - dst.layoutMatrix = src.layoutMatrix; - if (src.hasPacking()) - dst.layoutPacking = src.layoutPacking; - - if (src.hasStream()) - dst.layoutStream = src.layoutStream; - - if (src.hasFormat()) - dst.layoutFormat = src.layoutFormat; - - if (src.hasXfbBuffer()) - dst.layoutXfbBuffer = src.layoutXfbBuffer; - - if (src.hasAlign()) - dst.layoutAlign = src.layoutAlign; - - if (! inheritOnly) { - if (src.hasLocation()) - dst.layoutLocation = src.layoutLocation; - if (src.hasComponent()) - dst.layoutComponent = src.layoutComponent; - if (src.hasIndex()) - dst.layoutIndex = src.layoutIndex; - - if (src.hasOffset()) - dst.layoutOffset = src.layoutOffset; - - if (src.hasSet()) - dst.layoutSet = src.layoutSet; - if (src.layoutBinding != TQualifier::layoutBindingEnd) - dst.layoutBinding = src.layoutBinding; - - if (src.hasXfbStride()) - dst.layoutXfbStride = src.layoutXfbStride; - if (src.hasXfbOffset()) - dst.layoutXfbOffset = src.layoutXfbOffset; - if (src.hasAttachment()) - dst.layoutAttachment = src.layoutAttachment; - if (src.hasSpecConstantId()) - dst.layoutSpecConstantId = src.layoutSpecConstantId; - - if (src.layoutPushConstant) - dst.layoutPushConstant = true; - } -} - - -// -// Look up a function name in the symbol table, and make sure it is a function. -// -// First, look for an exact match. If there is none, use the generic selector -// TParseContextBase::selectFunction() to find one, parameterized by the -// convertible() and better() predicates defined below. -// -// Return the function symbol if found, otherwise nullptr. -// -const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, int& thisDepth, - TIntermTyped*& args) -{ - if (symbolTable.isFunctionNameVariable(call.getName())) { - error(loc, "can't use function syntax on variable", call.getName().c_str(), ""); - return nullptr; - } - - // first, look for an exact match - bool dummyScope; - TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn, &dummyScope, &thisDepth); - if (symbol) - return symbol->getAsFunction(); - - // no exact match, use the generic selector, parameterized by the GLSL rules - - // create list of candidates to send - TVector candidateList; - symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); - - // These built-in ops can accept any type, so we bypass the argument selection - if (candidateList.size() == 1 && builtIn && - (candidateList[0]->getBuiltInOp() == EOpMethodAppend || - candidateList[0]->getBuiltInOp() == EOpMethodRestartStrip || - candidateList[0]->getBuiltInOp() == EOpMethodIncrementCounter || - candidateList[0]->getBuiltInOp() == EOpMethodDecrementCounter || - candidateList[0]->getBuiltInOp() == EOpMethodConsume)) { - return candidateList[0]; - } - - bool allowOnlyUpConversions = true; - - // can 'from' convert to 'to'? - const auto convertible = [&](const TType& from, const TType& to, TOperator op, int arg) -> bool { - if (from == to) - return true; - - // no aggregate conversions - if (from.isArray() || to.isArray() || - from.isStruct() || to.isStruct()) - return false; - - switch (op) { - case EOpInterlockedAdd: - case EOpInterlockedAnd: - case EOpInterlockedCompareExchange: - case EOpInterlockedCompareStore: - case EOpInterlockedExchange: - case EOpInterlockedMax: - case EOpInterlockedMin: - case EOpInterlockedOr: - case EOpInterlockedXor: - // We do not promote the texture or image type for these ocodes. Normally that would not - // be an issue because it's a buffer, but we haven't decomposed the opcode yet, and at this - // stage it's merely e.g, a basic integer type. - // - // Instead, we want to promote other arguments, but stay within the same family. In other - // words, InterlockedAdd(RWBuffer, ...) will always use the int flavor, never the uint flavor, - // but it is allowed to promote its other arguments. - if (arg == 0) - return false; - break; - case EOpMethodSample: - case EOpMethodSampleBias: - case EOpMethodSampleCmp: - case EOpMethodSampleCmpLevelZero: - case EOpMethodSampleGrad: - case EOpMethodSampleLevel: - case EOpMethodLoad: - case EOpMethodGetDimensions: - case EOpMethodGetSamplePosition: - case EOpMethodGather: - case EOpMethodCalculateLevelOfDetail: - case EOpMethodCalculateLevelOfDetailUnclamped: - case EOpMethodGatherRed: - case EOpMethodGatherGreen: - case EOpMethodGatherBlue: - case EOpMethodGatherAlpha: - case EOpMethodGatherCmp: - case EOpMethodGatherCmpRed: - case EOpMethodGatherCmpGreen: - case EOpMethodGatherCmpBlue: - case EOpMethodGatherCmpAlpha: - case EOpMethodAppend: - case EOpMethodRestartStrip: - // those are method calls, the object type can not be changed - // they are equal if the dim and type match (is dim sufficient?) - if (arg == 0) - return from.getSampler().type == to.getSampler().type && - from.getSampler().arrayed == to.getSampler().arrayed && - from.getSampler().shadow == to.getSampler().shadow && - from.getSampler().ms == to.getSampler().ms && - from.getSampler().dim == to.getSampler().dim; - break; - default: - break; - } - - // basic types have to be convertible - if (allowOnlyUpConversions) - if (! intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType(), EOpFunctionCall)) - return false; - - // shapes have to be convertible - if ((from.isScalarOrVec1() && to.isScalarOrVec1()) || - (from.isScalarOrVec1() && to.isVector()) || - (from.isScalarOrVec1() && to.isMatrix()) || - (from.isVector() && to.isVector() && from.getVectorSize() >= to.getVectorSize())) - return true; - - // TODO: what are the matrix rules? they go here - - return false; - }; - - // Is 'to2' a better conversion than 'to1'? - // Ties should not be considered as better. - // Assumes 'convertible' already said true. - const auto better = [](const TType& from, const TType& to1, const TType& to2) -> bool { - // exact match is always better than mismatch - if (from == to2) - return from != to1; - if (from == to1) - return false; - - // shape changes are always worse - if (from.isScalar() || from.isVector()) { - if (from.getVectorSize() == to2.getVectorSize() && - from.getVectorSize() != to1.getVectorSize()) - return true; - if (from.getVectorSize() == to1.getVectorSize() && - from.getVectorSize() != to2.getVectorSize()) - return false; - } - - // Handle sampler betterness: An exact sampler match beats a non-exact match. - // (If we just looked at basic type, all EbtSamplers would look the same). - // If any type is not a sampler, just use the linearize function below. - if (from.getBasicType() == EbtSampler && to1.getBasicType() == EbtSampler && to2.getBasicType() == EbtSampler) { - // We can ignore the vector size in the comparison. - TSampler to1Sampler = to1.getSampler(); - TSampler to2Sampler = to2.getSampler(); - - to1Sampler.vectorSize = to2Sampler.vectorSize = from.getSampler().vectorSize; - - if (from.getSampler() == to2Sampler) - return from.getSampler() != to1Sampler; - if (from.getSampler() == to1Sampler) - return false; - } - - // Might or might not be changing shape, which means basic type might - // or might not match, so within that, the question is how big a - // basic-type conversion is being done. - // - // Use a hierarchy of domains, translated to order of magnitude - // in a linearized view: - // - floating-point vs. integer - // - 32 vs. 64 bit (or width in general) - // - bool vs. non bool - // - signed vs. not signed - const auto linearize = [](const TBasicType& basicType) -> int { - switch (basicType) { - case EbtBool: return 1; - case EbtInt: return 10; - case EbtUint: return 11; - case EbtInt64: return 20; - case EbtUint64: return 21; - case EbtFloat: return 100; - case EbtDouble: return 110; - default: return 0; - } - }; - - return abs(linearize(to2.getBasicType()) - linearize(from.getBasicType())) < - abs(linearize(to1.getBasicType()) - linearize(from.getBasicType())); - }; - - // for ambiguity reporting - bool tie = false; - - // send to the generic selector - const TFunction* bestMatch = nullptr; - - // printf has var args and is in the symbol table as "printf()", - // mangled to "printf(" - if (call.getName() == "printf") { - TSymbol* symbol = symbolTable.find("printf(", &builtIn); - if (symbol) - return symbol->getAsFunction(); - } - - bestMatch = selectFunction(candidateList, call, convertible, better, tie); - - if (bestMatch == nullptr) { - // If there is nothing selected by allowing only up-conversions (to a larger linearize() value), - // we instead try down-conversions, which are valid in HLSL, but not preferred if there are any - // upconversions possible. - allowOnlyUpConversions = false; - bestMatch = selectFunction(candidateList, call, convertible, better, tie); - } - - if (bestMatch == nullptr) { - error(loc, "no matching overloaded function found", call.getName().c_str(), ""); - return nullptr; - } - - // For built-ins, we can convert across the arguments. This will happen in several steps: - // Step 1: If there's an exact match, use it. - // Step 2a: Otherwise, get the operator from the best match and promote arguments: - // Step 2b: reconstruct the TFunction based on the new arg types - // Step 3: Re-select after type promotion is applied, to find proper candidate. - if (builtIn) { - // Step 1: If there's an exact match, use it. - if (call.getMangledName() == bestMatch->getMangledName()) - return bestMatch; - - // Step 2a: Otherwise, get the operator from the best match and promote arguments as if we - // are that kind of operator. - if (args != nullptr) { - // The arg list can be a unary node, or an aggregate. We have to handle both. - // We will use the normal promote() facilities, which require an interm node. - TIntermOperator* promote = nullptr; - - if (call.getParamCount() == 1) { - promote = new TIntermUnary(bestMatch->getBuiltInOp()); - promote->getAsUnaryNode()->setOperand(args->getAsTyped()); - } else { - promote = new TIntermAggregate(bestMatch->getBuiltInOp()); - promote->getAsAggregate()->getSequence().swap(args->getAsAggregate()->getSequence()); - } - - if (! intermediate.promote(promote)) - return nullptr; - - // Obtain the promoted arg list. - if (call.getParamCount() == 1) { - args = promote->getAsUnaryNode()->getOperand(); - } else { - promote->getAsAggregate()->getSequence().swap(args->getAsAggregate()->getSequence()); - } - } - - // Step 2b: reconstruct the TFunction based on the new arg types - TFunction convertedCall(&call.getName(), call.getType(), call.getBuiltInOp()); - - if (args->getAsAggregate()) { - // Handle aggregates: put all args into the new function call - for (int arg = 0; arg < int(args->getAsAggregate()->getSequence().size()); ++arg) { - // TODO: But for constness, we could avoid the new & shallowCopy, and use the pointer directly. - TParameter param = { nullptr, new TType, nullptr }; - param.type->shallowCopy(args->getAsAggregate()->getSequence()[arg]->getAsTyped()->getType()); - convertedCall.addParameter(param); - } - } else if (args->getAsUnaryNode()) { - // Handle unaries: put all args into the new function call - TParameter param = { nullptr, new TType, nullptr }; - param.type->shallowCopy(args->getAsUnaryNode()->getOperand()->getAsTyped()->getType()); - convertedCall.addParameter(param); - } else if (args->getAsTyped()) { - // Handle bare e.g, floats, not in an aggregate. - TParameter param = { nullptr, new TType, nullptr }; - param.type->shallowCopy(args->getAsTyped()->getType()); - convertedCall.addParameter(param); - } else { - assert(0); // unknown argument list. - return nullptr; - } - - // Step 3: Re-select after type promotion, to find proper candidate - // send to the generic selector - bestMatch = selectFunction(candidateList, convertedCall, convertible, better, tie); - - // At this point, there should be no tie. - } - - if (tie) - error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), ""); - - // Append default parameter values if needed - if (!tie && bestMatch != nullptr) { - for (int defParam = call.getParamCount(); defParam < bestMatch->getParamCount(); ++defParam) { - handleFunctionArgument(&call, args, (*bestMatch)[defParam].defaultValue); - } - } - - return bestMatch; -} - -// -// Do everything necessary to handle a typedef declaration, for a single symbol. -// -// 'parseType' is the type part of the declaration (to the left) -// 'arraySizes' is the arrayness tagged on the identifier (to the right) -// -void HlslParseContext::declareTypedef(const TSourceLoc& loc, const TString& identifier, const TType& parseType) -{ - TVariable* typeSymbol = new TVariable(&identifier, parseType, true); - if (! symbolTable.insert(*typeSymbol)) - error(loc, "name already defined", "typedef", identifier.c_str()); -} - -// Do everything necessary to handle a struct declaration, including -// making IO aliases because HLSL allows mixed IO in a struct that specializes -// based on the usage (input, output, uniform, none). -void HlslParseContext::declareStruct(const TSourceLoc& loc, TString& structName, TType& type) -{ - // If it was named, which means the type can be reused later, add - // it to the symbol table. (Unless it's a block, in which - // case the name is not a type.) - if (type.getBasicType() == EbtBlock || structName.size() == 0) - return; - - TVariable* userTypeDef = new TVariable(&structName, type, true); - if (! symbolTable.insert(*userTypeDef)) { - error(loc, "redefinition", structName.c_str(), "struct"); - return; - } - - // See if we need IO aliases for the structure typeList - - const auto condAlloc = [](bool pred, TTypeList*& list) { - if (pred && list == nullptr) - list = new TTypeList; - }; - - tIoKinds newLists = { nullptr, nullptr, nullptr }; // allocate for each kind found - for (auto member = type.getStruct()->begin(); member != type.getStruct()->end(); ++member) { - condAlloc(hasUniform(member->type->getQualifier()), newLists.uniform); - condAlloc( hasInput(member->type->getQualifier()), newLists.input); - condAlloc( hasOutput(member->type->getQualifier()), newLists.output); - - if (member->type->isStruct()) { - auto it = ioTypeMap.find(member->type->getStruct()); - if (it != ioTypeMap.end()) { - condAlloc(it->second.uniform != nullptr, newLists.uniform); - condAlloc(it->second.input != nullptr, newLists.input); - condAlloc(it->second.output != nullptr, newLists.output); - } - } - } - if (newLists.uniform == nullptr && - newLists.input == nullptr && - newLists.output == nullptr) { - // Won't do any IO caching, clear up the type and get out now. - for (auto member = type.getStruct()->begin(); member != type.getStruct()->end(); ++member) - clearUniformInputOutput(member->type->getQualifier()); - return; - } - - // We have IO involved. - - // Make a pure typeList for the symbol table, and cache side copies of IO versions. - for (auto member = type.getStruct()->begin(); member != type.getStruct()->end(); ++member) { - const auto inheritStruct = [&](TTypeList* s, TTypeLoc& ioMember) { - if (s != nullptr) { - ioMember.type = new TType; - ioMember.type->shallowCopy(*member->type); - ioMember.type->setStruct(s); - } - }; - const auto newMember = [&](TTypeLoc& m) { - if (m.type == nullptr) { - m.type = new TType; - m.type->shallowCopy(*member->type); - } - }; - - TTypeLoc newUniformMember = { nullptr, member->loc }; - TTypeLoc newInputMember = { nullptr, member->loc }; - TTypeLoc newOutputMember = { nullptr, member->loc }; - if (member->type->isStruct()) { - // swap in an IO child if there is one - auto it = ioTypeMap.find(member->type->getStruct()); - if (it != ioTypeMap.end()) { - inheritStruct(it->second.uniform, newUniformMember); - inheritStruct(it->second.input, newInputMember); - inheritStruct(it->second.output, newOutputMember); - } - } - if (newLists.uniform) { - newMember(newUniformMember); - - // inherit default matrix layout (changeable via #pragma pack_matrix), if none given. - if (member->type->isMatrix() && member->type->getQualifier().layoutMatrix == ElmNone) - newUniformMember.type->getQualifier().layoutMatrix = globalUniformDefaults.layoutMatrix; - - correctUniform(newUniformMember.type->getQualifier()); - newLists.uniform->push_back(newUniformMember); - } - if (newLists.input) { - newMember(newInputMember); - correctInput(newInputMember.type->getQualifier()); - newLists.input->push_back(newInputMember); - } - if (newLists.output) { - newMember(newOutputMember); - correctOutput(newOutputMember.type->getQualifier()); - newLists.output->push_back(newOutputMember); - } - - // make original pure - clearUniformInputOutput(member->type->getQualifier()); - } - ioTypeMap[type.getStruct()] = newLists; -} - -// Lookup a user-type by name. -// If found, fill in the type and return the defining symbol. -// If not found, return nullptr. -TSymbol* HlslParseContext::lookupUserType(const TString& typeName, TType& type) -{ - TSymbol* symbol = symbolTable.find(typeName); - if (symbol && symbol->getAsVariable() && symbol->getAsVariable()->isUserType()) { - type.shallowCopy(symbol->getType()); - return symbol; - } else - return nullptr; -} - -// -// Do everything necessary to handle a variable (non-block) declaration. -// Either redeclaring a variable, or making a new one, updating the symbol -// table, and all error checking. -// -// Returns a subtree node that computes an initializer, if needed. -// Returns nullptr if there is no code to execute for initialization. -// -// 'parseType' is the type part of the declaration (to the left) -// 'arraySizes' is the arrayness tagged on the identifier (to the right) -// -TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, const TString& identifier, TType& type, - TIntermTyped* initializer) -{ - if (voidErrorCheck(loc, identifier, type.getBasicType())) - return nullptr; - - // Global consts with initializers that are non-const act like EvqGlobal in HLSL. - // This test is implicitly recursive, because initializers propagate constness - // up the aggregate node tree during creation. E.g, for: - // { { 1, 2 }, { 3, 4 } } - // the initializer list is marked EvqConst at the top node, and remains so here. However: - // { 1, { myvar, 2 }, 3 } - // is not a const intializer, and still becomes EvqGlobal here. - - const bool nonConstInitializer = (initializer != nullptr && initializer->getQualifier().storage != EvqConst); - - if (type.getQualifier().storage == EvqConst && symbolTable.atGlobalLevel() && nonConstInitializer) { - // Force to global - type.getQualifier().storage = EvqGlobal; - } - - // make const and initialization consistent - fixConstInit(loc, identifier, type, initializer); - - // Check for redeclaration of built-ins and/or attempting to declare a reserved name - TSymbol* symbol = nullptr; - - inheritGlobalDefaults(type.getQualifier()); - - const bool flattenVar = shouldFlatten(type, type.getQualifier().storage, true); - - // correct IO in the type - switch (type.getQualifier().storage) { - case EvqGlobal: - case EvqTemporary: - clearUniformInputOutput(type.getQualifier()); - break; - case EvqUniform: - case EvqBuffer: - correctUniform(type.getQualifier()); - if (type.isStruct()) { - auto it = ioTypeMap.find(type.getStruct()); - if (it != ioTypeMap.end()) - type.setStruct(it->second.uniform); - } - - break; - default: - break; - } - - // Declare the variable - if (type.isArray()) { - // array case - declareArray(loc, identifier, type, symbol, !flattenVar); - } else { - // non-array case - if (symbol == nullptr) - symbol = declareNonArray(loc, identifier, type, !flattenVar); - else if (type != symbol->getType()) - error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str()); - } - - if (symbol == nullptr) - return nullptr; - - if (flattenVar) - flatten(*symbol->getAsVariable(), symbolTable.atGlobalLevel()); - - TVariable* variable = symbol->getAsVariable(); - - if (initializer == nullptr) { - if (intermediate.getDebugInfo()) - return executeDeclaration(loc, variable); - else - return nullptr; - } - - // Deal with initializer - if (variable == nullptr) { - error(loc, "initializer requires a variable, not a member", identifier.c_str(), ""); - return nullptr; - } - return executeInitializer(loc, initializer, variable); -} - -// Pick up global defaults from the provide global defaults into dst. -void HlslParseContext::inheritGlobalDefaults(TQualifier& dst) const -{ - if (dst.storage == EvqVaryingOut) { - if (! dst.hasStream() && language == EShLangGeometry) - dst.layoutStream = globalOutputDefaults.layoutStream; - if (! dst.hasXfbBuffer()) - dst.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; - } -} - -// -// Make an internal-only variable whose name is for debug purposes only -// and won't be searched for. Callers will only use the return value to use -// the variable, not the name to look it up. It is okay if the name -// is the same as other names; there won't be any conflict. -// -TVariable* HlslParseContext::makeInternalVariable(const char* name, const TType& type) const -{ - TString* nameString = NewPoolTString(name); - TVariable* variable = new TVariable(nameString, type); - symbolTable.makeInternalVariable(*variable); - - return variable; -} - -// Make a symbol node holding a new internal temporary variable. -TIntermSymbol* HlslParseContext::makeInternalVariableNode(const TSourceLoc& loc, const char* name, - const TType& type) const -{ - TVariable* tmpVar = makeInternalVariable(name, type); - tmpVar->getWritableType().getQualifier().makeTemporary(); - - return intermediate.addSymbol(*tmpVar, loc); -} - -// -// Declare a non-array variable, the main point being there is no redeclaration -// for resizing allowed. -// -// Return the successfully declared variable. -// -TVariable* HlslParseContext::declareNonArray(const TSourceLoc& loc, const TString& identifier, const TType& type, - bool track) -{ - // make a new variable - TVariable* variable = new TVariable(&identifier, type); - - // add variable to symbol table - if (symbolTable.insert(*variable)) { - if (track && symbolTable.atGlobalLevel()) - trackLinkage(*variable); - return variable; - } - - error(loc, "redefinition", variable->getName().c_str(), ""); - return nullptr; -} - -// Return a declaration of a temporary variable -// -// This is used to force a variable to be declared in the correct scope -// when debug information is being generated. - -TIntermNode* HlslParseContext::executeDeclaration(const TSourceLoc& loc, TVariable* variable) -{ - // - // Identifier must be of type temporary. - // - TStorageQualifier qualifier = variable->getType().getQualifier().storage; - if (qualifier != EvqTemporary) - return nullptr; - - TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc); - return handleDeclare(loc, intermSymbol); -} - -// -// Handle all types of initializers from the grammar. -// -// Returning nullptr just means there is no code to execute to handle the -// initializer, which will, for example, be the case for constant initializers. -// -// Returns a subtree that accomplished the initialization. -// -TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable) -{ - // - // Identifier must be of type constant, a global, or a temporary, and - // starting at version 120, desktop allows uniforms to have initializers. - // - TStorageQualifier qualifier = variable->getType().getQualifier().storage; - - // - // If the initializer was from braces { ... }, we convert the whole subtree to a - // constructor-style subtree, allowing the rest of the code to operate - // identically for both kinds of initializers. - // - // - // Type can't be deduced from the initializer list, so a skeletal type to - // follow has to be passed in. Constness and specialization-constness - // should be deduced bottom up, not dictated by the skeletal type. - // - TType skeletalType; - skeletalType.shallowCopy(variable->getType()); - skeletalType.getQualifier().makeTemporary(); - if (initializer->getAsAggregate() && initializer->getAsAggregate()->getOp() == EOpNull) - initializer = convertInitializerList(loc, skeletalType, initializer, nullptr); - if (initializer == nullptr) { - // error recovery; don't leave const without constant values - if (qualifier == EvqConst) - variable->getWritableType().getQualifier().storage = EvqTemporary; - return nullptr; - } - - // Fix outer arrayness if variable is unsized, getting size from the initializer - if (initializer->getType().isSizedArray() && variable->getType().isUnsizedArray()) - variable->getWritableType().changeOuterArraySize(initializer->getType().getOuterArraySize()); - - // Inner arrayness can also get set by an initializer - if (initializer->getType().isArrayOfArrays() && variable->getType().isArrayOfArrays() && - initializer->getType().getArraySizes()->getNumDims() == - variable->getType().getArraySizes()->getNumDims()) { - // adopt unsized sizes from the initializer's sizes - for (int d = 1; d < variable->getType().getArraySizes()->getNumDims(); ++d) { - if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize) { - variable->getWritableType().getArraySizes()->setDimSize(d, - initializer->getType().getArraySizes()->getDimSize(d)); - } - } - } - - // Uniform and global consts require a constant initializer - if (qualifier == EvqUniform && initializer->getType().getQualifier().storage != EvqConst) { - error(loc, "uniform initializers must be constant", "=", "'%s'", variable->getType().getCompleteString().c_str()); - variable->getWritableType().getQualifier().storage = EvqTemporary; - return nullptr; - } - - // Const variables require a constant initializer - if (qualifier == EvqConst) { - if (initializer->getType().getQualifier().storage != EvqConst) { - variable->getWritableType().getQualifier().storage = EvqConstReadOnly; - qualifier = EvqConstReadOnly; - } - } - - if (qualifier == EvqConst || qualifier == EvqUniform) { - // Compile-time tagging of the variable with its constant value... - - initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer); - if (initializer != nullptr && variable->getType() != initializer->getType()) - initializer = intermediate.addUniShapeConversion(EOpAssign, variable->getType(), initializer); - if (initializer == nullptr || !initializer->getAsConstantUnion() || - variable->getType() != initializer->getType()) { - error(loc, "non-matching or non-convertible constant type for const initializer", - variable->getType().getStorageQualifierString(), ""); - variable->getWritableType().getQualifier().storage = EvqTemporary; - return nullptr; - } - - variable->setConstArray(initializer->getAsConstantUnion()->getConstArray()); - } else { - // normal assigning of a value to a variable... - specializationCheck(loc, initializer->getType(), "initializer"); - TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc); - TIntermNode* initNode = handleAssign(loc, EOpAssign, intermSymbol, initializer); - if (initNode == nullptr) - assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString()); - return initNode; - } - - return nullptr; -} - -// -// Reprocess any initializer-list { ... } parts of the initializer. -// Need to hierarchically assign correct types and implicit -// conversions. Will do this mimicking the same process used for -// creating a constructor-style initializer, ensuring we get the -// same form. -// -// Returns a node representing an expression for the initializer list expressed -// as the correct type. -// -// Returns nullptr if there is an error. -// -TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, const TType& type, - TIntermTyped* initializer, TIntermTyped* scalarInit) -{ - // Will operate recursively. Once a subtree is found that is constructor style, - // everything below it is already good: Only the "top part" of the initializer - // can be an initializer list, where "top part" can extend for several (or all) levels. - - // see if we have bottomed out in the tree within the initializer-list part - TIntermAggregate* initList = initializer->getAsAggregate(); - if (initList == nullptr || initList->getOp() != EOpNull) { - // We don't have a list, but if it's a scalar and the 'type' is a - // composite, we need to lengthen below to make it useful. - // Otherwise, this is an already formed object to initialize with. - if (type.isScalar() || !initializer->getType().isScalar()) - return initializer; - else - initList = intermediate.makeAggregate(initializer); - } - - // Of the initializer-list set of nodes, need to process bottom up, - // so recurse deep, then process on the way up. - - // Go down the tree here... - if (type.isArray()) { - // The type's array might be unsized, which could be okay, so base sizes on the size of the aggregate. - // Later on, initializer execution code will deal with array size logic. - TType arrayType; - arrayType.shallowCopy(type); // sharing struct stuff is fine - arrayType.copyArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below - - // edit array sizes to fill in unsized dimensions - if (type.isUnsizedArray()) - arrayType.changeOuterArraySize((int)initList->getSequence().size()); - - // set unsized array dimensions that can be derived from the initializer's first element - if (arrayType.isArrayOfArrays() && initList->getSequence().size() > 0) { - TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped(); - if (firstInit->getType().isArray() && - arrayType.getArraySizes()->getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) { - for (int d = 1; d < arrayType.getArraySizes()->getNumDims(); ++d) { - if (arrayType.getArraySizes()->getDimSize(d) == UnsizedArraySize) - arrayType.getArraySizes()->setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1)); - } - } - } - - // lengthen list to be long enough - lengthenList(loc, initList->getSequence(), arrayType.getOuterArraySize(), scalarInit); - - // recursively process each element - TType elementType(arrayType, 0); // dereferenced type - for (int i = 0; i < arrayType.getOuterArraySize(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, elementType, - initList->getSequence()[i]->getAsTyped(), scalarInit); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - - return addConstructor(loc, initList, arrayType); - } else if (type.isStruct()) { - // do we have implicit assignments to opaques? - for (size_t i = initList->getSequence().size(); i < type.getStruct()->size(); ++i) { - if ((*type.getStruct())[i].type->containsOpaque()) { - error(loc, "cannot implicitly initialize opaque members", "initializer list", ""); - return nullptr; - } - } - - // lengthen list to be long enough - lengthenList(loc, initList->getSequence(), static_cast(type.getStruct()->size()), scalarInit); - - if (type.getStruct()->size() != initList->getSequence().size()) { - error(loc, "wrong number of structure members", "initializer list", ""); - return nullptr; - } - for (size_t i = 0; i < type.getStruct()->size(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, *(*type.getStruct())[i].type, - initList->getSequence()[i]->getAsTyped(), scalarInit); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - } else if (type.isMatrix()) { - if (type.computeNumComponents() == (int)initList->getSequence().size()) { - // This means the matrix is initialized component-wise, rather than as - // a series of rows and columns. We can just use the list directly as - // a constructor; no further processing needed. - } else { - // lengthen list to be long enough - lengthenList(loc, initList->getSequence(), type.getMatrixCols(), scalarInit); - - if (type.getMatrixCols() != (int)initList->getSequence().size()) { - error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString().c_str()); - return nullptr; - } - TType vectorType(type, 0); // dereferenced type - for (int i = 0; i < type.getMatrixCols(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, vectorType, - initList->getSequence()[i]->getAsTyped(), scalarInit); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - } - } else if (type.isVector()) { - // lengthen list to be long enough - lengthenList(loc, initList->getSequence(), type.getVectorSize(), scalarInit); - - // error check; we're at bottom, so work is finished below - if (type.getVectorSize() != (int)initList->getSequence().size()) { - error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", - type.getCompleteString().c_str()); - return nullptr; - } - } else if (type.isScalar()) { - // lengthen list to be long enough - lengthenList(loc, initList->getSequence(), 1, scalarInit); - - if ((int)initList->getSequence().size() != 1) { - error(loc, "scalar expected one element:", "initializer list", type.getCompleteString().c_str()); - return nullptr; - } - } else { - error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString().c_str()); - return nullptr; - } - - // Now that the subtree is processed, process this node as if the - // initializer list is a set of arguments to a constructor. - TIntermTyped* emulatedConstructorArguments; - if (initList->getSequence().size() == 1) - emulatedConstructorArguments = initList->getSequence()[0]->getAsTyped(); - else - emulatedConstructorArguments = initList; - - return addConstructor(loc, emulatedConstructorArguments, type); -} - -// Lengthen list to be long enough to cover any gap from the current list size -// to 'size'. If the list is longer, do nothing. -// The value to lengthen with is the default for short lists. -// -// By default, lists that are too short due to lack of initializers initialize to zero. -// Alternatively, it could be a scalar initializer for a structure. Both cases are handled, -// based on whether something is passed in as 'scalarInit'. -// -// 'scalarInit' must be safe to use each time this is called (no side effects replication). -// -void HlslParseContext::lengthenList(const TSourceLoc& loc, TIntermSequence& list, int size, TIntermTyped* scalarInit) -{ - for (int c = (int)list.size(); c < size; ++c) { - if (scalarInit == nullptr) - list.push_back(intermediate.addConstantUnion(0, loc)); - else - list.push_back(scalarInit); - } -} - -// -// Test for the correctness of the parameters passed to various constructor functions -// and also convert them to the right data type, if allowed and required. -// -// Returns nullptr for an error or the constructed node (aggregate or typed) for no error. -// -TIntermTyped* HlslParseContext::handleConstructor(const TSourceLoc& loc, TIntermTyped* node, const TType& type) -{ - if (node == nullptr) - return nullptr; - - // Construct identical type - if (type == node->getType()) - return node; - - // Handle the idiom "(struct type)" - if (type.isStruct() && isScalarConstructor(node)) { - // 'node' will almost always get used multiple times, so should not be used directly, - // it would create a DAG instead of a tree, which might be okay (would - // like to formalize that for constants and symbols), but if it has - // side effects, they would get executed multiple times, which is not okay. - if (node->getAsConstantUnion() == nullptr && node->getAsSymbolNode() == nullptr) { - TIntermAggregate* seq = intermediate.makeAggregate(loc); - TIntermSymbol* copy = makeInternalVariableNode(loc, "scalarCopy", node->getType()); - seq = intermediate.growAggregate(seq, intermediate.addBinaryNode(EOpAssign, copy, node, loc)); - seq = intermediate.growAggregate(seq, convertInitializerList(loc, type, intermediate.makeAggregate(loc), copy)); - seq->setOp(EOpComma); - seq->setType(type); - return seq; - } else - return convertInitializerList(loc, type, intermediate.makeAggregate(loc), node); - } - - return addConstructor(loc, node, type); -} - -// Add a constructor, either from the grammar, or other programmatic reasons. -// -// 'node' is what to construct from. -// 'type' is what type to construct. -// -// Returns the constructed object. -// Return nullptr if it can't be done. -// -TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyped* node, const TType& type) -{ - TIntermAggregate* aggrNode = node->getAsAggregate(); - TOperator op = intermediate.mapTypeToConstructorOp(type); - - if (op == EOpConstructTextureSampler) - return intermediate.setAggregateOperator(aggrNode, op, type, loc); - - TTypeList::const_iterator memberTypes; - if (op == EOpConstructStruct) - memberTypes = type.getStruct()->begin(); - - TType elementType; - if (type.isArray()) { - TType dereferenced(type, 0); - elementType.shallowCopy(dereferenced); - } else - elementType.shallowCopy(type); - - bool singleArg; - if (aggrNode != nullptr) { - if (aggrNode->getOp() != EOpNull) - singleArg = true; - else - singleArg = false; - } else - singleArg = true; - - TIntermTyped *newNode; - if (singleArg) { - // Handle array -> array conversion - // Constructing an array of one type from an array of another type is allowed, - // assuming there are enough components available (semantic-checked earlier). - if (type.isArray() && node->isArray()) - newNode = convertArray(node, type); - - // If structure constructor or array constructor is being called - // for only one parameter inside the aggregate, we need to call constructAggregate function once. - else if (type.isArray()) - newNode = constructAggregate(node, elementType, 1, node->getLoc()); - else if (op == EOpConstructStruct) - newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc()); - else { - // shape conversion for matrix constructor from scalar. HLSL semantics are: scalar - // is replicated into every element of the matrix (not just the diagnonal), so - // that is handled specially here. - if (type.isMatrix() && node->getType().isScalarOrVec1()) - node = intermediate.addShapeConversion(type, node); - - newNode = constructBuiltIn(type, op, node, node->getLoc(), false); - } - - if (newNode && (type.isArray() || op == EOpConstructStruct)) - newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc); - - return newNode; - } - - // - // Handle list of arguments. - // - TIntermSequence& sequenceVector = aggrNode->getSequence(); // Stores the information about the parameter to the constructor - // if the structure constructor contains more than one parameter, then construct - // each parameter - - int paramCount = 0; // keeps a track of the constructor parameter number being checked - - // for each parameter to the constructor call, check to see if the right type is passed or convert them - // to the right type if possible (and allowed). - // for structure constructors, just check if the right type is passed, no conversion is allowed. - - for (TIntermSequence::iterator p = sequenceVector.begin(); - p != sequenceVector.end(); p++, paramCount++) { - if (type.isArray()) - newNode = constructAggregate(*p, elementType, paramCount + 1, node->getLoc()); - else if (op == EOpConstructStruct) - newNode = constructAggregate(*p, *(memberTypes[paramCount]).type, paramCount + 1, node->getLoc()); - else - newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true); - - if (newNode) - *p = newNode; - else - return nullptr; - } - - TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, type, loc); - - return constructor; -} - -// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value -// for the parameter to the constructor (passed to this function). Essentially, it converts -// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a -// float, then float is converted to int. -// -// Returns nullptr for an error or the constructed node. -// -TIntermTyped* HlslParseContext::constructBuiltIn(const TType& type, TOperator op, TIntermTyped* node, - const TSourceLoc& loc, bool subset) -{ - TIntermTyped* newNode; - TOperator basicOp; - - // - // First, convert types as needed. - // - switch (op) { - case EOpConstructF16Vec2: - case EOpConstructF16Vec3: - case EOpConstructF16Vec4: - case EOpConstructF16Mat2x2: - case EOpConstructF16Mat2x3: - case EOpConstructF16Mat2x4: - case EOpConstructF16Mat3x2: - case EOpConstructF16Mat3x3: - case EOpConstructF16Mat3x4: - case EOpConstructF16Mat4x2: - case EOpConstructF16Mat4x3: - case EOpConstructF16Mat4x4: - case EOpConstructFloat16: - basicOp = EOpConstructFloat16; - break; - - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2x2: - case EOpConstructMat2x3: - case EOpConstructMat2x4: - case EOpConstructMat3x2: - case EOpConstructMat3x3: - case EOpConstructMat3x4: - case EOpConstructMat4x2: - case EOpConstructMat4x3: - case EOpConstructMat4x4: - case EOpConstructFloat: - basicOp = EOpConstructFloat; - break; - - case EOpConstructDVec2: - case EOpConstructDVec3: - case EOpConstructDVec4: - case EOpConstructDMat2x2: - case EOpConstructDMat2x3: - case EOpConstructDMat2x4: - case EOpConstructDMat3x2: - case EOpConstructDMat3x3: - case EOpConstructDMat3x4: - case EOpConstructDMat4x2: - case EOpConstructDMat4x3: - case EOpConstructDMat4x4: - case EOpConstructDouble: - basicOp = EOpConstructDouble; - break; - - case EOpConstructI16Vec2: - case EOpConstructI16Vec3: - case EOpConstructI16Vec4: - case EOpConstructInt16: - basicOp = EOpConstructInt16; - break; - - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructIMat2x2: - case EOpConstructIMat2x3: - case EOpConstructIMat2x4: - case EOpConstructIMat3x2: - case EOpConstructIMat3x3: - case EOpConstructIMat3x4: - case EOpConstructIMat4x2: - case EOpConstructIMat4x3: - case EOpConstructIMat4x4: - case EOpConstructInt: - basicOp = EOpConstructInt; - break; - - case EOpConstructU16Vec2: - case EOpConstructU16Vec3: - case EOpConstructU16Vec4: - case EOpConstructUint16: - basicOp = EOpConstructUint16; - break; - - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructUMat2x2: - case EOpConstructUMat2x3: - case EOpConstructUMat2x4: - case EOpConstructUMat3x2: - case EOpConstructUMat3x3: - case EOpConstructUMat3x4: - case EOpConstructUMat4x2: - case EOpConstructUMat4x3: - case EOpConstructUMat4x4: - case EOpConstructUint: - basicOp = EOpConstructUint; - break; - - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBMat2x2: - case EOpConstructBMat2x3: - case EOpConstructBMat2x4: - case EOpConstructBMat3x2: - case EOpConstructBMat3x3: - case EOpConstructBMat3x4: - case EOpConstructBMat4x2: - case EOpConstructBMat4x3: - case EOpConstructBMat4x4: - case EOpConstructBool: - basicOp = EOpConstructBool; - break; - - default: - error(loc, "unsupported construction", "", ""); - - return nullptr; - } - newNode = intermediate.addUnaryMath(basicOp, node, node->getLoc()); - if (newNode == nullptr) { - error(loc, "can't convert", "constructor", ""); - return nullptr; - } - - // - // Now, if there still isn't an operation to do the construction, and we need one, add one. - // - - // Otherwise, skip out early. - if (subset || (newNode != node && newNode->getType() == type)) - return newNode; - - // setAggregateOperator will insert a new node for the constructor, as needed. - return intermediate.setAggregateOperator(newNode, op, type, loc); -} - -// Convert the array in node to the requested type, which is also an array. -// Returns nullptr on failure, otherwise returns aggregate holding the list of -// elements needed to construct the array. -TIntermTyped* HlslParseContext::convertArray(TIntermTyped* node, const TType& type) -{ - assert(node->isArray() && type.isArray()); - if (node->getType().computeNumComponents() < type.computeNumComponents()) - return nullptr; - - // TODO: write an argument replicator, for the case the argument should not be - // executed multiple times, yet multiple copies are needed. - - TIntermTyped* constructee = node->getAsTyped(); - // track where we are in consuming the argument - int constructeeElement = 0; - int constructeeComponent = 0; - - // bump up to the next component to consume - const auto getNextComponent = [&]() { - TIntermTyped* component; - component = handleBracketDereference(node->getLoc(), constructee, - intermediate.addConstantUnion(constructeeElement, node->getLoc())); - if (component->isVector()) - component = handleBracketDereference(node->getLoc(), component, - intermediate.addConstantUnion(constructeeComponent, node->getLoc())); - // bump component pointer up - ++constructeeComponent; - if (constructeeComponent == constructee->getVectorSize()) { - constructeeComponent = 0; - ++constructeeElement; - } - return component; - }; - - // make one subnode per constructed array element - TIntermAggregate* constructor = nullptr; - TType derefType(type, 0); - TType speculativeComponentType(derefType, 0); - TType* componentType = derefType.isVector() ? &speculativeComponentType : &derefType; - TOperator componentOp = intermediate.mapTypeToConstructorOp(*componentType); - TType crossType(node->getBasicType(), EvqTemporary, type.getVectorSize()); - for (int e = 0; e < type.getOuterArraySize(); ++e) { - // construct an element - TIntermTyped* elementArg; - if (type.getVectorSize() == constructee->getVectorSize()) { - // same element shape - elementArg = handleBracketDereference(node->getLoc(), constructee, - intermediate.addConstantUnion(e, node->getLoc())); - } else { - // mismatched element shapes - if (type.getVectorSize() == 1) - elementArg = getNextComponent(); - else { - // make a vector - TIntermAggregate* elementConstructee = nullptr; - for (int c = 0; c < type.getVectorSize(); ++c) - elementConstructee = intermediate.growAggregate(elementConstructee, getNextComponent()); - elementArg = addConstructor(node->getLoc(), elementConstructee, crossType); - } - } - // convert basic types - elementArg = intermediate.addConversion(componentOp, derefType, elementArg); - if (elementArg == nullptr) - return nullptr; - // combine with top-level constructor - constructor = intermediate.growAggregate(constructor, elementArg); - } - - return constructor; -} - -// This function tests for the type of the parameters to the structure or array constructor. Raises -// an error message if the expected type does not match the parameter passed to the constructor. -// -// Returns nullptr for an error or the input node itself if the expected and the given parameter types match. -// -TIntermTyped* HlslParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, - const TSourceLoc& loc) -{ - // Handle cases that map more 1:1 between constructor arguments and constructed. - TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped()); - if (converted == nullptr || converted->getType() != type) { - error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount, - node->getAsTyped()->getType().getCompleteString().c_str(), type.getCompleteString().c_str()); - - return nullptr; - } - - return converted; -} - -// -// Do everything needed to add an interface block. -// -void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TString* instanceName) -{ - assert(type.getWritableStruct() != nullptr); - - // Clean up top-level decorations that don't belong. - switch (type.getQualifier().storage) { - case EvqUniform: - case EvqBuffer: - correctUniform(type.getQualifier()); - break; - case EvqVaryingIn: - correctInput(type.getQualifier()); - break; - case EvqVaryingOut: - correctOutput(type.getQualifier()); - break; - default: - break; - } - - TTypeList& typeList = *type.getWritableStruct(); - // fix and check for member storage qualifiers and types that don't belong within a block - for (unsigned int member = 0; member < typeList.size(); ++member) { - TType& memberType = *typeList[member].type; - TQualifier& memberQualifier = memberType.getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - globalQualifierFix(memberLoc, memberQualifier); - memberQualifier.storage = type.getQualifier().storage; - - if (memberType.isStruct()) { - // clean up and pick up the right set of decorations - auto it = ioTypeMap.find(memberType.getStruct()); - switch (type.getQualifier().storage) { - case EvqUniform: - case EvqBuffer: - correctUniform(type.getQualifier()); - if (it != ioTypeMap.end() && it->second.uniform) - memberType.setStruct(it->second.uniform); - break; - case EvqVaryingIn: - correctInput(type.getQualifier()); - if (it != ioTypeMap.end() && it->second.input) - memberType.setStruct(it->second.input); - break; - case EvqVaryingOut: - correctOutput(type.getQualifier()); - if (it != ioTypeMap.end() && it->second.output) - memberType.setStruct(it->second.output); - break; - default: - break; - } - } - } - - // Make default block qualification, and adjust the member qualifications - - TQualifier defaultQualification; - switch (type.getQualifier().storage) { - case EvqUniform: defaultQualification = globalUniformDefaults; break; - case EvqBuffer: defaultQualification = globalBufferDefaults; break; - case EvqVaryingIn: defaultQualification = globalInputDefaults; break; - case EvqVaryingOut: defaultQualification = globalOutputDefaults; break; - default: defaultQualification.clear(); break; - } - - // Special case for "push_constant uniform", which has a default of std430, - // contrary to normal uniform defaults, and can't have a default tracked for it. - if (type.getQualifier().layoutPushConstant && ! type.getQualifier().hasPacking()) - type.getQualifier().layoutPacking = ElpStd430; - - // fix and check for member layout qualifiers - - mergeObjectLayoutQualifiers(defaultQualification, type.getQualifier(), true); - - bool memberWithLocation = false; - bool memberWithoutLocation = false; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - if (memberQualifier.hasStream()) { - if (defaultQualification.layoutStream != memberQualifier.layoutStream) - error(memberLoc, "member cannot contradict block", "stream", ""); - } - - // "This includes a block's inheritance of the - // current global default buffer, a block member's inheritance of the block's - // buffer, and the requirement that any *xfb_buffer* declared on a block - // member must match the buffer inherited from the block." - if (memberQualifier.hasXfbBuffer()) { - if (defaultQualification.layoutXfbBuffer != memberQualifier.layoutXfbBuffer) - error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", ""); - } - - if (memberQualifier.hasLocation()) { - switch (type.getQualifier().storage) { - case EvqVaryingIn: - case EvqVaryingOut: - memberWithLocation = true; - break; - default: - break; - } - } else - memberWithoutLocation = true; - - TQualifier newMemberQualification = defaultQualification; - mergeQualifiers(newMemberQualification, memberQualifier); - memberQualifier = newMemberQualification; - } - - // Process the members - fixBlockLocations(loc, type.getQualifier(), typeList, memberWithLocation, memberWithoutLocation); - fixXfbOffsets(type.getQualifier(), typeList); - fixBlockUniformOffsets(type.getQualifier(), typeList); - - // reverse merge, so that currentBlockQualifier now has all layout information - // (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers) - mergeObjectLayoutQualifiers(type.getQualifier(), defaultQualification, true); - - // - // Build and add the interface block as a new type named 'blockName' - // - - // Use the instance name as the interface name if one exists, else the block name. - const TString& interfaceName = (instanceName && !instanceName->empty()) ? *instanceName : type.getTypeName(); - - TType blockType(&typeList, interfaceName, type.getQualifier()); - if (type.isArray()) - blockType.transferArraySizes(type.getArraySizes()); - - // Add the variable, as anonymous or named instanceName. - // Make an anonymous variable if no name was provided. - if (instanceName == nullptr) - instanceName = NewPoolTString(""); - - TVariable& variable = *new TVariable(instanceName, blockType); - if (! symbolTable.insert(variable)) { - if (*instanceName == "") - error(loc, "nameless block contains a member that already has a name at global scope", - "" /* blockName->c_str() */, ""); - else - error(loc, "block instance name redefinition", variable.getName().c_str(), ""); - - return; - } - - // Save it in the AST for linker use. - if (symbolTable.atGlobalLevel()) - trackLinkage(variable); -} - -// -// "For a block, this process applies to the entire block, or until the first member -// is reached that has a location layout qualifier. When a block member is declared with a location -// qualifier, its location comes from that qualifier: The member's location qualifier overrides the block-level -// declaration. Subsequent members are again assigned consecutive locations, based on the newest location, -// until the next member declared with a location qualifier. The values used for locations do not have to be -// declared in increasing order." -void HlslParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifier, TTypeList& typeList, bool memberWithLocation, bool memberWithoutLocation) -{ - // "If a block has no block-level location layout qualifier, it is required that either all or none of its members - // have a location layout qualifier, or a compile-time error results." - if (! qualifier.hasLocation() && memberWithLocation && memberWithoutLocation) - error(loc, "either the block needs a location, or all members need a location, or no members have a location", "location", ""); - else { - if (memberWithLocation) { - // remove any block-level location and make it per *every* member - int nextLocation = 0; // by the rule above, initial value is not relevant - if (qualifier.hasAnyLocation()) { - nextLocation = qualifier.layoutLocation; - qualifier.layoutLocation = TQualifier::layoutLocationEnd; - if (qualifier.hasComponent()) { - // "It is a compile-time error to apply the *component* qualifier to a ... block" - error(loc, "cannot apply to a block", "component", ""); - } - if (qualifier.hasIndex()) { - error(loc, "cannot apply to a block", "index", ""); - } - } - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - if (! memberQualifier.hasLocation()) { - if (nextLocation >= (int)TQualifier::layoutLocationEnd) - error(memberLoc, "location is too large", "location", ""); - memberQualifier.layoutLocation = nextLocation; - memberQualifier.layoutComponent = 0; - } - nextLocation = memberQualifier.layoutLocation + - intermediate.computeTypeLocationSize(*typeList[member].type, language); - } - } - } -} - -void HlslParseContext::fixXfbOffsets(TQualifier& qualifier, TTypeList& typeList) -{ - // "If a block is qualified with xfb_offset, all its - // members are assigned transform feedback buffer offsets. If a block is not qualified with xfb_offset, any - // members of that block not qualified with an xfb_offset will not be assigned transform feedback buffer - // offsets." - - if (! qualifier.hasXfbBuffer() || ! qualifier.hasXfbOffset()) - return; - - int nextOffset = qualifier.layoutXfbOffset; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - bool contains64BitType = false; - bool contains32BitType = false; - bool contains16BitType = false; - int memberSize = intermediate.computeTypeXfbSize(*typeList[member].type, contains64BitType, contains32BitType, contains16BitType); - // see if we need to auto-assign an offset to this member - if (! memberQualifier.hasXfbOffset()) { - // "if applied to an aggregate containing a double or 64-bit integer, the offset must also be a multiple of 8" - if (contains64BitType) - RoundToPow2(nextOffset, 8); - else if (contains32BitType) - RoundToPow2(nextOffset, 4); - // "if applied to an aggregate containing a half float or 16-bit integer, the offset must also be a multiple of 2" - else if (contains16BitType) - RoundToPow2(nextOffset, 2); - memberQualifier.layoutXfbOffset = nextOffset; - } else - nextOffset = memberQualifier.layoutXfbOffset; - nextOffset += memberSize; - } - - // The above gave all block members an offset, so we can take it off the block now, - // which will avoid double counting the offset usage. - qualifier.layoutXfbOffset = TQualifier::layoutXfbOffsetEnd; -} - -// Calculate and save the offset of each block member, using the recursively -// defined block offset rules and the user-provided offset and align. -// -// Also, compute and save the total size of the block. For the block's size, arrayness -// is not taken into account, as each element is backed by a separate buffer. -// -void HlslParseContext::fixBlockUniformOffsets(const TQualifier& qualifier, TTypeList& typeList) -{ - if (! qualifier.isUniformOrBuffer()) - return; - if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar) - return; - - int offset = 0; - int memberSize; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - - // "When align is applied to an array, it effects only the start of the array, not the array's internal stride." - - // modify just the children's view of matrix layout, if there is one for this member - TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix; - int dummyStride; - int memberAlignment = intermediate.getMemberAlignment(*typeList[member].type, memberSize, dummyStride, - qualifier.layoutPacking, - subMatrixLayout != ElmNone - ? subMatrixLayout == ElmRowMajor - : qualifier.layoutMatrix == ElmRowMajor); - if (memberQualifier.hasOffset()) { - // "The specified offset must be a multiple - // of the base alignment of the type of the block member it qualifies, or a compile-time error results." - if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment)) - error(memberLoc, "must be a multiple of the member's alignment", "offset", - "(layout offset = %d | member alignment = %d)", memberQualifier.layoutOffset, memberAlignment); - - // "The offset qualifier forces the qualified member to start at or after the specified - // integral-constant expression, which will be its byte offset from the beginning of the buffer. - // "The actual offset of a member is computed as - // follows: If offset was declared, start with that offset, otherwise start with the next available offset." - offset = std::max(offset, memberQualifier.layoutOffset); - } - - // "The actual alignment of a member will be the greater of the specified align alignment and the standard - // (e.g., std140) base alignment for the member's type." - if (memberQualifier.hasAlign()) - memberAlignment = std::max(memberAlignment, memberQualifier.layoutAlign); - - // "If the resulting offset is not a multiple of the actual alignment, - // increase it to the first offset that is a multiple of - // the actual alignment." - RoundToPow2(offset, memberAlignment); - typeList[member].type->getQualifier().layoutOffset = offset; - offset += memberSize; - } -} - -// For an identifier that is already declared, add more qualification to it. -void HlslParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier) -{ - TSymbol* symbol = symbolTable.find(identifier); - if (symbol == nullptr) { - error(loc, "identifier not previously declared", identifier.c_str(), ""); - return; - } - if (symbol->getAsFunction()) { - error(loc, "cannot re-qualify a function name", identifier.c_str(), ""); - return; - } - - if (qualifier.isAuxiliary() || - qualifier.isMemory() || - qualifier.isInterpolation() || - qualifier.hasLayout() || - qualifier.storage != EvqTemporary || - qualifier.precision != EpqNone) { - error(loc, "cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable", identifier.c_str(), ""); - return; - } - - // For read-only built-ins, add a new symbol for holding the modified qualifier. - // This will bring up an entire block, if a block type has to be modified (e.g., gl_Position inside a block) - if (symbol->isReadOnly()) - symbol = symbolTable.copyUp(symbol); - - if (qualifier.invariant) { - if (intermediate.inIoAccessed(identifier)) - error(loc, "cannot change qualification after use", "invariant", ""); - symbol->getWritableType().getQualifier().invariant = true; - } else if (qualifier.noContraction) { - if (intermediate.inIoAccessed(identifier)) - error(loc, "cannot change qualification after use", "precise", ""); - symbol->getWritableType().getQualifier().noContraction = true; - } else if (qualifier.specConstant) { - symbol->getWritableType().getQualifier().makeSpecConstant(); - if (qualifier.hasSpecConstantId()) - symbol->getWritableType().getQualifier().layoutSpecConstantId = qualifier.layoutSpecConstantId; - } else - warn(loc, "unknown requalification", "", ""); -} - -void HlslParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, TIdentifierList& identifiers) -{ - for (unsigned int i = 0; i < identifiers.size(); ++i) - addQualifierToExisting(loc, qualifier, *identifiers[i]); -} - -// -// Update the intermediate for the given input geometry -// -bool HlslParseContext::handleInputGeometry(const TSourceLoc& loc, const TLayoutGeometry& geometry) -{ - // these can be declared on non-entry-points, in which case they lose their meaning - if (! parsingEntrypointParameters) - return true; - - switch (geometry) { - case ElgPoints: // fall through - case ElgLines: // ... - case ElgTriangles: // ... - case ElgLinesAdjacency: // ... - case ElgTrianglesAdjacency: // ... - if (! intermediate.setInputPrimitive(geometry)) { - error(loc, "input primitive geometry redefinition", TQualifier::getGeometryString(geometry), ""); - return false; - } - break; - - default: - error(loc, "cannot apply to 'in'", TQualifier::getGeometryString(geometry), ""); - return false; - } - - return true; -} - -// -// Update the intermediate for the given output geometry -// -bool HlslParseContext::handleOutputGeometry(const TSourceLoc& loc, const TLayoutGeometry& geometry) -{ - // If this is not a geometry shader, ignore. It might be a mixed shader including several stages. - // Since that's an OK situation, return true for success. - if (language != EShLangGeometry) - return true; - - // these can be declared on non-entry-points, in which case they lose their meaning - if (! parsingEntrypointParameters) - return true; - - switch (geometry) { - case ElgPoints: - case ElgLineStrip: - case ElgTriangleStrip: - if (! intermediate.setOutputPrimitive(geometry)) { - error(loc, "output primitive geometry redefinition", TQualifier::getGeometryString(geometry), ""); - return false; - } - break; - default: - error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(geometry), ""); - return false; - } - - return true; -} - -// -// Selection attributes -// -void HlslParseContext::handleSelectionAttributes(const TSourceLoc& loc, TIntermSelection* selection, - const TAttributes& attributes) -{ - if (selection == nullptr) - return; - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - switch (it->name) { - case EatFlatten: - selection->setFlatten(); - break; - case EatBranch: - selection->setDontFlatten(); - break; - default: - warn(loc, "attribute does not apply to a selection", "", ""); - break; - } - } -} - -// -// Switch attributes -// -void HlslParseContext::handleSwitchAttributes(const TSourceLoc& loc, TIntermSwitch* selection, - const TAttributes& attributes) -{ - if (selection == nullptr) - return; - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - switch (it->name) { - case EatFlatten: - selection->setFlatten(); - break; - case EatBranch: - selection->setDontFlatten(); - break; - default: - warn(loc, "attribute does not apply to a switch", "", ""); - break; - } - } -} - -// -// Loop attributes -// -void HlslParseContext::handleLoopAttributes(const TSourceLoc& loc, TIntermLoop* loop, - const TAttributes& attributes) -{ - if (loop == nullptr) - return; - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - switch (it->name) { - case EatUnroll: - loop->setUnroll(); - break; - case EatLoop: - loop->setDontUnroll(); - break; - default: - warn(loc, "attribute does not apply to a loop", "", ""); - break; - } - } -} - -// -// Updating default qualifier for the case of a declaration with just a qualifier, -// no type, block, or identifier. -// -void HlslParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, const TPublicType& publicType) -{ - if (publicType.shaderQualifiers.vertices != TQualifier::layoutNotSet) { - assert(language == EShLangTessControl || language == EShLangGeometry); - // const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices"; - } - if (publicType.shaderQualifiers.invocations != TQualifier::layoutNotSet) { - if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations)) - error(loc, "cannot change previously set layout value", "invocations", ""); - } - if (publicType.shaderQualifiers.geometry != ElgNone) { - if (publicType.qualifier.storage == EvqVaryingIn) { - switch (publicType.shaderQualifiers.geometry) { - case ElgPoints: - case ElgLines: - case ElgLinesAdjacency: - case ElgTriangles: - case ElgTrianglesAdjacency: - case ElgQuads: - case ElgIsolines: - break; - default: - error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), - ""); - } - } else if (publicType.qualifier.storage == EvqVaryingOut) { - handleOutputGeometry(loc, publicType.shaderQualifiers.geometry); - } else - error(loc, "cannot apply to:", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), - GetStorageQualifierString(publicType.qualifier.storage)); - } - if (publicType.shaderQualifiers.spacing != EvsNone) - intermediate.setVertexSpacing(publicType.shaderQualifiers.spacing); - if (publicType.shaderQualifiers.order != EvoNone) - intermediate.setVertexOrder(publicType.shaderQualifiers.order); - if (publicType.shaderQualifiers.pointMode) - intermediate.setPointMode(); - for (int i = 0; i < 3; ++i) { - if (publicType.shaderQualifiers.localSize[i] > 1) { - int max = 0; - switch (i) { - case 0: max = resources.maxComputeWorkGroupSizeX; break; - case 1: max = resources.maxComputeWorkGroupSizeY; break; - case 2: max = resources.maxComputeWorkGroupSizeZ; break; - default: break; - } - if (intermediate.getLocalSize(i) > (unsigned int)max) - error(loc, "too large; see gl_MaxComputeWorkGroupSize", "local_size", ""); - - // Fix the existing constant gl_WorkGroupSize with this new information. - TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); - workGroupSize->getWritableConstArray()[i].setUConst(intermediate.getLocalSize(i)); - } - if (publicType.shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) { - intermediate.setLocalSizeSpecId(i, publicType.shaderQualifiers.localSizeSpecId[i]); - // Set the workgroup built-in variable as a specialization constant - TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); - workGroupSize->getWritableType().getQualifier().specConstant = true; - } - } - if (publicType.shaderQualifiers.earlyFragmentTests) - intermediate.setEarlyFragmentTests(); - - const TQualifier& qualifier = publicType.qualifier; - - switch (qualifier.storage) { - case EvqUniform: - if (qualifier.hasMatrix()) - globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.hasPacking()) - globalUniformDefaults.layoutPacking = qualifier.layoutPacking; - break; - case EvqBuffer: - if (qualifier.hasMatrix()) - globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.hasPacking()) - globalBufferDefaults.layoutPacking = qualifier.layoutPacking; - break; - case EvqVaryingIn: - break; - case EvqVaryingOut: - if (qualifier.hasStream()) - globalOutputDefaults.layoutStream = qualifier.layoutStream; - if (qualifier.hasXfbBuffer()) - globalOutputDefaults.layoutXfbBuffer = qualifier.layoutXfbBuffer; - if (globalOutputDefaults.hasXfbBuffer() && qualifier.hasXfbStride()) { - if (! intermediate.setXfbBufferStride(globalOutputDefaults.layoutXfbBuffer, qualifier.layoutXfbStride)) - error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", - qualifier.layoutXfbBuffer); - } - break; - default: - error(loc, "default qualifier requires 'uniform', 'buffer', 'in', or 'out' storage qualification", "", ""); - return; - } -} - -// -// Take the sequence of statements that has been built up since the last case/default, -// put it on the list of top-level nodes for the current (inner-most) switch statement, -// and follow that by the case/default we are on now. (See switch topology comment on -// TIntermSwitch.) -// -void HlslParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode) -{ - TIntermSequence* switchSequence = switchSequenceStack.back(); - - if (statements) { - statements->setOperator(EOpSequence); - switchSequence->push_back(statements); - } - if (branchNode) { - // check all previous cases for the same label (or both are 'default') - for (unsigned int s = 0; s < switchSequence->size(); ++s) { - TIntermBranch* prevBranch = (*switchSequence)[s]->getAsBranchNode(); - if (prevBranch) { - TIntermTyped* prevExpression = prevBranch->getExpression(); - TIntermTyped* newExpression = branchNode->getAsBranchNode()->getExpression(); - if (prevExpression == nullptr && newExpression == nullptr) - error(branchNode->getLoc(), "duplicate label", "default", ""); - else if (prevExpression != nullptr && - newExpression != nullptr && - prevExpression->getAsConstantUnion() && - newExpression->getAsConstantUnion() && - prevExpression->getAsConstantUnion()->getConstArray()[0].getIConst() == - newExpression->getAsConstantUnion()->getConstArray()[0].getIConst()) - error(branchNode->getLoc(), "duplicated value", "case", ""); - } - } - switchSequence->push_back(branchNode); - } -} - -// -// Turn the top-level node sequence built up of wrapupSwitchSubsequence -// into a switch node. -// -TIntermNode* HlslParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression, - TIntermAggregate* lastStatements, const TAttributes& attributes) -{ - wrapupSwitchSubsequence(lastStatements, nullptr); - - if (expression == nullptr || - (expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint) || - expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector()) - error(loc, "condition must be a scalar integer expression", "switch", ""); - - // If there is nothing to do, drop the switch but still execute the expression - TIntermSequence* switchSequence = switchSequenceStack.back(); - if (switchSequence->size() == 0) - return expression; - - if (lastStatements == nullptr) { - // emulate a break for error recovery - lastStatements = intermediate.makeAggregate(intermediate.addBranch(EOpBreak, loc)); - lastStatements->setOperator(EOpSequence); - switchSequence->push_back(lastStatements); - } - - TIntermAggregate* body = new TIntermAggregate(EOpSequence); - body->getSequence() = *switchSequenceStack.back(); - body->setLoc(loc); - - TIntermSwitch* switchNode = new TIntermSwitch(expression, body); - switchNode->setLoc(loc); - handleSwitchAttributes(loc, switchNode, attributes); - - return switchNode; -} - -// Make a new symbol-table level that is made out of the members of a structure. -// This should be done as an anonymous struct (name is "") so that the symbol table -// finds the members with no explicit reference to a 'this' variable. -void HlslParseContext::pushThisScope(const TType& thisStruct, const TVector& functionDeclarators) -{ - // member variables - TVariable& thisVariable = *new TVariable(NewPoolTString(""), thisStruct); - symbolTable.pushThis(thisVariable); - - // member functions - for (auto it = functionDeclarators.begin(); it != functionDeclarators.end(); ++it) { - // member should have a prefix matching currentTypePrefix.back() - // but, symbol lookup within the class scope will just use the - // unprefixed name. Hence, there are two: one fully prefixed and - // one with no prefix. - TFunction& member = *it->function->clone(); - member.removePrefix(currentTypePrefix.back()); - symbolTable.insert(member); - } -} - -// Track levels of class/struct/namespace nesting with a prefix string using -// the type names separated by the scoping operator. E.g., two levels -// would look like: -// -// outer::inner -// -// The string is empty when at normal global level. -// -void HlslParseContext::pushNamespace(const TString& typeName) -{ - // make new type prefix - TString newPrefix; - if (currentTypePrefix.size() > 0) - newPrefix = currentTypePrefix.back(); - newPrefix.append(typeName); - newPrefix.append(scopeMangler); - currentTypePrefix.push_back(newPrefix); -} - -// Opposite of pushNamespace(), see above -void HlslParseContext::popNamespace() -{ - currentTypePrefix.pop_back(); -} - -// Use the class/struct nesting string to create a global name for -// a member of a class/struct. -void HlslParseContext::getFullNamespaceName(TString*& name) const -{ - if (currentTypePrefix.size() == 0) - return; - - TString* fullName = NewPoolTString(currentTypePrefix.back().c_str()); - fullName->append(*name); - name = fullName; -} - -// Helper function to add the namespace scope mangling syntax to a string. -void HlslParseContext::addScopeMangler(TString& name) -{ - name.append(scopeMangler); -} - -// Return true if this has uniform-interface like decorations. -bool HlslParseContext::hasUniform(const TQualifier& qualifier) const -{ - return qualifier.hasUniformLayout() || - qualifier.layoutPushConstant; -} - -// Potentially not the opposite of hasUniform(), as if some characteristic is -// ever used for more than one thing (e.g., uniform or input), hasUniform() should -// say it exists, but clearUniform() should leave it in place. -void HlslParseContext::clearUniform(TQualifier& qualifier) -{ - qualifier.clearUniformLayout(); - qualifier.layoutPushConstant = false; -} - -// Return false if builtIn by itself doesn't force this qualifier to be an input qualifier. -bool HlslParseContext::isInputBuiltIn(const TQualifier& qualifier) const -{ - switch (qualifier.builtIn) { - case EbvPosition: - case EbvPointSize: - return language != EShLangVertex && language != EShLangCompute && language != EShLangFragment; - case EbvClipDistance: - case EbvCullDistance: - return language != EShLangVertex && language != EShLangCompute; - case EbvFragCoord: - case EbvFace: - case EbvHelperInvocation: - case EbvLayer: - case EbvPointCoord: - case EbvSampleId: - case EbvSampleMask: - case EbvSamplePosition: - case EbvViewportIndex: - return language == EShLangFragment; - case EbvGlobalInvocationId: - case EbvLocalInvocationIndex: - case EbvLocalInvocationId: - case EbvNumWorkGroups: - case EbvWorkGroupId: - case EbvWorkGroupSize: - return language == EShLangCompute; - case EbvInvocationId: - return language == EShLangTessControl || language == EShLangTessEvaluation || language == EShLangGeometry; - case EbvPatchVertices: - return language == EShLangTessControl || language == EShLangTessEvaluation; - case EbvInstanceId: - case EbvInstanceIndex: - case EbvVertexId: - case EbvVertexIndex: - return language == EShLangVertex; - case EbvPrimitiveId: - return language == EShLangGeometry || language == EShLangFragment || language == EShLangTessControl; - case EbvTessLevelInner: - case EbvTessLevelOuter: - return language == EShLangTessEvaluation; - case EbvTessCoord: - return language == EShLangTessEvaluation; - case EbvViewIndex: - return language != EShLangCompute; - default: - return false; - } -} - -// Return true if there are decorations to preserve for input-like storage. -bool HlslParseContext::hasInput(const TQualifier& qualifier) const -{ - if (qualifier.hasAnyLocation()) - return true; - - if (language == EShLangFragment && (qualifier.isInterpolation() || qualifier.centroid || qualifier.sample)) - return true; - - if (language == EShLangTessEvaluation && qualifier.patch) - return true; - - if (isInputBuiltIn(qualifier)) - return true; - - return false; -} - -// Return false if builtIn by itself doesn't force this qualifier to be an output qualifier. -bool HlslParseContext::isOutputBuiltIn(const TQualifier& qualifier) const -{ - switch (qualifier.builtIn) { - case EbvPosition: - case EbvPointSize: - case EbvClipVertex: - case EbvClipDistance: - case EbvCullDistance: - return language != EShLangFragment && language != EShLangCompute; - case EbvFragDepth: - case EbvFragDepthGreater: - case EbvFragDepthLesser: - case EbvSampleMask: - return language == EShLangFragment; - case EbvLayer: - case EbvViewportIndex: - return language == EShLangGeometry || language == EShLangVertex; - case EbvPrimitiveId: - return language == EShLangGeometry; - case EbvTessLevelInner: - case EbvTessLevelOuter: - return language == EShLangTessControl; - default: - return false; - } -} - -// Return true if there are decorations to preserve for output-like storage. -bool HlslParseContext::hasOutput(const TQualifier& qualifier) const -{ - if (qualifier.hasAnyLocation()) - return true; - - if (language != EShLangFragment && language != EShLangCompute && qualifier.hasXfb()) - return true; - - if (language == EShLangTessControl && qualifier.patch) - return true; - - if (language == EShLangGeometry && qualifier.hasStream()) - return true; - - if (isOutputBuiltIn(qualifier)) - return true; - - return false; -} - -// Make the IO decorations etc. be appropriate only for an input interface. -void HlslParseContext::correctInput(TQualifier& qualifier) -{ - clearUniform(qualifier); - if (language == EShLangVertex) - qualifier.clearInterstage(); - if (language != EShLangTessEvaluation) - qualifier.patch = false; - if (language != EShLangFragment) { - qualifier.clearInterpolation(); - qualifier.sample = false; - } - - qualifier.clearStreamLayout(); - qualifier.clearXfbLayout(); - - if (! isInputBuiltIn(qualifier)) - qualifier.builtIn = EbvNone; -} - -// Make the IO decorations etc. be appropriate only for an output interface. -void HlslParseContext::correctOutput(TQualifier& qualifier) -{ - clearUniform(qualifier); - if (language == EShLangFragment) - qualifier.clearInterstage(); - if (language != EShLangGeometry) - qualifier.clearStreamLayout(); - if (language == EShLangFragment) - qualifier.clearXfbLayout(); - if (language != EShLangTessControl) - qualifier.patch = false; - - switch (qualifier.builtIn) { - case EbvFragDepth: - intermediate.setDepthReplacing(); - intermediate.setDepth(EldAny); - break; - case EbvFragDepthGreater: - intermediate.setDepthReplacing(); - intermediate.setDepth(EldGreater); - qualifier.builtIn = EbvFragDepth; - break; - case EbvFragDepthLesser: - intermediate.setDepthReplacing(); - intermediate.setDepth(EldLess); - qualifier.builtIn = EbvFragDepth; - break; - default: - break; - } - - if (! isOutputBuiltIn(qualifier)) - qualifier.builtIn = EbvNone; -} - -// Make the IO decorations etc. be appropriate only for uniform type interfaces. -void HlslParseContext::correctUniform(TQualifier& qualifier) -{ - if (qualifier.declaredBuiltIn == EbvNone) - qualifier.declaredBuiltIn = qualifier.builtIn; - - qualifier.builtIn = EbvNone; - qualifier.clearInterstage(); - qualifier.clearInterstageLayout(); -} - -// Clear out all IO/Uniform stuff, so this has nothing to do with being an IO interface. -void HlslParseContext::clearUniformInputOutput(TQualifier& qualifier) -{ - clearUniform(qualifier); - correctUniform(qualifier); -} - - -// Set texture return type. Returns success (not all types are valid). -bool HlslParseContext::setTextureReturnType(TSampler& sampler, const TType& retType, const TSourceLoc& loc) -{ - // Seed the output with an invalid index. We will set it to a valid one if we can. - sampler.structReturnIndex = TSampler::noReturnStruct; - - // Arrays aren't supported. - if (retType.isArray()) { - error(loc, "Arrays not supported in texture template types", "", ""); - return false; - } - - // If return type is a vector, remember the vector size in the sampler, and return. - if (retType.isVector() || retType.isScalar()) { - sampler.vectorSize = retType.getVectorSize(); - return true; - } - - // If it wasn't a vector, it must be a struct meeting certain requirements. The requirements - // are checked below: just check for struct-ness here. - if (!retType.isStruct()) { - error(loc, "Invalid texture template type", "", ""); - return false; - } - - // TODO: Subpass doesn't handle struct returns, due to some oddities with fn overloading. - if (sampler.isSubpass()) { - error(loc, "Unimplemented: structure template type in subpass input", "", ""); - return false; - } - - TTypeList* members = retType.getWritableStruct(); - - // Check for too many or not enough structure members. - if (members->size() > 4 || members->size() == 0) { - error(loc, "Invalid member count in texture template structure", "", ""); - return false; - } - - // Error checking: We must have <= 4 total components, all of the same basic type. - unsigned totalComponents = 0; - for (unsigned m = 0; m < members->size(); ++m) { - // Check for bad member types - if (!(*members)[m].type->isScalar() && !(*members)[m].type->isVector()) { - error(loc, "Invalid texture template struct member type", "", ""); - return false; - } - - const unsigned memberVectorSize = (*members)[m].type->getVectorSize(); - totalComponents += memberVectorSize; - - // too many total member components - if (totalComponents > 4) { - error(loc, "Too many components in texture template structure type", "", ""); - return false; - } - - // All members must be of a common basic type - if ((*members)[m].type->getBasicType() != (*members)[0].type->getBasicType()) { - error(loc, "Texture template structure members must same basic type", "", ""); - return false; - } - } - - // If the structure in the return type already exists in the table, we'll use it. Otherwise, we'll make - // a new entry. This is a linear search, but it hardly ever happens, and the list cannot be very large. - for (unsigned int idx = 0; idx < textureReturnStruct.size(); ++idx) { - if (textureReturnStruct[idx] == members) { - sampler.structReturnIndex = idx; - return true; - } - } - - // It wasn't found as an existing entry. See if we have room for a new one. - if (textureReturnStruct.size() >= TSampler::structReturnSlots) { - error(loc, "Texture template struct return slots exceeded", "", ""); - return false; - } - - // Insert it in the vector that tracks struct return types. - sampler.structReturnIndex = unsigned(textureReturnStruct.size()); - textureReturnStruct.push_back(members); - - // Success! - return true; -} - -// Return the sampler return type in retType. -void HlslParseContext::getTextureReturnType(const TSampler& sampler, TType& retType) const -{ - if (sampler.hasReturnStruct()) { - assert(textureReturnStruct.size() >= sampler.structReturnIndex); - - // We land here if the texture return is a structure. - TTypeList* blockStruct = textureReturnStruct[sampler.structReturnIndex]; - - const TType resultType(blockStruct, ""); - retType.shallowCopy(resultType); - } else { - // We land here if the texture return is a vector or scalar. - const TType resultType(sampler.type, EvqTemporary, sampler.getVectorSize()); - retType.shallowCopy(resultType); - } -} - - -// Return a symbol for the tessellation linkage variable of the given TBuiltInVariable type -TIntermSymbol* HlslParseContext::findTessLinkageSymbol(TBuiltInVariable biType) const -{ - const auto it = builtInTessLinkageSymbols.find(biType); - if (it == builtInTessLinkageSymbols.end()) // if it wasn't declared by the user, return nullptr - return nullptr; - - return intermediate.addSymbol(*it->second->getAsVariable()); -} - -// Find the patch constant function (issues error, returns nullptr if not found) -const TFunction* HlslParseContext::findPatchConstantFunction(const TSourceLoc& loc) -{ - if (symbolTable.isFunctionNameVariable(patchConstantFunctionName)) { - error(loc, "can't use variable in patch constant function", patchConstantFunctionName.c_str(), ""); - return nullptr; - } - - const TString mangledName = patchConstantFunctionName + "("; - - // create list of PCF candidates - TVector candidateList; - bool builtIn; - symbolTable.findFunctionNameList(mangledName, candidateList, builtIn); - - // We have to have one and only one, or we don't know which to pick: the patchconstantfunc does not - // allow any disambiguation of overloads. - if (candidateList.empty()) { - error(loc, "patch constant function not found", patchConstantFunctionName.c_str(), ""); - return nullptr; - } - - // Based on directed experiments, it appears that if there are overloaded patchconstantfunctions, - // HLSL picks the last one in shader source order. Since that isn't yet implemented here, error - // out if there is more than one candidate. - if (candidateList.size() > 1) { - error(loc, "ambiguous patch constant function", patchConstantFunctionName.c_str(), ""); - return nullptr; - } - - return candidateList[0]; -} - -// Finalization step: Add patch constant function invocation -void HlslParseContext::addPatchConstantInvocation() -{ - TSourceLoc loc; - loc.init(); - - // If there's no patch constant function, or we're not a HS, do nothing. - if (patchConstantFunctionName.empty() || language != EShLangTessControl) - return; - - // Look for built-in variables in a function's parameter list. - const auto findBuiltIns = [&](const TFunction& function, std::set& builtIns) { - for (int p=0; pgetQualifier().storage; - - if (storage == EvqConstReadOnly) // treated identically to input - storage = EvqIn; - - if (function[p].getDeclaredBuiltIn() != EbvNone) - builtIns.insert(HlslParseContext::tInterstageIoData(function[p].getDeclaredBuiltIn(), storage)); - else - builtIns.insert(HlslParseContext::tInterstageIoData(function[p].type->getQualifier().builtIn, storage)); - } - }; - - // If we synthesize a built-in interface variable, we must add it to the linkage. - const auto addToLinkage = [&](const TType& type, const TString* name, TIntermSymbol** symbolNode) { - if (name == nullptr) { - error(loc, "unable to locate patch function parameter name", "", ""); - return; - } else { - TVariable& variable = *new TVariable(name, type); - if (! symbolTable.insert(variable)) { - error(loc, "unable to declare patch constant function interface variable", name->c_str(), ""); - return; - } - - globalQualifierFix(loc, variable.getWritableType().getQualifier()); - - if (symbolNode != nullptr) - *symbolNode = intermediate.addSymbol(variable); - - trackLinkage(variable); - } - }; - - const auto isOutputPatch = [](TFunction& patchConstantFunction, int param) { - const TType& type = *patchConstantFunction[param].type; - const TBuiltInVariable biType = patchConstantFunction[param].getDeclaredBuiltIn(); - - return type.isSizedArray() && biType == EbvOutputPatch; - }; - - // We will perform these steps. Each is in a scoped block for separation: they could - // become separate functions to make addPatchConstantInvocation shorter. - // - // 1. Union the interfaces, and create built-ins for anything present in the PCF and - // declared as a built-in variable that isn't present in the entry point's signature. - // - // 2. Synthesizes a call to the patchconstfunction using built-in variables from either main, - // or the ones we created. Matching is based on built-in type. We may use synthesized - // variables from (1) above. - // - // 2B: Synthesize per control point invocations of wrapped entry point if the PCF requires them. - // - // 3. Create a return sequence: copy the return value (if any) from the PCF to a - // (non-sanitized) output variable. In case this may involve multiple copies, such as for - // an arrayed variable, a temporary copy of the PCF output is created to avoid multiple - // indirections into a complex R-value coming from the call to the PCF. - // - // 4. Create a barrier. - // - // 5/5B. Call the PCF inside an if test for (invocation id == 0). - - TFunction* patchConstantFunctionPtr = const_cast(findPatchConstantFunction(loc)); - - if (patchConstantFunctionPtr == nullptr) - return; - - TFunction& patchConstantFunction = *patchConstantFunctionPtr; - - const int pcfParamCount = patchConstantFunction.getParamCount(); - TIntermSymbol* invocationIdSym = findTessLinkageSymbol(EbvInvocationId); - TIntermSequence& epBodySeq = entryPointFunctionBody->getAsAggregate()->getSequence(); - - int outPatchParam = -1; // -1 means there isn't one. - - // ================ Step 1A: Union Interfaces ================ - // Our patch constant function. - { - std::set pcfBuiltIns; // patch constant function built-ins - std::set epfBuiltIns; // entry point function built-ins - - assert(entryPointFunction); - assert(entryPointFunctionBody); - - findBuiltIns(patchConstantFunction, pcfBuiltIns); - findBuiltIns(*entryPointFunction, epfBuiltIns); - - // Find the set of built-ins in the PCF that are not present in the entry point. - std::set notInEntryPoint; - - notInEntryPoint = pcfBuiltIns; - - // std::set_difference not usable on unordered containers - for (auto bi = epfBuiltIns.begin(); bi != epfBuiltIns.end(); ++bi) - notInEntryPoint.erase(*bi); - - // Now we'll add those to the entry and to the linkage. - for (int p=0; pgetQualifier().storage; - - // Track whether there is an output patch param - if (isOutputPatch(patchConstantFunction, p)) { - if (outPatchParam >= 0) { - // Presently we only support one per ctrl pt input. - error(loc, "unimplemented: multiple output patches in patch constant function", "", ""); - return; - } - outPatchParam = p; - } - - if (biType != EbvNone) { - TType* paramType = patchConstantFunction[p].type->clone(); - - if (storage == EvqConstReadOnly) // treated identically to input - storage = EvqIn; - - // Presently, the only non-built-in we support is InputPatch, which is treated as - // a pseudo-built-in. - if (biType == EbvInputPatch) { - builtInTessLinkageSymbols[biType] = inputPatch; - } else if (biType == EbvOutputPatch) { - // Nothing... - } else { - // Use the original declaration type for the linkage - paramType->getQualifier().builtIn = biType; - if (biType == EbvTessLevelInner || biType == EbvTessLevelOuter) - paramType->getQualifier().patch = true; - - if (notInEntryPoint.count(tInterstageIoData(biType, storage)) == 1) - addToLinkage(*paramType, patchConstantFunction[p].name, nullptr); - } - } - } - - // If we didn't find it because the shader made one, add our own. - if (invocationIdSym == nullptr) { - TType invocationIdType(EbtUint, EvqIn, 1); - TString* invocationIdName = NewPoolTString("InvocationId"); - invocationIdType.getQualifier().builtIn = EbvInvocationId; - addToLinkage(invocationIdType, invocationIdName, &invocationIdSym); - } - - assert(invocationIdSym); - } - - TIntermTyped* pcfArguments = nullptr; - TVariable* perCtrlPtVar = nullptr; - - // ================ Step 1B: Argument synthesis ================ - // Create pcfArguments for synthesis of patchconstantfunction invocation - { - for (int p=0; pgetWritableType().getQualifier().makeTemporary(); - } - inputArg = intermediate.addSymbol(*perCtrlPtVar, loc); - } else { - // find which built-in it is - const TBuiltInVariable biType = patchConstantFunction[p].getDeclaredBuiltIn(); - - if (biType == EbvInputPatch && inputPatch == nullptr) { - error(loc, "unimplemented: PCF input patch without entry point input patch parameter", "", ""); - return; - } - - inputArg = findTessLinkageSymbol(biType); - - if (inputArg == nullptr) { - error(loc, "unable to find patch constant function built-in variable", "", ""); - return; - } - } - - if (pcfParamCount == 1) - pcfArguments = inputArg; - else - pcfArguments = intermediate.growAggregate(pcfArguments, inputArg); - } - } - - // ================ Step 2: Synthesize call to PCF ================ - TIntermAggregate* pcfCallSequence = nullptr; - TIntermTyped* pcfCall = nullptr; - - { - // Create a function call to the patchconstantfunction - if (pcfArguments) - addInputArgumentConversions(patchConstantFunction, pcfArguments); - - // Synthetic call. - pcfCall = intermediate.setAggregateOperator(pcfArguments, EOpFunctionCall, patchConstantFunction.getType(), loc); - pcfCall->getAsAggregate()->setUserDefined(); - pcfCall->getAsAggregate()->setName(patchConstantFunction.getMangledName()); - intermediate.addToCallGraph(infoSink, intermediate.getEntryPointMangledName().c_str(), - patchConstantFunction.getMangledName()); - - if (pcfCall->getAsAggregate()) { - TQualifierList& qualifierList = pcfCall->getAsAggregate()->getQualifierList(); - for (int i = 0; i < patchConstantFunction.getParamCount(); ++i) { - TStorageQualifier qual = patchConstantFunction[i].type->getQualifier().storage; - qualifierList.push_back(qual); - } - pcfCall = addOutputArgumentConversions(patchConstantFunction, *pcfCall->getAsOperator()); - } - } - - // ================ Step 2B: Per Control Point synthesis ================ - // If there is per control point data, we must either emulate that with multiple - // invocations of the entry point to build up an array, or (TODO:) use a yet - // unavailable extension to look across the SIMD lanes. This is the former - // as a placeholder for the latter. - if (outPatchParam >= 0) { - // We must introduce a local temp variable of the type wanted by the PCF input. - const int arraySize = patchConstantFunction[outPatchParam].type->getOuterArraySize(); - - if (entryPointFunction->getType().getBasicType() == EbtVoid) { - error(loc, "entry point must return a value for use with patch constant function", "", ""); - return; - } - - // Create calls to wrapped main to fill in the array. We will substitute fixed values - // of invocation ID when calling the wrapped main. - - // This is the type of the each member of the per ctrl point array. - const TType derefType(perCtrlPtVar->getType(), 0); - - for (int cpt = 0; cpt < arraySize; ++cpt) { - // TODO: improve. substr(1) here is to avoid the '@' that was grafted on but isn't in the symtab - // for this function. - const TString origName = entryPointFunction->getName().substr(1); - TFunction callee(&origName, TType(EbtVoid)); - TIntermTyped* callingArgs = nullptr; - - for (int i = 0; i < entryPointFunction->getParamCount(); i++) { - TParameter& param = (*entryPointFunction)[i]; - TType& paramType = *param.type; - - if (paramType.getQualifier().isParamOutput()) { - error(loc, "unimplemented: entry point outputs in patch constant function invocation", "", ""); - return; - } - - if (paramType.getQualifier().isParamInput()) { - TIntermTyped* arg = nullptr; - if ((*entryPointFunction)[i].getDeclaredBuiltIn() == EbvInvocationId) { - // substitute invocation ID with the array element ID - arg = intermediate.addConstantUnion(cpt, loc); - } else { - TVariable* argVar = makeInternalVariable(*param.name, *param.type); - argVar->getWritableType().getQualifier().makeTemporary(); - arg = intermediate.addSymbol(*argVar); - } - - handleFunctionArgument(&callee, callingArgs, arg); - } - } - - // Call and assign to per ctrl point variable - currentCaller = intermediate.getEntryPointMangledName().c_str(); - TIntermTyped* callReturn = handleFunctionCall(loc, &callee, callingArgs); - TIntermTyped* index = intermediate.addConstantUnion(cpt, loc); - TIntermSymbol* perCtrlPtSym = intermediate.addSymbol(*perCtrlPtVar, loc); - TIntermTyped* element = intermediate.addIndex(EOpIndexDirect, perCtrlPtSym, index, loc); - element->setType(derefType); - element->setLoc(loc); - - pcfCallSequence = intermediate.growAggregate(pcfCallSequence, - handleAssign(loc, EOpAssign, element, callReturn)); - } - } - - // ================ Step 3: Create return Sequence ================ - // Return sequence: copy PCF result to a temporary, then to shader output variable. - if (pcfCall->getBasicType() != EbtVoid) { - const TType* retType = &patchConstantFunction.getType(); // return type from the PCF - TType outType; // output type that goes with the return type. - outType.shallowCopy(*retType); - - // substitute the output type - const auto newLists = ioTypeMap.find(retType->getStruct()); - if (newLists != ioTypeMap.end()) - outType.setStruct(newLists->second.output); - - // Substitute the top level type's built-in type - if (patchConstantFunction.getDeclaredBuiltInType() != EbvNone) - outType.getQualifier().builtIn = patchConstantFunction.getDeclaredBuiltInType(); - - outType.getQualifier().patch = true; // make it a per-patch variable - - TVariable* pcfOutput = makeInternalVariable("@patchConstantOutput", outType); - pcfOutput->getWritableType().getQualifier().storage = EvqVaryingOut; - - if (pcfOutput->getType().isStruct()) - flatten(*pcfOutput, false); - - assignToInterface(*pcfOutput); - - TIntermSymbol* pcfOutputSym = intermediate.addSymbol(*pcfOutput, loc); - - // The call to the PCF is a complex R-value: we want to store it in a temp to avoid - // repeated calls to the PCF: - TVariable* pcfCallResult = makeInternalVariable("@patchConstantResult", *retType); - pcfCallResult->getWritableType().getQualifier().makeTemporary(); - - TIntermSymbol* pcfResultVar = intermediate.addSymbol(*pcfCallResult, loc); - TIntermNode* pcfResultAssign = handleAssign(loc, EOpAssign, pcfResultVar, pcfCall); - TIntermNode* pcfResultToOut = handleAssign(loc, EOpAssign, pcfOutputSym, - intermediate.addSymbol(*pcfCallResult, loc)); - - pcfCallSequence = intermediate.growAggregate(pcfCallSequence, pcfResultAssign); - pcfCallSequence = intermediate.growAggregate(pcfCallSequence, pcfResultToOut); - } else { - pcfCallSequence = intermediate.growAggregate(pcfCallSequence, pcfCall); - } - - // ================ Step 4: Barrier ================ - TIntermTyped* barrier = new TIntermAggregate(EOpBarrier); - barrier->setLoc(loc); - barrier->setType(TType(EbtVoid)); - epBodySeq.insert(epBodySeq.end(), barrier); - - // ================ Step 5: Test on invocation ID ================ - TIntermTyped* zero = intermediate.addConstantUnion(0, loc, true); - TIntermTyped* cmp = intermediate.addBinaryNode(EOpEqual, invocationIdSym, zero, loc, TType(EbtBool)); - - - // ================ Step 5B: Create if statement on Invocation ID == 0 ================ - intermediate.setAggregateOperator(pcfCallSequence, EOpSequence, TType(EbtVoid), loc); - TIntermTyped* invocationIdTest = new TIntermSelection(cmp, pcfCallSequence, nullptr); - invocationIdTest->setLoc(loc); - - // add our test sequence before the return. - epBodySeq.insert(epBodySeq.end(), invocationIdTest); -} - -// Finalization step: remove unused buffer blocks from linkage (we don't know until the -// shader is entirely compiled). -// Preserve order of remaining symbols. -void HlslParseContext::removeUnusedStructBufferCounters() -{ - const auto endIt = std::remove_if(linkageSymbols.begin(), linkageSymbols.end(), - [this](const TSymbol* sym) { - const auto sbcIt = structBufferCounter.find(sym->getName()); - return sbcIt != structBufferCounter.end() && !sbcIt->second; - }); - - linkageSymbols.erase(endIt, linkageSymbols.end()); -} - -// Finalization step: patch texture shadow modes to match samplers they were combined with -void HlslParseContext::fixTextureShadowModes() -{ - for (auto symbol = linkageSymbols.begin(); symbol != linkageSymbols.end(); ++symbol) { - TSampler& sampler = (*symbol)->getWritableType().getSampler(); - - if (sampler.isTexture()) { - const auto shadowMode = textureShadowVariant.find((*symbol)->getUniqueId()); - if (shadowMode != textureShadowVariant.end()) { - - if (shadowMode->second->overloaded()) - // Texture needs legalization if it's been seen with both shadow and non-shadow modes. - intermediate.setNeedsLegalization(); - - sampler.shadow = shadowMode->second->isShadowId((*symbol)->getUniqueId()); - } - } - } -} - -// Finalization step: patch append methods to use proper stream output, which isn't known until -// main is parsed, which could happen after the append method is parsed. -void HlslParseContext::finalizeAppendMethods() -{ - TSourceLoc loc; - loc.init(); - - // Nothing to do: bypass test for valid stream output. - if (gsAppends.empty()) - return; - - if (gsStreamOutput == nullptr) { - error(loc, "unable to find output symbol for Append()", "", ""); - return; - } - - // Patch append sequences, now that we know the stream output symbol. - for (auto append = gsAppends.begin(); append != gsAppends.end(); ++append) { - append->node->getSequence()[0] = - handleAssign(append->loc, EOpAssign, - intermediate.addSymbol(*gsStreamOutput, append->loc), - append->node->getSequence()[0]->getAsTyped()); - } -} - -// post-processing -void HlslParseContext::finish() -{ - // Error check: There was a dangling .mips operator. These are not nested constructs in the grammar, so - // cannot be detected there. This is not strictly needed in a non-validating parser; it's just helpful. - if (! mipsOperatorMipArg.empty()) { - error(mipsOperatorMipArg.back().loc, "unterminated mips operator:", "", ""); - } - - removeUnusedStructBufferCounters(); - addPatchConstantInvocation(); - fixTextureShadowModes(); - finalizeAppendMethods(); - - // Communicate out (esp. for command line) that we formed AST that will make - // illegal AST SPIR-V and it needs transforms to legalize it. - if (intermediate.needsLegalization() && (messages & EShMsgHlslLegalization)) - infoSink.info << "WARNING: AST will form illegal SPIR-V; need to transform to legalize"; - - TParseContextBase::finish(); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/HLSL/hlslParseHelper.h b/3rdparty/glslang/glslang/HLSL/hlslParseHelper.h deleted file mode 100644 index 97c52d45..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslParseHelper.h +++ /dev/null @@ -1,517 +0,0 @@ -// -// Copyright (C) 2016-2018 Google, Inc. -// Copyright (C) 2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -#ifndef HLSL_PARSE_INCLUDED_ -#define HLSL_PARSE_INCLUDED_ - -#include "../MachineIndependent/parseVersions.h" -#include "../MachineIndependent/ParseHelper.h" -#include "../MachineIndependent/attribute.h" - -#include - -namespace glslang { - -class TFunctionDeclarator; - -class HlslParseContext : public TParseContextBase { -public: - HlslParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, - int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, - const TString sourceEntryPointName, - bool forwardCompatible = false, EShMessages messages = EShMsgDefault); - virtual ~HlslParseContext(); - void initializeExtensionBehavior() override; - - void setLimits(const TBuiltInResource&) override; - bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; - virtual const char* getGlobalUniformBlockName() const override { return "$Global"; } - virtual void setUniformBlockDefaults(TType& block) const override - { - block.getQualifier().layoutPacking = globalUniformDefaults.layoutPacking; - block.getQualifier().layoutMatrix = globalUniformDefaults.layoutMatrix; - } - - void reservedPpErrorCheck(const TSourceLoc&, const char* /*name*/, const char* /*op*/) override { } - bool lineContinuationCheck(const TSourceLoc&, bool /*endOfComment*/) override { return true; } - bool lineDirectiveShouldSetNextLine() const override { return true; } - bool builtInName(const TString&); - - void handlePragma(const TSourceLoc&, const TVector&) override; - TIntermTyped* handleVariable(const TSourceLoc&, const TString* string); - TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); - TIntermTyped* handleBracketOperator(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); - - TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); - TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); - TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); - bool isBuiltInMethod(const TSourceLoc&, TIntermTyped* base, const TString& field); - void assignToInterface(TVariable& variable); - void handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); - TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&, const TAttributes&, TIntermNode*& entryPointTree); - TIntermNode* transformEntryPoint(const TSourceLoc&, TFunction&, const TAttributes&); - void handleEntryPointAttributes(const TSourceLoc&, const TAttributes&); - void transferTypeAttributes(const TSourceLoc&, const TAttributes&, TType&, bool allowEntry = false); - void handleFunctionBody(const TSourceLoc&, TFunction&, TIntermNode* functionBody, TIntermNode*& node); - void remapEntryPointIO(TFunction& function, TVariable*& returnValue, TVector& inputs, TVector& outputs); - void remapNonEntryPointIO(TFunction& function); - TIntermNode* handleDeclare(const TSourceLoc&, TIntermTyped*); - TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); - void handleFunctionArgument(TFunction*, TIntermTyped*& arguments, TIntermTyped* newArg); - TIntermTyped* handleAssign(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right); - TIntermTyped* handleAssignToMatrixSwizzle(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right); - TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermTyped*); - TIntermAggregate* assignClipCullDistance(const TSourceLoc&, TOperator, int semanticId, TIntermTyped* left, TIntermTyped* right); - TIntermTyped* assignPosition(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right); - TIntermTyped* assignFromFragCoord(const TSourceLoc&, TOperator, TIntermTyped* left, TIntermTyped* right); - void decomposeIntrinsic(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); - void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); - void decomposeStructBufferMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); - void decomposeGeometryMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); - void pushFrontArguments(TIntermTyped* front, TIntermTyped*& arguments); - void addInputArgumentConversions(const TFunction&, TIntermTyped*&); - void expandArguments(const TSourceLoc&, const TFunction&, TIntermTyped*&); - TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&); - void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); - TFunction* makeConstructorCall(const TSourceLoc&, const TType&); - void handleSemantic(TSourceLoc, TQualifier&, TBuiltInVariable, const TString& upperCase); - void handlePackOffset(const TSourceLoc&, TQualifier&, const glslang::TString& location, - const glslang::TString* component); - void handleRegister(const TSourceLoc&, TQualifier&, const glslang::TString* profile, const glslang::TString& desc, - int subComponent, const glslang::TString*); - TIntermTyped* convertConditionalExpression(const TSourceLoc&, TIntermTyped*, bool mustBeScalar = true); - TIntermAggregate* handleSamplerTextureCombine(const TSourceLoc& loc, TIntermTyped* argTex, TIntermTyped* argSampler); - - bool parseMatrixSwizzleSelector(const TSourceLoc&, const TString&, int cols, int rows, TSwizzleSelectors&); - int getMatrixComponentsColumn(int rows, const TSwizzleSelectors&); - void assignError(const TSourceLoc&, const char* op, TString left, TString right); - void unaryOpError(const TSourceLoc&, const char* op, TString operand); - void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); - void variableCheck(TIntermTyped*& nodePtr); - void constantValueCheck(TIntermTyped* node, const char* token); - void integerCheck(const TIntermTyped* node, const char* token); - void globalCheck(const TSourceLoc&, const char* token); - bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&); - void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&); - void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); - void structArrayCheck(const TSourceLoc&, const TType& structure); - bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); - void globalQualifierFix(const TSourceLoc&, TQualifier&); - bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); - void mergeQualifiers(TQualifier& dst, const TQualifier& src); - int computeSamplerTypeIndex(TSampler&); - TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&); - void paramFix(TType& type); - void specializationCheck(const TSourceLoc&, const TType&, const char* op); - - void setLayoutQualifier(const TSourceLoc&, TQualifier&, TString&); - void setLayoutQualifier(const TSourceLoc&, TQualifier&, TString&, const TIntermTyped*); - void setSpecConstantId(const TSourceLoc&, TQualifier&, int value); - void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); - void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); - - const TFunction* findFunction(const TSourceLoc& loc, TFunction& call, bool& builtIn, int& thisDepth, TIntermTyped*& args); - void addGenMulArgumentConversion(const TSourceLoc& loc, TFunction& call, TIntermTyped*& args); - void declareTypedef(const TSourceLoc&, const TString& identifier, const TType&); - void declareStruct(const TSourceLoc&, TString& structName, TType&); - TSymbol* lookupUserType(const TString&, TType&); - TIntermNode* declareVariable(const TSourceLoc&, const TString& identifier, TType&, TIntermTyped* initializer = nullptr); - void lengthenList(const TSourceLoc&, TIntermSequence& list, int size, TIntermTyped* scalarInit); - TIntermTyped* handleConstructor(const TSourceLoc&, TIntermTyped*, const TType&); - TIntermTyped* addConstructor(const TSourceLoc&, TIntermTyped*, const TType&); - TIntermTyped* convertArray(TIntermTyped*, const TType&); - TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); - TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); - void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = nullptr); - void declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name); - void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); - void fixXfbOffsets(TQualifier&, TTypeList&); - void fixBlockUniformOffsets(const TQualifier&, TTypeList&); - void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); - void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); - void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); - void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); - TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body, const TAttributes&); - - void nestLooping() { ++loopNestingLevel; } - void unnestLooping() { --loopNestingLevel; } - void nestAnnotations() { ++annotationNestingLevel; } - void unnestAnnotations() { --annotationNestingLevel; } - int getAnnotationNestingLevel() { return annotationNestingLevel; } - void pushScope() { symbolTable.push(); } - void popScope() { symbolTable.pop(nullptr); } - - void pushThisScope(const TType&, const TVector&); - void popThisScope() { symbolTable.pop(nullptr); } - - void pushImplicitThis(TVariable* thisParameter) { implicitThisStack.push_back(thisParameter); } - void popImplicitThis() { implicitThisStack.pop_back(); } - TVariable* getImplicitThis(int thisDepth) const { return implicitThisStack[implicitThisStack.size() - thisDepth]; } - - void pushNamespace(const TString& name); - void popNamespace(); - void getFullNamespaceName(TString*&) const; - void addScopeMangler(TString&); - - void beginParameterParsing(TFunction& function) - { - parsingEntrypointParameters = isEntrypointName(function.getName()); - } - - void pushSwitchSequence(TIntermSequence* sequence) { switchSequenceStack.push_back(sequence); } - void popSwitchSequence() { switchSequenceStack.pop_back(); } - - virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, - TTypeList* typeList = nullptr) override; - - // Apply L-value conversions. E.g, turning a write to a RWTexture into an ImageStore. - TIntermTyped* handleLvalue(const TSourceLoc&, const char* op, TIntermTyped*& node); - bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; - - TLayoutFormat getLayoutFromTxType(const TSourceLoc&, const TType&); - - bool handleOutputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry); - bool handleInputGeometry(const TSourceLoc&, const TLayoutGeometry& geometry); - - // Determine selection control from attributes - void handleSelectionAttributes(const TSourceLoc& loc, TIntermSelection*, const TAttributes& attributes); - void handleSwitchAttributes(const TSourceLoc& loc, TIntermSwitch*, const TAttributes& attributes); - - // Determine loop control from attributes - void handleLoopAttributes(const TSourceLoc& loc, TIntermLoop*, const TAttributes& attributes); - - // Share struct buffer deep types - void shareStructBufferType(TType&); - - // Set texture return type of the given sampler. Returns success (not all types are valid). - bool setTextureReturnType(TSampler& sampler, const TType& retType, const TSourceLoc& loc); - - // Obtain the sampler return type of the given sampler in retType. - void getTextureReturnType(const TSampler& sampler, TType& retType) const; - - TAttributeType attributeFromName(const TString& nameSpace, const TString& name) const; - -protected: - struct TFlattenData { - TFlattenData() : nextBinding(TQualifier::layoutBindingEnd), - nextLocation(TQualifier::layoutLocationEnd) { } - TFlattenData(int nb, int nl) : nextBinding(nb), nextLocation(nl) { } - - TVector members; // individual flattened variables - TVector offsets; // offset to next tree level - unsigned int nextBinding; // next binding to use. - unsigned int nextLocation; // next location to use - }; - - void fixConstInit(const TSourceLoc&, const TString& identifier, TType& type, TIntermTyped*& initializer); - void inheritGlobalDefaults(TQualifier& dst) const; - TVariable* makeInternalVariable(const char* name, const TType&) const; - TVariable* makeInternalVariable(const TString& name, const TType& type) const { - return makeInternalVariable(name.c_str(), type); - } - TIntermSymbol* makeInternalVariableNode(const TSourceLoc&, const char* name, const TType&) const; - TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&, bool track); - void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&, bool track); - TIntermNode* executeDeclaration(const TSourceLoc&, TVariable* variable); - TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable); - TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer, TIntermTyped* scalarInit); - bool isScalarConstructor(const TIntermNode*); - TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage); - bool isEntrypointName(const TString& name) { return name.compare(intermediate.getEntryPointName().c_str()) == 0; } - - // Return true if this node requires L-value conversion (e.g, to an imageStore). - bool shouldConvertLValue(const TIntermNode*) const; - - // Array and struct flattening - TIntermTyped* flattenAccess(TIntermTyped* base, int member); - TIntermTyped* flattenAccess(long long uniqueId, int member, TStorageQualifier outerStorage, const TType&, int subset = -1); - int findSubtreeOffset(const TIntermNode&) const; - int findSubtreeOffset(const TType&, int subset, const TVector& offsets) const; - bool shouldFlatten(const TType&, TStorageQualifier, bool topLevel) const; - bool wasFlattened(const TIntermTyped* node) const; - bool wasFlattened(long long id) const { return flattenMap.find(id) != flattenMap.end(); } - int addFlattenedMember(const TVariable&, const TType&, TFlattenData&, const TString& name, bool linkage, - const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes); - - // Structure splitting (splits interstage built-in types into its own struct) - void split(const TVariable&); - void splitBuiltIn(const TString& baseName, const TType& memberType, const TArraySizes*, const TQualifier&); - const TType& split(const TType& type, const TString& name, const TQualifier&); - bool wasSplit(const TIntermTyped* node) const; - bool wasSplit(long long id) const { return splitNonIoVars.find(id) != splitNonIoVars.end(); } - TVariable* getSplitNonIoVar(long long id) const; - void addPatchConstantInvocation(); - void fixTextureShadowModes(); - void finalizeAppendMethods(); - TIntermTyped* makeIntegerIndex(TIntermTyped*); - - void fixBuiltInIoType(TType&); - - void flatten(const TVariable& variable, bool linkage, bool arrayed = false); - int flatten(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage, - const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes); - int flattenStruct(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage, - const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes); - int flattenArray(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage, - const TQualifier& outerQualifier); - - bool hasUniform(const TQualifier& qualifier) const; - void clearUniform(TQualifier& qualifier); - bool isInputBuiltIn(const TQualifier& qualifier) const; - bool hasInput(const TQualifier& qualifier) const; - void correctOutput(TQualifier& qualifier); - bool isOutputBuiltIn(const TQualifier& qualifier) const; - bool hasOutput(const TQualifier& qualifier) const; - void correctInput(TQualifier& qualifier); - void correctUniform(TQualifier& qualifier); - void clearUniformInputOutput(TQualifier& qualifier); - - // Test method names - bool isStructBufferMethod(const TString& name) const; - void counterBufferType(const TSourceLoc& loc, TType& type); - - // Return standard sample position array - TIntermConstantUnion* getSamplePosArray(int count); - - TType* getStructBufferContentType(const TType& type) const; - bool isStructBufferType(const TType& type) const { return getStructBufferContentType(type) != nullptr; } - TIntermTyped* indexStructBufferContent(const TSourceLoc& loc, TIntermTyped* buffer) const; - TIntermTyped* getStructBufferCounter(const TSourceLoc& loc, TIntermTyped* buffer); - TString getStructBuffCounterName(const TString&) const; - void addStructBuffArguments(const TSourceLoc& loc, TIntermAggregate*&); - void addStructBufferHiddenCounterParam(const TSourceLoc& loc, TParameter&, TIntermAggregate*&); - - // Return true if this type is a reference. This is not currently a type method in case that's - // a language specific answer. - bool isReference(const TType& type) const { return isStructBufferType(type); } - - // Return true if this a buffer type that has an associated counter buffer. - bool hasStructBuffCounter(const TType&) const; - - // Finalization step: remove unused buffer blocks from linkage (we don't know until the - // shader is entirely compiled) - void removeUnusedStructBufferCounters(); - - static bool isClipOrCullDistance(TBuiltInVariable); - static bool isClipOrCullDistance(const TQualifier& qual) { return isClipOrCullDistance(qual.builtIn); } - static bool isClipOrCullDistance(const TType& type) { return isClipOrCullDistance(type.getQualifier()); } - - // Find the patch constant function (issues error, returns nullptr if not found) - const TFunction* findPatchConstantFunction(const TSourceLoc& loc); - - // Pass through to base class after remembering built-in mappings. - using TParseContextBase::trackLinkage; - void trackLinkage(TSymbol& variable) override; - - void finish() override; // post-processing - - // Linkage symbol helpers - TIntermSymbol* findTessLinkageSymbol(TBuiltInVariable biType) const; - - // Current state of parsing - int annotationNestingLevel; // 0 if outside all annotations - - HlslParseContext(HlslParseContext&); - HlslParseContext& operator=(HlslParseContext&); - - static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2)); // see computeSamplerTypeIndex() - TQualifier globalBufferDefaults; - TQualifier globalUniformDefaults; - TQualifier globalInputDefaults; - TQualifier globalOutputDefaults; - TString currentCaller; // name of last function body entered (not valid when at global scope) - TIdSetType inductiveLoopIds; - TVector needsIndexLimitationChecking; - - // - // Geometry shader input arrays: - // - array sizing is based on input primitive and/or explicit size - // - // Tessellation control output arrays: - // - array sizing is based on output layout(vertices=...) and/or explicit size - // - // Both: - // - array sizing is retroactive - // - built-in block redeclarations interact with this - // - // Design: - // - use a per-context "resize-list", a list of symbols whose array sizes - // can be fixed - // - // - the resize-list starts empty at beginning of user-shader compilation, it does - // not have built-ins in it - // - // - on built-in array use: copyUp() symbol and add it to the resize-list - // - // - on user array declaration: add it to the resize-list - // - // - on block redeclaration: copyUp() symbol and add it to the resize-list - // * note, that appropriately gives an error if redeclaring a block that - // was already used and hence already copied-up - // - // - on seeing a layout declaration that sizes the array, fix everything in the - // resize-list, giving errors for mismatch - // - // - on seeing an array size declaration, give errors on mismatch between it and previous - // array-sizing declarations - // - TVector ioArraySymbolResizeList; - - TMap flattenMap; - - // IO-type map. Maps a pure symbol-table form of a structure-member list into - // each of the (up to) three kinds of IO, as each as different allowed decorations, - // but HLSL allows mixing all in the same structure. - struct tIoKinds { - TTypeList* input; - TTypeList* output; - TTypeList* uniform; - }; - TMap ioTypeMap; - - // Structure splitting data: - TMap splitNonIoVars; // variables with the built-in interstage IO removed, indexed by unique ID. - - // Structuredbuffer shared types. Typically there are only a few. - TVector structBufferTypes; - - // This tracks texture sample user structure return types. Only a limited number are supported, as - // may fit in TSampler::structReturnIndex. - TVector textureReturnStruct; - - TMap structBufferCounter; // true if counter buffer is in use - - // The built-in interstage IO map considers e.g, EvqPosition on input and output separately, so that we - // can build the linkage correctly if position appears on both sides. Otherwise, multiple positions - // are considered identical. - struct tInterstageIoData { - tInterstageIoData(TBuiltInVariable bi, TStorageQualifier q) : - builtIn(bi), storage(q) { } - - TBuiltInVariable builtIn; - TStorageQualifier storage; - - // ordering for maps - bool operator<(const tInterstageIoData d) const { - return (builtIn != d.builtIn) ? (builtIn < d.builtIn) : (storage < d.storage); - } - }; - - TMap splitBuiltIns; // split built-ins, indexed by built-in type. - TVariable* inputPatch; // input patch is special for PCF: it's the only non-builtin PCF input, - // and is handled as a pseudo-builtin. - - unsigned int nextInLocation; - unsigned int nextOutLocation; - - TFunction* entryPointFunction; - TIntermNode* entryPointFunctionBody; - - TString patchConstantFunctionName; // hull shader patch constant function name, from function level attribute. - TMap builtInTessLinkageSymbols; // used for tessellation, finding declared built-ins - - TVector currentTypePrefix; // current scoping prefix for nested structures - TVector implicitThisStack; // currently active 'this' variables for nested structures - - TVariable* gsStreamOutput; // geometry shader stream outputs, for emit (Append method) - - TVariable* clipDistanceOutput; // synthesized clip distance out variable (shader might have >1) - TVariable* cullDistanceOutput; // synthesized cull distance out variable (shader might have >1) - TVariable* clipDistanceInput; // synthesized clip distance in variable (shader might have >1) - TVariable* cullDistanceInput; // synthesized cull distance in variable (shader might have >1) - - static const int maxClipCullRegs = 2; - std::array clipSemanticNSizeIn; // vector, indexed by clip semantic ID - std::array cullSemanticNSizeIn; // vector, indexed by cull semantic ID - std::array clipSemanticNSizeOut; // vector, indexed by clip semantic ID - std::array cullSemanticNSizeOut; // vector, indexed by cull semantic ID - - // This tracks the first (mip level) argument to the .mips[][] operator. Since this can be nested as - // in tx.mips[tx.mips[0][1].x][2], we need a stack. We also track the TSourceLoc for error reporting - // purposes. - struct tMipsOperatorData { - tMipsOperatorData(TSourceLoc l, TIntermTyped* m) : loc(l), mipLevel(m) { } - TSourceLoc loc; - TIntermTyped* mipLevel; - }; - - TVector mipsOperatorMipArg; - - // The geometry output stream is not copied out from the entry point as a typical output variable - // is. It's written via EmitVertex (hlsl=Append), which may happen in arbitrary control flow. - // For this we need the real output symbol. Since it may not be known at the time and Append() - // method is parsed, the sequence will be patched during finalization. - struct tGsAppendData { - TIntermAggregate* node; - TSourceLoc loc; - }; - - TVector gsAppends; - - // A texture object may be used with shadow and non-shadow samplers, but both may not be - // alive post-DCE in the same shader. We do not know at compilation time which are alive: that's - // only known post-DCE. If a texture is used both ways, we create two textures, and - // leave the elimiation of one to the optimizer. This maps the shader variant to - // the shadow variant. - // - // This can be removed if and when the texture shadow code in - // HlslParseContext::handleSamplerTextureCombine is removed. - struct tShadowTextureSymbols { - tShadowTextureSymbols() { symId.fill(-1); } - - void set(bool shadow, long long id) { symId[int(shadow)] = id; } - long long get(bool shadow) const { return symId[int(shadow)]; } - - // True if this texture has been seen with both shadow and non-shadow modes - bool overloaded() const { return symId[0] != -1 && symId[1] != -1; } - bool isShadowId(long long id) const { return symId[1] == id; } - - private: - std::array symId; - }; - - TMap textureShadowVariant; - bool parsingEntrypointParameters; -}; - -// This is the prefix we use for built-in methods to avoid namespace collisions with -// global scope user functions. -// TODO: this would be better as a nonparseable character, but that would -// require changing the scanner. -#define BUILTIN_PREFIX "__BI_" - -} // end namespace glslang - -#endif // HLSL_PARSE_INCLUDED_ diff --git a/3rdparty/glslang/glslang/HLSL/hlslParseables.cpp b/3rdparty/glslang/glslang/HLSL/hlslParseables.cpp deleted file mode 100644 index 8fb1d290..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslParseables.cpp +++ /dev/null @@ -1,1259 +0,0 @@ -// -// Copyright (C) 2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Create strings that declare built-in definitions, add built-ins programmatically -// that cannot be expressed in the strings, and establish mappings between -// built-in functions and operators. -// -// Where to put a built-in: -// TBuiltInParseablesHlsl::initialize(version,profile) context-independent textual built-ins; add them to the right string -// TBuiltInParseablesHlsl::initialize(resources,...) context-dependent textual built-ins; add them to the right string -// TBuiltInParseablesHlsl::identifyBuiltIns(...,symbolTable) context-independent programmatic additions/mappings to the symbol table, -// including identifying what extensions are needed if a version does not allow a symbol -// TBuiltInParseablesHlsl::identifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the -// symbol table, including identifying what extensions are needed if a version does -// not allow a symbol -// - -#include "hlslParseables.h" -#include "hlslParseHelper.h" -#include -#include -#include - -namespace { // anonymous namespace functions - -// arg order queries -bool IsSamplerType(const char argType) { return argType == 'S' || argType == 's'; } -bool IsArrayed(const char argOrder) { return argOrder == '@' || argOrder == '&' || argOrder == '#'; } -bool IsTextureNonMS(const char argOrder) { return argOrder == '%'; } -bool IsSubpassInput(const char argOrder) { return argOrder == '[' || argOrder == ']'; } -bool IsArrayedTexture(const char argOrder) { return argOrder == '@'; } -bool IsTextureMS(const char argOrder) { return argOrder == '$' || argOrder == '&'; } -bool IsMS(const char argOrder) { return IsTextureMS(argOrder) || argOrder == ']'; } -bool IsBuffer(const char argOrder) { return argOrder == '*' || argOrder == '~'; } -bool IsImage(const char argOrder) { return argOrder == '!' || argOrder == '#' || argOrder == '~'; } - -bool IsTextureType(const char argOrder) -{ - return IsTextureNonMS(argOrder) || IsArrayedTexture(argOrder) || - IsTextureMS(argOrder) || IsBuffer(argOrder) || IsImage(argOrder); -} - -// Reject certain combinations that are illegal sample methods. For example, -// 3D arrays. -bool IsIllegalSample(const glslang::TString& name, const char* argOrder, int dim0) -{ - const bool isArrayed = IsArrayed(*argOrder); - const bool isMS = IsTextureMS(*argOrder); - const bool isBuffer = IsBuffer(*argOrder); - - // there are no 3D arrayed textures, or 3D SampleCmp(LevelZero) - if (dim0 == 3 && (isArrayed || name == "SampleCmp" || name == "SampleCmpLevelZero")) - return true; - - const int numArgs = int(std::count(argOrder, argOrder + strlen(argOrder), ',')) + 1; - - // Reject invalid offset forms with cubemaps - if (dim0 == 4) { - if ((name == "Sample" && numArgs >= 4) || - (name == "SampleBias" && numArgs >= 5) || - (name == "SampleCmp" && numArgs >= 5) || - (name == "SampleCmpLevelZero" && numArgs >= 5) || - (name == "SampleGrad" && numArgs >= 6) || - (name == "SampleLevel" && numArgs >= 5)) - return true; - } - - const bool isGather = - (name == "Gather" || - name == "GatherRed" || - name == "GatherGreen" || - name == "GatherBlue" || - name == "GatherAlpha"); - - const bool isGatherCmp = - (name == "GatherCmp" || - name == "GatherCmpRed" || - name == "GatherCmpGreen" || - name == "GatherCmpBlue" || - name == "GatherCmpAlpha"); - - // Reject invalid Gathers - if (isGather || isGatherCmp) { - if (dim0 == 1 || dim0 == 3) // there are no 1D or 3D gathers - return true; - - // no offset on cube or cube array gathers - if (dim0 == 4) { - if ((isGather && numArgs > 3) || (isGatherCmp && numArgs > 4)) - return true; - } - } - - // Reject invalid Loads - if (name == "Load" && dim0 == 4) - return true; // Load does not support any cubemaps, arrayed or not. - - // Multisample formats are only 2D and 2Darray - if (isMS && dim0 != 2) - return true; - - // Buffer are only 1D - if (isBuffer && dim0 != 1) - return true; - - return false; -} - -// Return the number of the coordinate arg, if any -int CoordinateArgPos(const glslang::TString& name, bool isTexture) -{ - if (!isTexture || (name == "GetDimensions")) - return -1; // has none - else if (name == "Load") - return 1; - else - return 2; // other texture methods are 2 -} - -// Some texture methods use an addition coordinate dimension for the mip -bool HasMipInCoord(const glslang::TString& name, bool isMS, bool isBuffer, bool isImage) -{ - return name == "Load" && !isMS && !isBuffer && !isImage; -} - -// LOD calculations don't pass the array level in the coordinate. -bool NoArrayCoord(const glslang::TString& name) -{ - return name == "CalculateLevelOfDetail" || name == "CalculateLevelOfDetailUnclamped"; -} - -// Handle IO params marked with > or < -const char* IoParam(glslang::TString& s, const char* nthArgOrder) -{ - if (*nthArgOrder == '>') { // output params - ++nthArgOrder; - s.append("out "); - } else if (*nthArgOrder == '<') { // input params - ++nthArgOrder; - s.append("in "); - } - - return nthArgOrder; -} - -// Handle repeated args -void HandleRepeatArg(const char*& arg, const char*& prev, const char* current) -{ - if (*arg == ',' || *arg == '\0') - arg = prev; - else - prev = current; -} - -// Return true for the end of a single argument key, which can be the end of the string, or -// the comma separator. -inline bool IsEndOfArg(const char* arg) -{ - return arg == nullptr || *arg == '\0' || *arg == ','; -} - -// If this is a fixed vector size, such as V3, return the size. Else return 0. -int FixedVecSize(const char* arg) -{ - while (!IsEndOfArg(arg)) { - if (isdigit(*arg)) - return *arg - '0'; - ++arg; - } - - return 0; // none found. -} - -// Create and return a type name, using HLSL type conventions. -// -// order: S = scalar, V = vector, M = matrix -// argType: F = float, D = double, I = int, U = uint, B = bool, S = sampler -// dim0 = vector dimension, or matrix 1st dimension -// dim1 = matrix 2nd dimension -glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, const char* argType, int dim0, int dim1) -{ - const bool isTranspose = (argOrder[0] == '^'); - const bool isTexture = IsTextureType(argOrder[0]); - const bool isArrayed = IsArrayed(argOrder[0]); - const bool isSampler = IsSamplerType(argType[0]); - const bool isMS = IsMS(argOrder[0]); - const bool isBuffer = IsBuffer(argOrder[0]); - const bool isImage = IsImage(argOrder[0]); - const bool isSubpass = IsSubpassInput(argOrder[0]); - - char type = *argType; - - if (isTranspose) { // Take transpose of matrix dimensions - std::swap(dim0, dim1); - } else if (isTexture || isSubpass) { - if (type == 'F') // map base type to texture of that type. - type = 'T'; // e.g, int -> itexture, uint -> utexture, etc. - else if (type == 'I') - type = 'i'; - else if (type == 'U') - type = 'u'; - } - - if (isTranspose) - ++argOrder; - - char order = *argOrder; - - switch (type) { - case '-': s += "void"; break; - case 'F': s += "float"; break; - case 'D': s += "double"; break; - case 'I': s += "int"; break; - case 'U': s += "uint"; break; - case 'L': s += "int64_t"; break; - case 'M': s += "uint64_t"; break; - case 'B': s += "bool"; break; - case 'S': s += "sampler"; break; - case 's': s += "SamplerComparisonState"; break; - case 'T': s += ((isBuffer && isImage) ? "RWBuffer" : - isSubpass ? "SubpassInput" : - isBuffer ? "Buffer" : - isImage ? "RWTexture" : "Texture"); break; - case 'i': s += ((isBuffer && isImage) ? "RWBuffer" : - isSubpass ? "SubpassInput" : - isBuffer ? "Buffer" : - isImage ? "RWTexture" : "Texture"); break; - case 'u': s += ((isBuffer && isImage) ? "RWBuffer" : - isSubpass ? "SubpassInput" : - isBuffer ? "Buffer" : - isImage ? "RWTexture" : "Texture"); break; - default: s += "UNKNOWN_TYPE"; break; - } - - if (isSubpass && isMS) - s += "MS"; - - // handle fixed vector sizes, such as float3, and only ever 3. - const int fixedVecSize = FixedVecSize(argOrder); - if (fixedVecSize != 0) - dim0 = dim1 = fixedVecSize; - - const char dim0Char = ('0' + char(dim0)); - const char dim1Char = ('0' + char(dim1)); - - // Add sampler dimensions - if (isSampler || isTexture) { - if ((order == 'V' || isTexture) && !isBuffer) { - switch (dim0) { - case 1: s += "1D"; break; - case 2: s += (isMS ? "2DMS" : "2D"); break; - case 3: s += "3D"; break; - case 4: s += (type == 'S'? "CUBE" : "Cube"); break; - default: s += "UNKNOWN_SAMPLER"; break; - } - } - } else { - // Non-sampler type: - // verify dimensions - if (((order == 'V' || order == 'M') && (dim0 < 1 || dim0 > 4)) || - (order == 'M' && (dim1 < 1 || dim1 > 4))) { - s += "UNKNOWN_DIMENSION"; - return s; - } - - switch (order) { - case '-': break; // no dimensions for voids - case 'S': break; // no dimensions on scalars - case 'V': - s += dim0Char; - break; - case 'M': - s += dim0Char; - s += 'x'; - s += dim1Char; - break; - default: - break; - } - } - - // handle arrayed textures - if (isArrayed) - s += "Array"; - - switch (type) { - case 'i': s += " 0) // handle fixed sized vectors - dim0Min = dim0Max = fixedVecSize; -} - -} // end anonymous namespace - -namespace glslang { - -TBuiltInParseablesHlsl::TBuiltInParseablesHlsl() -{ -} - -// -// Handle creation of mat*mat specially, since it doesn't fall conveniently out of -// the generic prototype creation code below. -// -void TBuiltInParseablesHlsl::createMatTimesMat() -{ - TString& s = commonBuiltins; - - for (int xRows = 1; xRows <=4; xRows++) { - for (int xCols = 1; xCols <=4; xCols++) { - const int yRows = xCols; - for (int yCols = 1; yCols <=4; yCols++) { - const int retRows = xRows; - const int retCols = yCols; - - // Create a mat * mat of the appropriate dimensions - AppendTypeName(s, "M", "F", retRows, retCols); // add return type - s.append(" "); // space between type and name - s.append("mul"); // intrinsic name - s.append("("); // open paren - - AppendTypeName(s, "M", "F", xRows, xCols); // add X input - s.append(", "); - AppendTypeName(s, "M", "F", yRows, yCols); // add Y input - - s.append(");\n"); // close paren - } - - // Create M*V - AppendTypeName(s, "V", "F", xRows, 1); // add return type - s.append(" "); // space between type and name - s.append("mul"); // intrinsic name - s.append("("); // open paren - - AppendTypeName(s, "M", "F", xRows, xCols); // add X input - s.append(", "); - AppendTypeName(s, "V", "F", xCols, 1); // add Y input - - s.append(");\n"); // close paren - - // Create V*M - AppendTypeName(s, "V", "F", xCols, 1); // add return type - s.append(" "); // space between type and name - s.append("mul"); // intrinsic name - s.append("("); // open paren - - AppendTypeName(s, "V", "F", xRows, 1); // add Y input - s.append(", "); - AppendTypeName(s, "M", "F", xRows, xCols); // add X input - - s.append(");\n"); // close paren - } - } -} - -// -// Add all context-independent built-in functions and variables that are present -// for the given version and profile. Share common ones across stages, otherwise -// make stage-specific entries. -// -// Most built-ins variables can be added as simple text strings. Some need to -// be added programmatically, which is done later in IdentifyBuiltIns() below. -// -void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/) -{ - static const EShLanguageMask EShLangAll = EShLanguageMask(EShLangCount - 1); - - // These are the actual stage masks defined in the documentation, in case they are - // needed for future validation. For now, they are commented out, and set below - // to EShLangAll, to allow any intrinsic to be used in any shader, which is legal - // if it is not called. - // - // static const EShLanguageMask EShLangPSCS = EShLanguageMask(EShLangFragmentMask | EShLangComputeMask); - // static const EShLanguageMask EShLangVSPSGS = EShLanguageMask(EShLangVertexMask | EShLangFragmentMask | EShLangGeometryMask); - // static const EShLanguageMask EShLangCS = EShLangComputeMask; - // static const EShLanguageMask EShLangPS = EShLangFragmentMask; - // static const EShLanguageMask EShLangHS = EShLangTessControlMask; - - // This set uses EShLangAll for everything. - static const EShLanguageMask EShLangPSCS = EShLangAll; - static const EShLanguageMask EShLangVSPSGS = EShLangAll; - static const EShLanguageMask EShLangCS = EShLangAll; - static const EShLanguageMask EShLangPS = EShLangAll; - static const EShLanguageMask EShLangHS = EShLangAll; - static const EShLanguageMask EShLangGS = EShLangAll; - - // This structure encodes the prototype information for each HLSL intrinsic. - // Because explicit enumeration would be cumbersome, it's procedurally generated. - // orderKey can be: - // S = scalar, V = vector, M = matrix, - = void - // typekey can be: - // D = double, F = float, U = uint, I = int, B = bool, S = sampler, s = shadowSampler, M = uint64_t, L = int64_t - // An empty order or type key repeats the first one. E.g: SVM,, means 3 args each of SVM. - // '>' as first letter of order creates an output parameter - // '<' as first letter of order creates an input parameter - // '^' as first letter of order takes transpose dimensions - // '%' as first letter of order creates texture of given F/I/U type (texture, itexture, etc) - // '@' as first letter of order creates arrayed texture of given type - // '$' / '&' as first letter of order creates 2DMS / 2DMSArray textures - // '*' as first letter of order creates buffer object - // '!' as first letter of order creates image object - // '#' as first letter of order creates arrayed image object - // '~' as first letter of order creates an image buffer object - // '[' / ']' as first letter of order creates a SubpassInput/SubpassInputMS object - - static const struct { - const char* name; // intrinsic name - const char* retOrder; // return type key: empty matches order of 1st argument - const char* retType; // return type key: empty matches type of 1st argument - const char* argOrder; // argument order key - const char* argType; // argument type key - unsigned int stage; // stage mask - bool method; // true if it's a method. - } hlslIntrinsics[] = { - // name retOrd retType argOrder argType stage mask method - // ---------------------------------------------------------------------------------------------------------------- - { "abort", nullptr, nullptr, "-", "-", EShLangAll, false }, - { "abs", nullptr, nullptr, "SVM", "DFUI", EShLangAll, false }, - { "acos", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "all", "S", "B", "SVM", "BFIU", EShLangAll, false }, - { "AllMemoryBarrier", nullptr, nullptr, "-", "-", EShLangCS, false }, - { "AllMemoryBarrierWithGroupSync", nullptr, nullptr, "-", "-", EShLangCS, false }, - { "any", "S", "B", "SVM", "BFIU", EShLangAll, false }, - { "asdouble", "S", "D", "S,", "UI,", EShLangAll, false }, - { "asdouble", "V2", "D", "V2,", "UI,", EShLangAll, false }, - { "asfloat", nullptr, "F", "SVM", "BFIU", EShLangAll, false }, - { "asin", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "asint", nullptr, "I", "SVM", "FIU", EShLangAll, false }, - { "asuint", nullptr, "U", "SVM", "FIU", EShLangAll, false }, - { "atan", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "atan2", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - { "ceil", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "CheckAccessFullyMapped", "S", "B" , "S", "U", EShLangPSCS, false }, - { "clamp", nullptr, nullptr, "SVM,,", "FUI,,", EShLangAll, false }, - { "clip", "-", "-", "SVM", "FUI", EShLangPS, false }, - { "cos", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "cosh", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "countbits", nullptr, nullptr, "SV", "UI", EShLangAll, false }, - { "cross", nullptr, nullptr, "V3,", "F,", EShLangAll, false }, - { "D3DCOLORtoUBYTE4", "V4", "I", "V4", "F", EShLangAll, false }, - { "ddx", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "ddx_coarse", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "ddx_fine", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "ddy", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "ddy_coarse", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "ddy_fine", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "degrees", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "determinant", "S", "F", "M", "F", EShLangAll, false }, - { "DeviceMemoryBarrier", nullptr, nullptr, "-", "-", EShLangPSCS, false }, - { "DeviceMemoryBarrierWithGroupSync", nullptr, nullptr, "-", "-", EShLangCS, false }, - { "distance", "S", "F", "SV,", "F,", EShLangAll, false }, - { "dot", "S", nullptr, "SV,", "FI,", EShLangAll, false }, - { "dst", nullptr, nullptr, "V4,", "F,", EShLangAll, false }, - // { "errorf", "-", "-", "", "", EShLangAll, false }, TODO: varargs - { "EvaluateAttributeAtCentroid", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "EvaluateAttributeAtSample", nullptr, nullptr, "SVM,S", "F,U", EShLangPS, false }, - { "EvaluateAttributeSnapped", nullptr, nullptr, "SVM,V2", "F,I", EShLangPS, false }, - { "exp", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "exp2", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "f16tof32", nullptr, "F", "SV", "U", EShLangAll, false }, - { "f32tof16", nullptr, "U", "SV", "F", EShLangAll, false }, - { "faceforward", nullptr, nullptr, "V,,", "F,,", EShLangAll, false }, - { "firstbithigh", nullptr, nullptr, "SV", "UI", EShLangAll, false }, - { "firstbitlow", nullptr, nullptr, "SV", "UI", EShLangAll, false }, - { "floor", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "fma", nullptr, nullptr, "SVM,,", "D,,", EShLangAll, false }, - { "fmod", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - { "frac", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "frexp", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - { "fwidth", nullptr, nullptr, "SVM", "F", EShLangPS, false }, - { "GetRenderTargetSampleCount", "S", "U", "-", "-", EShLangAll, false }, - { "GetRenderTargetSamplePosition", "V2", "F", "V1", "I", EShLangAll, false }, - { "GroupMemoryBarrier", nullptr, nullptr, "-", "-", EShLangCS, false }, - { "GroupMemoryBarrierWithGroupSync", nullptr, nullptr, "-", "-", EShLangCS, false }, - { "InterlockedAdd", "-", "-", "SVM,,>", "FUI,,", EShLangPSCS, false }, - { "InterlockedAdd", "-", "-", "SVM,", "FUI,", EShLangPSCS, false }, - { "InterlockedAnd", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedAnd", "-", "-", "SVM,", "UI,", EShLangPSCS, false }, - { "InterlockedCompareExchange", "-", "-", "SVM,,,>", "UI,,,", EShLangPSCS, false }, - { "InterlockedCompareStore", "-", "-", "SVM,,", "UI,,", EShLangPSCS, false }, - { "InterlockedExchange", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedMax", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedMax", "-", "-", "SVM,", "UI,", EShLangPSCS, false }, - { "InterlockedMin", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedMin", "-", "-", "SVM,", "UI,", EShLangPSCS, false }, - { "InterlockedOr", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedOr", "-", "-", "SVM,", "UI,", EShLangPSCS, false }, - { "InterlockedXor", "-", "-", "SVM,,>", "UI,,", EShLangPSCS, false }, - { "InterlockedXor", "-", "-", "SVM,", "UI,", EShLangPSCS, false }, - { "isfinite", nullptr, "B" , "SVM", "F", EShLangAll, false }, - { "isinf", nullptr, "B" , "SVM", "F", EShLangAll, false }, - { "isnan", nullptr, "B" , "SVM", "F", EShLangAll, false }, - { "ldexp", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - { "length", "S", "F", "SV", "F", EShLangAll, false }, - { "lerp", nullptr, nullptr, "VM,,", "F,,", EShLangAll, false }, - { "lerp", nullptr, nullptr, "SVM,,S", "F,,", EShLangAll, false }, - { "lit", "V4", "F", "S,,", "F,,", EShLangAll, false }, - { "log", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "log10", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "log2", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "mad", nullptr, nullptr, "SVM,,", "DFUI,,", EShLangAll, false }, - { "max", nullptr, nullptr, "SVM,", "FIU,", EShLangAll, false }, - { "min", nullptr, nullptr, "SVM,", "FIU,", EShLangAll, false }, - { "modf", nullptr, nullptr, "SVM,>", "FIU,", EShLangAll, false }, - { "msad4", "V4", "U", "S,V2,V4", "U,,", EShLangAll, false }, - { "mul", "S", nullptr, "S,S", "FI,", EShLangAll, false }, - { "mul", "V", nullptr, "S,V", "FI,", EShLangAll, false }, - { "mul", "M", nullptr, "S,M", "FI,", EShLangAll, false }, - { "mul", "V", nullptr, "V,S", "FI,", EShLangAll, false }, - { "mul", "S", nullptr, "V,V", "FI,", EShLangAll, false }, - { "mul", "M", nullptr, "M,S", "FI,", EShLangAll, false }, - // mat*mat form of mul is handled in createMatTimesMat() - { "noise", "S", "F", "V", "F", EShLangPS, false }, - { "normalize", nullptr, nullptr, "V", "F", EShLangAll, false }, - { "pow", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - { "printf", nullptr, nullptr, "-", "-", EShLangAll, false }, - { "Process2DQuadTessFactorsAvg", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "Process2DQuadTessFactorsMax", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "Process2DQuadTessFactorsMin", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "ProcessIsolineTessFactors", "-", "-", "S,,>,>", "F,,,", EShLangHS, false }, - { "ProcessQuadTessFactorsAvg", "-", "-", "V4,S,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "ProcessQuadTessFactorsMax", "-", "-", "V4,S,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "ProcessQuadTessFactorsMin", "-", "-", "V4,S,>V4,>V2,", "F,,,,", EShLangHS, false }, - { "ProcessTriTessFactorsAvg", "-", "-", "V3,S,>V3,>S,", "F,,,,", EShLangHS, false }, - { "ProcessTriTessFactorsMax", "-", "-", "V3,S,>V3,>S,", "F,,,,", EShLangHS, false }, - { "ProcessTriTessFactorsMin", "-", "-", "V3,S,>V3,>S,", "F,,,,", EShLangHS, false }, - { "radians", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "rcp", nullptr, nullptr, "SVM", "FD", EShLangAll, false }, - { "reflect", nullptr, nullptr, "V,", "F,", EShLangAll, false }, - { "refract", nullptr, nullptr, "V,V,S", "F,,", EShLangAll, false }, - { "reversebits", nullptr, nullptr, "SV", "UI", EShLangAll, false }, - { "round", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "rsqrt", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "saturate", nullptr, nullptr , "SVM", "F", EShLangAll, false }, - { "sign", nullptr, nullptr, "SVM", "FI", EShLangAll, false }, - { "sin", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "sincos", "-", "-", "SVM,>,>", "F,,", EShLangAll, false }, - { "sinh", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "smoothstep", nullptr, nullptr, "SVM,,", "F,,", EShLangAll, false }, - { "sqrt", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "step", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, - { "tan", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "tanh", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - { "tex1D", "V4", "F", "S,S", "S,F", EShLangPS, false }, - { "tex1D", "V4", "F", "S,S,V1,", "S,F,,", EShLangPS, false }, - { "tex1Dbias", "V4", "F", "S,V4", "S,F", EShLangPS, false }, - { "tex1Dgrad", "V4", "F", "S,,,", "S,F,,", EShLangPS, false }, - { "tex1Dlod", "V4", "F", "S,V4", "S,F", EShLangPS, false }, - { "tex1Dproj", "V4", "F", "S,V4", "S,F", EShLangPS, false }, - { "tex2D", "V4", "F", "V2,", "S,F", EShLangPS, false }, - { "tex2D", "V4", "F", "V2,,,", "S,F,,", EShLangPS, false }, - { "tex2Dbias", "V4", "F", "V2,V4", "S,F", EShLangPS, false }, - { "tex2Dgrad", "V4", "F", "V2,,,", "S,F,,", EShLangPS, false }, - { "tex2Dlod", "V4", "F", "V2,V4", "S,F", EShLangAll, false }, - { "tex2Dproj", "V4", "F", "V2,V4", "S,F", EShLangPS, false }, - { "tex3D", "V4", "F", "V3,", "S,F", EShLangPS, false }, - { "tex3D", "V4", "F", "V3,,,", "S,F,,", EShLangPS, false }, - { "tex3Dbias", "V4", "F", "V3,V4", "S,F", EShLangPS, false }, - { "tex3Dgrad", "V4", "F", "V3,,,", "S,F,,", EShLangPS, false }, - { "tex3Dlod", "V4", "F", "V3,V4", "S,F", EShLangPS, false }, - { "tex3Dproj", "V4", "F", "V3,V4", "S,F", EShLangPS, false }, - { "texCUBE", "V4", "F", "V4,V3", "S,F", EShLangPS, false }, - { "texCUBE", "V4", "F", "V4,V3,,", "S,F,,", EShLangPS, false }, - { "texCUBEbias", "V4", "F", "V4,", "S,F", EShLangPS, false }, - { "texCUBEgrad", "V4", "F", "V4,V3,,", "S,F,,", EShLangPS, false }, - { "texCUBElod", "V4", "F", "V4,", "S,F", EShLangPS, false }, - { "texCUBEproj", "V4", "F", "V4,", "S,F", EShLangPS, false }, - { "transpose", "^M", nullptr, "M", "FUIB", EShLangAll, false }, - { "trunc", nullptr, nullptr, "SVM", "F", EShLangAll, false }, - - // Texture object methods. Return type can be overridden by shader declaration. - // !O = no offset, O = offset - { "Sample", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangPS, true }, - { "Sample", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangPS, true }, - - { "SampleBias", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,S,F,F", EShLangPS, true }, - { "SampleBias", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,S,F,F,I", EShLangPS, true }, - - // TODO: FXC accepts int/uint samplers here. unclear what that means. - { "SampleCmp", /*!O*/ "S", "F", "%@,S,V,S", "FIU,s,F,", EShLangPS, true }, - { "SampleCmp", /* O*/ "S", "F", "%@,S,V,S,V", "FIU,s,F,,I", EShLangPS, true }, - - // TODO: FXC accepts int/uint samplers here. unclear what that means. - { "SampleCmpLevelZero", /*!O*/ "S", "F", "%@,S,V,S", "FIU,s,F,F", EShLangPS, true }, - { "SampleCmpLevelZero", /* O*/ "S", "F", "%@,S,V,S,V", "FIU,s,F,F,I", EShLangPS, true }, - - { "SampleGrad", /*!O*/ "V4", nullptr, "%@,S,V,,", "FIU,S,F,,", EShLangAll, true }, - { "SampleGrad", /* O*/ "V4", nullptr, "%@,S,V,,,", "FIU,S,F,,,I", EShLangAll, true }, - - { "SampleLevel", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,S,F,", EShLangAll, true }, - { "SampleLevel", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,S,F,,I", EShLangAll, true }, - - { "Load", /*!O*/ "V4", nullptr, "%@,V", "FIU,I", EShLangAll, true }, - { "Load", /* O*/ "V4", nullptr, "%@,V,V", "FIU,I,I", EShLangAll, true }, - { "Load", /* +sampleidex*/ "V4", nullptr, "$&,V,S", "FIU,I,I", EShLangAll, true }, - { "Load", /* +samplindex, offset*/ "V4", nullptr, "$&,V,S,V", "FIU,I,I,I", EShLangAll, true }, - - // RWTexture loads - { "Load", "V4", nullptr, "!#,V", "FIU,I", EShLangAll, true }, - // (RW)Buffer loads - { "Load", "V4", nullptr, "~*1,V", "FIU,I", EShLangAll, true }, - - { "Gather", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangAll, true }, - { "Gather", /* O*/ "V4", nullptr, "%@,S,V,V", "FIU,S,F,I", EShLangAll, true }, - - { "CalculateLevelOfDetail", "S", "F", "%@,S,V", "FUI,S,F", EShLangPS, true }, - { "CalculateLevelOfDetailUnclamped", "S", "F", "%@,S,V", "FUI,S,F", EShLangPS, true }, - - { "GetSamplePosition", "V2", "F", "$&2,S", "FUI,I", EShLangVSPSGS,true }, - - // - // UINT Width - // UINT MipLevel, UINT Width, UINT NumberOfLevels - { "GetDimensions", /* 1D */ "-", "-", "%!~1,>S", "FUI,U", EShLangAll, true }, - { "GetDimensions", /* 1D */ "-", "-", "%!~1,>S", "FUI,F", EShLangAll, true }, - { "GetDimensions", /* 1D */ "-", "-", "%1,S,>S,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* 1D */ "-", "-", "%1,S,>S,", "FUI,U,F,", EShLangAll, true }, - - // UINT Width, UINT Elements - // UINT MipLevel, UINT Width, UINT Elements, UINT NumberOfLevels - { "GetDimensions", /* 1DArray */ "-", "-", "@#1,>S,", "FUI,U,", EShLangAll, true }, - { "GetDimensions", /* 1DArray */ "-", "-", "@#1,>S,", "FUI,F,", EShLangAll, true }, - { "GetDimensions", /* 1DArray */ "-", "-", "@1,S,>S,,", "FUI,U,,,", EShLangAll, true }, - { "GetDimensions", /* 1DArray */ "-", "-", "@1,S,>S,,", "FUI,U,F,,", EShLangAll, true }, - - // UINT Width, UINT Height - // UINT MipLevel, UINT Width, UINT Height, UINT NumberOfLevels - { "GetDimensions", /* 2D */ "-", "-", "%!2,>S,", "FUI,U,", EShLangAll, true }, - { "GetDimensions", /* 2D */ "-", "-", "%!2,>S,", "FUI,F,", EShLangAll, true }, - { "GetDimensions", /* 2D */ "-", "-", "%2,S,>S,,", "FUI,U,,,", EShLangAll, true }, - { "GetDimensions", /* 2D */ "-", "-", "%2,S,>S,,", "FUI,U,F,,", EShLangAll, true }, - - // UINT Width, UINT Height, UINT Elements - // UINT MipLevel, UINT Width, UINT Height, UINT Elements, UINT NumberOfLevels - { "GetDimensions", /* 2DArray */ "-", "-", "@#2,>S,,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* 2DArray */ "-", "-", "@#2,>S,,", "FUI,F,F,F", EShLangAll, true }, - { "GetDimensions", /* 2DArray */ "-", "-", "@2,S,>S,,,", "FUI,U,,,,", EShLangAll, true }, - { "GetDimensions", /* 2DArray */ "-", "-", "@2,S,>S,,,", "FUI,U,F,,,", EShLangAll, true }, - - // UINT Width, UINT Height, UINT Depth - // UINT MipLevel, UINT Width, UINT Height, UINT Depth, UINT NumberOfLevels - { "GetDimensions", /* 3D */ "-", "-", "%!3,>S,,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* 3D */ "-", "-", "%!3,>S,,", "FUI,F,,", EShLangAll, true }, - { "GetDimensions", /* 3D */ "-", "-", "%3,S,>S,,,", "FUI,U,,,,", EShLangAll, true }, - { "GetDimensions", /* 3D */ "-", "-", "%3,S,>S,,,", "FUI,U,F,,,", EShLangAll, true }, - - // UINT Width, UINT Height - // UINT MipLevel, UINT Width, UINT Height, UINT NumberOfLevels - { "GetDimensions", /* Cube */ "-", "-", "%4,>S,", "FUI,U,", EShLangAll, true }, - { "GetDimensions", /* Cube */ "-", "-", "%4,>S,", "FUI,F,", EShLangAll, true }, - { "GetDimensions", /* Cube */ "-", "-", "%4,S,>S,,", "FUI,U,,,", EShLangAll, true }, - { "GetDimensions", /* Cube */ "-", "-", "%4,S,>S,,", "FUI,U,F,,", EShLangAll, true }, - - // UINT Width, UINT Height, UINT Elements - // UINT MipLevel, UINT Width, UINT Height, UINT Elements, UINT NumberOfLevels - { "GetDimensions", /* CubeArray */ "-", "-", "@4,>S,,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* CubeArray */ "-", "-", "@4,>S,,", "FUI,F,,", EShLangAll, true }, - { "GetDimensions", /* CubeArray */ "-", "-", "@4,S,>S,,,", "FUI,U,,,,", EShLangAll, true }, - { "GetDimensions", /* CubeArray */ "-", "-", "@4,S,>S,,,", "FUI,U,F,,,", EShLangAll, true }, - - // UINT Width, UINT Height, UINT Samples - // UINT Width, UINT Height, UINT Elements, UINT Samples - { "GetDimensions", /* 2DMS */ "-", "-", "$2,>S,,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* 2DMS */ "-", "-", "$2,>S,,", "FUI,U,,", EShLangAll, true }, - { "GetDimensions", /* 2DMSArray */ "-", "-", "&2,>S,,,", "FUI,U,,,", EShLangAll, true }, - { "GetDimensions", /* 2DMSArray */ "-", "-", "&2,>S,,,", "FUI,U,,,", EShLangAll, true }, - - // SM5 texture methods - { "GatherRed", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangAll, true }, - { "GatherRed", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangAll, true }, - { "GatherRed", /* O, status*/ "V4", nullptr, "%@,S,V,,>S", "FIU,S,F,I,U", EShLangAll, true }, - { "GatherRed", /* O-4 */ "V4", nullptr, "%@,S,V,,,,", "FIU,S,F,I,,,", EShLangAll, true }, - { "GatherRed", /* O-4, status */"V4", nullptr, "%@,S,V,,,,,S", "FIU,S,F,I,,,,U", EShLangAll, true }, - - { "GatherGreen", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangAll, true }, - { "GatherGreen", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangAll, true }, - { "GatherGreen", /* O, status*/ "V4", nullptr, "%@,S,V,,>S", "FIU,S,F,I,U", EShLangAll, true }, - { "GatherGreen", /* O-4 */ "V4", nullptr, "%@,S,V,,,,", "FIU,S,F,I,,,", EShLangAll, true }, - { "GatherGreen", /* O-4, status */"V4", nullptr, "%@,S,V,,,,,S", "FIU,S,F,I,,,,U", EShLangAll, true }, - - { "GatherBlue", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangAll, true }, - { "GatherBlue", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangAll, true }, - { "GatherBlue", /* O, status*/ "V4", nullptr, "%@,S,V,,>S", "FIU,S,F,I,U", EShLangAll, true }, - { "GatherBlue", /* O-4 */ "V4", nullptr, "%@,S,V,,,,", "FIU,S,F,I,,,", EShLangAll, true }, - { "GatherBlue", /* O-4, status */"V4", nullptr, "%@,S,V,,,,,S", "FIU,S,F,I,,,,U", EShLangAll, true }, - - { "GatherAlpha", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangAll, true }, - { "GatherAlpha", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangAll, true }, - { "GatherAlpha", /* O, status*/ "V4", nullptr, "%@,S,V,,>S", "FIU,S,F,I,U", EShLangAll, true }, - { "GatherAlpha", /* O-4 */ "V4", nullptr, "%@,S,V,,,,", "FIU,S,F,I,,,", EShLangAll, true }, - { "GatherAlpha", /* O-4, status */"V4", nullptr, "%@,S,V,,,,,S", "FIU,S,F,I,,,,U", EShLangAll, true }, - - { "GatherCmp", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,s,F,", EShLangAll, true }, - { "GatherCmp", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,s,F,,I", EShLangAll, true }, - { "GatherCmp", /* O, status*/ "V4", nullptr, "%@,S,V,S,V,>S", "FIU,s,F,,I,U", EShLangAll, true }, - { "GatherCmp", /* O-4 */ "V4", nullptr, "%@,S,V,S,V,,,", "FIU,s,F,,I,,,", EShLangAll, true }, - { "GatherCmp", /* O-4, status */"V4", nullptr, "%@,S,V,S,V,,V,S","FIU,s,F,,I,,,,U",EShLangAll, true }, - - { "GatherCmpRed", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,s,F,", EShLangAll, true }, - { "GatherCmpRed", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,s,F,,I", EShLangAll, true }, - { "GatherCmpRed", /* O, status*/ "V4", nullptr, "%@,S,V,S,V,>S", "FIU,s,F,,I,U", EShLangAll, true }, - { "GatherCmpRed", /* O-4 */ "V4", nullptr, "%@,S,V,S,V,,,", "FIU,s,F,,I,,,", EShLangAll, true }, - { "GatherCmpRed", /* O-4, status */"V4", nullptr, "%@,S,V,S,V,,V,S","FIU,s,F,,I,,,,U",EShLangAll, true }, - - { "GatherCmpGreen", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,s,F,", EShLangAll, true }, - { "GatherCmpGreen", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,s,F,,I", EShLangAll, true }, - { "GatherCmpGreen", /* O, status*/ "V4", nullptr, "%@,S,V,S,V,>S", "FIU,s,F,,I,U", EShLangAll, true }, - { "GatherCmpGreen", /* O-4 */ "V4", nullptr, "%@,S,V,S,V,,,", "FIU,s,F,,I,,,", EShLangAll, true }, - { "GatherCmpGreen", /* O-4, status */"V4", nullptr, "%@,S,V,S,V,,,,S","FIU,s,F,,I,,,,U",EShLangAll, true }, - - { "GatherCmpBlue", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,s,F,", EShLangAll, true }, - { "GatherCmpBlue", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,s,F,,I", EShLangAll, true }, - { "GatherCmpBlue", /* O, status*/ "V4", nullptr, "%@,S,V,S,V,>S", "FIU,s,F,,I,U", EShLangAll, true }, - { "GatherCmpBlue", /* O-4 */ "V4", nullptr, "%@,S,V,S,V,,,", "FIU,s,F,,I,,,", EShLangAll, true }, - { "GatherCmpBlue", /* O-4, status */"V4", nullptr, "%@,S,V,S,V,,,,S","FIU,s,F,,I,,,,U",EShLangAll, true }, - - { "GatherCmpAlpha", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,s,F,", EShLangAll, true }, - { "GatherCmpAlpha", /* O*/ "V4", nullptr, "%@,S,V,S,V", "FIU,s,F,,I", EShLangAll, true }, - { "GatherCmpAlpha", /* O, status*/ "V4", nullptr, "%@,S,V,S,V,>S", "FIU,s,F,,I,U", EShLangAll, true }, - { "GatherCmpAlpha", /* O-4 */ "V4", nullptr, "%@,S,V,S,V,,,", "FIU,s,F,,I,,,", EShLangAll, true }, - { "GatherCmpAlpha", /* O-4, status */"V4", nullptr, "%@,S,V,S,V,,,,S","FIU,s,F,,I,,,,U",EShLangAll, true }, - - // geometry methods - { "Append", "-", "-", "-", "-", EShLangGS , true }, - { "RestartStrip", "-", "-", "-", "-", EShLangGS , true }, - - // Methods for structurebuffers. TODO: wildcard type matching. - { "Load", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Load2", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Load3", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Load4", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Store", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Store2", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Store3", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Store4", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "GetDimensions", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedAdd", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedAnd", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedCompareExchange", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedCompareStore", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedExchange", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedMax", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedMin", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedOr", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "InterlockedXor", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "IncrementCounter", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "DecrementCounter", nullptr, nullptr, "-", "-", EShLangAll, true }, - { "Consume", nullptr, nullptr, "-", "-", EShLangAll, true }, - - // SM 6.0 - - { "WaveIsFirstLane", "S", "B", "-", "-", EShLangPSCS, false}, - { "WaveGetLaneCount", "S", "U", "-", "-", EShLangPSCS, false}, - { "WaveGetLaneIndex", "S", "U", "-", "-", EShLangPSCS, false}, - { "WaveActiveAnyTrue", "S", "B", "S", "B", EShLangPSCS, false}, - { "WaveActiveAllTrue", "S", "B", "S", "B", EShLangPSCS, false}, - { "WaveActiveBallot", "V4", "U", "S", "B", EShLangPSCS, false}, - { "WaveReadLaneAt", nullptr, nullptr, "SV,S", "DFUI,U", EShLangPSCS, false}, - { "WaveReadLaneFirst", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveAllEqual", "S", "B", "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveAllEqualBool", "S", "B", "S", "B", EShLangPSCS, false}, - { "WaveActiveCountBits", "S", "U", "S", "B", EShLangPSCS, false}, - - { "WaveActiveSum", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveProduct", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveBitAnd", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveBitOr", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveBitXor", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveMin", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WaveActiveMax", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WavePrefixSum", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WavePrefixProduct", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "WavePrefixCountBits", "S", "U", "S", "B", EShLangPSCS, false}, - { "QuadReadAcrossX", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "QuadReadAcrossY", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "QuadReadAcrossDiagonal", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, - { "QuadReadLaneAt", nullptr, nullptr, "SV,S", "DFUI,U", EShLangPSCS, false}, - - // Methods for subpass input objects - { "SubpassLoad", "V4", nullptr, "[", "FIU", EShLangPS, true }, - { "SubpassLoad", "V4", nullptr, "],S", "FIU,I", EShLangPS, true }, - - // Mark end of list, since we want to avoid a range-based for, as some compilers don't handle it yet. - { nullptr, nullptr, nullptr, nullptr, nullptr, 0, false }, - }; - - // Create prototypes for the intrinsics. TODO: Avoid ranged based for until all compilers can handle it. - for (int icount = 0; hlslIntrinsics[icount].name; ++icount) { - const auto& intrinsic = hlslIntrinsics[icount]; - - for (int stage = 0; stage < EShLangCount; ++stage) { // for each stage... - if ((intrinsic.stage & (1< 0 ? std::min(dim0, 3) : dim0; - - s.append(arg > 0 ? ", ": ""); // comma separator if needed - - const char* orderBegin = nthArgOrder; - nthArgOrder = IoParam(s, nthArgOrder); - - // Comma means use the previous argument order and type. - HandleRepeatArg(nthArgOrder, prevArgOrder, orderBegin); - HandleRepeatArg(nthArgType, prevArgType, nthArgType); - - // In case the repeated arg has its own I/O marker - nthArgOrder = IoParam(s, nthArgOrder); - - // arrayed textures have one extra coordinate dimension, except for - // the CalculateLevelOfDetail family. - if (isArrayed && arg == coordArg && !NoArrayCoord(intrinsic.name)) - argDim0++; - - // Some texture methods use an addition arg dimension to hold mip - if (arg == coordArg && mipInCoord) - argDim0++; - - // For textures, the 1D case isn't a 1-vector, but a scalar. - if (isTexture && argDim0 == 1 && arg > 0 && *nthArgOrder == 'V') - nthArgOrder = "S"; - - AppendTypeName(s, nthArgOrder, nthArgType, argDim0, dim1); // Add arguments - } - - s.append(");\n"); // close paren and trailing semicolon - } // dim 1 loop - } // dim 0 loop - } // arg type loop - - // skip over special characters - if (isTexture && isalpha(argOrder[1])) - ++argOrder; - if (isdigit(argOrder[1])) - ++argOrder; - } // arg order loop - - if (intrinsic.stage == EShLangAll) // common builtins are only added once. - break; - } - } - - createMatTimesMat(); // handle this case separately, for convenience - - // printf("Common:\n%s\n", getCommonString().c_str()); - // printf("Frag:\n%s\n", getStageString(EShLangFragment).c_str()); - // printf("Vertex:\n%s\n", getStageString(EShLangVertex).c_str()); - // printf("Geo:\n%s\n", getStageString(EShLangGeometry).c_str()); - // printf("TessCtrl:\n%s\n", getStageString(EShLangTessControl).c_str()); - // printf("TessEval:\n%s\n", getStageString(EShLangTessEvaluation).c_str()); - // printf("Compute:\n%s\n", getStageString(EShLangCompute).c_str()); -} - -// -// Add context-dependent built-in functions and variables that are present -// for the given version and profile. All the results are put into just the -// commonBuiltins, because it is called for just a specific stage. So, -// add stage-specific entries to the commonBuiltins, and only if that stage -// was requested. -// -void TBuiltInParseablesHlsl::initialize(const TBuiltInResource& /*resources*/, int /*version*/, EProfile /*profile*/, - const SpvVersion& /*spvVersion*/, EShLanguage /*language*/) -{ -} - -// -// Finish adding/processing context-independent built-in symbols. -// 1) Programmatically add symbols that could not be added by simple text strings above. -// 2) Map built-in functions to operators, for those that will turn into an operation node -// instead of remaining a function call. -// 3) Tag extension-related symbols added to their base version with their extensions, so -// that if an early version has the extension turned off, there is an error reported on use. -// -void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/, EShLanguage /*language*/, - TSymbolTable& symbolTable) -{ - // symbolTable.relateToOperator("abort", EOpAbort); - symbolTable.relateToOperator("abs", EOpAbs); - symbolTable.relateToOperator("acos", EOpAcos); - symbolTable.relateToOperator("all", EOpAll); - symbolTable.relateToOperator("AllMemoryBarrier", EOpMemoryBarrier); - symbolTable.relateToOperator("AllMemoryBarrierWithGroupSync", EOpAllMemoryBarrierWithGroupSync); - symbolTable.relateToOperator("any", EOpAny); - symbolTable.relateToOperator("asdouble", EOpAsDouble); - symbolTable.relateToOperator("asfloat", EOpIntBitsToFloat); - symbolTable.relateToOperator("asin", EOpAsin); - symbolTable.relateToOperator("asint", EOpFloatBitsToInt); - symbolTable.relateToOperator("asuint", EOpFloatBitsToUint); - symbolTable.relateToOperator("atan", EOpAtan); - symbolTable.relateToOperator("atan2", EOpAtan); - symbolTable.relateToOperator("ceil", EOpCeil); - // symbolTable.relateToOperator("CheckAccessFullyMapped"); - symbolTable.relateToOperator("clamp", EOpClamp); - symbolTable.relateToOperator("clip", EOpClip); - symbolTable.relateToOperator("cos", EOpCos); - symbolTable.relateToOperator("cosh", EOpCosh); - symbolTable.relateToOperator("countbits", EOpBitCount); - symbolTable.relateToOperator("cross", EOpCross); - symbolTable.relateToOperator("D3DCOLORtoUBYTE4", EOpD3DCOLORtoUBYTE4); - symbolTable.relateToOperator("ddx", EOpDPdx); - symbolTable.relateToOperator("ddx_coarse", EOpDPdxCoarse); - symbolTable.relateToOperator("ddx_fine", EOpDPdxFine); - symbolTable.relateToOperator("ddy", EOpDPdy); - symbolTable.relateToOperator("ddy_coarse", EOpDPdyCoarse); - symbolTable.relateToOperator("ddy_fine", EOpDPdyFine); - symbolTable.relateToOperator("degrees", EOpDegrees); - symbolTable.relateToOperator("determinant", EOpDeterminant); - symbolTable.relateToOperator("DeviceMemoryBarrier", EOpDeviceMemoryBarrier); - symbolTable.relateToOperator("DeviceMemoryBarrierWithGroupSync", EOpDeviceMemoryBarrierWithGroupSync); - symbolTable.relateToOperator("distance", EOpDistance); - symbolTable.relateToOperator("dot", EOpDot); - symbolTable.relateToOperator("dst", EOpDst); - // symbolTable.relateToOperator("errorf", EOpErrorf); - symbolTable.relateToOperator("EvaluateAttributeAtCentroid", EOpInterpolateAtCentroid); - symbolTable.relateToOperator("EvaluateAttributeAtSample", EOpInterpolateAtSample); - symbolTable.relateToOperator("EvaluateAttributeSnapped", EOpEvaluateAttributeSnapped); - symbolTable.relateToOperator("exp", EOpExp); - symbolTable.relateToOperator("exp2", EOpExp2); - symbolTable.relateToOperator("f16tof32", EOpF16tof32); - symbolTable.relateToOperator("f32tof16", EOpF32tof16); - symbolTable.relateToOperator("faceforward", EOpFaceForward); - symbolTable.relateToOperator("firstbithigh", EOpFindMSB); - symbolTable.relateToOperator("firstbitlow", EOpFindLSB); - symbolTable.relateToOperator("floor", EOpFloor); - symbolTable.relateToOperator("fma", EOpFma); - symbolTable.relateToOperator("fmod", EOpMod); - symbolTable.relateToOperator("frac", EOpFract); - symbolTable.relateToOperator("frexp", EOpFrexp); - symbolTable.relateToOperator("fwidth", EOpFwidth); - // symbolTable.relateToOperator("GetRenderTargetSampleCount"); - // symbolTable.relateToOperator("GetRenderTargetSamplePosition"); - symbolTable.relateToOperator("GroupMemoryBarrier", EOpWorkgroupMemoryBarrier); - symbolTable.relateToOperator("GroupMemoryBarrierWithGroupSync", EOpWorkgroupMemoryBarrierWithGroupSync); - symbolTable.relateToOperator("InterlockedAdd", EOpInterlockedAdd); - symbolTable.relateToOperator("InterlockedAnd", EOpInterlockedAnd); - symbolTable.relateToOperator("InterlockedCompareExchange", EOpInterlockedCompareExchange); - symbolTable.relateToOperator("InterlockedCompareStore", EOpInterlockedCompareStore); - symbolTable.relateToOperator("InterlockedExchange", EOpInterlockedExchange); - symbolTable.relateToOperator("InterlockedMax", EOpInterlockedMax); - symbolTable.relateToOperator("InterlockedMin", EOpInterlockedMin); - symbolTable.relateToOperator("InterlockedOr", EOpInterlockedOr); - symbolTable.relateToOperator("InterlockedXor", EOpInterlockedXor); - symbolTable.relateToOperator("isfinite", EOpIsFinite); - symbolTable.relateToOperator("isinf", EOpIsInf); - symbolTable.relateToOperator("isnan", EOpIsNan); - symbolTable.relateToOperator("ldexp", EOpLdexp); - symbolTable.relateToOperator("length", EOpLength); - symbolTable.relateToOperator("lerp", EOpMix); - symbolTable.relateToOperator("lit", EOpLit); - symbolTable.relateToOperator("log", EOpLog); - symbolTable.relateToOperator("log10", EOpLog10); - symbolTable.relateToOperator("log2", EOpLog2); - symbolTable.relateToOperator("mad", EOpFma); - symbolTable.relateToOperator("max", EOpMax); - symbolTable.relateToOperator("min", EOpMin); - symbolTable.relateToOperator("modf", EOpModf); - // symbolTable.relateToOperator("msad4", EOpMsad4); - symbolTable.relateToOperator("mul", EOpGenMul); - // symbolTable.relateToOperator("noise", EOpNoise); // TODO: check return type - symbolTable.relateToOperator("normalize", EOpNormalize); - symbolTable.relateToOperator("pow", EOpPow); - symbolTable.relateToOperator("printf", EOpDebugPrintf); - // symbolTable.relateToOperator("Process2DQuadTessFactorsAvg"); - // symbolTable.relateToOperator("Process2DQuadTessFactorsMax"); - // symbolTable.relateToOperator("Process2DQuadTessFactorsMin"); - // symbolTable.relateToOperator("ProcessIsolineTessFactors"); - // symbolTable.relateToOperator("ProcessQuadTessFactorsAvg"); - // symbolTable.relateToOperator("ProcessQuadTessFactorsMax"); - // symbolTable.relateToOperator("ProcessQuadTessFactorsMin"); - // symbolTable.relateToOperator("ProcessTriTessFactorsAvg"); - // symbolTable.relateToOperator("ProcessTriTessFactorsMax"); - // symbolTable.relateToOperator("ProcessTriTessFactorsMin"); - symbolTable.relateToOperator("radians", EOpRadians); - symbolTable.relateToOperator("rcp", EOpRcp); - symbolTable.relateToOperator("reflect", EOpReflect); - symbolTable.relateToOperator("refract", EOpRefract); - symbolTable.relateToOperator("reversebits", EOpBitFieldReverse); - symbolTable.relateToOperator("round", EOpRound); - symbolTable.relateToOperator("rsqrt", EOpInverseSqrt); - symbolTable.relateToOperator("saturate", EOpSaturate); - symbolTable.relateToOperator("sign", EOpSign); - symbolTable.relateToOperator("sin", EOpSin); - symbolTable.relateToOperator("sincos", EOpSinCos); - symbolTable.relateToOperator("sinh", EOpSinh); - symbolTable.relateToOperator("smoothstep", EOpSmoothStep); - symbolTable.relateToOperator("sqrt", EOpSqrt); - symbolTable.relateToOperator("step", EOpStep); - symbolTable.relateToOperator("tan", EOpTan); - symbolTable.relateToOperator("tanh", EOpTanh); - symbolTable.relateToOperator("tex1D", EOpTexture); - symbolTable.relateToOperator("tex1Dbias", EOpTextureBias); - symbolTable.relateToOperator("tex1Dgrad", EOpTextureGrad); - symbolTable.relateToOperator("tex1Dlod", EOpTextureLod); - symbolTable.relateToOperator("tex1Dproj", EOpTextureProj); - symbolTable.relateToOperator("tex2D", EOpTexture); - symbolTable.relateToOperator("tex2Dbias", EOpTextureBias); - symbolTable.relateToOperator("tex2Dgrad", EOpTextureGrad); - symbolTable.relateToOperator("tex2Dlod", EOpTextureLod); - symbolTable.relateToOperator("tex2Dproj", EOpTextureProj); - symbolTable.relateToOperator("tex3D", EOpTexture); - symbolTable.relateToOperator("tex3Dbias", EOpTextureBias); - symbolTable.relateToOperator("tex3Dgrad", EOpTextureGrad); - symbolTable.relateToOperator("tex3Dlod", EOpTextureLod); - symbolTable.relateToOperator("tex3Dproj", EOpTextureProj); - symbolTable.relateToOperator("texCUBE", EOpTexture); - symbolTable.relateToOperator("texCUBEbias", EOpTextureBias); - symbolTable.relateToOperator("texCUBEgrad", EOpTextureGrad); - symbolTable.relateToOperator("texCUBElod", EOpTextureLod); - symbolTable.relateToOperator("texCUBEproj", EOpTextureProj); - symbolTable.relateToOperator("transpose", EOpTranspose); - symbolTable.relateToOperator("trunc", EOpTrunc); - - // Texture methods - symbolTable.relateToOperator(BUILTIN_PREFIX "Sample", EOpMethodSample); - symbolTable.relateToOperator(BUILTIN_PREFIX "SampleBias", EOpMethodSampleBias); - symbolTable.relateToOperator(BUILTIN_PREFIX "SampleCmp", EOpMethodSampleCmp); - symbolTable.relateToOperator(BUILTIN_PREFIX "SampleCmpLevelZero", EOpMethodSampleCmpLevelZero); - symbolTable.relateToOperator(BUILTIN_PREFIX "SampleGrad", EOpMethodSampleGrad); - symbolTable.relateToOperator(BUILTIN_PREFIX "SampleLevel", EOpMethodSampleLevel); - symbolTable.relateToOperator(BUILTIN_PREFIX "Load", EOpMethodLoad); - symbolTable.relateToOperator(BUILTIN_PREFIX "GetDimensions", EOpMethodGetDimensions); - symbolTable.relateToOperator(BUILTIN_PREFIX "GetSamplePosition", EOpMethodGetSamplePosition); - symbolTable.relateToOperator(BUILTIN_PREFIX "Gather", EOpMethodGather); - symbolTable.relateToOperator(BUILTIN_PREFIX "CalculateLevelOfDetail", EOpMethodCalculateLevelOfDetail); - symbolTable.relateToOperator(BUILTIN_PREFIX "CalculateLevelOfDetailUnclamped", EOpMethodCalculateLevelOfDetailUnclamped); - - // Structure buffer methods (excluding associations already made above for texture methods w/ same name) - symbolTable.relateToOperator(BUILTIN_PREFIX "Load2", EOpMethodLoad2); - symbolTable.relateToOperator(BUILTIN_PREFIX "Load3", EOpMethodLoad3); - symbolTable.relateToOperator(BUILTIN_PREFIX "Load4", EOpMethodLoad4); - symbolTable.relateToOperator(BUILTIN_PREFIX "Store", EOpMethodStore); - symbolTable.relateToOperator(BUILTIN_PREFIX "Store2", EOpMethodStore2); - symbolTable.relateToOperator(BUILTIN_PREFIX "Store3", EOpMethodStore3); - symbolTable.relateToOperator(BUILTIN_PREFIX "Store4", EOpMethodStore4); - symbolTable.relateToOperator(BUILTIN_PREFIX "IncrementCounter", EOpMethodIncrementCounter); - symbolTable.relateToOperator(BUILTIN_PREFIX "DecrementCounter", EOpMethodDecrementCounter); - // Append is also a GS method: we don't add it twice - symbolTable.relateToOperator(BUILTIN_PREFIX "Consume", EOpMethodConsume); - - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedAdd", EOpInterlockedAdd); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedAnd", EOpInterlockedAnd); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedCompareExchange", EOpInterlockedCompareExchange); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedCompareStore", EOpInterlockedCompareStore); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedExchange", EOpInterlockedExchange); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedMax", EOpInterlockedMax); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedMin", EOpInterlockedMin); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedOr", EOpInterlockedOr); - symbolTable.relateToOperator(BUILTIN_PREFIX "InterlockedXor", EOpInterlockedXor); - - // SM5 Texture methods - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherRed", EOpMethodGatherRed); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherGreen", EOpMethodGatherGreen); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherBlue", EOpMethodGatherBlue); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherAlpha", EOpMethodGatherAlpha); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmp", EOpMethodGatherCmpRed); // alias - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpRed", EOpMethodGatherCmpRed); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpGreen", EOpMethodGatherCmpGreen); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpBlue", EOpMethodGatherCmpBlue); - symbolTable.relateToOperator(BUILTIN_PREFIX "GatherCmpAlpha", EOpMethodGatherCmpAlpha); - - // GS methods - symbolTable.relateToOperator(BUILTIN_PREFIX "Append", EOpMethodAppend); - symbolTable.relateToOperator(BUILTIN_PREFIX "RestartStrip", EOpMethodRestartStrip); - - // Wave ops - symbolTable.relateToOperator("WaveIsFirstLane", EOpSubgroupElect); - symbolTable.relateToOperator("WaveGetLaneCount", EOpWaveGetLaneCount); - symbolTable.relateToOperator("WaveGetLaneIndex", EOpWaveGetLaneIndex); - symbolTable.relateToOperator("WaveActiveAnyTrue", EOpSubgroupAny); - symbolTable.relateToOperator("WaveActiveAllTrue", EOpSubgroupAll); - symbolTable.relateToOperator("WaveActiveBallot", EOpSubgroupBallot); - symbolTable.relateToOperator("WaveReadLaneFirst", EOpSubgroupBroadcastFirst); - symbolTable.relateToOperator("WaveReadLaneAt", EOpSubgroupShuffle); - symbolTable.relateToOperator("WaveActiveAllEqual", EOpSubgroupAllEqual); - symbolTable.relateToOperator("WaveActiveAllEqualBool", EOpSubgroupAllEqual); - symbolTable.relateToOperator("WaveActiveCountBits", EOpWaveActiveCountBits); - symbolTable.relateToOperator("WaveActiveSum", EOpSubgroupAdd); - symbolTable.relateToOperator("WaveActiveProduct", EOpSubgroupMul); - symbolTable.relateToOperator("WaveActiveBitAnd", EOpSubgroupAnd); - symbolTable.relateToOperator("WaveActiveBitOr", EOpSubgroupOr); - symbolTable.relateToOperator("WaveActiveBitXor", EOpSubgroupXor); - symbolTable.relateToOperator("WaveActiveMin", EOpSubgroupMin); - symbolTable.relateToOperator("WaveActiveMax", EOpSubgroupMax); - symbolTable.relateToOperator("WavePrefixSum", EOpSubgroupInclusiveAdd); - symbolTable.relateToOperator("WavePrefixProduct", EOpSubgroupInclusiveMul); - symbolTable.relateToOperator("WavePrefixCountBits", EOpWavePrefixCountBits); - symbolTable.relateToOperator("QuadReadAcrossX", EOpSubgroupQuadSwapHorizontal); - symbolTable.relateToOperator("QuadReadAcrossY", EOpSubgroupQuadSwapVertical); - symbolTable.relateToOperator("QuadReadAcrossDiagonal", EOpSubgroupQuadSwapDiagonal); - symbolTable.relateToOperator("QuadReadLaneAt", EOpSubgroupQuadBroadcast); - - // Subpass input methods - symbolTable.relateToOperator(BUILTIN_PREFIX "SubpassLoad", EOpSubpassLoad); - symbolTable.relateToOperator(BUILTIN_PREFIX "SubpassLoadMS", EOpSubpassLoadMS); -} - -// -// Add context-dependent (resource-specific) built-ins not handled by the above. These -// would be ones that need to be programmatically added because they cannot -// be added by simple text strings. For these, also -// 1) Map built-in functions to operators, for those that will turn into an operation node -// instead of remaining a function call. -// 2) Tag extension-related symbols added to their base version with their extensions, so -// that if an early version has the extension turned off, there is an error reported on use. -// -void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profile*/, const SpvVersion& /*spvVersion*/, EShLanguage /*language*/, - TSymbolTable& /*symbolTable*/, const TBuiltInResource& /*resources*/) -{ -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/HLSL/hlslParseables.h b/3rdparty/glslang/glslang/HLSL/hlslParseables.h deleted file mode 100644 index a4aef6c3..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslParseables.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright (C) 2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _HLSLPARSEABLES_INCLUDED_ -#define _HLSLPARSEABLES_INCLUDED_ - -#include "../MachineIndependent/Initialize.h" - -namespace glslang { - -// -// This is an HLSL specific derivation of TBuiltInParseables. See comment -// above TBuiltInParseables for details. -// -class TBuiltInParseablesHlsl : public TBuiltInParseables { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - TBuiltInParseablesHlsl(); - void initialize(int version, EProfile, const SpvVersion& spvVersion); - void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage); - - void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable); - - void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources); - -private: - void createMatTimesMat(); -}; - -} // end namespace glslang - -#endif // _HLSLPARSEABLES_INCLUDED_ diff --git a/3rdparty/glslang/glslang/HLSL/hlslScanContext.cpp b/3rdparty/glslang/glslang/HLSL/hlslScanContext.cpp deleted file mode 100644 index e9edb619..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslScanContext.cpp +++ /dev/null @@ -1,1064 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// Copyright (C) 2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// HLSL scanning, leveraging the scanning done by the preprocessor. -// - -#include -#include -#include - -#include "../Include/Types.h" -#include "../MachineIndependent/SymbolTable.h" -#include "../MachineIndependent/ParseHelper.h" -#include "hlslScanContext.h" -#include "hlslTokens.h" - -// preprocessor includes -#include "../MachineIndependent/preprocessor/PpContext.h" -#include "../MachineIndependent/preprocessor/PpTokens.h" - -namespace { - -struct str_eq -{ - bool operator()(const char* lhs, const char* rhs) const - { - return strcmp(lhs, rhs) == 0; - } -}; - -struct str_hash -{ - size_t operator()(const char* str) const - { - // djb2 - unsigned long hash = 5381; - int c; - - while ((c = *str++) != 0) - hash = ((hash << 5) + hash) + c; - - return hash; - } -}; - -// A single global usable by all threads, by all versions, by all languages. -// After a single process-level initialization, this is read only and thread safe -std::unordered_map* KeywordMap = nullptr; -std::unordered_set* ReservedSet = nullptr; -std::unordered_map* SemanticMap = nullptr; - -}; - -namespace glslang { - -void HlslScanContext::fillInKeywordMap() -{ - if (KeywordMap != nullptr) { - // this is really an error, as this should called only once per process - // but, the only risk is if two threads called simultaneously - return; - } - KeywordMap = new std::unordered_map; - - (*KeywordMap)["static"] = EHTokStatic; - (*KeywordMap)["const"] = EHTokConst; - (*KeywordMap)["unorm"] = EHTokUnorm; - (*KeywordMap)["snorm"] = EHTokSNorm; - (*KeywordMap)["extern"] = EHTokExtern; - (*KeywordMap)["uniform"] = EHTokUniform; - (*KeywordMap)["volatile"] = EHTokVolatile; - (*KeywordMap)["precise"] = EHTokPrecise; - (*KeywordMap)["shared"] = EHTokShared; - (*KeywordMap)["groupshared"] = EHTokGroupShared; - (*KeywordMap)["linear"] = EHTokLinear; - (*KeywordMap)["centroid"] = EHTokCentroid; - (*KeywordMap)["nointerpolation"] = EHTokNointerpolation; - (*KeywordMap)["noperspective"] = EHTokNoperspective; - (*KeywordMap)["sample"] = EHTokSample; - (*KeywordMap)["row_major"] = EHTokRowMajor; - (*KeywordMap)["column_major"] = EHTokColumnMajor; - (*KeywordMap)["packoffset"] = EHTokPackOffset; - (*KeywordMap)["in"] = EHTokIn; - (*KeywordMap)["out"] = EHTokOut; - (*KeywordMap)["inout"] = EHTokInOut; - (*KeywordMap)["layout"] = EHTokLayout; - (*KeywordMap)["globallycoherent"] = EHTokGloballyCoherent; - (*KeywordMap)["inline"] = EHTokInline; - - (*KeywordMap)["point"] = EHTokPoint; - (*KeywordMap)["line"] = EHTokLine; - (*KeywordMap)["triangle"] = EHTokTriangle; - (*KeywordMap)["lineadj"] = EHTokLineAdj; - (*KeywordMap)["triangleadj"] = EHTokTriangleAdj; - - (*KeywordMap)["PointStream"] = EHTokPointStream; - (*KeywordMap)["LineStream"] = EHTokLineStream; - (*KeywordMap)["TriangleStream"] = EHTokTriangleStream; - - (*KeywordMap)["InputPatch"] = EHTokInputPatch; - (*KeywordMap)["OutputPatch"] = EHTokOutputPatch; - - (*KeywordMap)["Buffer"] = EHTokBuffer; - (*KeywordMap)["vector"] = EHTokVector; - (*KeywordMap)["matrix"] = EHTokMatrix; - - (*KeywordMap)["void"] = EHTokVoid; - (*KeywordMap)["string"] = EHTokString; - (*KeywordMap)["bool"] = EHTokBool; - (*KeywordMap)["int"] = EHTokInt; - (*KeywordMap)["uint"] = EHTokUint; - (*KeywordMap)["uint64_t"] = EHTokUint64; - (*KeywordMap)["dword"] = EHTokDword; - (*KeywordMap)["half"] = EHTokHalf; - (*KeywordMap)["float"] = EHTokFloat; - (*KeywordMap)["double"] = EHTokDouble; - (*KeywordMap)["min16float"] = EHTokMin16float; - (*KeywordMap)["min10float"] = EHTokMin10float; - (*KeywordMap)["min16int"] = EHTokMin16int; - (*KeywordMap)["min12int"] = EHTokMin12int; - (*KeywordMap)["min16uint"] = EHTokMin16uint; - - (*KeywordMap)["bool1"] = EHTokBool1; - (*KeywordMap)["bool2"] = EHTokBool2; - (*KeywordMap)["bool3"] = EHTokBool3; - (*KeywordMap)["bool4"] = EHTokBool4; - (*KeywordMap)["float1"] = EHTokFloat1; - (*KeywordMap)["float2"] = EHTokFloat2; - (*KeywordMap)["float3"] = EHTokFloat3; - (*KeywordMap)["float4"] = EHTokFloat4; - (*KeywordMap)["int1"] = EHTokInt1; - (*KeywordMap)["int2"] = EHTokInt2; - (*KeywordMap)["int3"] = EHTokInt3; - (*KeywordMap)["int4"] = EHTokInt4; - (*KeywordMap)["double1"] = EHTokDouble1; - (*KeywordMap)["double2"] = EHTokDouble2; - (*KeywordMap)["double3"] = EHTokDouble3; - (*KeywordMap)["double4"] = EHTokDouble4; - (*KeywordMap)["uint1"] = EHTokUint1; - (*KeywordMap)["uint2"] = EHTokUint2; - (*KeywordMap)["uint3"] = EHTokUint3; - (*KeywordMap)["uint4"] = EHTokUint4; - - (*KeywordMap)["half1"] = EHTokHalf1; - (*KeywordMap)["half2"] = EHTokHalf2; - (*KeywordMap)["half3"] = EHTokHalf3; - (*KeywordMap)["half4"] = EHTokHalf4; - (*KeywordMap)["min16float1"] = EHTokMin16float1; - (*KeywordMap)["min16float2"] = EHTokMin16float2; - (*KeywordMap)["min16float3"] = EHTokMin16float3; - (*KeywordMap)["min16float4"] = EHTokMin16float4; - (*KeywordMap)["min10float1"] = EHTokMin10float1; - (*KeywordMap)["min10float2"] = EHTokMin10float2; - (*KeywordMap)["min10float3"] = EHTokMin10float3; - (*KeywordMap)["min10float4"] = EHTokMin10float4; - (*KeywordMap)["min16int1"] = EHTokMin16int1; - (*KeywordMap)["min16int2"] = EHTokMin16int2; - (*KeywordMap)["min16int3"] = EHTokMin16int3; - (*KeywordMap)["min16int4"] = EHTokMin16int4; - (*KeywordMap)["min12int1"] = EHTokMin12int1; - (*KeywordMap)["min12int2"] = EHTokMin12int2; - (*KeywordMap)["min12int3"] = EHTokMin12int3; - (*KeywordMap)["min12int4"] = EHTokMin12int4; - (*KeywordMap)["min16uint1"] = EHTokMin16uint1; - (*KeywordMap)["min16uint2"] = EHTokMin16uint2; - (*KeywordMap)["min16uint3"] = EHTokMin16uint3; - (*KeywordMap)["min16uint4"] = EHTokMin16uint4; - - (*KeywordMap)["bool1x1"] = EHTokBool1x1; - (*KeywordMap)["bool1x2"] = EHTokBool1x2; - (*KeywordMap)["bool1x3"] = EHTokBool1x3; - (*KeywordMap)["bool1x4"] = EHTokBool1x4; - (*KeywordMap)["bool2x1"] = EHTokBool2x1; - (*KeywordMap)["bool2x2"] = EHTokBool2x2; - (*KeywordMap)["bool2x3"] = EHTokBool2x3; - (*KeywordMap)["bool2x4"] = EHTokBool2x4; - (*KeywordMap)["bool3x1"] = EHTokBool3x1; - (*KeywordMap)["bool3x2"] = EHTokBool3x2; - (*KeywordMap)["bool3x3"] = EHTokBool3x3; - (*KeywordMap)["bool3x4"] = EHTokBool3x4; - (*KeywordMap)["bool4x1"] = EHTokBool4x1; - (*KeywordMap)["bool4x2"] = EHTokBool4x2; - (*KeywordMap)["bool4x3"] = EHTokBool4x3; - (*KeywordMap)["bool4x4"] = EHTokBool4x4; - (*KeywordMap)["int1x1"] = EHTokInt1x1; - (*KeywordMap)["int1x2"] = EHTokInt1x2; - (*KeywordMap)["int1x3"] = EHTokInt1x3; - (*KeywordMap)["int1x4"] = EHTokInt1x4; - (*KeywordMap)["int2x1"] = EHTokInt2x1; - (*KeywordMap)["int2x2"] = EHTokInt2x2; - (*KeywordMap)["int2x3"] = EHTokInt2x3; - (*KeywordMap)["int2x4"] = EHTokInt2x4; - (*KeywordMap)["int3x1"] = EHTokInt3x1; - (*KeywordMap)["int3x2"] = EHTokInt3x2; - (*KeywordMap)["int3x3"] = EHTokInt3x3; - (*KeywordMap)["int3x4"] = EHTokInt3x4; - (*KeywordMap)["int4x1"] = EHTokInt4x1; - (*KeywordMap)["int4x2"] = EHTokInt4x2; - (*KeywordMap)["int4x3"] = EHTokInt4x3; - (*KeywordMap)["int4x4"] = EHTokInt4x4; - (*KeywordMap)["uint1x1"] = EHTokUint1x1; - (*KeywordMap)["uint1x2"] = EHTokUint1x2; - (*KeywordMap)["uint1x3"] = EHTokUint1x3; - (*KeywordMap)["uint1x4"] = EHTokUint1x4; - (*KeywordMap)["uint2x1"] = EHTokUint2x1; - (*KeywordMap)["uint2x2"] = EHTokUint2x2; - (*KeywordMap)["uint2x3"] = EHTokUint2x3; - (*KeywordMap)["uint2x4"] = EHTokUint2x4; - (*KeywordMap)["uint3x1"] = EHTokUint3x1; - (*KeywordMap)["uint3x2"] = EHTokUint3x2; - (*KeywordMap)["uint3x3"] = EHTokUint3x3; - (*KeywordMap)["uint3x4"] = EHTokUint3x4; - (*KeywordMap)["uint4x1"] = EHTokUint4x1; - (*KeywordMap)["uint4x2"] = EHTokUint4x2; - (*KeywordMap)["uint4x3"] = EHTokUint4x3; - (*KeywordMap)["uint4x4"] = EHTokUint4x4; - (*KeywordMap)["bool1x1"] = EHTokBool1x1; - (*KeywordMap)["bool1x2"] = EHTokBool1x2; - (*KeywordMap)["bool1x3"] = EHTokBool1x3; - (*KeywordMap)["bool1x4"] = EHTokBool1x4; - (*KeywordMap)["bool2x1"] = EHTokBool2x1; - (*KeywordMap)["bool2x2"] = EHTokBool2x2; - (*KeywordMap)["bool2x3"] = EHTokBool2x3; - (*KeywordMap)["bool2x4"] = EHTokBool2x4; - (*KeywordMap)["bool3x1"] = EHTokBool3x1; - (*KeywordMap)["bool3x2"] = EHTokBool3x2; - (*KeywordMap)["bool3x3"] = EHTokBool3x3; - (*KeywordMap)["bool3x4"] = EHTokBool3x4; - (*KeywordMap)["bool4x1"] = EHTokBool4x1; - (*KeywordMap)["bool4x2"] = EHTokBool4x2; - (*KeywordMap)["bool4x3"] = EHTokBool4x3; - (*KeywordMap)["bool4x4"] = EHTokBool4x4; - (*KeywordMap)["float1x1"] = EHTokFloat1x1; - (*KeywordMap)["float1x2"] = EHTokFloat1x2; - (*KeywordMap)["float1x3"] = EHTokFloat1x3; - (*KeywordMap)["float1x4"] = EHTokFloat1x4; - (*KeywordMap)["float2x1"] = EHTokFloat2x1; - (*KeywordMap)["float2x2"] = EHTokFloat2x2; - (*KeywordMap)["float2x3"] = EHTokFloat2x3; - (*KeywordMap)["float2x4"] = EHTokFloat2x4; - (*KeywordMap)["float3x1"] = EHTokFloat3x1; - (*KeywordMap)["float3x2"] = EHTokFloat3x2; - (*KeywordMap)["float3x3"] = EHTokFloat3x3; - (*KeywordMap)["float3x4"] = EHTokFloat3x4; - (*KeywordMap)["float4x1"] = EHTokFloat4x1; - (*KeywordMap)["float4x2"] = EHTokFloat4x2; - (*KeywordMap)["float4x3"] = EHTokFloat4x3; - (*KeywordMap)["float4x4"] = EHTokFloat4x4; - (*KeywordMap)["half1x1"] = EHTokHalf1x1; - (*KeywordMap)["half1x2"] = EHTokHalf1x2; - (*KeywordMap)["half1x3"] = EHTokHalf1x3; - (*KeywordMap)["half1x4"] = EHTokHalf1x4; - (*KeywordMap)["half2x1"] = EHTokHalf2x1; - (*KeywordMap)["half2x2"] = EHTokHalf2x2; - (*KeywordMap)["half2x3"] = EHTokHalf2x3; - (*KeywordMap)["half2x4"] = EHTokHalf2x4; - (*KeywordMap)["half3x1"] = EHTokHalf3x1; - (*KeywordMap)["half3x2"] = EHTokHalf3x2; - (*KeywordMap)["half3x3"] = EHTokHalf3x3; - (*KeywordMap)["half3x4"] = EHTokHalf3x4; - (*KeywordMap)["half4x1"] = EHTokHalf4x1; - (*KeywordMap)["half4x2"] = EHTokHalf4x2; - (*KeywordMap)["half4x3"] = EHTokHalf4x3; - (*KeywordMap)["half4x4"] = EHTokHalf4x4; - (*KeywordMap)["double1x1"] = EHTokDouble1x1; - (*KeywordMap)["double1x2"] = EHTokDouble1x2; - (*KeywordMap)["double1x3"] = EHTokDouble1x3; - (*KeywordMap)["double1x4"] = EHTokDouble1x4; - (*KeywordMap)["double2x1"] = EHTokDouble2x1; - (*KeywordMap)["double2x2"] = EHTokDouble2x2; - (*KeywordMap)["double2x3"] = EHTokDouble2x3; - (*KeywordMap)["double2x4"] = EHTokDouble2x4; - (*KeywordMap)["double3x1"] = EHTokDouble3x1; - (*KeywordMap)["double3x2"] = EHTokDouble3x2; - (*KeywordMap)["double3x3"] = EHTokDouble3x3; - (*KeywordMap)["double3x4"] = EHTokDouble3x4; - (*KeywordMap)["double4x1"] = EHTokDouble4x1; - (*KeywordMap)["double4x2"] = EHTokDouble4x2; - (*KeywordMap)["double4x3"] = EHTokDouble4x3; - (*KeywordMap)["double4x4"] = EHTokDouble4x4; - (*KeywordMap)["min16float1x1"] = EHTokMin16float1x1; - (*KeywordMap)["min16float1x2"] = EHTokMin16float1x2; - (*KeywordMap)["min16float1x3"] = EHTokMin16float1x3; - (*KeywordMap)["min16float1x4"] = EHTokMin16float1x4; - (*KeywordMap)["min16float2x1"] = EHTokMin16float2x1; - (*KeywordMap)["min16float2x2"] = EHTokMin16float2x2; - (*KeywordMap)["min16float2x3"] = EHTokMin16float2x3; - (*KeywordMap)["min16float2x4"] = EHTokMin16float2x4; - (*KeywordMap)["min16float3x1"] = EHTokMin16float3x1; - (*KeywordMap)["min16float3x2"] = EHTokMin16float3x2; - (*KeywordMap)["min16float3x3"] = EHTokMin16float3x3; - (*KeywordMap)["min16float3x4"] = EHTokMin16float3x4; - (*KeywordMap)["min16float4x1"] = EHTokMin16float4x1; - (*KeywordMap)["min16float4x2"] = EHTokMin16float4x2; - (*KeywordMap)["min16float4x3"] = EHTokMin16float4x3; - (*KeywordMap)["min16float4x4"] = EHTokMin16float4x4; - (*KeywordMap)["min10float1x1"] = EHTokMin10float1x1; - (*KeywordMap)["min10float1x2"] = EHTokMin10float1x2; - (*KeywordMap)["min10float1x3"] = EHTokMin10float1x3; - (*KeywordMap)["min10float1x4"] = EHTokMin10float1x4; - (*KeywordMap)["min10float2x1"] = EHTokMin10float2x1; - (*KeywordMap)["min10float2x2"] = EHTokMin10float2x2; - (*KeywordMap)["min10float2x3"] = EHTokMin10float2x3; - (*KeywordMap)["min10float2x4"] = EHTokMin10float2x4; - (*KeywordMap)["min10float3x1"] = EHTokMin10float3x1; - (*KeywordMap)["min10float3x2"] = EHTokMin10float3x2; - (*KeywordMap)["min10float3x3"] = EHTokMin10float3x3; - (*KeywordMap)["min10float3x4"] = EHTokMin10float3x4; - (*KeywordMap)["min10float4x1"] = EHTokMin10float4x1; - (*KeywordMap)["min10float4x2"] = EHTokMin10float4x2; - (*KeywordMap)["min10float4x3"] = EHTokMin10float4x3; - (*KeywordMap)["min10float4x4"] = EHTokMin10float4x4; - (*KeywordMap)["min16int1x1"] = EHTokMin16int1x1; - (*KeywordMap)["min16int1x2"] = EHTokMin16int1x2; - (*KeywordMap)["min16int1x3"] = EHTokMin16int1x3; - (*KeywordMap)["min16int1x4"] = EHTokMin16int1x4; - (*KeywordMap)["min16int2x1"] = EHTokMin16int2x1; - (*KeywordMap)["min16int2x2"] = EHTokMin16int2x2; - (*KeywordMap)["min16int2x3"] = EHTokMin16int2x3; - (*KeywordMap)["min16int2x4"] = EHTokMin16int2x4; - (*KeywordMap)["min16int3x1"] = EHTokMin16int3x1; - (*KeywordMap)["min16int3x2"] = EHTokMin16int3x2; - (*KeywordMap)["min16int3x3"] = EHTokMin16int3x3; - (*KeywordMap)["min16int3x4"] = EHTokMin16int3x4; - (*KeywordMap)["min16int4x1"] = EHTokMin16int4x1; - (*KeywordMap)["min16int4x2"] = EHTokMin16int4x2; - (*KeywordMap)["min16int4x3"] = EHTokMin16int4x3; - (*KeywordMap)["min16int4x4"] = EHTokMin16int4x4; - (*KeywordMap)["min12int1x1"] = EHTokMin12int1x1; - (*KeywordMap)["min12int1x2"] = EHTokMin12int1x2; - (*KeywordMap)["min12int1x3"] = EHTokMin12int1x3; - (*KeywordMap)["min12int1x4"] = EHTokMin12int1x4; - (*KeywordMap)["min12int2x1"] = EHTokMin12int2x1; - (*KeywordMap)["min12int2x2"] = EHTokMin12int2x2; - (*KeywordMap)["min12int2x3"] = EHTokMin12int2x3; - (*KeywordMap)["min12int2x4"] = EHTokMin12int2x4; - (*KeywordMap)["min12int3x1"] = EHTokMin12int3x1; - (*KeywordMap)["min12int3x2"] = EHTokMin12int3x2; - (*KeywordMap)["min12int3x3"] = EHTokMin12int3x3; - (*KeywordMap)["min12int3x4"] = EHTokMin12int3x4; - (*KeywordMap)["min12int4x1"] = EHTokMin12int4x1; - (*KeywordMap)["min12int4x2"] = EHTokMin12int4x2; - (*KeywordMap)["min12int4x3"] = EHTokMin12int4x3; - (*KeywordMap)["min12int4x4"] = EHTokMin12int4x4; - (*KeywordMap)["min16uint1x1"] = EHTokMin16uint1x1; - (*KeywordMap)["min16uint1x2"] = EHTokMin16uint1x2; - (*KeywordMap)["min16uint1x3"] = EHTokMin16uint1x3; - (*KeywordMap)["min16uint1x4"] = EHTokMin16uint1x4; - (*KeywordMap)["min16uint2x1"] = EHTokMin16uint2x1; - (*KeywordMap)["min16uint2x2"] = EHTokMin16uint2x2; - (*KeywordMap)["min16uint2x3"] = EHTokMin16uint2x3; - (*KeywordMap)["min16uint2x4"] = EHTokMin16uint2x4; - (*KeywordMap)["min16uint3x1"] = EHTokMin16uint3x1; - (*KeywordMap)["min16uint3x2"] = EHTokMin16uint3x2; - (*KeywordMap)["min16uint3x3"] = EHTokMin16uint3x3; - (*KeywordMap)["min16uint3x4"] = EHTokMin16uint3x4; - (*KeywordMap)["min16uint4x1"] = EHTokMin16uint4x1; - (*KeywordMap)["min16uint4x2"] = EHTokMin16uint4x2; - (*KeywordMap)["min16uint4x3"] = EHTokMin16uint4x3; - (*KeywordMap)["min16uint4x4"] = EHTokMin16uint4x4; - - (*KeywordMap)["sampler"] = EHTokSampler; - (*KeywordMap)["sampler1D"] = EHTokSampler1d; - (*KeywordMap)["sampler2D"] = EHTokSampler2d; - (*KeywordMap)["sampler3D"] = EHTokSampler3d; - (*KeywordMap)["samplerCUBE"] = EHTokSamplerCube; - (*KeywordMap)["sampler_state"] = EHTokSamplerState; - (*KeywordMap)["SamplerState"] = EHTokSamplerState; - (*KeywordMap)["SamplerComparisonState"] = EHTokSamplerComparisonState; - (*KeywordMap)["texture"] = EHTokTexture; - (*KeywordMap)["Texture1D"] = EHTokTexture1d; - (*KeywordMap)["Texture1DArray"] = EHTokTexture1darray; - (*KeywordMap)["Texture2D"] = EHTokTexture2d; - (*KeywordMap)["Texture2DArray"] = EHTokTexture2darray; - (*KeywordMap)["Texture3D"] = EHTokTexture3d; - (*KeywordMap)["TextureCube"] = EHTokTextureCube; - (*KeywordMap)["TextureCubeArray"] = EHTokTextureCubearray; - (*KeywordMap)["Texture2DMS"] = EHTokTexture2DMS; - (*KeywordMap)["Texture2DMSArray"] = EHTokTexture2DMSarray; - (*KeywordMap)["RWTexture1D"] = EHTokRWTexture1d; - (*KeywordMap)["RWTexture1DArray"] = EHTokRWTexture1darray; - (*KeywordMap)["RWTexture2D"] = EHTokRWTexture2d; - (*KeywordMap)["RWTexture2DArray"] = EHTokRWTexture2darray; - (*KeywordMap)["RWTexture3D"] = EHTokRWTexture3d; - (*KeywordMap)["RWBuffer"] = EHTokRWBuffer; - (*KeywordMap)["SubpassInput"] = EHTokSubpassInput; - (*KeywordMap)["SubpassInputMS"] = EHTokSubpassInputMS; - - (*KeywordMap)["AppendStructuredBuffer"] = EHTokAppendStructuredBuffer; - (*KeywordMap)["ByteAddressBuffer"] = EHTokByteAddressBuffer; - (*KeywordMap)["ConsumeStructuredBuffer"] = EHTokConsumeStructuredBuffer; - (*KeywordMap)["RWByteAddressBuffer"] = EHTokRWByteAddressBuffer; - (*KeywordMap)["RWStructuredBuffer"] = EHTokRWStructuredBuffer; - (*KeywordMap)["StructuredBuffer"] = EHTokStructuredBuffer; - (*KeywordMap)["TextureBuffer"] = EHTokTextureBuffer; - - (*KeywordMap)["class"] = EHTokClass; - (*KeywordMap)["struct"] = EHTokStruct; - (*KeywordMap)["cbuffer"] = EHTokCBuffer; - (*KeywordMap)["ConstantBuffer"] = EHTokConstantBuffer; - (*KeywordMap)["tbuffer"] = EHTokTBuffer; - (*KeywordMap)["typedef"] = EHTokTypedef; - (*KeywordMap)["this"] = EHTokThis; - (*KeywordMap)["namespace"] = EHTokNamespace; - - (*KeywordMap)["true"] = EHTokBoolConstant; - (*KeywordMap)["false"] = EHTokBoolConstant; - - (*KeywordMap)["for"] = EHTokFor; - (*KeywordMap)["do"] = EHTokDo; - (*KeywordMap)["while"] = EHTokWhile; - (*KeywordMap)["break"] = EHTokBreak; - (*KeywordMap)["continue"] = EHTokContinue; - (*KeywordMap)["if"] = EHTokIf; - (*KeywordMap)["else"] = EHTokElse; - (*KeywordMap)["discard"] = EHTokDiscard; - (*KeywordMap)["return"] = EHTokReturn; - (*KeywordMap)["switch"] = EHTokSwitch; - (*KeywordMap)["case"] = EHTokCase; - (*KeywordMap)["default"] = EHTokDefault; - - // TODO: get correct set here - ReservedSet = new std::unordered_set; - - ReservedSet->insert("auto"); - ReservedSet->insert("catch"); - ReservedSet->insert("char"); - ReservedSet->insert("const_cast"); - ReservedSet->insert("enum"); - ReservedSet->insert("explicit"); - ReservedSet->insert("friend"); - ReservedSet->insert("goto"); - ReservedSet->insert("long"); - ReservedSet->insert("mutable"); - ReservedSet->insert("new"); - ReservedSet->insert("operator"); - ReservedSet->insert("private"); - ReservedSet->insert("protected"); - ReservedSet->insert("public"); - ReservedSet->insert("reinterpret_cast"); - ReservedSet->insert("short"); - ReservedSet->insert("signed"); - ReservedSet->insert("sizeof"); - ReservedSet->insert("static_cast"); - ReservedSet->insert("template"); - ReservedSet->insert("throw"); - ReservedSet->insert("try"); - ReservedSet->insert("typename"); - ReservedSet->insert("union"); - ReservedSet->insert("unsigned"); - ReservedSet->insert("using"); - ReservedSet->insert("virtual"); - - SemanticMap = new std::unordered_map; - - // in DX9, all outputs had to have a semantic associated with them, that was either consumed - // by the system or was a specific register assignment - // in DX10+, only semantics with the SV_ prefix have any meaning beyond decoration - // Fxc will only accept DX9 style semantics in compat mode - // Also, in DX10 if a SV value is present as the input of a stage, but isn't appropriate for that - // stage, it would just be ignored as it is likely there as part of an output struct from one stage - // to the next - bool bParseDX9 = false; - if (bParseDX9) { - (*SemanticMap)["PSIZE"] = EbvPointSize; - (*SemanticMap)["FOG"] = EbvFogFragCoord; - (*SemanticMap)["DEPTH"] = EbvFragDepth; - (*SemanticMap)["VFACE"] = EbvFace; - (*SemanticMap)["VPOS"] = EbvFragCoord; - } - - (*SemanticMap)["SV_POSITION"] = EbvPosition; - (*SemanticMap)["SV_VERTEXID"] = EbvVertexIndex; - (*SemanticMap)["SV_VIEWPORTARRAYINDEX"] = EbvViewportIndex; - (*SemanticMap)["SV_TESSFACTOR"] = EbvTessLevelOuter; - (*SemanticMap)["SV_SAMPLEINDEX"] = EbvSampleId; - (*SemanticMap)["SV_RENDERTARGETARRAYINDEX"] = EbvLayer; - (*SemanticMap)["SV_PRIMITIVEID"] = EbvPrimitiveId; - (*SemanticMap)["SV_OUTPUTCONTROLPOINTID"] = EbvInvocationId; - (*SemanticMap)["SV_ISFRONTFACE"] = EbvFace; - (*SemanticMap)["SV_VIEWID"] = EbvViewIndex; - (*SemanticMap)["SV_INSTANCEID"] = EbvInstanceIndex; - (*SemanticMap)["SV_INSIDETESSFACTOR"] = EbvTessLevelInner; - (*SemanticMap)["SV_GSINSTANCEID"] = EbvInvocationId; - (*SemanticMap)["SV_DISPATCHTHREADID"] = EbvGlobalInvocationId; - (*SemanticMap)["SV_GROUPTHREADID"] = EbvLocalInvocationId; - (*SemanticMap)["SV_GROUPINDEX"] = EbvLocalInvocationIndex; - (*SemanticMap)["SV_GROUPID"] = EbvWorkGroupId; - (*SemanticMap)["SV_DOMAINLOCATION"] = EbvTessCoord; - (*SemanticMap)["SV_DEPTH"] = EbvFragDepth; - (*SemanticMap)["SV_COVERAGE"] = EbvSampleMask; - (*SemanticMap)["SV_DEPTHGREATEREQUAL"] = EbvFragDepthGreater; - (*SemanticMap)["SV_DEPTHLESSEQUAL"] = EbvFragDepthLesser; - (*SemanticMap)["SV_STENCILREF"] = EbvFragStencilRef; -} - -void HlslScanContext::deleteKeywordMap() -{ - delete KeywordMap; - KeywordMap = nullptr; - delete ReservedSet; - ReservedSet = nullptr; - delete SemanticMap; - SemanticMap = nullptr; -} - -// Wrapper for tokenizeClass() to get everything inside the token. -void HlslScanContext::tokenize(HlslToken& token) -{ - EHlslTokenClass tokenClass = tokenizeClass(token); - token.tokenClass = tokenClass; -} - -glslang::TBuiltInVariable HlslScanContext::mapSemantic(const char* upperCase) -{ - auto it = SemanticMap->find(upperCase); - if (it != SemanticMap->end()) - return it->second; - else - return glslang::EbvNone; -} - -// -// Fill in token information for the next token, except for the token class. -// Returns the enum value of the token class of the next token found. -// Return 0 (EndOfTokens) on end of input. -// -EHlslTokenClass HlslScanContext::tokenizeClass(HlslToken& token) -{ - do { - parserToken = &token; - TPpToken ppToken; - int token = ppContext.tokenize(ppToken); - if (token == EndOfInput) - return EHTokNone; - - tokenText = ppToken.name; - loc = ppToken.loc; - parserToken->loc = loc; - switch (token) { - case ';': return EHTokSemicolon; - case ',': return EHTokComma; - case ':': return EHTokColon; - case '=': return EHTokAssign; - case '(': return EHTokLeftParen; - case ')': return EHTokRightParen; - case '.': return EHTokDot; - case '!': return EHTokBang; - case '-': return EHTokDash; - case '~': return EHTokTilde; - case '+': return EHTokPlus; - case '*': return EHTokStar; - case '/': return EHTokSlash; - case '%': return EHTokPercent; - case '<': return EHTokLeftAngle; - case '>': return EHTokRightAngle; - case '|': return EHTokVerticalBar; - case '^': return EHTokCaret; - case '&': return EHTokAmpersand; - case '?': return EHTokQuestion; - case '[': return EHTokLeftBracket; - case ']': return EHTokRightBracket; - case '{': return EHTokLeftBrace; - case '}': return EHTokRightBrace; - case '\\': - parseContext.error(loc, "illegal use of escape character", "\\", ""); - break; - - case PPAtomAddAssign: return EHTokAddAssign; - case PPAtomSubAssign: return EHTokSubAssign; - case PPAtomMulAssign: return EHTokMulAssign; - case PPAtomDivAssign: return EHTokDivAssign; - case PPAtomModAssign: return EHTokModAssign; - - case PpAtomRight: return EHTokRightOp; - case PpAtomLeft: return EHTokLeftOp; - - case PpAtomRightAssign: return EHTokRightAssign; - case PpAtomLeftAssign: return EHTokLeftAssign; - case PpAtomAndAssign: return EHTokAndAssign; - case PpAtomOrAssign: return EHTokOrAssign; - case PpAtomXorAssign: return EHTokXorAssign; - - case PpAtomAnd: return EHTokAndOp; - case PpAtomOr: return EHTokOrOp; - case PpAtomXor: return EHTokXorOp; - - case PpAtomEQ: return EHTokEqOp; - case PpAtomGE: return EHTokGeOp; - case PpAtomNE: return EHTokNeOp; - case PpAtomLE: return EHTokLeOp; - - case PpAtomDecrement: return EHTokDecOp; - case PpAtomIncrement: return EHTokIncOp; - - case PpAtomColonColon: return EHTokColonColon; - - case PpAtomConstInt: parserToken->i = ppToken.ival; return EHTokIntConstant; - case PpAtomConstUint: parserToken->i = ppToken.ival; return EHTokUintConstant; - case PpAtomConstFloat16: parserToken->d = ppToken.dval; return EHTokFloat16Constant; - case PpAtomConstFloat: parserToken->d = ppToken.dval; return EHTokFloatConstant; - case PpAtomConstDouble: parserToken->d = ppToken.dval; return EHTokDoubleConstant; - case PpAtomIdentifier: - { - EHlslTokenClass token = tokenizeIdentifier(); - return token; - } - - case PpAtomConstString: { - parserToken->string = NewPoolTString(tokenText); - return EHTokStringConstant; - } - - case EndOfInput: return EHTokNone; - - default: - if (token < PpAtomMaxSingle) { - char buf[2]; - buf[0] = (char)token; - buf[1] = 0; - parseContext.error(loc, "unexpected token", buf, ""); - } else if (tokenText[0] != 0) - parseContext.error(loc, "unexpected token", tokenText, ""); - else - parseContext.error(loc, "unexpected token", "", ""); - break; - } - } while (true); -} - -EHlslTokenClass HlslScanContext::tokenizeIdentifier() -{ - if (ReservedSet->find(tokenText) != ReservedSet->end()) - return reservedWord(); - - auto it = KeywordMap->find(tokenText); - if (it == KeywordMap->end()) { - // Should have an identifier of some sort - return identifierOrType(); - } - keyword = it->second; - - switch (keyword) { - - // qualifiers - case EHTokStatic: - case EHTokConst: - case EHTokSNorm: - case EHTokUnorm: - case EHTokExtern: - case EHTokUniform: - case EHTokVolatile: - case EHTokShared: - case EHTokGroupShared: - case EHTokLinear: - case EHTokCentroid: - case EHTokNointerpolation: - case EHTokNoperspective: - case EHTokSample: - case EHTokRowMajor: - case EHTokColumnMajor: - case EHTokPackOffset: - case EHTokIn: - case EHTokOut: - case EHTokInOut: - case EHTokPrecise: - case EHTokLayout: - case EHTokGloballyCoherent: - case EHTokInline: - return keyword; - - // primitive types - case EHTokPoint: - case EHTokLine: - case EHTokTriangle: - case EHTokLineAdj: - case EHTokTriangleAdj: - return keyword; - - // stream out types - case EHTokPointStream: - case EHTokLineStream: - case EHTokTriangleStream: - return keyword; - - // Tessellation patches - case EHTokInputPatch: - case EHTokOutputPatch: - return keyword; - - case EHTokBuffer: - case EHTokVector: - case EHTokMatrix: - return keyword; - - // scalar types - case EHTokVoid: - case EHTokString: - case EHTokBool: - case EHTokInt: - case EHTokUint: - case EHTokUint64: - case EHTokDword: - case EHTokHalf: - case EHTokFloat: - case EHTokDouble: - case EHTokMin16float: - case EHTokMin10float: - case EHTokMin16int: - case EHTokMin12int: - case EHTokMin16uint: - - // vector types - case EHTokBool1: - case EHTokBool2: - case EHTokBool3: - case EHTokBool4: - case EHTokFloat1: - case EHTokFloat2: - case EHTokFloat3: - case EHTokFloat4: - case EHTokInt1: - case EHTokInt2: - case EHTokInt3: - case EHTokInt4: - case EHTokDouble1: - case EHTokDouble2: - case EHTokDouble3: - case EHTokDouble4: - case EHTokUint1: - case EHTokUint2: - case EHTokUint3: - case EHTokUint4: - case EHTokHalf1: - case EHTokHalf2: - case EHTokHalf3: - case EHTokHalf4: - case EHTokMin16float1: - case EHTokMin16float2: - case EHTokMin16float3: - case EHTokMin16float4: - case EHTokMin10float1: - case EHTokMin10float2: - case EHTokMin10float3: - case EHTokMin10float4: - case EHTokMin16int1: - case EHTokMin16int2: - case EHTokMin16int3: - case EHTokMin16int4: - case EHTokMin12int1: - case EHTokMin12int2: - case EHTokMin12int3: - case EHTokMin12int4: - case EHTokMin16uint1: - case EHTokMin16uint2: - case EHTokMin16uint3: - case EHTokMin16uint4: - - // matrix types - case EHTokBool1x1: - case EHTokBool1x2: - case EHTokBool1x3: - case EHTokBool1x4: - case EHTokBool2x1: - case EHTokBool2x2: - case EHTokBool2x3: - case EHTokBool2x4: - case EHTokBool3x1: - case EHTokBool3x2: - case EHTokBool3x3: - case EHTokBool3x4: - case EHTokBool4x1: - case EHTokBool4x2: - case EHTokBool4x3: - case EHTokBool4x4: - case EHTokInt1x1: - case EHTokInt1x2: - case EHTokInt1x3: - case EHTokInt1x4: - case EHTokInt2x1: - case EHTokInt2x2: - case EHTokInt2x3: - case EHTokInt2x4: - case EHTokInt3x1: - case EHTokInt3x2: - case EHTokInt3x3: - case EHTokInt3x4: - case EHTokInt4x1: - case EHTokInt4x2: - case EHTokInt4x3: - case EHTokInt4x4: - case EHTokUint1x1: - case EHTokUint1x2: - case EHTokUint1x3: - case EHTokUint1x4: - case EHTokUint2x1: - case EHTokUint2x2: - case EHTokUint2x3: - case EHTokUint2x4: - case EHTokUint3x1: - case EHTokUint3x2: - case EHTokUint3x3: - case EHTokUint3x4: - case EHTokUint4x1: - case EHTokUint4x2: - case EHTokUint4x3: - case EHTokUint4x4: - case EHTokFloat1x1: - case EHTokFloat1x2: - case EHTokFloat1x3: - case EHTokFloat1x4: - case EHTokFloat2x1: - case EHTokFloat2x2: - case EHTokFloat2x3: - case EHTokFloat2x4: - case EHTokFloat3x1: - case EHTokFloat3x2: - case EHTokFloat3x3: - case EHTokFloat3x4: - case EHTokFloat4x1: - case EHTokFloat4x2: - case EHTokFloat4x3: - case EHTokFloat4x4: - case EHTokHalf1x1: - case EHTokHalf1x2: - case EHTokHalf1x3: - case EHTokHalf1x4: - case EHTokHalf2x1: - case EHTokHalf2x2: - case EHTokHalf2x3: - case EHTokHalf2x4: - case EHTokHalf3x1: - case EHTokHalf3x2: - case EHTokHalf3x3: - case EHTokHalf3x4: - case EHTokHalf4x1: - case EHTokHalf4x2: - case EHTokHalf4x3: - case EHTokHalf4x4: - case EHTokDouble1x1: - case EHTokDouble1x2: - case EHTokDouble1x3: - case EHTokDouble1x4: - case EHTokDouble2x1: - case EHTokDouble2x2: - case EHTokDouble2x3: - case EHTokDouble2x4: - case EHTokDouble3x1: - case EHTokDouble3x2: - case EHTokDouble3x3: - case EHTokDouble3x4: - case EHTokDouble4x1: - case EHTokDouble4x2: - case EHTokDouble4x3: - case EHTokDouble4x4: - case EHTokMin16float1x1: - case EHTokMin16float1x2: - case EHTokMin16float1x3: - case EHTokMin16float1x4: - case EHTokMin16float2x1: - case EHTokMin16float2x2: - case EHTokMin16float2x3: - case EHTokMin16float2x4: - case EHTokMin16float3x1: - case EHTokMin16float3x2: - case EHTokMin16float3x3: - case EHTokMin16float3x4: - case EHTokMin16float4x1: - case EHTokMin16float4x2: - case EHTokMin16float4x3: - case EHTokMin16float4x4: - case EHTokMin10float1x1: - case EHTokMin10float1x2: - case EHTokMin10float1x3: - case EHTokMin10float1x4: - case EHTokMin10float2x1: - case EHTokMin10float2x2: - case EHTokMin10float2x3: - case EHTokMin10float2x4: - case EHTokMin10float3x1: - case EHTokMin10float3x2: - case EHTokMin10float3x3: - case EHTokMin10float3x4: - case EHTokMin10float4x1: - case EHTokMin10float4x2: - case EHTokMin10float4x3: - case EHTokMin10float4x4: - case EHTokMin16int1x1: - case EHTokMin16int1x2: - case EHTokMin16int1x3: - case EHTokMin16int1x4: - case EHTokMin16int2x1: - case EHTokMin16int2x2: - case EHTokMin16int2x3: - case EHTokMin16int2x4: - case EHTokMin16int3x1: - case EHTokMin16int3x2: - case EHTokMin16int3x3: - case EHTokMin16int3x4: - case EHTokMin16int4x1: - case EHTokMin16int4x2: - case EHTokMin16int4x3: - case EHTokMin16int4x4: - case EHTokMin12int1x1: - case EHTokMin12int1x2: - case EHTokMin12int1x3: - case EHTokMin12int1x4: - case EHTokMin12int2x1: - case EHTokMin12int2x2: - case EHTokMin12int2x3: - case EHTokMin12int2x4: - case EHTokMin12int3x1: - case EHTokMin12int3x2: - case EHTokMin12int3x3: - case EHTokMin12int3x4: - case EHTokMin12int4x1: - case EHTokMin12int4x2: - case EHTokMin12int4x3: - case EHTokMin12int4x4: - case EHTokMin16uint1x1: - case EHTokMin16uint1x2: - case EHTokMin16uint1x3: - case EHTokMin16uint1x4: - case EHTokMin16uint2x1: - case EHTokMin16uint2x2: - case EHTokMin16uint2x3: - case EHTokMin16uint2x4: - case EHTokMin16uint3x1: - case EHTokMin16uint3x2: - case EHTokMin16uint3x3: - case EHTokMin16uint3x4: - case EHTokMin16uint4x1: - case EHTokMin16uint4x2: - case EHTokMin16uint4x3: - case EHTokMin16uint4x4: - return keyword; - - // texturing types - case EHTokSampler: - case EHTokSampler1d: - case EHTokSampler2d: - case EHTokSampler3d: - case EHTokSamplerCube: - case EHTokSamplerState: - case EHTokSamplerComparisonState: - case EHTokTexture: - case EHTokTexture1d: - case EHTokTexture1darray: - case EHTokTexture2d: - case EHTokTexture2darray: - case EHTokTexture3d: - case EHTokTextureCube: - case EHTokTextureCubearray: - case EHTokTexture2DMS: - case EHTokTexture2DMSarray: - case EHTokRWTexture1d: - case EHTokRWTexture1darray: - case EHTokRWTexture2d: - case EHTokRWTexture2darray: - case EHTokRWTexture3d: - case EHTokRWBuffer: - case EHTokAppendStructuredBuffer: - case EHTokByteAddressBuffer: - case EHTokConsumeStructuredBuffer: - case EHTokRWByteAddressBuffer: - case EHTokRWStructuredBuffer: - case EHTokStructuredBuffer: - case EHTokTextureBuffer: - case EHTokSubpassInput: - case EHTokSubpassInputMS: - return keyword; - - // variable, user type, ... - case EHTokClass: - case EHTokStruct: - case EHTokTypedef: - case EHTokCBuffer: - case EHTokConstantBuffer: - case EHTokTBuffer: - case EHTokThis: - case EHTokNamespace: - return keyword; - - case EHTokBoolConstant: - if (strcmp("true", tokenText) == 0) - parserToken->b = true; - else - parserToken->b = false; - return keyword; - - // control flow - case EHTokFor: - case EHTokDo: - case EHTokWhile: - case EHTokBreak: - case EHTokContinue: - case EHTokIf: - case EHTokElse: - case EHTokDiscard: - case EHTokReturn: - case EHTokCase: - case EHTokSwitch: - case EHTokDefault: - return keyword; - - default: - parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc); - return EHTokNone; - } -} - -EHlslTokenClass HlslScanContext::identifierOrType() -{ - parserToken->string = NewPoolTString(tokenText); - - return EHTokIdentifier; -} - -// Give an error for use of a reserved symbol. -// However, allow built-in declarations to use reserved words, to allow -// extension support before the extension is enabled. -EHlslTokenClass HlslScanContext::reservedWord() -{ - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.error(loc, "Reserved word.", tokenText, "", ""); - - return EHTokNone; -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/HLSL/hlslScanContext.h b/3rdparty/glslang/glslang/HLSL/hlslScanContext.h deleted file mode 100644 index 3b191e48..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslScanContext.h +++ /dev/null @@ -1,109 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// This holds context specific to the HLSL scanner, which -// sits between the preprocessor scanner and HLSL parser. -// - -#ifndef HLSLSCANCONTEXT_H_ -#define HLSLSCANCONTEXT_H_ - -#include "../MachineIndependent/ParseHelper.h" -#include "hlslTokens.h" - -namespace glslang { - -class TPpContext; -class TPpToken; - - -// -// Everything needed to fully describe a token. -// -struct HlslToken { - HlslToken() : string(nullptr) { loc.init(); } - TSourceLoc loc; // location of token in the source - EHlslTokenClass tokenClass; // what kind of token it is - union { // what data the token holds - glslang::TString *string; // for identifiers - int i; // for literals - unsigned int u; - bool b; - double d; - }; -}; - -// -// The state of scanning and translating raw tokens to slightly richer -// semantics, like knowing if an identifier is an existing symbol, or -// user-defined type. -// -class HlslScanContext { -public: - HlslScanContext(TParseContextBase& parseContext, TPpContext& ppContext) - : parseContext(parseContext), ppContext(ppContext) { } - virtual ~HlslScanContext() { } - - static void fillInKeywordMap(); - static void deleteKeywordMap(); - - void tokenize(HlslToken&); - glslang::TBuiltInVariable mapSemantic(const char*); - -protected: - HlslScanContext(HlslScanContext&); - HlslScanContext& operator=(HlslScanContext&); - - EHlslTokenClass tokenizeClass(HlslToken&); - EHlslTokenClass tokenizeIdentifier(); - EHlslTokenClass identifierOrType(); - EHlslTokenClass reservedWord(); - EHlslTokenClass identifierOrReserved(bool reserved); - EHlslTokenClass nonreservedKeyword(int version); - - TParseContextBase& parseContext; - TPpContext& ppContext; - TSourceLoc loc; - TPpToken* ppToken; - HlslToken* parserToken; - - const char* tokenText; - EHlslTokenClass keyword; -}; - -} // end namespace glslang - -#endif // HLSLSCANCONTEXT_H_ diff --git a/3rdparty/glslang/glslang/HLSL/hlslTokenStream.cpp b/3rdparty/glslang/glslang/HLSL/hlslTokenStream.cpp deleted file mode 100644 index 5d9311cf..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslTokenStream.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "hlslTokenStream.h" - -namespace glslang { - -void HlslTokenStream::pushPreToken(const HlslToken& tok) -{ - assert(preTokenStackSize < tokenBufferSize); - preTokenStack[preTokenStackSize++] = tok; -} - -HlslToken HlslTokenStream::popPreToken() -{ - assert(preTokenStackSize > 0); - - return preTokenStack[--preTokenStackSize]; -} - -void HlslTokenStream::pushTokenBuffer(const HlslToken& tok) -{ - tokenBuffer[tokenBufferPos] = tok; - tokenBufferPos = (tokenBufferPos+1) % tokenBufferSize; -} - -HlslToken HlslTokenStream::popTokenBuffer() -{ - // Back up - tokenBufferPos = (tokenBufferPos+tokenBufferSize-1) % tokenBufferSize; - - return tokenBuffer[tokenBufferPos]; -} - -// -// Make a new source of tokens, not from the source, but from an -// already pre-processed token stream. -// -// This interrupts current token processing which must be restored -// later. Some simplifying assumptions are made (and asserted). -// -void HlslTokenStream::pushTokenStream(const TVector* tokens) -{ - // not yet setup to interrupt a stream that has been receded - // and not yet reconsumed - assert(preTokenStackSize == 0); - - // save current state - currentTokenStack.push_back(token); - - // set up new token stream - tokenStreamStack.push_back(tokens); - - // start position at first token: - token = (*tokens)[0]; - tokenPosition.push_back(0); -} - -// Undo pushTokenStream(), see above -void HlslTokenStream::popTokenStream() -{ - tokenStreamStack.pop_back(); - tokenPosition.pop_back(); - token = currentTokenStack.back(); - currentTokenStack.pop_back(); -} - -// Load 'token' with the next token in the stream of tokens. -void HlslTokenStream::advanceToken() -{ - pushTokenBuffer(token); - if (preTokenStackSize > 0) - token = popPreToken(); - else { - if (tokenStreamStack.size() == 0) - scanner.tokenize(token); - else { - ++tokenPosition.back(); - if (tokenPosition.back() >= (int)tokenStreamStack.back()->size()) - token.tokenClass = EHTokNone; - else - token = (*tokenStreamStack.back())[tokenPosition.back()]; - } - } -} - -void HlslTokenStream::recedeToken() -{ - pushPreToken(token); - token = popTokenBuffer(); -} - -// Return the current token class. -EHlslTokenClass HlslTokenStream::peek() const -{ - return token.tokenClass; -} - -// Return true, without advancing to the next token, if the current token is -// the expected (passed in) token class. -bool HlslTokenStream::peekTokenClass(EHlslTokenClass tokenClass) const -{ - return peek() == tokenClass; -} - -// Return true and advance to the next token if the current token is the -// expected (passed in) token class. -bool HlslTokenStream::acceptTokenClass(EHlslTokenClass tokenClass) -{ - if (peekTokenClass(tokenClass)) { - advanceToken(); - return true; - } - - return false; -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/HLSL/hlslTokenStream.h b/3rdparty/glslang/glslang/HLSL/hlslTokenStream.h deleted file mode 100644 index cb6c9e72..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslTokenStream.h +++ /dev/null @@ -1,96 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef HLSLTOKENSTREAM_H_ -#define HLSLTOKENSTREAM_H_ - -#include "hlslScanContext.h" - -namespace glslang { - - class HlslTokenStream { - public: - explicit HlslTokenStream(HlslScanContext& scanner) - : scanner(scanner), preTokenStackSize(0), tokenBufferPos(0) { } - virtual ~HlslTokenStream() { } - - public: - void advanceToken(); - void recedeToken(); - bool acceptTokenClass(EHlslTokenClass); - EHlslTokenClass peek() const; - bool peekTokenClass(EHlslTokenClass) const; - glslang::TBuiltInVariable mapSemantic(const char* upperCase) { return scanner.mapSemantic(upperCase); } - - void pushTokenStream(const TVector* tokens); - void popTokenStream(); - - protected: - HlslToken token; // the token we are currently looking at, but have not yet accepted - - private: - HlslTokenStream(); - HlslTokenStream& operator=(const HlslTokenStream&); - - HlslScanContext& scanner; // lexical scanner, to get next token from source file - TVector*> tokenStreamStack; // for getting the next token from an existing vector of tokens - TVector tokenPosition; - TVector currentTokenStack; - - // This is the number of tokens we can recedeToken() over. - static const int tokenBufferSize = 2; - - // Previously scanned tokens, returned for future advances, - // so logically in front of the token stream. - // Is logically a stack; needs last in last out semantics. - // Currently implemented as a stack of size 2. - HlslToken preTokenStack[tokenBufferSize]; - int preTokenStackSize; - void pushPreToken(const HlslToken&); - HlslToken popPreToken(); - - // Previously scanned tokens, not yet returned for future advances, - // but available for that. - // Is logically a fifo for normal advances, and a stack for recession. - // Currently implemented with an intrinsic size of 2. - HlslToken tokenBuffer[tokenBufferSize]; - int tokenBufferPos; - void pushTokenBuffer(const HlslToken&); - HlslToken popTokenBuffer(); - }; - -} // end namespace glslang - -#endif // HLSLTOKENSTREAM_H_ diff --git a/3rdparty/glslang/glslang/HLSL/hlslTokens.h b/3rdparty/glslang/glslang/HLSL/hlslTokens.h deleted file mode 100644 index a7c12990..00000000 --- a/3rdparty/glslang/glslang/HLSL/hlslTokens.h +++ /dev/null @@ -1,454 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// Copyright (C) 2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef EHLSLTOKENS_H_ -#define EHLSLTOKENS_H_ - -namespace glslang { - -enum EHlslTokenClass { - EHTokNone = 0, - - // qualifiers - EHTokStatic, - EHTokConst, - EHTokSNorm, - EHTokUnorm, - EHTokExtern, - EHTokUniform, - EHTokVolatile, - EHTokPrecise, - EHTokShared, - EHTokGroupShared, - EHTokLinear, - EHTokCentroid, - EHTokNointerpolation, - EHTokNoperspective, - EHTokSample, - EHTokRowMajor, - EHTokColumnMajor, - EHTokPackOffset, - EHTokIn, - EHTokOut, - EHTokInOut, - EHTokLayout, - EHTokGloballyCoherent, - EHTokInline, - - // primitive types - EHTokPoint, - EHTokLine, - EHTokTriangle, - EHTokLineAdj, - EHTokTriangleAdj, - - // stream out types - EHTokPointStream, - EHTokLineStream, - EHTokTriangleStream, - - // Tessellation patches - EHTokInputPatch, - EHTokOutputPatch, - - // template types - EHTokBuffer, - EHTokVector, - EHTokMatrix, - - // scalar types - EHTokVoid, - EHTokString, - EHTokBool, - EHTokInt, - EHTokUint, - EHTokUint64, - EHTokDword, - EHTokHalf, - EHTokFloat, - EHTokDouble, - EHTokMin16float, - EHTokMin10float, - EHTokMin16int, - EHTokMin12int, - EHTokMin16uint, - - // vector types - EHTokBool1, - EHTokBool2, - EHTokBool3, - EHTokBool4, - EHTokFloat1, - EHTokFloat2, - EHTokFloat3, - EHTokFloat4, - EHTokInt1, - EHTokInt2, - EHTokInt3, - EHTokInt4, - EHTokDouble1, - EHTokDouble2, - EHTokDouble3, - EHTokDouble4, - EHTokUint1, - EHTokUint2, - EHTokUint3, - EHTokUint4, - EHTokHalf1, - EHTokHalf2, - EHTokHalf3, - EHTokHalf4, - EHTokMin16float1, - EHTokMin16float2, - EHTokMin16float3, - EHTokMin16float4, - EHTokMin10float1, - EHTokMin10float2, - EHTokMin10float3, - EHTokMin10float4, - EHTokMin16int1, - EHTokMin16int2, - EHTokMin16int3, - EHTokMin16int4, - EHTokMin12int1, - EHTokMin12int2, - EHTokMin12int3, - EHTokMin12int4, - EHTokMin16uint1, - EHTokMin16uint2, - EHTokMin16uint3, - EHTokMin16uint4, - - // matrix types - EHTokInt1x1, - EHTokInt1x2, - EHTokInt1x3, - EHTokInt1x4, - EHTokInt2x1, - EHTokInt2x2, - EHTokInt2x3, - EHTokInt2x4, - EHTokInt3x1, - EHTokInt3x2, - EHTokInt3x3, - EHTokInt3x4, - EHTokInt4x1, - EHTokInt4x2, - EHTokInt4x3, - EHTokInt4x4, - EHTokUint1x1, - EHTokUint1x2, - EHTokUint1x3, - EHTokUint1x4, - EHTokUint2x1, - EHTokUint2x2, - EHTokUint2x3, - EHTokUint2x4, - EHTokUint3x1, - EHTokUint3x2, - EHTokUint3x3, - EHTokUint3x4, - EHTokUint4x1, - EHTokUint4x2, - EHTokUint4x3, - EHTokUint4x4, - EHTokBool1x1, - EHTokBool1x2, - EHTokBool1x3, - EHTokBool1x4, - EHTokBool2x1, - EHTokBool2x2, - EHTokBool2x3, - EHTokBool2x4, - EHTokBool3x1, - EHTokBool3x2, - EHTokBool3x3, - EHTokBool3x4, - EHTokBool4x1, - EHTokBool4x2, - EHTokBool4x3, - EHTokBool4x4, - EHTokFloat1x1, - EHTokFloat1x2, - EHTokFloat1x3, - EHTokFloat1x4, - EHTokFloat2x1, - EHTokFloat2x2, - EHTokFloat2x3, - EHTokFloat2x4, - EHTokFloat3x1, - EHTokFloat3x2, - EHTokFloat3x3, - EHTokFloat3x4, - EHTokFloat4x1, - EHTokFloat4x2, - EHTokFloat4x3, - EHTokFloat4x4, - EHTokHalf1x1, - EHTokHalf1x2, - EHTokHalf1x3, - EHTokHalf1x4, - EHTokHalf2x1, - EHTokHalf2x2, - EHTokHalf2x3, - EHTokHalf2x4, - EHTokHalf3x1, - EHTokHalf3x2, - EHTokHalf3x3, - EHTokHalf3x4, - EHTokHalf4x1, - EHTokHalf4x2, - EHTokHalf4x3, - EHTokHalf4x4, - EHTokDouble1x1, - EHTokDouble1x2, - EHTokDouble1x3, - EHTokDouble1x4, - EHTokDouble2x1, - EHTokDouble2x2, - EHTokDouble2x3, - EHTokDouble2x4, - EHTokDouble3x1, - EHTokDouble3x2, - EHTokDouble3x3, - EHTokDouble3x4, - EHTokDouble4x1, - EHTokDouble4x2, - EHTokDouble4x3, - EHTokDouble4x4, - EHTokMin16float1x1, - EHTokMin16float1x2, - EHTokMin16float1x3, - EHTokMin16float1x4, - EHTokMin16float2x1, - EHTokMin16float2x2, - EHTokMin16float2x3, - EHTokMin16float2x4, - EHTokMin16float3x1, - EHTokMin16float3x2, - EHTokMin16float3x3, - EHTokMin16float3x4, - EHTokMin16float4x1, - EHTokMin16float4x2, - EHTokMin16float4x3, - EHTokMin16float4x4, - EHTokMin10float1x1, - EHTokMin10float1x2, - EHTokMin10float1x3, - EHTokMin10float1x4, - EHTokMin10float2x1, - EHTokMin10float2x2, - EHTokMin10float2x3, - EHTokMin10float2x4, - EHTokMin10float3x1, - EHTokMin10float3x2, - EHTokMin10float3x3, - EHTokMin10float3x4, - EHTokMin10float4x1, - EHTokMin10float4x2, - EHTokMin10float4x3, - EHTokMin10float4x4, - EHTokMin16int1x1, - EHTokMin16int1x2, - EHTokMin16int1x3, - EHTokMin16int1x4, - EHTokMin16int2x1, - EHTokMin16int2x2, - EHTokMin16int2x3, - EHTokMin16int2x4, - EHTokMin16int3x1, - EHTokMin16int3x2, - EHTokMin16int3x3, - EHTokMin16int3x4, - EHTokMin16int4x1, - EHTokMin16int4x2, - EHTokMin16int4x3, - EHTokMin16int4x4, - EHTokMin12int1x1, - EHTokMin12int1x2, - EHTokMin12int1x3, - EHTokMin12int1x4, - EHTokMin12int2x1, - EHTokMin12int2x2, - EHTokMin12int2x3, - EHTokMin12int2x4, - EHTokMin12int3x1, - EHTokMin12int3x2, - EHTokMin12int3x3, - EHTokMin12int3x4, - EHTokMin12int4x1, - EHTokMin12int4x2, - EHTokMin12int4x3, - EHTokMin12int4x4, - EHTokMin16uint1x1, - EHTokMin16uint1x2, - EHTokMin16uint1x3, - EHTokMin16uint1x4, - EHTokMin16uint2x1, - EHTokMin16uint2x2, - EHTokMin16uint2x3, - EHTokMin16uint2x4, - EHTokMin16uint3x1, - EHTokMin16uint3x2, - EHTokMin16uint3x3, - EHTokMin16uint3x4, - EHTokMin16uint4x1, - EHTokMin16uint4x2, - EHTokMin16uint4x3, - EHTokMin16uint4x4, - - // texturing types - EHTokSampler, - EHTokSampler1d, - EHTokSampler2d, - EHTokSampler3d, - EHTokSamplerCube, - EHTokSamplerState, - EHTokSamplerComparisonState, - EHTokTexture, - EHTokTexture1d, - EHTokTexture1darray, - EHTokTexture2d, - EHTokTexture2darray, - EHTokTexture3d, - EHTokTextureCube, - EHTokTextureCubearray, - EHTokTexture2DMS, - EHTokTexture2DMSarray, - EHTokRWTexture1d, - EHTokRWTexture1darray, - EHTokRWTexture2d, - EHTokRWTexture2darray, - EHTokRWTexture3d, - EHTokRWBuffer, - EHTokSubpassInput, - EHTokSubpassInputMS, - - // Structure buffer variants - EHTokAppendStructuredBuffer, - EHTokByteAddressBuffer, - EHTokConsumeStructuredBuffer, - EHTokRWByteAddressBuffer, - EHTokRWStructuredBuffer, - EHTokStructuredBuffer, - EHTokTextureBuffer, - - // variable, user type, ... - EHTokIdentifier, - EHTokClass, - EHTokStruct, - EHTokCBuffer, - EHTokTBuffer, - EHTokTypedef, - EHTokThis, - EHTokNamespace, - EHTokConstantBuffer, - - // constant - EHTokFloat16Constant, - EHTokFloatConstant, - EHTokDoubleConstant, - EHTokIntConstant, - EHTokUintConstant, - EHTokBoolConstant, - EHTokStringConstant, - - // control flow - EHTokFor, - EHTokDo, - EHTokWhile, - EHTokBreak, - EHTokContinue, - EHTokIf, - EHTokElse, - EHTokDiscard, - EHTokReturn, - EHTokSwitch, - EHTokCase, - EHTokDefault, - - // expressions - EHTokLeftOp, - EHTokRightOp, - EHTokIncOp, - EHTokDecOp, - EHTokLeOp, - EHTokGeOp, - EHTokEqOp, - EHTokNeOp, - EHTokAndOp, - EHTokOrOp, - EHTokXorOp, - EHTokAssign, - EHTokMulAssign, - EHTokDivAssign, - EHTokAddAssign, - EHTokModAssign, - EHTokLeftAssign, - EHTokRightAssign, - EHTokAndAssign, - EHTokXorAssign, - EHTokOrAssign, - EHTokSubAssign, - EHTokLeftParen, - EHTokRightParen, - EHTokLeftBracket, - EHTokRightBracket, - EHTokLeftBrace, - EHTokRightBrace, - EHTokDot, - EHTokComma, - EHTokColon, - EHTokColonColon, - EHTokSemicolon, - EHTokBang, - EHTokDash, - EHTokTilde, - EHTokPlus, - EHTokStar, - EHTokSlash, - EHTokPercent, - EHTokLeftAngle, - EHTokRightAngle, - EHTokVerticalBar, - EHTokCaret, - EHTokAmpersand, - EHTokQuestion, -}; - -} // end namespace glslang - -#endif // EHLSLTOKENS_H_ diff --git a/3rdparty/glslang/glslang/HLSL/pch.h b/3rdparty/glslang/glslang/HLSL/pch.h deleted file mode 100644 index 465e7c14..00000000 --- a/3rdparty/glslang/glslang/HLSL/pch.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _PCH_H -#define _PCH_H -// -// Copyright (C) 2018 The Khronos Group Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "hlslAttributes.h" -#include "hlslGrammar.h" -#include "hlslParseHelper.h" -#include "hlslScanContext.h" - -#include "../MachineIndependent/Scan.h" -#include "../MachineIndependent/preprocessor/PpContext.h" - -#include "../OSDependent/osinclude.h" - -#include -#include -#include -#include -#include - -#endif /* _PCH_H */ diff --git a/3rdparty/glslang/glslang/Include/BaseTypes.h b/3rdparty/glslang/glslang/Include/BaseTypes.h deleted file mode 100644 index 64bffa89..00000000 --- a/3rdparty/glslang/glslang/Include/BaseTypes.h +++ /dev/null @@ -1,622 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _BASICTYPES_INCLUDED_ -#define _BASICTYPES_INCLUDED_ - -namespace glslang { - -// -// Basic type. Arrays, vectors, sampler details, etc., are orthogonal to this. -// -enum TBasicType { - EbtVoid, - EbtFloat, - EbtDouble, - EbtFloat16, - EbtInt8, - EbtUint8, - EbtInt16, - EbtUint16, - EbtInt, - EbtUint, - EbtInt64, - EbtUint64, - EbtBool, - EbtAtomicUint, - EbtSampler, - EbtStruct, - EbtBlock, - EbtAccStruct, - EbtReference, - EbtRayQuery, - EbtHitObjectNV, - EbtCoopmat, - // SPIR-V type defined by spirv_type - EbtSpirvType, - - // HLSL types that live only temporarily. - EbtString, - - EbtNumTypes -}; - -// -// Storage qualifiers. Should align with different kinds of storage or -// resource or GLSL storage qualifier. Expansion is deprecated. -// -// N.B.: You probably DON'T want to add anything here, but rather just add it -// to the built-in variables. See the comment above TBuiltInVariable. -// -// A new built-in variable will normally be an existing qualifier, like 'in', 'out', etc. -// DO NOT follow the design pattern of, say EvqInstanceId, etc. -// -enum TStorageQualifier { - EvqTemporary, // For temporaries (within a function), read/write - EvqGlobal, // For globals read/write - EvqConst, // User-defined constant values, will be semantically constant and constant folded - EvqVaryingIn, // pipeline input, read only, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) - EvqVaryingOut, // pipeline output, read/write, also supercategory for all built-ins not included in this enum (see TBuiltInVariable) - EvqUniform, // read only, shared with app - EvqBuffer, // read/write, shared with app - EvqShared, // compute shader's read/write 'shared' qualifier - EvqSpirvStorageClass, // spirv_storage_class - - EvqPayload, - EvqPayloadIn, - EvqHitAttr, - EvqCallableData, - EvqCallableDataIn, - EvqHitObjectAttrNV, - - EvqtaskPayloadSharedEXT, - - // parameters - EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter - EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter - EvqInOut, - EvqConstReadOnly, // input; also other read-only types having neither a constant value nor constant-value semantics - - // built-ins read by vertex shader - EvqVertexId, - EvqInstanceId, - - // built-ins written by vertex shader - EvqPosition, - EvqPointSize, - EvqClipVertex, - - // built-ins read by fragment shader - EvqFace, - EvqFragCoord, - EvqPointCoord, - - // built-ins written by fragment shader - EvqFragColor, - EvqFragDepth, - EvqFragStencil, - - EvqTileImageEXT, - - // end of list - EvqLast -}; - -// -// Subcategories of the TStorageQualifier, simply to give a direct mapping -// between built-in variable names and an numerical value (the enum). -// -// For backward compatibility, there is some redundancy between the -// TStorageQualifier and these. Existing members should both be maintained accurately. -// However, any new built-in variable (and any existing non-redundant one) -// must follow the pattern that the specific built-in is here, and only its -// general qualifier is in TStorageQualifier. -// -// Something like gl_Position, which is sometimes 'in' and sometimes 'out' -// shows up as two different built-in variables in a single stage, but -// only has a single enum in TBuiltInVariable, so both the -// TStorageQualifier and the TBuitinVariable are needed to distinguish -// between them. -// -enum TBuiltInVariable { - EbvNone, - EbvNumWorkGroups, - EbvWorkGroupSize, - EbvWorkGroupId, - EbvLocalInvocationId, - EbvGlobalInvocationId, - EbvLocalInvocationIndex, - EbvNumSubgroups, - EbvSubgroupID, - EbvSubGroupSize, - EbvSubGroupInvocation, - EbvSubGroupEqMask, - EbvSubGroupGeMask, - EbvSubGroupGtMask, - EbvSubGroupLeMask, - EbvSubGroupLtMask, - EbvSubgroupSize2, - EbvSubgroupInvocation2, - EbvSubgroupEqMask2, - EbvSubgroupGeMask2, - EbvSubgroupGtMask2, - EbvSubgroupLeMask2, - EbvSubgroupLtMask2, - EbvVertexId, - EbvInstanceId, - EbvVertexIndex, - EbvInstanceIndex, - EbvBaseVertex, - EbvBaseInstance, - EbvDrawId, - EbvPosition, - EbvPointSize, - EbvClipVertex, - EbvClipDistance, - EbvCullDistance, - EbvNormal, - EbvVertex, - EbvMultiTexCoord0, - EbvMultiTexCoord1, - EbvMultiTexCoord2, - EbvMultiTexCoord3, - EbvMultiTexCoord4, - EbvMultiTexCoord5, - EbvMultiTexCoord6, - EbvMultiTexCoord7, - EbvFrontColor, - EbvBackColor, - EbvFrontSecondaryColor, - EbvBackSecondaryColor, - EbvTexCoord, - EbvFogFragCoord, - EbvInvocationId, - EbvPrimitiveId, - EbvLayer, - EbvViewportIndex, - EbvPatchVertices, - EbvTessLevelOuter, - EbvTessLevelInner, - EbvBoundingBox, - EbvTessCoord, - EbvColor, - EbvSecondaryColor, - EbvFace, - EbvFragCoord, - EbvPointCoord, - EbvFragColor, - EbvFragData, - EbvFragDepth, - EbvFragStencilRef, - EbvSampleId, - EbvSamplePosition, - EbvSampleMask, - EbvHelperInvocation, - - EbvBaryCoordNoPersp, - EbvBaryCoordNoPerspCentroid, - EbvBaryCoordNoPerspSample, - EbvBaryCoordSmooth, - EbvBaryCoordSmoothCentroid, - EbvBaryCoordSmoothSample, - EbvBaryCoordPullModel, - - EbvViewIndex, - EbvDeviceIndex, - - EbvShadingRateKHR, - EbvPrimitiveShadingRateKHR, - - EbvFragSizeEXT, - EbvFragInvocationCountEXT, - - EbvSecondaryFragDataEXT, - EbvSecondaryFragColorEXT, - - EbvViewportMaskNV, - EbvSecondaryPositionNV, - EbvSecondaryViewportMaskNV, - EbvPositionPerViewNV, - EbvViewportMaskPerViewNV, - EbvFragFullyCoveredNV, - EbvFragmentSizeNV, - EbvInvocationsPerPixelNV, - // ray tracing - EbvLaunchId, - EbvLaunchSize, - EbvInstanceCustomIndex, - EbvGeometryIndex, - EbvWorldRayOrigin, - EbvWorldRayDirection, - EbvObjectRayOrigin, - EbvObjectRayDirection, - EbvRayTmin, - EbvRayTmax, - EbvCullMask, - EbvHitT, - EbvHitKind, - EbvObjectToWorld, - EbvObjectToWorld3x4, - EbvWorldToObject, - EbvWorldToObject3x4, - EbvIncomingRayFlags, - EbvCurrentRayTimeNV, - // barycentrics - EbvBaryCoordNV, - EbvBaryCoordNoPerspNV, - EbvBaryCoordEXT, - EbvBaryCoordNoPerspEXT, - // mesh shaders - EbvTaskCountNV, - EbvPrimitiveCountNV, - EbvPrimitiveIndicesNV, - EbvClipDistancePerViewNV, - EbvCullDistancePerViewNV, - EbvLayerPerViewNV, - EbvMeshViewCountNV, - EbvMeshViewIndicesNV, - - EbvMicroTrianglePositionNV, - EbvMicroTriangleBaryNV, - EbvHitKindFrontFacingMicroTriangleNV, - EbvHitKindBackFacingMicroTriangleNV, - - //GL_EXT_mesh_shader - EbvPrimitivePointIndicesEXT, - EbvPrimitiveLineIndicesEXT, - EbvPrimitiveTriangleIndicesEXT, - EbvCullPrimitiveEXT, - - // sm builtins - EbvWarpsPerSM, - EbvSMCount, - EbvWarpID, - EbvSMID, - - // HLSL built-ins that live only temporarily, until they get remapped - // to one of the above. - EbvFragDepthGreater, - EbvFragDepthLesser, - EbvGsOutputStream, - EbvOutputPatch, - EbvInputPatch, - - // structbuffer types - EbvAppendConsume, // no need to differentiate append and consume - EbvRWStructuredBuffer, - EbvStructuredBuffer, - EbvByteAddressBuffer, - EbvRWByteAddressBuffer, - - // ARM specific core builtins - EbvCoreCountARM, - EbvCoreIDARM, - EbvCoreMaxIDARM, - EbvWarpIDARM, - EbvWarpMaxIDARM, - - EbvPositionFetch, - - EbvLast -}; - -// In this enum, order matters; users can assume higher precision is a bigger value -// and EpqNone is 0. -enum TPrecisionQualifier { - EpqNone = 0, - EpqLow, - EpqMedium, - EpqHigh -}; - -// These will show up in error messages -__inline const char* GetStorageQualifierString(TStorageQualifier q) -{ - switch (q) { - case EvqTemporary: return "temp"; break; - case EvqGlobal: return "global"; break; - case EvqConst: return "const"; break; - case EvqConstReadOnly: return "const (read only)"; break; - case EvqSpirvStorageClass: return "spirv_storage_class"; break; - case EvqVaryingIn: return "in"; break; - case EvqVaryingOut: return "out"; break; - case EvqUniform: return "uniform"; break; - case EvqBuffer: return "buffer"; break; - case EvqShared: return "shared"; break; - case EvqIn: return "in"; break; - case EvqOut: return "out"; break; - case EvqInOut: return "inout"; break; - case EvqVertexId: return "gl_VertexId"; break; - case EvqInstanceId: return "gl_InstanceId"; break; - case EvqPosition: return "gl_Position"; break; - case EvqPointSize: return "gl_PointSize"; break; - case EvqClipVertex: return "gl_ClipVertex"; break; - case EvqFace: return "gl_FrontFacing"; break; - case EvqFragCoord: return "gl_FragCoord"; break; - case EvqPointCoord: return "gl_PointCoord"; break; - case EvqFragColor: return "fragColor"; break; - case EvqFragDepth: return "gl_FragDepth"; break; - case EvqFragStencil: return "gl_FragStencilRefARB"; break; - case EvqPayload: return "rayPayloadNV"; break; - case EvqPayloadIn: return "rayPayloadInNV"; break; - case EvqHitAttr: return "hitAttributeNV"; break; - case EvqCallableData: return "callableDataNV"; break; - case EvqCallableDataIn: return "callableDataInNV"; break; - case EvqtaskPayloadSharedEXT: return "taskPayloadSharedEXT"; break; - case EvqHitObjectAttrNV:return "hitObjectAttributeNV"; break; - default: return "unknown qualifier"; - } -} - -__inline const char* GetBuiltInVariableString(TBuiltInVariable v) -{ - switch (v) { - case EbvNone: return ""; - case EbvNumWorkGroups: return "NumWorkGroups"; - case EbvWorkGroupSize: return "WorkGroupSize"; - case EbvWorkGroupId: return "WorkGroupID"; - case EbvLocalInvocationId: return "LocalInvocationID"; - case EbvGlobalInvocationId: return "GlobalInvocationID"; - case EbvLocalInvocationIndex: return "LocalInvocationIndex"; - case EbvNumSubgroups: return "NumSubgroups"; - case EbvSubgroupID: return "SubgroupID"; - case EbvSubGroupSize: return "SubGroupSize"; - case EbvSubGroupInvocation: return "SubGroupInvocation"; - case EbvSubGroupEqMask: return "SubGroupEqMask"; - case EbvSubGroupGeMask: return "SubGroupGeMask"; - case EbvSubGroupGtMask: return "SubGroupGtMask"; - case EbvSubGroupLeMask: return "SubGroupLeMask"; - case EbvSubGroupLtMask: return "SubGroupLtMask"; - case EbvSubgroupSize2: return "SubgroupSize"; - case EbvSubgroupInvocation2: return "SubgroupInvocationID"; - case EbvSubgroupEqMask2: return "SubgroupEqMask"; - case EbvSubgroupGeMask2: return "SubgroupGeMask"; - case EbvSubgroupGtMask2: return "SubgroupGtMask"; - case EbvSubgroupLeMask2: return "SubgroupLeMask"; - case EbvSubgroupLtMask2: return "SubgroupLtMask"; - case EbvVertexId: return "VertexId"; - case EbvInstanceId: return "InstanceId"; - case EbvVertexIndex: return "VertexIndex"; - case EbvInstanceIndex: return "InstanceIndex"; - case EbvBaseVertex: return "BaseVertex"; - case EbvBaseInstance: return "BaseInstance"; - case EbvDrawId: return "DrawId"; - case EbvPosition: return "Position"; - case EbvPointSize: return "PointSize"; - case EbvClipVertex: return "ClipVertex"; - case EbvClipDistance: return "ClipDistance"; - case EbvCullDistance: return "CullDistance"; - case EbvNormal: return "Normal"; - case EbvVertex: return "Vertex"; - case EbvMultiTexCoord0: return "MultiTexCoord0"; - case EbvMultiTexCoord1: return "MultiTexCoord1"; - case EbvMultiTexCoord2: return "MultiTexCoord2"; - case EbvMultiTexCoord3: return "MultiTexCoord3"; - case EbvMultiTexCoord4: return "MultiTexCoord4"; - case EbvMultiTexCoord5: return "MultiTexCoord5"; - case EbvMultiTexCoord6: return "MultiTexCoord6"; - case EbvMultiTexCoord7: return "MultiTexCoord7"; - case EbvFrontColor: return "FrontColor"; - case EbvBackColor: return "BackColor"; - case EbvFrontSecondaryColor: return "FrontSecondaryColor"; - case EbvBackSecondaryColor: return "BackSecondaryColor"; - case EbvTexCoord: return "TexCoord"; - case EbvFogFragCoord: return "FogFragCoord"; - case EbvInvocationId: return "InvocationID"; - case EbvPrimitiveId: return "PrimitiveID"; - case EbvLayer: return "Layer"; - case EbvViewportIndex: return "ViewportIndex"; - case EbvPatchVertices: return "PatchVertices"; - case EbvTessLevelOuter: return "TessLevelOuter"; - case EbvTessLevelInner: return "TessLevelInner"; - case EbvBoundingBox: return "BoundingBox"; - case EbvTessCoord: return "TessCoord"; - case EbvColor: return "Color"; - case EbvSecondaryColor: return "SecondaryColor"; - case EbvFace: return "Face"; - case EbvFragCoord: return "FragCoord"; - case EbvPointCoord: return "PointCoord"; - case EbvFragColor: return "FragColor"; - case EbvFragData: return "FragData"; - case EbvFragDepth: return "FragDepth"; - case EbvFragStencilRef: return "FragStencilRef"; - case EbvSampleId: return "SampleId"; - case EbvSamplePosition: return "SamplePosition"; - case EbvSampleMask: return "SampleMaskIn"; - case EbvHelperInvocation: return "HelperInvocation"; - - case EbvBaryCoordNoPersp: return "BaryCoordNoPersp"; - case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid"; - case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample"; - case EbvBaryCoordSmooth: return "BaryCoordSmooth"; - case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid"; - case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample"; - case EbvBaryCoordPullModel: return "BaryCoordPullModel"; - - case EbvViewIndex: return "ViewIndex"; - case EbvDeviceIndex: return "DeviceIndex"; - - case EbvFragSizeEXT: return "FragSizeEXT"; - case EbvFragInvocationCountEXT: return "FragInvocationCountEXT"; - - case EbvSecondaryFragDataEXT: return "SecondaryFragDataEXT"; - case EbvSecondaryFragColorEXT: return "SecondaryFragColorEXT"; - - case EbvViewportMaskNV: return "ViewportMaskNV"; - case EbvSecondaryPositionNV: return "SecondaryPositionNV"; - case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; - case EbvPositionPerViewNV: return "PositionPerViewNV"; - case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; - case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; - case EbvFragmentSizeNV: return "FragmentSizeNV"; - case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV"; - case EbvLaunchId: return "LaunchIdNV"; - case EbvLaunchSize: return "LaunchSizeNV"; - case EbvInstanceCustomIndex: return "InstanceCustomIndexNV"; - case EbvGeometryIndex: return "GeometryIndexEXT"; - case EbvWorldRayOrigin: return "WorldRayOriginNV"; - case EbvWorldRayDirection: return "WorldRayDirectionNV"; - case EbvObjectRayOrigin: return "ObjectRayOriginNV"; - case EbvObjectRayDirection: return "ObjectRayDirectionNV"; - case EbvRayTmin: return "ObjectRayTminNV"; - case EbvRayTmax: return "ObjectRayTmaxNV"; - case EbvHitT: return "HitTNV"; - case EbvHitKind: return "HitKindNV"; - case EbvIncomingRayFlags: return "IncomingRayFlagsNV"; - case EbvObjectToWorld: return "ObjectToWorldNV"; - case EbvWorldToObject: return "WorldToObjectNV"; - case EbvCurrentRayTimeNV: return "CurrentRayTimeNV"; - - case EbvBaryCoordEXT: - case EbvBaryCoordNV: return "BaryCoordKHR"; - case EbvBaryCoordNoPerspEXT: - case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspKHR"; - - case EbvTaskCountNV: return "TaskCountNV"; - case EbvPrimitiveCountNV: return "PrimitiveCountNV"; - case EbvPrimitiveIndicesNV: return "PrimitiveIndicesNV"; - case EbvClipDistancePerViewNV: return "ClipDistancePerViewNV"; - case EbvCullDistancePerViewNV: return "CullDistancePerViewNV"; - case EbvLayerPerViewNV: return "LayerPerViewNV"; - case EbvMeshViewCountNV: return "MeshViewCountNV"; - case EbvMeshViewIndicesNV: return "MeshViewIndicesNV"; - // GL_EXT_mesh_shader - case EbvPrimitivePointIndicesEXT: return "PrimitivePointIndicesEXT"; - case EbvPrimitiveLineIndicesEXT: return "PrimitiveLineIndicesEXT"; - case EbvPrimitiveTriangleIndicesEXT: return "PrimitiveTriangleIndicesEXT"; - case EbvCullPrimitiveEXT: return "CullPrimitiveEXT"; - - case EbvWarpsPerSM: return "WarpsPerSMNV"; - case EbvSMCount: return "SMCountNV"; - case EbvWarpID: return "WarpIDNV"; - case EbvSMID: return "SMIDNV"; - - case EbvShadingRateKHR: return "ShadingRateKHR"; - case EbvPrimitiveShadingRateKHR: return "PrimitiveShadingRateKHR"; - - case EbvHitKindFrontFacingMicroTriangleNV: return "HitKindFrontFacingMicroTriangleNV"; - case EbvHitKindBackFacingMicroTriangleNV: return "HitKindBackFacingMicroTriangleNV"; - - default: return "unknown built-in variable"; - } -} - -__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) -{ - switch (p) { - case EpqNone: return ""; break; - case EpqLow: return "lowp"; break; - case EpqMedium: return "mediump"; break; - case EpqHigh: return "highp"; break; - default: return "unknown precision qualifier"; - } -} - -__inline bool isTypeSignedInt(TBasicType type) -{ - switch (type) { - case EbtInt8: - case EbtInt16: - case EbtInt: - case EbtInt64: - return true; - default: - return false; - } -} - -__inline bool isTypeUnsignedInt(TBasicType type) -{ - switch (type) { - case EbtUint8: - case EbtUint16: - case EbtUint: - case EbtUint64: - return true; - default: - return false; - } -} - -__inline bool isTypeInt(TBasicType type) -{ - return isTypeSignedInt(type) || isTypeUnsignedInt(type); -} - -__inline bool isTypeFloat(TBasicType type) -{ - switch (type) { - case EbtFloat: - case EbtDouble: - case EbtFloat16: - return true; - default: - return false; - } -} - -__inline int getTypeRank(TBasicType type) -{ - int res = -1; - switch(type) { - case EbtInt8: - case EbtUint8: - res = 0; - break; - case EbtInt16: - case EbtUint16: - res = 1; - break; - case EbtInt: - case EbtUint: - res = 2; - break; - case EbtInt64: - case EbtUint64: - res = 3; - break; - default: - assert(false); - break; - } - return res; -} - -} // end namespace glslang - -#endif // _BASICTYPES_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Include/Common.h b/3rdparty/glslang/glslang/Include/Common.h deleted file mode 100644 index af7dfe62..00000000 --- a/3rdparty/glslang/glslang/Include/Common.h +++ /dev/null @@ -1,297 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _COMMON_INCLUDED_ -#define _COMMON_INCLUDED_ - -#include -#include -#ifdef _MSC_VER -#include -#else -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__ANDROID__) -#include -namespace std { -template -std::string to_string(const T& val) { - std::ostringstream os; - os << val; - return os.str(); -} -} -#endif - -#if defined(MINGW_HAS_SECURE_API) && MINGW_HAS_SECURE_API - #include - #ifndef snprintf - #define snprintf sprintf_s - #endif - #define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args)) -#elif defined (solaris) - #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) - #include - #define UINT_PTR uintptr_t -#else - #define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args)) - #include - #define UINT_PTR uintptr_t -#endif - -#if defined(_MSC_VER) -#define strdup _strdup -#endif - -/* windows only pragma */ -#ifdef _MSC_VER - #pragma warning(disable : 4786) // Don't warn about too long identifiers - #pragma warning(disable : 4514) // unused inline method - #pragma warning(disable : 4201) // nameless union -#endif - -#include "PoolAlloc.h" - -// -// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme. -// -#define POOL_ALLOCATOR_NEW_DELETE(A) \ - void* operator new(size_t s) { return (A).allocate(s); } \ - void* operator new(size_t, void *_Where) { return (_Where); } \ - void operator delete(void*) { } \ - void operator delete(void *, void *) { } \ - void* operator new[](size_t s) { return (A).allocate(s); } \ - void* operator new[](size_t, void *_Where) { return (_Where); } \ - void operator delete[](void*) { } \ - void operator delete[](void *, void *) { } - -namespace glslang { - - // - // Pool version of string. - // - typedef pool_allocator TStringAllocator; - typedef std::basic_string , TStringAllocator> TString; - -} // end namespace glslang - -// Repackage the std::hash for use by unordered map/set with a TString key. -namespace std { - - template<> struct hash { - std::size_t operator()(const glslang::TString& s) const - { - const unsigned _FNV_offset_basis = 2166136261U; - const unsigned _FNV_prime = 16777619U; - unsigned _Val = _FNV_offset_basis; - size_t _Count = s.size(); - const char* _First = s.c_str(); - for (size_t _Next = 0; _Next < _Count; ++_Next) - { - _Val ^= (unsigned)_First[_Next]; - _Val *= _FNV_prime; - } - - return _Val; - } - }; -} - -namespace glslang { - -inline TString* NewPoolTString(const char* s) -{ - void* memory = GetThreadPoolAllocator().allocate(sizeof(TString)); - return new(memory) TString(s); -} - -template inline T* NewPoolObject(T*) -{ - return new(GetThreadPoolAllocator().allocate(sizeof(T))) T; -} - -template inline T* NewPoolObject(T, int instances) -{ - return new(GetThreadPoolAllocator().allocate(instances * sizeof(T))) T[instances]; -} - -// -// Pool allocator versions of vectors, lists, and maps -// -template class TVector : public std::vector > { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - typedef typename std::vector >::size_type size_type; - TVector() : std::vector >() {} - TVector(const pool_allocator& a) : std::vector >(a) {} - TVector(size_type i) : std::vector >(i) {} - TVector(size_type i, const T& val) : std::vector >(i, val) {} -}; - -template class TList : public std::list > { -}; - -template > -class TMap : public std::map > > { -}; - -template , class PRED = std::equal_to > -class TUnorderedMap : public std::unordered_map > > { -}; - -template > -class TSet : public std::set > { -}; - -// -// Persistent string memory. Should only be used for strings that survive -// across compiles/links. -// -typedef std::basic_string TPersistString; - -// -// templatized min and max functions. -// -template T Min(const T a, const T b) { return a < b ? a : b; } -template T Max(const T a, const T b) { return a > b ? a : b; } - -// -// Create a TString object from an integer. -// -#if defined(_MSC_VER) || (defined(MINGW_HAS_SECURE_API) && MINGW_HAS_SECURE_API) -inline const TString String(const int i, const int base = 10) -{ - char text[16]; // 32 bit ints are at most 10 digits in base 10 - _itoa_s(i, text, sizeof(text), base); - return text; -} -#else -inline const TString String(const int i, const int /*base*/ = 10) -{ - char text[16]; // 32 bit ints are at most 10 digits in base 10 - - // we assume base 10 for all cases - snprintf(text, sizeof(text), "%d", i); - - return text; -} -#endif - -struct TSourceLoc { - void init() - { - name = nullptr; string = 0; line = 0; column = 0; - } - void init(int stringNum) { init(); string = stringNum; } - // Returns the name if it exists. Otherwise, returns the string number. - std::string getStringNameOrNum(bool quoteStringName = true) const - { - if (name != nullptr) { - TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name; - std::string ret_str(qstr.c_str()); - return ret_str; - } - return std::to_string((long long)string); - } - const char* getFilename() const - { - if (name == nullptr) - return nullptr; - return name->c_str(); - } - const char* getFilenameStr() const { return name == nullptr ? "" : name->c_str(); } - TString* name; // descriptive name for this string, when a textual name is available, otherwise nullptr - int string; - int line; - int column; -}; - -class TPragmaTable : public TMap { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) -}; - -const int MaxTokenLength = 1024; - -template bool IsPow2(T powerOf2) -{ - if (powerOf2 <= 0) - return false; - - return (powerOf2 & (powerOf2 - 1)) == 0; -} - -// Round number up to a multiple of the given powerOf2, which is not -// a power, just a number that must be a power of 2. -template void RoundToPow2(T& number, int powerOf2) -{ - assert(IsPow2(powerOf2)); - number = (number + powerOf2 - 1) & ~(powerOf2 - 1); -} - -template bool IsMultipleOfPow2(T number, int powerOf2) -{ - assert(IsPow2(powerOf2)); - return ! (number & (powerOf2 - 1)); -} - -// Returns log2 of an integer power of 2. -// T should be integral. -template int IntLog2(T n) -{ - assert(IsPow2(n)); - int result = 0; - while ((T(1) << result) != n) { - result++; - } - return result; -} - -} // end namespace glslang - -#endif // _COMMON_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Include/ConstantUnion.h b/3rdparty/glslang/glslang/Include/ConstantUnion.h deleted file mode 100644 index da4737b6..00000000 --- a/3rdparty/glslang/glslang/Include/ConstantUnion.h +++ /dev/null @@ -1,938 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _CONSTANT_UNION_INCLUDED_ -#define _CONSTANT_UNION_INCLUDED_ - -#include "../Include/Common.h" -#include "../Include/BaseTypes.h" - -namespace glslang { - -class TConstUnion { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - TConstUnion() : iConst(0), type(EbtInt) { } - - void setI8Const(signed char i) - { - i8Const = i; - type = EbtInt8; - } - - void setU8Const(unsigned char u) - { - u8Const = u; - type = EbtUint8; - } - - void setI16Const(signed short i) - { - i16Const = i; - type = EbtInt16; - } - - void setU16Const(unsigned short u) - { - u16Const = u; - type = EbtUint16; - } - - void setIConst(int i) - { - iConst = i; - type = EbtInt; - } - - void setUConst(unsigned int u) - { - uConst = u; - type = EbtUint; - } - - void setI64Const(long long i64) - { - i64Const = i64; - type = EbtInt64; - } - - void setU64Const(unsigned long long u64) - { - u64Const = u64; - type = EbtUint64; - } - - void setDConst(double d) - { - dConst = d; - type = EbtDouble; - } - - void setBConst(bool b) - { - bConst = b; - type = EbtBool; - } - - void setSConst(const TString* s) - { - sConst = s; - type = EbtString; - } - - signed char getI8Const() const { return i8Const; } - unsigned char getU8Const() const { return u8Const; } - signed short getI16Const() const { return i16Const; } - unsigned short getU16Const() const { return u16Const; } - int getIConst() const { return iConst; } - unsigned int getUConst() const { return uConst; } - long long getI64Const() const { return i64Const; } - unsigned long long getU64Const() const { return u64Const; } - double getDConst() const { return dConst; } - bool getBConst() const { return bConst; } - const TString* getSConst() const { return sConst; } - - bool operator==(const signed char i) const - { - if (i == i8Const) - return true; - - return false; - } - - bool operator==(const unsigned char u) const - { - if (u == u8Const) - return true; - - return false; - } - - bool operator==(const signed short i) const - { - if (i == i16Const) - return true; - - return false; - } - - bool operator==(const unsigned short u) const - { - if (u == u16Const) - return true; - - return false; - } - - bool operator==(const int i) const - { - if (i == iConst) - return true; - - return false; - } - - bool operator==(const unsigned int u) const - { - if (u == uConst) - return true; - - return false; - } - - bool operator==(const long long i64) const - { - if (i64 == i64Const) - return true; - - return false; - } - - bool operator==(const unsigned long long u64) const - { - if (u64 == u64Const) - return true; - - return false; - } - - bool operator==(const double d) const - { - if (d == dConst) - return true; - - return false; - } - - bool operator==(const bool b) const - { - if (b == bConst) - return true; - - return false; - } - - bool operator==(const TConstUnion& constant) const - { - if (constant.type != type) - return false; - - switch (type) { - case EbtInt: - if (constant.iConst == iConst) - return true; - - break; - case EbtUint: - if (constant.uConst == uConst) - return true; - - break; - case EbtBool: - if (constant.bConst == bConst) - return true; - - break; - case EbtDouble: - if (constant.dConst == dConst) - return true; - - break; - - case EbtInt16: - if (constant.i16Const == i16Const) - return true; - - break; - case EbtUint16: - if (constant.u16Const == u16Const) - return true; - - break; - case EbtInt8: - if (constant.i8Const == i8Const) - return true; - - break; - case EbtUint8: - if (constant.u8Const == u8Const) - return true; - - break; - case EbtInt64: - if (constant.i64Const == i64Const) - return true; - - break; - case EbtUint64: - if (constant.u64Const == u64Const) - return true; - - break; - default: - assert(false && "Default missing"); - } - - return false; - } - - bool operator!=(const signed char i) const - { - return !operator==(i); - } - - bool operator!=(const unsigned char u) const - { - return !operator==(u); - } - - bool operator!=(const signed short i) const - { - return !operator==(i); - } - - bool operator!=(const unsigned short u) const - { - return !operator==(u); - } - - bool operator!=(const int i) const - { - return !operator==(i); - } - - bool operator!=(const unsigned int u) const - { - return !operator==(u); - } - - bool operator!=(const long long i) const - { - return !operator==(i); - } - - bool operator!=(const unsigned long long u) const - { - return !operator==(u); - } - - bool operator!=(const float f) const - { - return !operator==(f); - } - - bool operator!=(const bool b) const - { - return !operator==(b); - } - - bool operator!=(const TConstUnion& constant) const - { - return !operator==(constant); - } - - bool operator>(const TConstUnion& constant) const - { - assert(type == constant.type); - switch (type) { - case EbtInt: - if (iConst > constant.iConst) - return true; - - return false; - case EbtUint: - if (uConst > constant.uConst) - return true; - - return false; - case EbtDouble: - if (dConst > constant.dConst) - return true; - - return false; - case EbtInt8: - if (i8Const > constant.i8Const) - return true; - - return false; - case EbtUint8: - if (u8Const > constant.u8Const) - return true; - - return false; - case EbtInt16: - if (i16Const > constant.i16Const) - return true; - - return false; - case EbtUint16: - if (u16Const > constant.u16Const) - return true; - - return false; - case EbtInt64: - if (i64Const > constant.i64Const) - return true; - - return false; - case EbtUint64: - if (u64Const > constant.u64Const) - return true; - - return false; - default: - assert(false && "Default missing"); - return false; - } - } - - bool operator<(const TConstUnion& constant) const - { - assert(type == constant.type); - switch (type) { - case EbtInt8: - if (i8Const < constant.i8Const) - return true; - - return false; - case EbtUint8: - if (u8Const < constant.u8Const) - return true; - - return false; - case EbtInt16: - if (i16Const < constant.i16Const) - return true; - - return false; - case EbtUint16: - if (u16Const < constant.u16Const) - return true; - return false; - case EbtInt64: - if (i64Const < constant.i64Const) - return true; - - return false; - case EbtUint64: - if (u64Const < constant.u64Const) - return true; - - return false; - case EbtDouble: - if (dConst < constant.dConst) - return true; - - return false; - case EbtInt: - if (iConst < constant.iConst) - return true; - - return false; - case EbtUint: - if (uConst < constant.uConst) - return true; - - return false; - default: - assert(false && "Default missing"); - return false; - } - } - - TConstUnion operator+(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst + constant.uConst); break; - case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break; - case EbtInt8: returnValue.setI8Const(i8Const + constant.i8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const + constant.i16Const); break; - case EbtInt64: returnValue.setI64Const(i64Const + constant.i64Const); break; - case EbtUint8: returnValue.setU8Const(u8Const + constant.u8Const); break; - case EbtUint16: returnValue.setU16Const(u16Const + constant.u16Const); break; - case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator-(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst - constant.uConst); break; - case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break; - case EbtInt8: returnValue.setI8Const(i8Const - constant.i8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const - constant.i16Const); break; - case EbtInt64: returnValue.setI64Const(i64Const - constant.i64Const); break; - case EbtUint8: returnValue.setU8Const(u8Const - constant.u8Const); break; - case EbtUint16: returnValue.setU16Const(u16Const - constant.u16Const); break; - case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator*(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst * constant.uConst); break; - case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break; - case EbtInt8: returnValue.setI8Const(i8Const * constant.i8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const * constant.i16Const); break; - case EbtInt64: returnValue.setI64Const(i64Const * constant.i64Const); break; - case EbtUint8: returnValue.setU8Const(u8Const * constant.u8Const); break; - case EbtUint16: returnValue.setU16Const(u16Const * constant.u16Const); break; - case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator%(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst % constant.uConst); break; - case EbtInt8: returnValue.setI8Const(i8Const % constant.i8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const % constant.i16Const); break; - case EbtInt64: returnValue.setI64Const(i64Const % constant.i64Const); break; - case EbtUint8: returnValue.setU8Const(u8Const % constant.u8Const); break; - case EbtUint16: returnValue.setU16Const(u16Const % constant.u16Const); break; - case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator>>(const TConstUnion& constant) const - { - TConstUnion returnValue; - switch (type) { - case EbtInt8: - switch (constant.type) { - case EbtInt8: returnValue.setI8Const(i8Const >> constant.i8Const); break; - case EbtUint8: returnValue.setI8Const(i8Const >> constant.u8Const); break; - case EbtInt16: returnValue.setI8Const(i8Const >> constant.i16Const); break; - case EbtUint16: returnValue.setI8Const(i8Const >> constant.u16Const); break; - case EbtInt: returnValue.setI8Const(i8Const >> constant.iConst); break; - case EbtUint: returnValue.setI8Const(i8Const >> constant.uConst); break; - case EbtInt64: returnValue.setI8Const(i8Const >> constant.i64Const); break; - case EbtUint64: returnValue.setI8Const(i8Const >> constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtUint8: - switch (constant.type) { - case EbtInt8: returnValue.setU8Const(u8Const >> constant.i8Const); break; - case EbtUint8: returnValue.setU8Const(u8Const >> constant.u8Const); break; - case EbtInt16: returnValue.setU8Const(u8Const >> constant.i16Const); break; - case EbtUint16: returnValue.setU8Const(u8Const >> constant.u16Const); break; - case EbtInt: returnValue.setU8Const(u8Const >> constant.iConst); break; - case EbtUint: returnValue.setU8Const(u8Const >> constant.uConst); break; - case EbtInt64: returnValue.setU8Const(u8Const >> constant.i64Const); break; - case EbtUint64: returnValue.setU8Const(u8Const >> constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtInt16: - switch (constant.type) { - case EbtInt8: returnValue.setI16Const(i16Const >> constant.i8Const); break; - case EbtUint8: returnValue.setI16Const(i16Const >> constant.u8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const >> constant.i16Const); break; - case EbtUint16: returnValue.setI16Const(i16Const >> constant.u16Const); break; - case EbtInt: returnValue.setI16Const(i16Const >> constant.iConst); break; - case EbtUint: returnValue.setI16Const(i16Const >> constant.uConst); break; - case EbtInt64: returnValue.setI16Const(i16Const >> constant.i64Const); break; - case EbtUint64: returnValue.setI16Const(i16Const >> constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtUint16: - switch (constant.type) { - case EbtInt8: returnValue.setU16Const(u16Const >> constant.i8Const); break; - case EbtUint8: returnValue.setU16Const(u16Const >> constant.u8Const); break; - case EbtInt16: returnValue.setU16Const(u16Const >> constant.i16Const); break; - case EbtUint16: returnValue.setU16Const(u16Const >> constant.u16Const); break; - case EbtInt: returnValue.setU16Const(u16Const >> constant.iConst); break; - case EbtUint: returnValue.setU16Const(u16Const >> constant.uConst); break; - case EbtInt64: returnValue.setU16Const(u16Const >> constant.i64Const); break; - case EbtUint64: returnValue.setU16Const(u16Const >> constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtInt: - switch (constant.type) { - case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; - case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break; - case EbtInt8: returnValue.setIConst(iConst >> constant.i8Const); break; - case EbtUint8: returnValue.setIConst(iConst >> constant.u8Const); break; - case EbtInt16: returnValue.setIConst(iConst >> constant.i16Const); break; - case EbtUint16: returnValue.setIConst(iConst >> constant.u16Const); break; - case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break; - case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtUint: - switch (constant.type) { - case EbtInt: returnValue.setUConst(uConst >> constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break; - case EbtInt8: returnValue.setUConst(uConst >> constant.i8Const); break; - case EbtUint8: returnValue.setUConst(uConst >> constant.u8Const); break; - case EbtInt16: returnValue.setUConst(uConst >> constant.i16Const); break; - case EbtUint16: returnValue.setUConst(uConst >> constant.u16Const); break; - case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break; - case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtInt64: - switch (constant.type) { - case EbtInt8: returnValue.setI64Const(i64Const >> constant.i8Const); break; - case EbtUint8: returnValue.setI64Const(i64Const >> constant.u8Const); break; - case EbtInt16: returnValue.setI64Const(i64Const >> constant.i16Const); break; - case EbtUint16: returnValue.setI64Const(i64Const >> constant.u16Const); break; - case EbtInt: returnValue.setI64Const(i64Const >> constant.iConst); break; - case EbtUint: returnValue.setI64Const(i64Const >> constant.uConst); break; - case EbtInt64: returnValue.setI64Const(i64Const >> constant.i64Const); break; - case EbtUint64: returnValue.setI64Const(i64Const >> constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtUint64: - switch (constant.type) { - case EbtInt8: returnValue.setU64Const(u64Const >> constant.i8Const); break; - case EbtUint8: returnValue.setU64Const(u64Const >> constant.u8Const); break; - case EbtInt16: returnValue.setU64Const(u64Const >> constant.i16Const); break; - case EbtUint16: returnValue.setU64Const(u64Const >> constant.u16Const); break; - case EbtInt: returnValue.setU64Const(u64Const >> constant.iConst); break; - case EbtUint: returnValue.setU64Const(u64Const >> constant.uConst); break; - case EbtInt64: returnValue.setU64Const(u64Const >> constant.i64Const); break; - case EbtUint64: returnValue.setU64Const(u64Const >> constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator<<(const TConstUnion& constant) const - { - TConstUnion returnValue; - switch (type) { - case EbtInt8: - switch (constant.type) { - case EbtInt8: returnValue.setI8Const(i8Const << constant.i8Const); break; - case EbtUint8: returnValue.setI8Const(i8Const << constant.u8Const); break; - case EbtInt16: returnValue.setI8Const(i8Const << constant.i16Const); break; - case EbtUint16: returnValue.setI8Const(i8Const << constant.u16Const); break; - case EbtInt: returnValue.setI8Const(i8Const << constant.iConst); break; - case EbtUint: returnValue.setI8Const(i8Const << constant.uConst); break; - case EbtInt64: returnValue.setI8Const(i8Const << constant.i64Const); break; - case EbtUint64: returnValue.setI8Const(i8Const << constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtUint8: - switch (constant.type) { - case EbtInt8: returnValue.setU8Const(u8Const << constant.i8Const); break; - case EbtUint8: returnValue.setU8Const(u8Const << constant.u8Const); break; - case EbtInt16: returnValue.setU8Const(u8Const << constant.i16Const); break; - case EbtUint16: returnValue.setU8Const(u8Const << constant.u16Const); break; - case EbtInt: returnValue.setU8Const(u8Const << constant.iConst); break; - case EbtUint: returnValue.setU8Const(u8Const << constant.uConst); break; - case EbtInt64: returnValue.setU8Const(u8Const << constant.i64Const); break; - case EbtUint64: returnValue.setU8Const(u8Const << constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtInt16: - switch (constant.type) { - case EbtInt8: returnValue.setI16Const(i16Const << constant.i8Const); break; - case EbtUint8: returnValue.setI16Const(i16Const << constant.u8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const << constant.i16Const); break; - case EbtUint16: returnValue.setI16Const(i16Const << constant.u16Const); break; - case EbtInt: returnValue.setI16Const(i16Const << constant.iConst); break; - case EbtUint: returnValue.setI16Const(i16Const << constant.uConst); break; - case EbtInt64: returnValue.setI16Const(i16Const << constant.i64Const); break; - case EbtUint64: returnValue.setI16Const(i16Const << constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtUint16: - switch (constant.type) { - case EbtInt8: returnValue.setU16Const(u16Const << constant.i8Const); break; - case EbtUint8: returnValue.setU16Const(u16Const << constant.u8Const); break; - case EbtInt16: returnValue.setU16Const(u16Const << constant.i16Const); break; - case EbtUint16: returnValue.setU16Const(u16Const << constant.u16Const); break; - case EbtInt: returnValue.setU16Const(u16Const << constant.iConst); break; - case EbtUint: returnValue.setU16Const(u16Const << constant.uConst); break; - case EbtInt64: returnValue.setU16Const(u16Const << constant.i64Const); break; - case EbtUint64: returnValue.setU16Const(u16Const << constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtInt64: - switch (constant.type) { - case EbtInt8: returnValue.setI64Const(i64Const << constant.i8Const); break; - case EbtUint8: returnValue.setI64Const(i64Const << constant.u8Const); break; - case EbtInt16: returnValue.setI64Const(i64Const << constant.i16Const); break; - case EbtUint16: returnValue.setI64Const(i64Const << constant.u16Const); break; - case EbtInt: returnValue.setI64Const(i64Const << constant.iConst); break; - case EbtUint: returnValue.setI64Const(i64Const << constant.uConst); break; - case EbtInt64: returnValue.setI64Const(i64Const << constant.i64Const); break; - case EbtUint64: returnValue.setI64Const(i64Const << constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtUint64: - switch (constant.type) { - case EbtInt8: returnValue.setU64Const(u64Const << constant.i8Const); break; - case EbtUint8: returnValue.setU64Const(u64Const << constant.u8Const); break; - case EbtInt16: returnValue.setU64Const(u64Const << constant.i16Const); break; - case EbtUint16: returnValue.setU64Const(u64Const << constant.u16Const); break; - case EbtInt: returnValue.setU64Const(u64Const << constant.iConst); break; - case EbtUint: returnValue.setU64Const(u64Const << constant.uConst); break; - case EbtInt64: returnValue.setU64Const(u64Const << constant.i64Const); break; - case EbtUint64: returnValue.setU64Const(u64Const << constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtInt: - switch (constant.type) { - case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; - case EbtUint: returnValue.setIConst(iConst << constant.uConst); break; - case EbtInt8: returnValue.setIConst(iConst << constant.i8Const); break; - case EbtUint8: returnValue.setIConst(iConst << constant.u8Const); break; - case EbtInt16: returnValue.setIConst(iConst << constant.i16Const); break; - case EbtUint16: returnValue.setIConst(iConst << constant.u16Const); break; - case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break; - case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - case EbtUint: - switch (constant.type) { - case EbtInt: returnValue.setUConst(uConst << constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst << constant.uConst); break; - case EbtInt8: returnValue.setUConst(uConst << constant.i8Const); break; - case EbtUint8: returnValue.setUConst(uConst << constant.u8Const); break; - case EbtInt16: returnValue.setUConst(uConst << constant.i16Const); break; - case EbtUint16: returnValue.setUConst(uConst << constant.u16Const); break; - case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break; - case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break; - default: assert(false && "Default missing"); - } - break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator&(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst & constant.uConst); break; - case EbtInt8: returnValue.setI8Const(i8Const & constant.i8Const); break; - case EbtUint8: returnValue.setU8Const(u8Const & constant.u8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const & constant.i16Const); break; - case EbtUint16: returnValue.setU16Const(u16Const & constant.u16Const); break; - case EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break; - case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator|(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst | constant.uConst); break; - case EbtInt8: returnValue.setI8Const(i8Const | constant.i8Const); break; - case EbtUint8: returnValue.setU8Const(u8Const | constant.u8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const | constant.i16Const); break; - case EbtUint16: returnValue.setU16Const(u16Const | constant.u16Const); break; - case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break; - case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator^(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; - case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break; - case EbtInt8: returnValue.setI8Const(i8Const ^ constant.i8Const); break; - case EbtUint8: returnValue.setU8Const(u8Const ^ constant.u8Const); break; - case EbtInt16: returnValue.setI16Const(i16Const ^ constant.i16Const); break; - case EbtUint16: returnValue.setU16Const(u16Const ^ constant.u16Const); break; - case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break; - case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator~() const - { - TConstUnion returnValue; - switch (type) { - case EbtInt: returnValue.setIConst(~iConst); break; - case EbtUint: returnValue.setUConst(~uConst); break; - case EbtInt8: returnValue.setI8Const(~i8Const); break; - case EbtUint8: returnValue.setU8Const(~u8Const); break; - case EbtInt16: returnValue.setI16Const(~i16Const); break; - case EbtUint16: returnValue.setU16Const(~u16Const); break; - case EbtInt64: returnValue.setI64Const(~i64Const); break; - case EbtUint64: returnValue.setU64Const(~u64Const); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator&&(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtBool: returnValue.setBConst(bConst && constant.bConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TConstUnion operator||(const TConstUnion& constant) const - { - TConstUnion returnValue; - assert(type == constant.type); - switch (type) { - case EbtBool: returnValue.setBConst(bConst || constant.bConst); break; - default: assert(false && "Default missing"); - } - - return returnValue; - } - - TBasicType getType() const { return type; } - -private: - union { - signed char i8Const; // used for i8vec, scalar int8s - unsigned char u8Const; // used for u8vec, scalar uint8s - signed short i16Const; // used for i16vec, scalar int16s - unsigned short u16Const; // used for u16vec, scalar uint16s - int iConst; // used for ivec, scalar ints - unsigned int uConst; // used for uvec, scalar uints - long long i64Const; // used for i64vec, scalar int64s - unsigned long long u64Const; // used for u64vec, scalar uint64s - bool bConst; // used for bvec, scalar bools - double dConst; // used for vec, dvec, mat, dmat, scalar floats and doubles - const TString* sConst; // string constant - }; - - TBasicType type; -}; - -// Encapsulate having a pointer to an array of TConstUnion, -// which only needs to be allocated if its size is going to be -// bigger than 0. -// -// One convenience is being able to use [] to go inside the array, instead -// of C++ assuming it as an array of pointers to vectors. -// -// General usage is that the size is known up front, and it is -// created once with the proper size. -// -class TConstUnionArray { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - TConstUnionArray() : unionArray(nullptr) { } - virtual ~TConstUnionArray() { } - - explicit TConstUnionArray(int size) - { - if (size == 0) - unionArray = nullptr; - else - unionArray = new TConstUnionVector(size); - } - TConstUnionArray(const TConstUnionArray& a) = default; - TConstUnionArray(const TConstUnionArray& a, int start, int size) - { - unionArray = new TConstUnionVector(size); - for (int i = 0; i < size; ++i) - (*unionArray)[i] = a[start + i]; - } - - // Use this constructor for a smear operation - TConstUnionArray(int size, const TConstUnion& val) - { - unionArray = new TConstUnionVector(size, val); - } - - int size() const { return unionArray ? (int)unionArray->size() : 0; } - TConstUnion& operator[](size_t index) { return (*unionArray)[index]; } - const TConstUnion& operator[](size_t index) const { return (*unionArray)[index]; } - bool operator==(const TConstUnionArray& rhs) const - { - // this includes the case that both are unallocated - if (unionArray == rhs.unionArray) - return true; - - if (! unionArray || ! rhs.unionArray) - return false; - - return *unionArray == *rhs.unionArray; - } - bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); } - - double dot(const TConstUnionArray& rhs) - { - assert(rhs.unionArray->size() == unionArray->size()); - double sum = 0.0; - - for (size_t comp = 0; comp < unionArray->size(); ++comp) - sum += (*this)[comp].getDConst() * rhs[comp].getDConst(); - - return sum; - } - - bool empty() const { return unionArray == nullptr; } - -protected: - typedef TVector TConstUnionVector; - TConstUnionVector* unionArray; -}; - -} // end namespace glslang - -#endif // _CONSTANT_UNION_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Include/InfoSink.h b/3rdparty/glslang/glslang/Include/InfoSink.h deleted file mode 100644 index dceb603c..00000000 --- a/3rdparty/glslang/glslang/Include/InfoSink.h +++ /dev/null @@ -1,144 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _INFOSINK_INCLUDED_ -#define _INFOSINK_INCLUDED_ - -#include "../Include/Common.h" -#include - -namespace glslang { - -// -// TPrefixType is used to centralize how info log messages start. -// See below. -// -enum TPrefixType { - EPrefixNone, - EPrefixWarning, - EPrefixError, - EPrefixInternalError, - EPrefixUnimplemented, - EPrefixNote -}; - -enum TOutputStream { - ENull = 0, - EDebugger = 0x01, - EStdOut = 0x02, - EString = 0x04, -}; -// -// Encapsulate info logs for all objects that have them. -// -// The methods are a general set of tools for getting a variety of -// messages and types inserted into the log. -// -class TInfoSinkBase { -public: - TInfoSinkBase() : outputStream(4) {} - void erase() { sink.erase(); } - TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; } - TInfoSinkBase& operator<<(char c) { append(1, c); return *this; } - TInfoSinkBase& operator<<(const char* s) { append(s); return *this; } - TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; } - TInfoSinkBase& operator<<(unsigned int n) { append(String(n)); return *this; } - TInfoSinkBase& operator<<(float n) { const int size = 40; char buf[size]; - snprintf(buf, size, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? "%f" : "%g", n); - append(buf); - return *this; } - TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; } - TInfoSinkBase& operator+(const TString& t) { append(t); return *this; } - TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; } - TInfoSinkBase& operator+(const char* s) { append(s); return *this; } - const char* c_str() const { return sink.c_str(); } - void prefix(TPrefixType message) { - switch(message) { - case EPrefixNone: break; - case EPrefixWarning: append("WARNING: "); break; - case EPrefixError: append("ERROR: "); break; - case EPrefixInternalError: append("INTERNAL ERROR: "); break; - case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break; - case EPrefixNote: append("NOTE: "); break; - default: append("UNKNOWN ERROR: "); break; - } - } - void location(const TSourceLoc& loc) { - const int maxSize = 24; - char locText[maxSize]; - snprintf(locText, maxSize, ":%d", loc.line); - append(loc.getStringNameOrNum(false).c_str()); - append(locText); - append(": "); - } - void message(TPrefixType message, const char* s) { - prefix(message); - append(s); - append("\n"); - } - void message(TPrefixType message, const char* s, const TSourceLoc& loc) { - prefix(message); - location(loc); - append(s); - append("\n"); - } - - void setOutputStream(int output = 4) - { - outputStream = output; - } - -protected: - void append(const char* s); - - void append(int count, char c); - void append(const TPersistString& t); - void append(const TString& t); - - void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2) - sink.reserve(sink.capacity() + sink.capacity() / 2); } - void appendToStream(const char* s); - TPersistString sink; - int outputStream; -}; - -} // end namespace glslang - -class TInfoSink { -public: - glslang::TInfoSinkBase info; - glslang::TInfoSinkBase debug; -}; - -#endif // _INFOSINK_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Include/InitializeGlobals.h b/3rdparty/glslang/glslang/Include/InitializeGlobals.h deleted file mode 100644 index b7fdd7aa..00000000 --- a/3rdparty/glslang/glslang/Include/InitializeGlobals.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef __INITIALIZE_GLOBALS_INCLUDED_ -#define __INITIALIZE_GLOBALS_INCLUDED_ - -namespace glslang { - -inline bool InitializePoolIndex() { return true; } // DEPRECATED: No need to call - -} // end namespace glslang - -#endif // __INITIALIZE_GLOBALS_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Include/PoolAlloc.h b/3rdparty/glslang/glslang/Include/PoolAlloc.h deleted file mode 100644 index e84ac52c..00000000 --- a/3rdparty/glslang/glslang/Include/PoolAlloc.h +++ /dev/null @@ -1,323 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _POOLALLOC_INCLUDED_ -#define _POOLALLOC_INCLUDED_ - -#ifndef NDEBUG -# define GUARD_BLOCKS // define to enable guard block sanity checking -#endif - -// -// This header defines an allocator that can be used to efficiently -// allocate a large number of small requests for heap memory, with the -// intention that they are not individually deallocated, but rather -// collectively deallocated at one time. -// -// This simultaneously -// -// * Makes each individual allocation much more efficient; the -// typical allocation is trivial. -// * Completely avoids the cost of doing individual deallocation. -// * Saves the trouble of tracking down and plugging a large class of leaks. -// -// Individual classes can use this allocator by supplying their own -// new and delete methods. -// -// STL containers can use this allocator by using the pool_allocator -// class as the allocator (second) template argument. -// - -#include -#include -#include - -namespace glslang { - -// If we are using guard blocks, we must track each individual -// allocation. If we aren't using guard blocks, these -// never get instantiated, so won't have any impact. -// - -class TAllocation { -public: - TAllocation(size_t size, unsigned char* mem, TAllocation* prev = nullptr) : - size(size), mem(mem), prevAlloc(prev) { - // Allocations are bracketed: - // [allocationHeader][initialGuardBlock][userData][finalGuardBlock] - // This would be cleaner with if (guardBlockSize)..., but that - // makes the compiler print warnings about 0 length memsets, - // even with the if() protecting them. -# ifdef GUARD_BLOCKS - memset(preGuard(), guardBlockBeginVal, guardBlockSize); - memset(data(), userDataFill, size); - memset(postGuard(), guardBlockEndVal, guardBlockSize); -# endif - } - - void check() const { - checkGuardBlock(preGuard(), guardBlockBeginVal, "before"); - checkGuardBlock(postGuard(), guardBlockEndVal, "after"); - } - - void checkAllocList() const; - - // Return total size needed to accommodate user buffer of 'size', - // plus our tracking data. - inline static size_t allocationSize(size_t size) { - return size + 2 * guardBlockSize + headerSize(); - } - - // Offset from surrounding buffer to get to user data buffer. - inline static unsigned char* offsetAllocation(unsigned char* m) { - return m + guardBlockSize + headerSize(); - } - -private: - void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const; - - // Find offsets to pre and post guard blocks, and user data buffer - unsigned char* preGuard() const { return mem + headerSize(); } - unsigned char* data() const { return preGuard() + guardBlockSize; } - unsigned char* postGuard() const { return data() + size; } - - size_t size; // size of the user data area - unsigned char* mem; // beginning of our allocation (pts to header) - TAllocation* prevAlloc; // prior allocation in the chain - - static inline constexpr unsigned char guardBlockBeginVal = 0xfb; - static inline constexpr unsigned char guardBlockEndVal = 0xfe; - static inline constexpr unsigned char userDataFill = 0xcd; - -# ifdef GUARD_BLOCKS - static inline constexpr size_t guardBlockSize = 16; -# else - static inline constexpr size_t guardBlockSize = 0; -# endif - -# ifdef GUARD_BLOCKS - inline static size_t headerSize() { return sizeof(TAllocation); } -# else - inline static size_t headerSize() { return 0; } -# endif -}; - -// -// There are several stacks. One is to track the pushing and popping -// of the user, and not yet implemented. The others are simply a -// repositories of free pages or used pages. -// -// Page stacks are linked together with a simple header at the beginning -// of each allocation obtained from the underlying OS. Multi-page allocations -// are returned to the OS. Individual page allocations are kept for future -// re-use. -// -// The "page size" used is not, nor must it match, the underlying OS -// page size. But, having it be about that size or equal to a set of -// pages is likely most optimal. -// -class TPoolAllocator { -public: - TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16); - - // - // Don't call the destructor just to free up the memory, call pop() - // - ~TPoolAllocator(); - - // - // Call push() to establish a new place to pop memory too. Does not - // have to be called to get things started. - // - void push(); - - // - // Call pop() to free all memory allocated since the last call to push(), - // or if no last call to push, frees all memory since first allocation. - // - void pop(); - - // - // Call popAll() to free all memory allocated. - // - void popAll(); - - // - // Call allocate() to actually acquire memory. Returns nullptr if no memory - // available, otherwise a properly aligned pointer to 'numBytes' of memory. - // - void* allocate(size_t numBytes); - - // - // There is no deallocate. The point of this class is that - // deallocation can be skipped by the user of it, as the model - // of use is to simultaneously deallocate everything at once - // by calling pop(), and to not have to solve memory leak problems. - // - -protected: - friend struct tHeader; - - struct tHeader { - tHeader(tHeader* nextPage, size_t pageCount) : -#ifdef GUARD_BLOCKS - lastAllocation(nullptr), -#endif - nextPage(nextPage), pageCount(pageCount) { } - - ~tHeader() { -#ifdef GUARD_BLOCKS - if (lastAllocation) - lastAllocation->checkAllocList(); -#endif - } - -#ifdef GUARD_BLOCKS - TAllocation* lastAllocation; -#endif - tHeader* nextPage; - size_t pageCount; - }; - - struct tAllocState { - size_t offset; - tHeader* page; - }; - typedef std::vector tAllocStack; - - // Track allocations if and only if we're using guard blocks -#ifndef GUARD_BLOCKS - void* initializeAllocation(tHeader*, unsigned char* memory, size_t) { -#else - void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) { - new(memory) TAllocation(numBytes, memory, block->lastAllocation); - block->lastAllocation = reinterpret_cast(memory); -#endif - - // This is optimized entirely away if GUARD_BLOCKS is not defined. - return TAllocation::offsetAllocation(memory); - } - - size_t pageSize; // granularity of allocation from the OS - size_t alignment; // all returned allocations will be aligned at - // this granularity, which will be a power of 2 - size_t alignmentMask; - size_t headerSkip; // amount of memory to skip to make room for the - // header (basically, size of header, rounded - // up to make it aligned - size_t currentPageOffset; // next offset in top of inUseList to allocate from - tHeader* freeList; // list of popped memory - tHeader* inUseList; // list of all memory currently being used - tAllocStack stack; // stack of where to allocate from, to partition pool - - int numCalls; // just an interesting statistic - size_t totalBytes; // just an interesting statistic -private: - TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator - TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor -}; - -// -// There could potentially be many pools with pops happening at -// different times. But a simple use is to have a global pop -// with everyone using the same global allocator. -// -extern TPoolAllocator& GetThreadPoolAllocator(); -void SetThreadPoolAllocator(TPoolAllocator* poolAllocator); - -// -// This STL compatible allocator is intended to be used as the allocator -// parameter to templatized STL containers, like vector and map. -// -// It will use the pools for allocation, and not -// do any deallocation, but will still do destruction. -// -template -class pool_allocator { -public: - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T *pointer; - typedef const T *const_pointer; - typedef T& reference; - typedef const T& const_reference; - typedef T value_type; - template - struct rebind { - typedef pool_allocator other; - }; - pointer address(reference x) const { return &x; } - const_pointer address(const_reference x) const { return &x; } - - pool_allocator() : allocator(GetThreadPoolAllocator()) { } - pool_allocator(TPoolAllocator& a) : allocator(a) { } - pool_allocator(const pool_allocator& p) : allocator(p.allocator) { } - - template - pool_allocator(const pool_allocator& p) : allocator(p.getAllocator()) { } - - pointer allocate(size_type n) { - return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } - pointer allocate(size_type n, const void*) { - return reinterpret_cast(getAllocator().allocate(n * sizeof(T))); } - - void deallocate(void*, size_type) { } - void deallocate(pointer, size_type) { } - - pointer _Charalloc(size_t n) { - return reinterpret_cast(getAllocator().allocate(n)); } - - void construct(pointer p, const T& val) { new ((void *)p) T(val); } - void destroy(pointer p) { p->T::~T(); } - - bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); } - bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); } - - size_type max_size() const { return static_cast(-1) / sizeof(T); } - size_type max_size(int size) const { return static_cast(-1) / size; } - - TPoolAllocator& getAllocator() const { return allocator; } - - pool_allocator select_on_container_copy_construction() const { return pool_allocator{}; } - -protected: - pool_allocator& operator=(const pool_allocator&) { return *this; } - TPoolAllocator& allocator; -}; - -} // end namespace glslang - -#endif // _POOLALLOC_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Include/ResourceLimits.h b/3rdparty/glslang/glslang/Include/ResourceLimits.h deleted file mode 100644 index b36c8d62..00000000 --- a/3rdparty/glslang/glslang/Include/ResourceLimits.h +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _RESOURCE_LIMITS_INCLUDED_ -#define _RESOURCE_LIMITS_INCLUDED_ - -struct TLimits { - bool nonInductiveForLoops; - bool whileLoops; - bool doWhileLoops; - bool generalUniformIndexing; - bool generalAttributeMatrixVectorIndexing; - bool generalVaryingIndexing; - bool generalSamplerIndexing; - bool generalVariableIndexing; - bool generalConstantMatrixVectorIndexing; -}; - -struct TBuiltInResource { - int maxLights; - int maxClipPlanes; - int maxTextureUnits; - int maxTextureCoords; - int maxVertexAttribs; - int maxVertexUniformComponents; - int maxVaryingFloats; - int maxVertexTextureImageUnits; - int maxCombinedTextureImageUnits; - int maxTextureImageUnits; - int maxFragmentUniformComponents; - int maxDrawBuffers; - int maxVertexUniformVectors; - int maxVaryingVectors; - int maxFragmentUniformVectors; - int maxVertexOutputVectors; - int maxFragmentInputVectors; - int minProgramTexelOffset; - int maxProgramTexelOffset; - int maxClipDistances; - int maxComputeWorkGroupCountX; - int maxComputeWorkGroupCountY; - int maxComputeWorkGroupCountZ; - int maxComputeWorkGroupSizeX; - int maxComputeWorkGroupSizeY; - int maxComputeWorkGroupSizeZ; - int maxComputeUniformComponents; - int maxComputeTextureImageUnits; - int maxComputeImageUniforms; - int maxComputeAtomicCounters; - int maxComputeAtomicCounterBuffers; - int maxVaryingComponents; - int maxVertexOutputComponents; - int maxGeometryInputComponents; - int maxGeometryOutputComponents; - int maxFragmentInputComponents; - int maxImageUnits; - int maxCombinedImageUnitsAndFragmentOutputs; - int maxCombinedShaderOutputResources; - int maxImageSamples; - int maxVertexImageUniforms; - int maxTessControlImageUniforms; - int maxTessEvaluationImageUniforms; - int maxGeometryImageUniforms; - int maxFragmentImageUniforms; - int maxCombinedImageUniforms; - int maxGeometryTextureImageUnits; - int maxGeometryOutputVertices; - int maxGeometryTotalOutputComponents; - int maxGeometryUniformComponents; - int maxGeometryVaryingComponents; - int maxTessControlInputComponents; - int maxTessControlOutputComponents; - int maxTessControlTextureImageUnits; - int maxTessControlUniformComponents; - int maxTessControlTotalOutputComponents; - int maxTessEvaluationInputComponents; - int maxTessEvaluationOutputComponents; - int maxTessEvaluationTextureImageUnits; - int maxTessEvaluationUniformComponents; - int maxTessPatchComponents; - int maxPatchVertices; - int maxTessGenLevel; - int maxViewports; - int maxVertexAtomicCounters; - int maxTessControlAtomicCounters; - int maxTessEvaluationAtomicCounters; - int maxGeometryAtomicCounters; - int maxFragmentAtomicCounters; - int maxCombinedAtomicCounters; - int maxAtomicCounterBindings; - int maxVertexAtomicCounterBuffers; - int maxTessControlAtomicCounterBuffers; - int maxTessEvaluationAtomicCounterBuffers; - int maxGeometryAtomicCounterBuffers; - int maxFragmentAtomicCounterBuffers; - int maxCombinedAtomicCounterBuffers; - int maxAtomicCounterBufferSize; - int maxTransformFeedbackBuffers; - int maxTransformFeedbackInterleavedComponents; - int maxCullDistances; - int maxCombinedClipAndCullDistances; - int maxSamples; - int maxMeshOutputVerticesNV; - int maxMeshOutputPrimitivesNV; - int maxMeshWorkGroupSizeX_NV; - int maxMeshWorkGroupSizeY_NV; - int maxMeshWorkGroupSizeZ_NV; - int maxTaskWorkGroupSizeX_NV; - int maxTaskWorkGroupSizeY_NV; - int maxTaskWorkGroupSizeZ_NV; - int maxMeshViewCountNV; - int maxMeshOutputVerticesEXT; - int maxMeshOutputPrimitivesEXT; - int maxMeshWorkGroupSizeX_EXT; - int maxMeshWorkGroupSizeY_EXT; - int maxMeshWorkGroupSizeZ_EXT; - int maxTaskWorkGroupSizeX_EXT; - int maxTaskWorkGroupSizeY_EXT; - int maxTaskWorkGroupSizeZ_EXT; - int maxMeshViewCountEXT; - int maxDualSourceDrawBuffersEXT; - - TLimits limits; -}; - -#endif // _RESOURCE_LIMITS_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Include/ShHandle.h b/3rdparty/glslang/glslang/Include/ShHandle.h deleted file mode 100644 index dee47c0d..00000000 --- a/3rdparty/glslang/glslang/Include/ShHandle.h +++ /dev/null @@ -1,176 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _SHHANDLE_INCLUDED_ -#define _SHHANDLE_INCLUDED_ - -// -// Machine independent part of the compiler private objects -// sent as ShHandle to the driver. -// -// This should not be included by driver code. -// - -#define SH_EXPORTING -#include "../Public/ShaderLang.h" -#include "../MachineIndependent/Versions.h" -#include "InfoSink.h" - -class TCompiler; -class TLinker; -class TUniformMap; - -// -// The base class used to back handles returned to the driver. -// -class TShHandleBase { -public: - TShHandleBase() { pool = new glslang::TPoolAllocator; } - virtual ~TShHandleBase() { delete pool; } - virtual TCompiler* getAsCompiler() { return nullptr; } - virtual TLinker* getAsLinker() { return nullptr; } - virtual TUniformMap* getAsUniformMap() { return nullptr; } - virtual glslang::TPoolAllocator* getPool() const { return pool; } -private: - glslang::TPoolAllocator* pool; -}; - -// -// The base class for the machine dependent linker to derive from -// for managing where uniforms live. -// -class TUniformMap : public TShHandleBase { -public: - TUniformMap() { } - virtual ~TUniformMap() { } - virtual TUniformMap* getAsUniformMap() { return this; } - virtual int getLocation(const char* name) = 0; - virtual TInfoSink& getInfoSink() { return infoSink; } - TInfoSink infoSink; -}; - -class TIntermNode; - -// -// The base class for the machine dependent compiler to derive from -// for managing object code from the compile. -// -class TCompiler : public TShHandleBase { -public: - TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { } - virtual ~TCompiler() { } - EShLanguage getLanguage() { return language; } - virtual TInfoSink& getInfoSink() { return infoSink; } - - virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile) = 0; - - virtual TCompiler* getAsCompiler() { return this; } - virtual bool linkable() { return haveValidObjectCode; } - - TInfoSink& infoSink; -protected: - TCompiler& operator=(TCompiler&); - - EShLanguage language; - bool haveValidObjectCode; -}; - -// -// Link operations are based on a list of compile results... -// -typedef glslang::TVector TCompilerList; -typedef glslang::TVector THandleList; - -// -// The base class for the machine dependent linker to derive from -// to manage the resulting executable. -// - -class TLinker : public TShHandleBase { -public: - TLinker(EShExecutable e, TInfoSink& iSink) : - infoSink(iSink), - executable(e), - haveReturnableObjectCode(false), - appAttributeBindings(nullptr), - fixedAttributeBindings(nullptr), - excludedAttributes(nullptr), - excludedCount(0), - uniformBindings(nullptr) { } - virtual TLinker* getAsLinker() { return this; } - virtual ~TLinker() { } - virtual bool link(TCompilerList&, TUniformMap*) = 0; - virtual bool link(THandleList&) { return false; } - virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; } - virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; } - virtual void getAttributeBindings(ShBindingTable const **t) const = 0; - virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; } - virtual ShBindingTable* getUniformBindings() const { return uniformBindings; } - virtual const void* getObjectCode() const { return nullptr; } // a real compiler would be returning object code here - virtual TInfoSink& getInfoSink() { return infoSink; } - TInfoSink& infoSink; -protected: - TLinker& operator=(TLinker&); - EShExecutable executable; - bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver - - const ShBindingTable* appAttributeBindings; - const ShBindingTable* fixedAttributeBindings; - const int* excludedAttributes; - int excludedCount; - ShBindingTable* uniformBindings; // created by the linker -}; - -// -// This is the interface between the machine independent code -// and the machine dependent code. -// -// The machine dependent code should derive from the classes -// above. Then Construct*() and Delete*() will create and -// destroy the machine dependent objects, which contain the -// above machine independent information. -// -TCompiler* ConstructCompiler(EShLanguage, int); - -TShHandleBase* ConstructLinker(EShExecutable, int); -TShHandleBase* ConstructBindings(); -void DeleteLinker(TShHandleBase*); -void DeleteBindingList(TShHandleBase* bindingList); - -TUniformMap* ConstructUniformMap(); -void DeleteCompiler(TCompiler*); - -void DeleteUniformMap(TUniformMap*); - -#endif // _SHHANDLE_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Include/SpirvIntrinsics.h b/3rdparty/glslang/glslang/Include/SpirvIntrinsics.h deleted file mode 100644 index 0082a4d4..00000000 --- a/3rdparty/glslang/glslang/Include/SpirvIntrinsics.h +++ /dev/null @@ -1,140 +0,0 @@ -// -// Copyright(C) 2021 Advanced Micro Devices, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -// -// GL_EXT_spirv_intrinsics -// -#include "Common.h" -#include - -namespace glslang { - -class TIntermTyped; -class TIntermConstantUnion; -class TType; - -// SPIR-V requirements -struct TSpirvRequirement { - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - // capability = [..] - TSet extensions; - // extension = [..] - TSet capabilities; -}; - -// SPIR-V execution modes -struct TSpirvExecutionMode { - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - // spirv_execution_mode - TMap> modes; - // spirv_execution_mode_id - TMap > modeIds; -}; - -// SPIR-V decorations -struct TSpirvDecorate { - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - // spirv_decorate - TMap > decorates; - // spirv_decorate_id - TMap> decorateIds; - // spirv_decorate_string - TMap > decorateStrings; -}; - -// SPIR-V instruction -struct TSpirvInstruction { - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - TSpirvInstruction() { set = ""; id = -1; } - - bool operator==(const TSpirvInstruction& rhs) const { return set == rhs.set && id == rhs.id; } - bool operator!=(const TSpirvInstruction& rhs) const { return !operator==(rhs); } - - // spirv_instruction - TString set; - int id; -}; - -// SPIR-V type parameter -struct TSpirvTypeParameter { - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - TSpirvTypeParameter(const TIntermConstantUnion* arg) { value = arg; } - TSpirvTypeParameter(const TType* arg) { value = arg; } - - const TIntermConstantUnion* getAsConstant() const - { - if (value.index() == 0) - return std::get(value); - return nullptr; - } - const TType* getAsType() const - { - if (value.index() == 1) - return std::get(value); - return nullptr; - } - - bool operator==(const TSpirvTypeParameter& rhs) const; - bool operator!=(const TSpirvTypeParameter& rhs) const { return !operator==(rhs); } - - // Parameter value: constant expression or type specifier - std::variant value; -}; - -typedef TVector TSpirvTypeParameters; - -// SPIR-V type -struct TSpirvType { - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - bool operator==(const TSpirvType& rhs) const - { - return spirvInst == rhs.spirvInst && typeParams == rhs.typeParams; - } - bool operator!=(const TSpirvType& rhs) const { return !operator==(rhs); } - - // spirv_type - TSpirvInstruction spirvInst; - TSpirvTypeParameters typeParams; -}; - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/Include/Types.h b/3rdparty/glslang/glslang/Include/Types.h deleted file mode 100644 index 1fb59e5b..00000000 --- a/3rdparty/glslang/glslang/Include/Types.h +++ /dev/null @@ -1,2877 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2016 LunarG, Inc. -// Copyright (C) 2015-2016 Google, Inc. -// Copyright (C) 2017 ARM Limited. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _TYPES_INCLUDED -#define _TYPES_INCLUDED - -#include "../Include/Common.h" -#include "../Include/BaseTypes.h" -#include "../Public/ShaderLang.h" -#include "arrays.h" -#include "SpirvIntrinsics.h" - -#include - -namespace glslang { - -class TIntermAggregate; - -const int GlslangMaxTypeLength = 200; // TODO: need to print block/struct one member per line, so this can stay bounded - -const char* const AnonymousPrefix = "anon@"; // for something like a block whose members can be directly accessed -inline bool IsAnonymous(const TString& name) -{ - return name.compare(0, 5, AnonymousPrefix) == 0; -} - -// -// Details within a sampler type -// -enum TSamplerDim { - EsdNone, - Esd1D, - Esd2D, - Esd3D, - EsdCube, - EsdRect, - EsdBuffer, - EsdSubpass, // goes only with non-sampled image (image is true) - EsdAttachmentEXT, - EsdNumDims -}; - -struct TSampler { // misnomer now; includes images, textures without sampler, and textures with sampler - TBasicType type : 8; // type returned by sampler - TSamplerDim dim : 8; - bool arrayed : 1; - bool shadow : 1; - bool ms : 1; - bool image : 1; // image, combined should be false - bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler - bool sampler : 1; // true means a pure sampler, other fields should be clear() - - unsigned int vectorSize : 3; // vector return type size. - // Some languages support structures as sample results. Storing the whole structure in the - // TSampler is too large, so there is an index to a separate table. - static const unsigned structReturnIndexBits = 4; // number of index bits to use. - static const unsigned structReturnSlots = (1< TTypeList; - -typedef TVector TIdentifierList; - -// -// Following are a series of helper enums for managing layouts and qualifiers, -// used for TPublicType, TType, others. -// - -enum TLayoutPacking { - ElpNone, - ElpShared, // default, but different than saying nothing - ElpStd140, - ElpStd430, - ElpPacked, - ElpScalar, - ElpCount // If expanding, see bitfield width below -}; - -enum TLayoutMatrix { - ElmNone, - ElmRowMajor, - ElmColumnMajor, // default, but different than saying nothing - ElmCount // If expanding, see bitfield width below -}; - -// Union of geometry shader and tessellation shader geometry types. -// They don't go into TType, but rather have current state per shader or -// active parser type (TPublicType). -enum TLayoutGeometry { - ElgNone, - ElgPoints, - ElgLines, - ElgLinesAdjacency, - ElgLineStrip, - ElgTriangles, - ElgTrianglesAdjacency, - ElgTriangleStrip, - ElgQuads, - ElgIsolines, -}; - -enum TVertexSpacing { - EvsNone, - EvsEqual, - EvsFractionalEven, - EvsFractionalOdd -}; - -enum TVertexOrder { - EvoNone, - EvoCw, - EvoCcw -}; - -// Note: order matters, as type of format is done by comparison. -enum TLayoutFormat { - ElfNone, - - // Float image - ElfRgba32f, - ElfRgba16f, - ElfR32f, - ElfRgba8, - ElfRgba8Snorm, - - ElfEsFloatGuard, // to help with comparisons - - ElfRg32f, - ElfRg16f, - ElfR11fG11fB10f, - ElfR16f, - ElfRgba16, - ElfRgb10A2, - ElfRg16, - ElfRg8, - ElfR16, - ElfR8, - ElfRgba16Snorm, - ElfRg16Snorm, - ElfRg8Snorm, - ElfR16Snorm, - ElfR8Snorm, - - ElfFloatGuard, // to help with comparisons - - // Int image - ElfRgba32i, - ElfRgba16i, - ElfRgba8i, - ElfR32i, - - ElfEsIntGuard, // to help with comparisons - - ElfRg32i, - ElfRg16i, - ElfRg8i, - ElfR16i, - ElfR8i, - ElfR64i, - - ElfIntGuard, // to help with comparisons - - // Uint image - ElfRgba32ui, - ElfRgba16ui, - ElfRgba8ui, - ElfR32ui, - - ElfEsUintGuard, // to help with comparisons - - ElfRg32ui, - ElfRg16ui, - ElfRgb10a2ui, - ElfRg8ui, - ElfR16ui, - ElfR8ui, - ElfR64ui, - ElfExtSizeGuard, // to help with comparisons - ElfSize1x8, - ElfSize1x16, - ElfSize1x32, - ElfSize2x32, - ElfSize4x32, - - ElfCount -}; - -enum TLayoutDepth { - EldNone, - EldAny, - EldGreater, - EldLess, - EldUnchanged, - - EldCount -}; - -enum TLayoutStencil { - ElsNone, - ElsRefUnchangedFrontAMD, - ElsRefGreaterFrontAMD, - ElsRefLessFrontAMD, - ElsRefUnchangedBackAMD, - ElsRefGreaterBackAMD, - ElsRefLessBackAMD, - - ElsCount -}; - -enum TBlendEquationShift { - // No 'EBlendNone': - // These are used as bit-shift amounts. A mask of such shifts will have type 'int', - // and in that space, 0 means no bits set, or none. In this enum, 0 means (1 << 0), a bit is set. - EBlendMultiply, - EBlendScreen, - EBlendOverlay, - EBlendDarken, - EBlendLighten, - EBlendColordodge, - EBlendColorburn, - EBlendHardlight, - EBlendSoftlight, - EBlendDifference, - EBlendExclusion, - EBlendHslHue, - EBlendHslSaturation, - EBlendHslColor, - EBlendHslLuminosity, - EBlendAllEquations, - - EBlendCount -}; - -enum TInterlockOrdering { - EioNone, - EioPixelInterlockOrdered, - EioPixelInterlockUnordered, - EioSampleInterlockOrdered, - EioSampleInterlockUnordered, - EioShadingRateInterlockOrdered, - EioShadingRateInterlockUnordered, - - EioCount, -}; - -enum TShaderInterface -{ - // Includes both uniform blocks and buffer blocks - EsiUniform = 0, - EsiInput, - EsiOutput, - EsiNone, - - EsiCount -}; - -class TQualifier { -public: - static const int layoutNotSet = -1; - - void clear() - { - precision = EpqNone; - invariant = false; - makeTemporary(); - declaredBuiltIn = EbvNone; - noContraction = false; - nullInit = false; - spirvByReference = false; - spirvLiteral = false; - defaultBlock = false; - } - - // drop qualifiers that don't belong in a temporary variable - void makeTemporary() - { - semanticName = nullptr; - storage = EvqTemporary; - builtIn = EbvNone; - clearInterstage(); - clearMemory(); - specConstant = false; - nonUniform = false; - nullInit = false; - defaultBlock = false; - clearLayout(); - spirvStorageClass = -1; - spirvDecorate = nullptr; - spirvByReference = false; - spirvLiteral = false; - } - - void clearInterstage() - { - clearInterpolation(); - patch = false; - sample = false; - } - - void clearInterpolation() - { - centroid = false; - smooth = false; - flat = false; - nopersp = false; - explicitInterp = false; - pervertexNV = false; - perPrimitiveNV = false; - perViewNV = false; - perTaskNV = false; - pervertexEXT = false; - } - - void clearMemory() - { - coherent = false; - devicecoherent = false; - queuefamilycoherent = false; - workgroupcoherent = false; - subgroupcoherent = false; - shadercallcoherent = false; - nonprivate = false; - volatil = false; - restrict = false; - readonly = false; - writeonly = false; - } - - const char* semanticName; - TStorageQualifier storage : 6; - TBuiltInVariable builtIn : 9; - TBuiltInVariable declaredBuiltIn : 9; - static_assert(EbvLast < 256, "need to increase size of TBuiltInVariable bitfields!"); - TPrecisionQualifier precision : 3; - bool invariant : 1; // require canonical treatment for cross-shader invariance - bool centroid : 1; - bool smooth : 1; - bool flat : 1; - // having a constant_id is not sufficient: expressions have no id, but are still specConstant - bool specConstant : 1; - bool nonUniform : 1; - bool explicitOffset : 1; - bool defaultBlock : 1; // default blocks with matching names have structures merged when linking - - bool noContraction: 1; // prevent contraction and reassociation, e.g., for 'precise' keyword, and expressions it affects - bool nopersp : 1; - bool explicitInterp : 1; - bool pervertexNV : 1; - bool pervertexEXT : 1; - bool perPrimitiveNV : 1; - bool perViewNV : 1; - bool perTaskNV : 1; - bool patch : 1; - bool sample : 1; - bool restrict : 1; - bool readonly : 1; - bool writeonly : 1; - bool coherent : 1; - bool volatil : 1; - bool devicecoherent : 1; - bool queuefamilycoherent : 1; - bool workgroupcoherent : 1; - bool subgroupcoherent : 1; - bool shadercallcoherent : 1; - bool nonprivate : 1; - bool nullInit : 1; - bool spirvByReference : 1; - bool spirvLiteral : 1; - bool isWriteOnly() const { return writeonly; } - bool isReadOnly() const { return readonly; } - bool isRestrict() const { return restrict; } - bool isCoherent() const { return coherent; } - bool isVolatile() const { return volatil; } - bool isSample() const { return sample; } - bool isMemory() const - { - return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate; - } - bool isMemoryQualifierImageAndSSBOOnly() const - { - return shadercallcoherent || subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly; - } - bool bufferReferenceNeedsVulkanMemoryModel() const - { - // include qualifiers that map to load/store availability/visibility/nonprivate memory access operands - return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || nonprivate; - } - bool isInterpolation() const - { - return flat || smooth || nopersp || explicitInterp; - } - bool isExplicitInterpolation() const - { - return explicitInterp; - } - bool isAuxiliary() const - { - return centroid || patch || sample || pervertexNV || pervertexEXT; - } - bool isPatch() const { return patch; } - bool isNoContraction() const { return noContraction; } - void setNoContraction() { noContraction = true; } - bool isPervertexNV() const { return pervertexNV; } - bool isPervertexEXT() const { return pervertexEXT; } - void setNullInit() { nullInit = true; } - bool isNullInit() const { return nullInit; } - void setSpirvByReference() { spirvByReference = true; } - bool isSpirvByReference() const { return spirvByReference; } - void setSpirvLiteral() { spirvLiteral = true; } - bool isSpirvLiteral() const { return spirvLiteral; } - - bool isPipeInput() const - { - switch (storage) { - case EvqVaryingIn: - case EvqFragCoord: - case EvqPointCoord: - case EvqFace: - case EvqVertexId: - case EvqInstanceId: - return true; - default: - return false; - } - } - - bool isPipeOutput() const - { - switch (storage) { - case EvqPosition: - case EvqPointSize: - case EvqClipVertex: - case EvqVaryingOut: - case EvqFragColor: - case EvqFragDepth: - case EvqFragStencil: - return true; - default: - return false; - } - } - - bool isParamInput() const - { - switch (storage) { - case EvqIn: - case EvqInOut: - case EvqConstReadOnly: - return true; - default: - return false; - } - } - - bool isParamOutput() const - { - switch (storage) { - case EvqOut: - case EvqInOut: - return true; - default: - return false; - } - } - - bool isUniformOrBuffer() const - { - switch (storage) { - case EvqUniform: - case EvqBuffer: - return true; - default: - return false; - } - } - - bool isUniform() const - { - switch (storage) { - case EvqUniform: - return true; - default: - return false; - } - } - - bool isIo() const - { - switch (storage) { - case EvqUniform: - case EvqBuffer: - case EvqVaryingIn: - case EvqFragCoord: - case EvqPointCoord: - case EvqFace: - case EvqVertexId: - case EvqInstanceId: - case EvqPosition: - case EvqPointSize: - case EvqClipVertex: - case EvqVaryingOut: - case EvqFragColor: - case EvqFragDepth: - case EvqFragStencil: - return true; - default: - return false; - } - } - - // non-built-in symbols that might link between compilation units - bool isLinkable() const - { - switch (storage) { - case EvqGlobal: - case EvqVaryingIn: - case EvqVaryingOut: - case EvqUniform: - case EvqBuffer: - case EvqShared: - return true; - default: - return false; - } - } - - TBlockStorageClass getBlockStorage() const { - if (storage == EvqUniform && !isPushConstant()) { - return EbsUniform; - } - else if (storage == EvqUniform) { - return EbsPushConstant; - } - else if (storage == EvqBuffer) { - return EbsStorageBuffer; - } - return EbsNone; - } - - void setBlockStorage(TBlockStorageClass newBacking) { - layoutPushConstant = (newBacking == EbsPushConstant); - switch (newBacking) { - case EbsUniform : - if (layoutPacking == ElpStd430) { - // std430 would not be valid - layoutPacking = ElpStd140; - } - storage = EvqUniform; - break; - case EbsStorageBuffer : - storage = EvqBuffer; - break; - case EbsPushConstant : - storage = EvqUniform; - layoutSet = TQualifier::layoutSetEnd; - layoutBinding = TQualifier::layoutBindingEnd; - break; - default: - break; - } - } - - bool isPerPrimitive() const { return perPrimitiveNV; } - bool isPerView() const { return perViewNV; } - bool isTaskMemory() const { return perTaskNV; } - bool isTaskPayload() const { return storage == EvqtaskPayloadSharedEXT; } - bool isAnyPayload() const { - return storage == EvqPayload || storage == EvqPayloadIn; - } - bool isAnyCallable() const { - return storage == EvqCallableData || storage == EvqCallableDataIn; - } - bool isHitObjectAttrNV() const { - return storage == EvqHitObjectAttrNV; - } - - // True if this type of IO is supposed to be arrayed with extra level for per-vertex data - bool isArrayedIo(EShLanguage language) const - { - switch (language) { - case EShLangGeometry: - return isPipeInput(); - case EShLangTessControl: - return ! patch && (isPipeInput() || isPipeOutput()); - case EShLangTessEvaluation: - return ! patch && isPipeInput(); - case EShLangFragment: - return (pervertexNV || pervertexEXT) && isPipeInput(); - case EShLangMesh: - return ! perTaskNV && isPipeOutput(); - - default: - return false; - } - } - - // Implementing an embedded layout-qualifier class here, since C++ can't have a real class bitfield - void clearLayout() // all layout - { - clearUniformLayout(); - - layoutPushConstant = false; - layoutBufferReference = false; - layoutPassthrough = false; - layoutViewportRelative = false; - // -2048 as the default value indicating layoutSecondaryViewportRelative is not set - layoutSecondaryViewportRelativeOffset = -2048; - layoutShaderRecord = false; - layoutHitObjectShaderRecordNV = false; - layoutBindlessSampler = false; - layoutBindlessImage = false; - layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd; - layoutFormat = ElfNone; - - clearInterstageLayout(); - - layoutSpecConstantId = layoutSpecConstantIdEnd; - } - void clearInterstageLayout() - { - layoutLocation = layoutLocationEnd; - layoutComponent = layoutComponentEnd; - layoutIndex = layoutIndexEnd; - clearStreamLayout(); - clearXfbLayout(); - } - - void clearStreamLayout() - { - layoutStream = layoutStreamEnd; - } - void clearXfbLayout() - { - layoutXfbBuffer = layoutXfbBufferEnd; - layoutXfbStride = layoutXfbStrideEnd; - layoutXfbOffset = layoutXfbOffsetEnd; - } - - bool hasNonXfbLayout() const - { - return hasUniformLayout() || - hasAnyLocation() || - hasStream() || - hasFormat() || - isShaderRecord() || - isPushConstant() || - hasBufferReference(); - } - bool hasLayout() const - { - return hasNonXfbLayout() || - hasXfb(); - } - - TLayoutMatrix layoutMatrix : 3; - TLayoutPacking layoutPacking : 4; - int layoutOffset; - int layoutAlign; - - unsigned int layoutLocation : 12; - static const unsigned int layoutLocationEnd = 0xFFF; - - unsigned int layoutComponent : 3; - static const unsigned int layoutComponentEnd = 4; - - unsigned int layoutSet : 7; - static const unsigned int layoutSetEnd = 0x3F; - - unsigned int layoutBinding : 16; - static const unsigned int layoutBindingEnd = 0xFFFF; - - unsigned int layoutIndex : 8; - static const unsigned int layoutIndexEnd = 0xFF; - - unsigned int layoutStream : 8; - static const unsigned int layoutStreamEnd = 0xFF; - - unsigned int layoutXfbBuffer : 4; - static const unsigned int layoutXfbBufferEnd = 0xF; - - unsigned int layoutXfbStride : 14; - static const unsigned int layoutXfbStrideEnd = 0x3FFF; - - unsigned int layoutXfbOffset : 13; - static const unsigned int layoutXfbOffsetEnd = 0x1FFF; - - unsigned int layoutAttachment : 8; // for input_attachment_index - static const unsigned int layoutAttachmentEnd = 0XFF; - - unsigned int layoutSpecConstantId : 11; - static const unsigned int layoutSpecConstantIdEnd = 0x7FF; - - // stored as log2 of the actual alignment value - unsigned int layoutBufferReferenceAlign : 6; - static const unsigned int layoutBufferReferenceAlignEnd = 0x3F; - - TLayoutFormat layoutFormat : 8; - - bool layoutPushConstant; - bool layoutBufferReference; - bool layoutPassthrough; - bool layoutViewportRelative; - int layoutSecondaryViewportRelativeOffset; - bool layoutShaderRecord; - bool layoutHitObjectShaderRecordNV; - - // GL_EXT_spirv_intrinsics - int spirvStorageClass; - TSpirvDecorate* spirvDecorate; - - bool layoutBindlessSampler; - bool layoutBindlessImage; - - bool hasUniformLayout() const - { - return hasMatrix() || - hasPacking() || - hasOffset() || - hasBinding() || - hasSet() || - hasAlign(); - } - void clearUniformLayout() // only uniform specific - { - layoutMatrix = ElmNone; - layoutPacking = ElpNone; - layoutOffset = layoutNotSet; - layoutAlign = layoutNotSet; - - layoutSet = layoutSetEnd; - layoutBinding = layoutBindingEnd; - layoutAttachment = layoutAttachmentEnd; - } - - bool hasMatrix() const - { - return layoutMatrix != ElmNone; - } - bool hasPacking() const - { - return layoutPacking != ElpNone; - } - bool hasAlign() const - { - return layoutAlign != layoutNotSet; - } - bool hasAnyLocation() const - { - return hasLocation() || - hasComponent() || - hasIndex(); - } - bool hasLocation() const - { - return layoutLocation != layoutLocationEnd; - } - bool hasSet() const - { - return layoutSet != layoutSetEnd; - } - bool hasBinding() const - { - return layoutBinding != layoutBindingEnd; - } - bool hasOffset() const - { - return layoutOffset != layoutNotSet; - } - bool isNonPerspective() const { return nopersp; } - bool hasIndex() const - { - return layoutIndex != layoutIndexEnd; - } - unsigned getIndex() const { return layoutIndex; } - bool hasComponent() const - { - return layoutComponent != layoutComponentEnd; - } - bool hasStream() const - { - return layoutStream != layoutStreamEnd; - } - bool hasFormat() const - { - return layoutFormat != ElfNone; - } - bool hasXfb() const - { - return hasXfbBuffer() || - hasXfbStride() || - hasXfbOffset(); - } - bool hasXfbBuffer() const - { - return layoutXfbBuffer != layoutXfbBufferEnd; - } - bool hasXfbStride() const - { - return layoutXfbStride != layoutXfbStrideEnd; - } - bool hasXfbOffset() const - { - return layoutXfbOffset != layoutXfbOffsetEnd; - } - bool hasAttachment() const - { - return layoutAttachment != layoutAttachmentEnd; - } - TLayoutFormat getFormat() const { return layoutFormat; } - bool isPushConstant() const { return layoutPushConstant; } - bool isShaderRecord() const { return layoutShaderRecord; } - bool hasHitObjectShaderRecordNV() const { return layoutHitObjectShaderRecordNV; } - bool hasBufferReference() const { return layoutBufferReference; } - bool hasBufferReferenceAlign() const - { - return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd; - } - bool isNonUniform() const - { - return nonUniform; - } - bool isBindlessSampler() const - { - return layoutBindlessSampler; - } - bool isBindlessImage() const - { - return layoutBindlessImage; - } - - // GL_EXT_spirv_intrinsics - bool hasSpirvDecorate() const { return spirvDecorate != nullptr; } - void setSpirvDecorate(int decoration, const TIntermAggregate* args = nullptr); - void setSpirvDecorateId(int decoration, const TIntermAggregate* args); - void setSpirvDecorateString(int decoration, const TIntermAggregate* args); - const TSpirvDecorate& getSpirvDecorate() const { assert(spirvDecorate); return *spirvDecorate; } - TSpirvDecorate& getSpirvDecorate() { assert(spirvDecorate); return *spirvDecorate; } - TString getSpirvDecorateQualifierString() const; - - bool hasSpecConstantId() const - { - // Not the same thing as being a specialization constant, this - // is just whether or not it was declared with an ID. - return layoutSpecConstantId != layoutSpecConstantIdEnd; - } - bool isSpecConstant() const - { - // True if type is a specialization constant, whether or not it - // had a specialization-constant ID, and false if it is not a - // true front-end constant. - return specConstant; - } - bool isFrontEndConstant() const - { - // True if the front-end knows the final constant value. - // This allows front-end constant folding. - return storage == EvqConst && ! specConstant; - } - bool isConstant() const - { - // True if is either kind of constant; specialization or regular. - return isFrontEndConstant() || isSpecConstant(); - } - void makeSpecConstant() - { - storage = EvqConst; - specConstant = true; - } - static const char* getLayoutPackingString(TLayoutPacking packing) - { - switch (packing) { - case ElpStd140: return "std140"; - case ElpPacked: return "packed"; - case ElpShared: return "shared"; - case ElpStd430: return "std430"; - case ElpScalar: return "scalar"; - default: return "none"; - } - } - static const char* getLayoutMatrixString(TLayoutMatrix m) - { - switch (m) { - case ElmColumnMajor: return "column_major"; - case ElmRowMajor: return "row_major"; - default: return "none"; - } - } - static const char* getLayoutFormatString(TLayoutFormat f) - { - switch (f) { - case ElfRgba32f: return "rgba32f"; - case ElfRgba16f: return "rgba16f"; - case ElfRg32f: return "rg32f"; - case ElfRg16f: return "rg16f"; - case ElfR11fG11fB10f: return "r11f_g11f_b10f"; - case ElfR32f: return "r32f"; - case ElfR16f: return "r16f"; - case ElfRgba16: return "rgba16"; - case ElfRgb10A2: return "rgb10_a2"; - case ElfRgba8: return "rgba8"; - case ElfRg16: return "rg16"; - case ElfRg8: return "rg8"; - case ElfR16: return "r16"; - case ElfR8: return "r8"; - case ElfRgba16Snorm: return "rgba16_snorm"; - case ElfRgba8Snorm: return "rgba8_snorm"; - case ElfRg16Snorm: return "rg16_snorm"; - case ElfRg8Snorm: return "rg8_snorm"; - case ElfR16Snorm: return "r16_snorm"; - case ElfR8Snorm: return "r8_snorm"; - - case ElfRgba32i: return "rgba32i"; - case ElfRgba16i: return "rgba16i"; - case ElfRgba8i: return "rgba8i"; - case ElfRg32i: return "rg32i"; - case ElfRg16i: return "rg16i"; - case ElfRg8i: return "rg8i"; - case ElfR32i: return "r32i"; - case ElfR16i: return "r16i"; - case ElfR8i: return "r8i"; - - case ElfRgba32ui: return "rgba32ui"; - case ElfRgba16ui: return "rgba16ui"; - case ElfRgba8ui: return "rgba8ui"; - case ElfRg32ui: return "rg32ui"; - case ElfRg16ui: return "rg16ui"; - case ElfRgb10a2ui: return "rgb10_a2ui"; - case ElfRg8ui: return "rg8ui"; - case ElfR32ui: return "r32ui"; - case ElfR16ui: return "r16ui"; - case ElfR8ui: return "r8ui"; - case ElfR64ui: return "r64ui"; - case ElfR64i: return "r64i"; - case ElfSize1x8: return "size1x8"; - case ElfSize1x16: return "size1x16"; - case ElfSize1x32: return "size1x32"; - case ElfSize2x32: return "size2x32"; - case ElfSize4x32: return "size4x32"; - default: return "none"; - } - } - static const char* getLayoutDepthString(TLayoutDepth d) - { - switch (d) { - case EldAny: return "depth_any"; - case EldGreater: return "depth_greater"; - case EldLess: return "depth_less"; - case EldUnchanged: return "depth_unchanged"; - default: return "none"; - } - } - static const char* getLayoutStencilString(TLayoutStencil s) - { - switch (s) { - case ElsRefUnchangedFrontAMD: return "stencil_ref_unchanged_front_amd"; - case ElsRefGreaterFrontAMD: return "stencil_ref_greater_front_amd"; - case ElsRefLessFrontAMD: return "stencil_ref_less_front_amd"; - case ElsRefUnchangedBackAMD: return "stencil_ref_unchanged_back_amd"; - case ElsRefGreaterBackAMD: return "stencil_ref_greater_back_amd"; - case ElsRefLessBackAMD: return "stencil_ref_less_back_amd"; - default: return "none"; - } - } - static const char* getBlendEquationString(TBlendEquationShift e) - { - switch (e) { - case EBlendMultiply: return "blend_support_multiply"; - case EBlendScreen: return "blend_support_screen"; - case EBlendOverlay: return "blend_support_overlay"; - case EBlendDarken: return "blend_support_darken"; - case EBlendLighten: return "blend_support_lighten"; - case EBlendColordodge: return "blend_support_colordodge"; - case EBlendColorburn: return "blend_support_colorburn"; - case EBlendHardlight: return "blend_support_hardlight"; - case EBlendSoftlight: return "blend_support_softlight"; - case EBlendDifference: return "blend_support_difference"; - case EBlendExclusion: return "blend_support_exclusion"; - case EBlendHslHue: return "blend_support_hsl_hue"; - case EBlendHslSaturation: return "blend_support_hsl_saturation"; - case EBlendHslColor: return "blend_support_hsl_color"; - case EBlendHslLuminosity: return "blend_support_hsl_luminosity"; - case EBlendAllEquations: return "blend_support_all_equations"; - default: return "unknown"; - } - } - static const char* getGeometryString(TLayoutGeometry geometry) - { - switch (geometry) { - case ElgPoints: return "points"; - case ElgLines: return "lines"; - case ElgLinesAdjacency: return "lines_adjacency"; - case ElgLineStrip: return "line_strip"; - case ElgTriangles: return "triangles"; - case ElgTrianglesAdjacency: return "triangles_adjacency"; - case ElgTriangleStrip: return "triangle_strip"; - case ElgQuads: return "quads"; - case ElgIsolines: return "isolines"; - default: return "none"; - } - } - static const char* getVertexSpacingString(TVertexSpacing spacing) - { - switch (spacing) { - case EvsEqual: return "equal_spacing"; - case EvsFractionalEven: return "fractional_even_spacing"; - case EvsFractionalOdd: return "fractional_odd_spacing"; - default: return "none"; - } - } - static const char* getVertexOrderString(TVertexOrder order) - { - switch (order) { - case EvoCw: return "cw"; - case EvoCcw: return "ccw"; - default: return "none"; - } - } - static int mapGeometryToSize(TLayoutGeometry geometry) - { - switch (geometry) { - case ElgPoints: return 1; - case ElgLines: return 2; - case ElgLinesAdjacency: return 4; - case ElgTriangles: return 3; - case ElgTrianglesAdjacency: return 6; - default: return 0; - } - } - static const char* getInterlockOrderingString(TInterlockOrdering order) - { - switch (order) { - case EioPixelInterlockOrdered: return "pixel_interlock_ordered"; - case EioPixelInterlockUnordered: return "pixel_interlock_unordered"; - case EioSampleInterlockOrdered: return "sample_interlock_ordered"; - case EioSampleInterlockUnordered: return "sample_interlock_unordered"; - case EioShadingRateInterlockOrdered: return "shading_rate_interlock_ordered"; - case EioShadingRateInterlockUnordered: return "shading_rate_interlock_unordered"; - default: return "none"; - } - } -}; - -// Qualifiers that don't need to be keep per object. They have shader scope, not object scope. -// So, they will not be part of TType, TQualifier, etc. -struct TShaderQualifiers { - TLayoutGeometry geometry; // geometry/tessellation shader in/out primitives - bool pixelCenterInteger; // fragment shader - bool originUpperLeft; // fragment shader - int invocations; - int vertices; // for tessellation "vertices", geometry & mesh "max_vertices" - TVertexSpacing spacing; - TVertexOrder order; - bool pointMode; - int localSize[3]; // compute shader - bool localSizeNotDefault[3]; // compute shader - int localSizeSpecId[3]; // compute shader specialization id for gl_WorkGroupSize - bool earlyFragmentTests; // fragment input - bool postDepthCoverage; // fragment input - bool earlyAndLateFragmentTestsAMD; //fragment input - bool nonCoherentColorAttachmentReadEXT; // fragment input - bool nonCoherentDepthAttachmentReadEXT; // fragment input - bool nonCoherentStencilAttachmentReadEXT; // fragment input - TLayoutDepth layoutDepth; - TLayoutStencil layoutStencil; - bool blendEquation; // true if any blend equation was specified - int numViews; // multiview extenstions - TInterlockOrdering interlockOrdering; - bool layoutOverrideCoverage; // true if layout override_coverage set - bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set - bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set - int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set - bool layoutPrimitiveCulling; // true if layout primitive_culling set - TLayoutDepth getDepth() const { return layoutDepth; } - TLayoutStencil getStencil() const { return layoutStencil; } - - void init() - { - geometry = ElgNone; - originUpperLeft = false; - pixelCenterInteger = false; - invocations = TQualifier::layoutNotSet; - vertices = TQualifier::layoutNotSet; - spacing = EvsNone; - order = EvoNone; - pointMode = false; - localSize[0] = 1; - localSize[1] = 1; - localSize[2] = 1; - localSizeNotDefault[0] = false; - localSizeNotDefault[1] = false; - localSizeNotDefault[2] = false; - localSizeSpecId[0] = TQualifier::layoutNotSet; - localSizeSpecId[1] = TQualifier::layoutNotSet; - localSizeSpecId[2] = TQualifier::layoutNotSet; - earlyFragmentTests = false; - earlyAndLateFragmentTestsAMD = false; - postDepthCoverage = false; - nonCoherentColorAttachmentReadEXT = false; - nonCoherentDepthAttachmentReadEXT = false; - nonCoherentStencilAttachmentReadEXT = false; - layoutDepth = EldNone; - layoutStencil = ElsNone; - blendEquation = false; - numViews = TQualifier::layoutNotSet; - layoutOverrideCoverage = false; - layoutDerivativeGroupQuads = false; - layoutDerivativeGroupLinear = false; - layoutPrimitiveCulling = false; - primitives = TQualifier::layoutNotSet; - interlockOrdering = EioNone; - } - - bool hasBlendEquation() const { return blendEquation; } - - // Merge in characteristics from the 'src' qualifier. They can override when - // set, but never erase when not set. - void merge(const TShaderQualifiers& src) - { - if (src.geometry != ElgNone) - geometry = src.geometry; - if (src.pixelCenterInteger) - pixelCenterInteger = src.pixelCenterInteger; - if (src.originUpperLeft) - originUpperLeft = src.originUpperLeft; - if (src.invocations != TQualifier::layoutNotSet) - invocations = src.invocations; - if (src.vertices != TQualifier::layoutNotSet) - vertices = src.vertices; - if (src.spacing != EvsNone) - spacing = src.spacing; - if (src.order != EvoNone) - order = src.order; - if (src.pointMode) - pointMode = true; - for (int i = 0; i < 3; ++i) { - if (src.localSize[i] > 1) - localSize[i] = src.localSize[i]; - } - for (int i = 0; i < 3; ++i) { - localSizeNotDefault[i] = src.localSizeNotDefault[i] || localSizeNotDefault[i]; - } - for (int i = 0; i < 3; ++i) { - if (src.localSizeSpecId[i] != TQualifier::layoutNotSet) - localSizeSpecId[i] = src.localSizeSpecId[i]; - } - if (src.earlyFragmentTests) - earlyFragmentTests = true; - if (src.earlyAndLateFragmentTestsAMD) - earlyAndLateFragmentTestsAMD = true; - if (src.postDepthCoverage) - postDepthCoverage = true; - if (src.nonCoherentColorAttachmentReadEXT) - nonCoherentColorAttachmentReadEXT = true; - if (src.nonCoherentDepthAttachmentReadEXT) - nonCoherentDepthAttachmentReadEXT = true; - if (src.nonCoherentStencilAttachmentReadEXT) - nonCoherentStencilAttachmentReadEXT = true; - if (src.layoutDepth) - layoutDepth = src.layoutDepth; - if (src.layoutStencil) - layoutStencil = src.layoutStencil; - if (src.blendEquation) - blendEquation = src.blendEquation; - if (src.numViews != TQualifier::layoutNotSet) - numViews = src.numViews; - if (src.layoutOverrideCoverage) - layoutOverrideCoverage = src.layoutOverrideCoverage; - if (src.layoutDerivativeGroupQuads) - layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads; - if (src.layoutDerivativeGroupLinear) - layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear; - if (src.primitives != TQualifier::layoutNotSet) - primitives = src.primitives; - if (src.interlockOrdering != EioNone) - interlockOrdering = src.interlockOrdering; - if (src.layoutPrimitiveCulling) - layoutPrimitiveCulling = src.layoutPrimitiveCulling; - } -}; - -class TTypeParameters { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - TTypeParameters() : basicType(EbtVoid), arraySizes(nullptr) {} - - TBasicType basicType; - TArraySizes *arraySizes; - - bool operator==(const TTypeParameters& rhs) const { return basicType == rhs.basicType && *arraySizes == *rhs.arraySizes; } - bool operator!=(const TTypeParameters& rhs) const { return basicType != rhs.basicType || *arraySizes != *rhs.arraySizes; } -}; - -// -// TPublicType is just temporarily used while parsing and not quite the same -// information kept per node in TType. Due to the bison stack, it can't have -// types that it thinks have non-trivial constructors. It should -// just be used while recognizing the grammar, not anything else. -// Once enough is known about the situation, the proper information -// moved into a TType, or the parse context, etc. -// -class TPublicType { -public: - TBasicType basicType; - TSampler sampler; - TQualifier qualifier; - TShaderQualifiers shaderQualifiers; - uint32_t vectorSize : 4; - uint32_t matrixCols : 4; - uint32_t matrixRows : 4; - bool coopmatNV : 1; - bool coopmatKHR : 1; - TArraySizes* arraySizes; - const TType* userDef; - TSourceLoc loc; - TTypeParameters* typeParameters; - // SPIR-V type defined by spirv_type directive - TSpirvType* spirvType; - - bool isCoopmat() const { return coopmatNV || coopmatKHR; } - bool isCoopmatNV() const { return coopmatNV; } - bool isCoopmatKHR() const { return coopmatKHR; } - - void initType(const TSourceLoc& l) - { - basicType = EbtVoid; - vectorSize = 1u; - matrixRows = 0; - matrixCols = 0; - arraySizes = nullptr; - userDef = nullptr; - loc = l; - typeParameters = nullptr; - coopmatNV = false; - coopmatKHR = false; - spirvType = nullptr; - } - - void initQualifiers(bool global = false) - { - qualifier.clear(); - if (global) - qualifier.storage = EvqGlobal; - } - - void init(const TSourceLoc& l, bool global = false) - { - initType(l); - sampler.clear(); - initQualifiers(global); - shaderQualifiers.init(); - } - - void setVector(int s) - { - matrixRows = 0; - matrixCols = 0; - assert(s >= 0); - vectorSize = static_cast(s) & 0b1111; - } - - void setMatrix(int c, int r) - { - assert(r >= 0); - matrixRows = static_cast(r) & 0b1111; - assert(c >= 0); - matrixCols = static_cast(c) & 0b1111; - vectorSize = 0; - } - - bool isScalar() const - { - return matrixCols == 0u && vectorSize == 1u && arraySizes == nullptr && userDef == nullptr; - } - - // GL_EXT_spirv_intrinsics - void setSpirvType(const TSpirvInstruction& spirvInst, const TSpirvTypeParameters* typeParams = nullptr); - - // "Image" is a superset of "Subpass" - bool isImage() const { return basicType == EbtSampler && sampler.isImage(); } - bool isSubpass() const { return basicType == EbtSampler && sampler.isSubpass(); } - bool isAttachmentEXT() const { return basicType == EbtSampler && sampler.isAttachmentEXT(); } -}; - -// -// Base class for things that have a type. -// -class TType { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - // for "empty" type (no args) or simple scalar/vector/matrix - explicit TType(TBasicType t = EbtVoid, TStorageQualifier q = EvqTemporary, int vs = 1, int mc = 0, int mr = 0, - bool isVector = false) : - basicType(t), vectorSize(static_cast(vs) & 0b1111), matrixCols(static_cast(mc) & 0b1111), matrixRows(static_cast(mr) & 0b1111), vector1(isVector && vs == 1), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), - arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr), - spirvType(nullptr) - { - assert(vs >= 0); - assert(mc >= 0); - assert(mr >= 0); - - sampler.clear(); - qualifier.clear(); - qualifier.storage = q; - assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices - } - // for explicit precision qualifier - TType(TBasicType t, TStorageQualifier q, TPrecisionQualifier p, int vs = 1, int mc = 0, int mr = 0, - bool isVector = false) : - basicType(t), vectorSize(static_cast(vs) & 0b1111), matrixCols(static_cast(mc) & 0b1111), matrixRows(static_cast(mr) & 0b1111), vector1(isVector && vs == 1), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), - arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr), - spirvType(nullptr) - { - assert(vs >= 0); - assert(mc >= 0); - assert(mr >= 0); - - sampler.clear(); - qualifier.clear(); - qualifier.storage = q; - qualifier.precision = p; - assert(p >= EpqNone && p <= EpqHigh); - assert(!(isMatrix() && vectorSize != 0)); // prevent vectorSize != 0 on matrices - } - // for turning a TPublicType into a TType, using a shallow copy - explicit TType(const TPublicType& p) : - basicType(p.basicType), - vectorSize(p.vectorSize), matrixCols(p.matrixCols), matrixRows(p.matrixRows), vector1(false), coopmatNV(p.coopmatNV), coopmatKHR(p.coopmatKHR), coopmatKHRuse(0), coopmatKHRUseValid(false), - arraySizes(p.arraySizes), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(p.typeParameters), - spirvType(p.spirvType) - { - if (basicType == EbtSampler) - sampler = p.sampler; - else - sampler.clear(); - qualifier = p.qualifier; - if (p.userDef) { - if (p.userDef->basicType == EbtReference) { - basicType = EbtReference; - referentType = p.userDef->referentType; - } else { - structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues - } - typeName = NewPoolTString(p.userDef->getTypeName().c_str()); - } - if (p.isCoopmatNV() && p.typeParameters && p.typeParameters->arraySizes->getNumDims() > 0) { - int numBits = p.typeParameters->arraySizes->getDimSize(0); - if (p.basicType == EbtFloat && numBits == 16) { - basicType = EbtFloat16; - qualifier.precision = EpqNone; - } else if (p.basicType == EbtUint && numBits == 8) { - basicType = EbtUint8; - qualifier.precision = EpqNone; - } else if (p.basicType == EbtUint && numBits == 16) { - basicType = EbtUint16; - qualifier.precision = EpqNone; - } else if (p.basicType == EbtInt && numBits == 8) { - basicType = EbtInt8; - qualifier.precision = EpqNone; - } else if (p.basicType == EbtInt && numBits == 16) { - basicType = EbtInt16; - qualifier.precision = EpqNone; - } - } - if (p.isCoopmatKHR() && p.typeParameters && p.typeParameters->arraySizes->getNumDims() > 0) { - basicType = p.typeParameters->basicType; - - if (p.typeParameters->arraySizes->getNumDims() == 4) { - const int dimSize = p.typeParameters->arraySizes->getDimSize(3); - assert(dimSize >= 0); - coopmatKHRuse = static_cast(dimSize) & 0b111; - coopmatKHRUseValid = true; - p.typeParameters->arraySizes->removeLastSize(); - } - } - } - // for construction of sampler types - TType(const TSampler& sampler, TStorageQualifier q = EvqUniform, TArraySizes* as = nullptr) : - basicType(EbtSampler), vectorSize(1u), matrixCols(0u), matrixRows(0u), vector1(false), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), - arraySizes(as), structure(nullptr), fieldName(nullptr), typeName(nullptr), - sampler(sampler), typeParameters(nullptr), spirvType(nullptr) - { - qualifier.clear(); - qualifier.storage = q; - } - // to efficiently make a dereferenced type - // without ever duplicating the outer structure that will be thrown away - // and using only shallow copy - TType(const TType& type, int derefIndex, bool rowMajor = false) - { - if (type.isArray()) { - shallowCopy(type); - if (type.getArraySizes()->getNumDims() == 1) { - arraySizes = nullptr; - } else { - // want our own copy of the array, so we can edit it - arraySizes = new TArraySizes; - arraySizes->copyDereferenced(*type.arraySizes); - } - } else if (type.basicType == EbtStruct || type.basicType == EbtBlock) { - // do a structure dereference - const TTypeList& memberList = *type.getStruct(); - shallowCopy(*memberList[derefIndex].type); - return; - } else { - // do a vector/matrix dereference - shallowCopy(type); - if (matrixCols > 0) { - // dereference from matrix to vector - if (rowMajor) - vectorSize = matrixCols; - else - vectorSize = matrixRows; - matrixCols = 0; - matrixRows = 0; - if (vectorSize == 1) - vector1 = true; - } else if (isVector()) { - // dereference from vector to scalar - vectorSize = 1; - vector1 = false; - } else if (isCoopMat()) { - coopmatNV = false; - coopmatKHR = false; - coopmatKHRuse = 0; - coopmatKHRUseValid = false; - typeParameters = nullptr; - } - } - } - // for making structures, ... - TType(TTypeList* userDef, const TString& n) : - basicType(EbtStruct), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), - arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr), - spirvType(nullptr) - { - sampler.clear(); - qualifier.clear(); - typeName = NewPoolTString(n.c_str()); - } - // For interface blocks - TType(TTypeList* userDef, const TString& n, const TQualifier& q) : - basicType(EbtBlock), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), - qualifier(q), arraySizes(nullptr), structure(userDef), fieldName(nullptr), typeParameters(nullptr), - spirvType(nullptr) - { - sampler.clear(); - typeName = NewPoolTString(n.c_str()); - } - // for block reference (first parameter must be EbtReference) - explicit TType(TBasicType t, const TType &p, const TString& n) : - basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false), coopmatNV(false), coopmatKHR(false), coopmatKHRuse(0), coopmatKHRUseValid(false), - arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr), typeParameters(nullptr), - spirvType(nullptr) - { - assert(t == EbtReference); - typeName = NewPoolTString(n.c_str()); - sampler.clear(); - qualifier.clear(); - qualifier.storage = p.qualifier.storage; - referentType = p.clone(); - } - virtual ~TType() {} - - // Not for use across pool pops; it will cause multiple instances of TType to point to the same information. - // This only works if that information (like a structure's list of types) does not change and - // the instances are sharing the same pool. - void shallowCopy(const TType& copyOf) - { - basicType = copyOf.basicType; - sampler = copyOf.sampler; - qualifier = copyOf.qualifier; - vectorSize = copyOf.vectorSize; - matrixCols = copyOf.matrixCols; - matrixRows = copyOf.matrixRows; - vector1 = copyOf.vector1; - arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents - fieldName = copyOf.fieldName; - typeName = copyOf.typeName; - if (isStruct()) { - structure = copyOf.structure; - } else { - referentType = copyOf.referentType; - } - typeParameters = copyOf.typeParameters; - spirvType = copyOf.spirvType; - coopmatNV = copyOf.isCoopMatNV(); - coopmatKHR = copyOf.isCoopMatKHR(); - coopmatKHRuse = copyOf.coopmatKHRuse; - coopmatKHRUseValid = copyOf.coopmatKHRUseValid; - } - - // Make complete copy of the whole type graph rooted at 'copyOf'. - void deepCopy(const TType& copyOf) - { - TMap copied; // to enable copying a type graph as a graph, not a tree - deepCopy(copyOf, copied); - } - - // Recursively make temporary - void makeTemporary() - { - getQualifier().makeTemporary(); - - if (isStruct()) - for (unsigned int i = 0; i < structure->size(); ++i) - (*structure)[i].type->makeTemporary(); - } - - TType* clone() const - { - TType *newType = new TType(); - newType->deepCopy(*this); - - return newType; - } - - void makeVector() { vector1 = true; } - - virtual void hideMember() { basicType = EbtVoid; vectorSize = 1u; } - virtual bool hiddenMember() const { return basicType == EbtVoid; } - - virtual void setFieldName(const TString& n) { fieldName = NewPoolTString(n.c_str()); } - virtual const TString& getTypeName() const - { - assert(typeName); - return *typeName; - } - - virtual const TString& getFieldName() const - { - assert(fieldName); - return *fieldName; - } - TShaderInterface getShaderInterface() const - { - if (basicType != EbtBlock) - return EsiNone; - - switch (qualifier.storage) { - default: - return EsiNone; - case EvqVaryingIn: - return EsiInput; - case EvqVaryingOut: - return EsiOutput; - case EvqUniform: - case EvqBuffer: - return EsiUniform; - } - } - - virtual TBasicType getBasicType() const { return basicType; } - virtual const TSampler& getSampler() const { return sampler; } - virtual TSampler& getSampler() { return sampler; } - - virtual TQualifier& getQualifier() { return qualifier; } - virtual const TQualifier& getQualifier() const { return qualifier; } - - virtual int getVectorSize() const { return static_cast(vectorSize); } // returns 1 for either scalar or vector of size 1, valid for both - virtual int getMatrixCols() const { return static_cast(matrixCols); } - virtual int getMatrixRows() const { return static_cast(matrixRows); } - virtual int getOuterArraySize() const { return arraySizes->getOuterSize(); } - virtual TIntermTyped* getOuterArrayNode() const { return arraySizes->getOuterNode(); } - virtual int getCumulativeArraySize() const { return arraySizes->getCumulativeSize(); } - bool isArrayOfArrays() const { return arraySizes != nullptr && arraySizes->getNumDims() > 1; } - virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } - virtual const TArraySizes* getArraySizes() const { return arraySizes; } - virtual TArraySizes* getArraySizes() { return arraySizes; } - virtual TType* getReferentType() const { return referentType; } - virtual const TTypeParameters* getTypeParameters() const { return typeParameters; } - virtual TTypeParameters* getTypeParameters() { return typeParameters; } - - virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); } - virtual bool isScalarOrVec1() const { return isScalar() || vector1; } - virtual bool isScalarOrVector() const { return !isMatrix() && !isStruct() && !isArray(); } - virtual bool isVector() const { return vectorSize > 1u || vector1; } - virtual bool isMatrix() const { return matrixCols ? true : false; } - virtual bool isArray() const { return arraySizes != nullptr; } - virtual bool isSizedArray() const { return isArray() && arraySizes->isSized(); } - virtual bool isUnsizedArray() const { return isArray() && !arraySizes->isSized(); } - virtual bool isImplicitlySizedArray() const { return isArray() && arraySizes->isImplicitlySized(); } - virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); } - virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); } - virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); } - virtual void setImplicitlySized(bool isImplicitSized) { arraySizes->setImplicitlySized(isImplicitSized); } - virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; } - virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; } - virtual bool isIntegerDomain() const - { - switch (basicType) { - case EbtInt8: - case EbtUint8: - case EbtInt16: - case EbtUint16: - case EbtInt: - case EbtUint: - case EbtInt64: - case EbtUint64: - case EbtAtomicUint: - return true; - default: - break; - } - return false; - } - virtual bool isOpaque() const { return basicType == EbtSampler - || basicType == EbtAtomicUint || basicType == EbtAccStruct || basicType == EbtRayQuery - || basicType == EbtHitObjectNV; } - virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } - - virtual bool isAttachmentEXT() const { return basicType == EbtSampler && getSampler().isAttachmentEXT(); } - virtual bool isImage() const { return basicType == EbtSampler && getSampler().isImage(); } - virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); } - virtual bool isTexture() const { return basicType == EbtSampler && getSampler().isTexture(); } - virtual bool isBindlessImage() const { return isImage() && qualifier.layoutBindlessImage; } - virtual bool isBindlessTexture() const { return isTexture() && qualifier.layoutBindlessSampler; } - // Check the block-name convention of creating a block without populating it's members: - virtual bool isUnusableName() const { return isStruct() && structure == nullptr; } - virtual bool isParameterized() const { return typeParameters != nullptr; } - bool isAtomic() const { return basicType == EbtAtomicUint; } - bool isCoopMat() const { return coopmatNV || coopmatKHR; } - bool isCoopMatNV() const { return coopmatNV; } - bool isCoopMatKHR() const { return coopmatKHR; } - bool isReference() const { return getBasicType() == EbtReference; } - bool isSpirvType() const { return getBasicType() == EbtSpirvType; } - int getCoopMatKHRuse() const { return static_cast(coopmatKHRuse); } - - // return true if this type contains any subtype which satisfies the given predicate. - template - bool contains(P predicate) const - { - if (predicate(this)) - return true; - - const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); }; - - return isStruct() && std::any_of(structure->begin(), structure->end(), hasa); - } - - // Recursively checks if the type contains the given basic type - virtual bool containsBasicType(TBasicType checkType) const - { - return contains([checkType](const TType* t) { return t->basicType == checkType; } ); - } - - // Recursively check the structure for any arrays, needed for some error checks - virtual bool containsArray() const - { - return contains([](const TType* t) { return t->isArray(); } ); - } - - // Check the structure for any structures, needed for some error checks - virtual bool containsStructure() const - { - return contains([this](const TType* t) { return t != this && t->isStruct(); } ); - } - - // Recursively check the structure for any unsized arrays, needed for triggering a copyUp(). - virtual bool containsUnsizedArray() const - { - return contains([](const TType* t) { return t->isUnsizedArray(); } ); - } - - virtual bool containsOpaque() const - { - return contains([](const TType* t) { return t->isOpaque(); } ); - } - - virtual bool containsSampler() const - { - return contains([](const TType* t) { return t->isTexture() || t->isImage(); }); - } - - // Recursively checks if the type contains a built-in variable - virtual bool containsBuiltIn() const - { - return contains([](const TType* t) { return t->isBuiltIn(); } ); - } - - virtual bool containsNonOpaque() const - { - const auto nonOpaque = [](const TType* t) { - switch (t->basicType) { - case EbtVoid: - case EbtFloat: - case EbtDouble: - case EbtFloat16: - case EbtInt8: - case EbtUint8: - case EbtInt16: - case EbtUint16: - case EbtInt: - case EbtUint: - case EbtInt64: - case EbtUint64: - case EbtBool: - case EbtReference: - return true; - default: - return false; - } - }; - - return contains(nonOpaque); - } - - virtual bool containsSpecializationSize() const - { - return contains([](const TType* t) { return t->isArray() && t->arraySizes->isOuterSpecialization(); } ); - } - - bool containsDouble() const - { - return containsBasicType(EbtDouble); - } - bool contains16BitFloat() const - { - return containsBasicType(EbtFloat16); - } - bool contains64BitInt() const - { - return containsBasicType(EbtInt64) || containsBasicType(EbtUint64); - } - bool contains16BitInt() const - { - return containsBasicType(EbtInt16) || containsBasicType(EbtUint16); - } - bool contains8BitInt() const - { - return containsBasicType(EbtInt8) || containsBasicType(EbtUint8); - } - bool containsCoopMat() const - { - return contains([](const TType* t) { return t->coopmatNV || t->coopmatKHR; } ); - } - bool containsReference() const - { - return containsBasicType(EbtReference); - } - - // Array editing methods. Array descriptors can be shared across - // type instances. This allows all uses of the same array - // to be updated at once. E.g., all nodes can be explicitly sized - // by tracking and correcting one implicit size. Or, all nodes - // can get the explicit size on a redeclaration that gives size. - // - // N.B.: Don't share with the shared symbol tables (symbols are - // marked as isReadOnly(). Such symbols with arrays that will be - // edited need to copyUp() on first use, so that - // A) the edits don't effect the shared symbol table, and - // B) the edits are shared across all users. - void updateArraySizes(const TType& type) - { - // For when we may already be sharing existing array descriptors, - // keeping the pointers the same, just updating the contents. - assert(arraySizes != nullptr); - assert(type.arraySizes != nullptr); - *arraySizes = *type.arraySizes; - } - void copyArraySizes(const TArraySizes& s) - { - // For setting a fresh new set of array sizes, not yet worrying about sharing. - arraySizes = new TArraySizes; - *arraySizes = s; - } - void transferArraySizes(TArraySizes* s) - { - // For setting an already allocated set of sizes that this type can use - // (no copy made). - arraySizes = s; - } - void clearArraySizes() - { - arraySizes = nullptr; - } - - // Add inner array sizes, to any existing sizes, via copy; the - // sizes passed in can still be reused for other purposes. - void copyArrayInnerSizes(const TArraySizes* s) - { - if (s != nullptr) { - if (arraySizes == nullptr) - copyArraySizes(*s); - else - arraySizes->addInnerSizes(*s); - } - } - void changeOuterArraySize(int s) { arraySizes->changeOuterSize(s); } - - // Recursively make the implicit array size the explicit array size. - // Expicit arrays are compile-time or link-time sized, never run-time sized. - // Sometimes, policy calls for an array to be run-time sized even if it was - // never variably indexed: Don't turn a 'skipNonvariablyIndexed' array into - // an explicit array. - void adoptImplicitArraySizes(bool skipNonvariablyIndexed) - { - if (isUnsizedArray() && - (qualifier.builtIn == EbvSampleMask || - !(skipNonvariablyIndexed || isArrayVariablyIndexed()))) { - changeOuterArraySize(getImplicitArraySize()); - setImplicitlySized(true); - } - // For multi-dim per-view arrays, set unsized inner dimension size to 1 - if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized()) - arraySizes->clearInnerUnsized(); - if (isStruct() && structure->size() > 0) { - int lastMember = (int)structure->size() - 1; - for (int i = 0; i < lastMember; ++i) - (*structure)[i].type->adoptImplicitArraySizes(false); - // implement the "last member of an SSBO" policy - (*structure)[lastMember].type->adoptImplicitArraySizes(getQualifier().storage == EvqBuffer); - } - } - - void copyTypeParameters(const TTypeParameters& s) - { - // For setting a fresh new set of type parameters, not yet worrying about sharing. - typeParameters = new TTypeParameters; - *typeParameters = s; - } - - const char* getBasicString() const - { - return TType::getBasicString(basicType); - } - - static const char* getBasicString(TBasicType t) - { - switch (t) { - case EbtFloat: return "float"; - case EbtInt: return "int"; - case EbtUint: return "uint"; - case EbtSampler: return "sampler/image"; - case EbtVoid: return "void"; - case EbtDouble: return "double"; - case EbtFloat16: return "float16_t"; - case EbtInt8: return "int8_t"; - case EbtUint8: return "uint8_t"; - case EbtInt16: return "int16_t"; - case EbtUint16: return "uint16_t"; - case EbtInt64: return "int64_t"; - case EbtUint64: return "uint64_t"; - case EbtBool: return "bool"; - case EbtAtomicUint: return "atomic_uint"; - case EbtStruct: return "structure"; - case EbtBlock: return "block"; - case EbtAccStruct: return "accelerationStructureNV"; - case EbtRayQuery: return "rayQueryEXT"; - case EbtReference: return "reference"; - case EbtString: return "string"; - case EbtSpirvType: return "spirv_type"; - case EbtCoopmat: return "coopmat"; - default: return "unknown type"; - } - } - - TString getCompleteString(bool syntactic = false, bool getQualifiers = true, bool getPrecision = true, - bool getType = true, TString name = "", TString structName = "") const - { - TString typeString; - - const auto appendStr = [&](const char* s) { typeString.append(s); }; - const auto appendUint = [&](unsigned int u) { typeString.append(std::to_string(u).c_str()); }; - const auto appendInt = [&](int i) { typeString.append(std::to_string(i).c_str()); }; - - if (getQualifiers) { - if (qualifier.hasSpirvDecorate()) - appendStr(qualifier.getSpirvDecorateQualifierString().c_str()); - - if (qualifier.hasLayout()) { - // To reduce noise, skip this if the only layout is an xfb_buffer - // with no triggering xfb_offset. - TQualifier noXfbBuffer = qualifier; - noXfbBuffer.layoutXfbBuffer = TQualifier::layoutXfbBufferEnd; - if (noXfbBuffer.hasLayout()) { - appendStr("layout("); - if (qualifier.hasAnyLocation()) { - appendStr(" location="); - appendUint(qualifier.layoutLocation); - if (qualifier.hasComponent()) { - appendStr(" component="); - appendUint(qualifier.layoutComponent); - } - if (qualifier.hasIndex()) { - appendStr(" index="); - appendUint(qualifier.layoutIndex); - } - } - if (qualifier.hasSet()) { - appendStr(" set="); - appendUint(qualifier.layoutSet); - } - if (qualifier.hasBinding()) { - appendStr(" binding="); - appendUint(qualifier.layoutBinding); - } - if (qualifier.hasStream()) { - appendStr(" stream="); - appendUint(qualifier.layoutStream); - } - if (qualifier.hasMatrix()) { - appendStr(" "); - appendStr(TQualifier::getLayoutMatrixString(qualifier.layoutMatrix)); - } - if (qualifier.hasPacking()) { - appendStr(" "); - appendStr(TQualifier::getLayoutPackingString(qualifier.layoutPacking)); - } - if (qualifier.hasOffset()) { - appendStr(" offset="); - appendInt(qualifier.layoutOffset); - } - if (qualifier.hasAlign()) { - appendStr(" align="); - appendInt(qualifier.layoutAlign); - } - if (qualifier.hasFormat()) { - appendStr(" "); - appendStr(TQualifier::getLayoutFormatString(qualifier.layoutFormat)); - } - if (qualifier.hasXfbBuffer() && qualifier.hasXfbOffset()) { - appendStr(" xfb_buffer="); - appendUint(qualifier.layoutXfbBuffer); - } - if (qualifier.hasXfbOffset()) { - appendStr(" xfb_offset="); - appendUint(qualifier.layoutXfbOffset); - } - if (qualifier.hasXfbStride()) { - appendStr(" xfb_stride="); - appendUint(qualifier.layoutXfbStride); - } - if (qualifier.hasAttachment()) { - appendStr(" input_attachment_index="); - appendUint(qualifier.layoutAttachment); - } - if (qualifier.hasSpecConstantId()) { - appendStr(" constant_id="); - appendUint(qualifier.layoutSpecConstantId); - } - if (qualifier.layoutPushConstant) - appendStr(" push_constant"); - if (qualifier.layoutBufferReference) - appendStr(" buffer_reference"); - if (qualifier.hasBufferReferenceAlign()) { - appendStr(" buffer_reference_align="); - appendUint(1u << qualifier.layoutBufferReferenceAlign); - } - - if (qualifier.layoutPassthrough) - appendStr(" passthrough"); - if (qualifier.layoutViewportRelative) - appendStr(" layoutViewportRelative"); - if (qualifier.layoutSecondaryViewportRelativeOffset != -2048) { - appendStr(" layoutSecondaryViewportRelativeOffset="); - appendInt(qualifier.layoutSecondaryViewportRelativeOffset); - } - - if (qualifier.layoutShaderRecord) - appendStr(" shaderRecordNV"); - if (qualifier.layoutHitObjectShaderRecordNV) - appendStr(" hitobjectshaderrecordnv"); - - if (qualifier.layoutBindlessSampler) - appendStr(" layoutBindlessSampler"); - if (qualifier.layoutBindlessImage) - appendStr(" layoutBindlessImage"); - - appendStr(")"); - } - } - - if (qualifier.invariant) - appendStr(" invariant"); - if (qualifier.noContraction) - appendStr(" noContraction"); - if (qualifier.centroid) - appendStr(" centroid"); - if (qualifier.smooth) - appendStr(" smooth"); - if (qualifier.flat) - appendStr(" flat"); - if (qualifier.nopersp) - appendStr(" noperspective"); - if (qualifier.explicitInterp) - appendStr(" __explicitInterpAMD"); - if (qualifier.pervertexNV) - appendStr(" pervertexNV"); - if (qualifier.pervertexEXT) - appendStr(" pervertexEXT"); - if (qualifier.perPrimitiveNV) - appendStr(" perprimitiveNV"); - if (qualifier.perViewNV) - appendStr(" perviewNV"); - if (qualifier.perTaskNV) - appendStr(" taskNV"); - if (qualifier.patch) - appendStr(" patch"); - if (qualifier.sample) - appendStr(" sample"); - if (qualifier.coherent) - appendStr(" coherent"); - if (qualifier.devicecoherent) - appendStr(" devicecoherent"); - if (qualifier.queuefamilycoherent) - appendStr(" queuefamilycoherent"); - if (qualifier.workgroupcoherent) - appendStr(" workgroupcoherent"); - if (qualifier.subgroupcoherent) - appendStr(" subgroupcoherent"); - if (qualifier.shadercallcoherent) - appendStr(" shadercallcoherent"); - if (qualifier.nonprivate) - appendStr(" nonprivate"); - if (qualifier.volatil) - appendStr(" volatile"); - if (qualifier.restrict) - appendStr(" restrict"); - if (qualifier.readonly) - appendStr(" readonly"); - if (qualifier.writeonly) - appendStr(" writeonly"); - if (qualifier.specConstant) - appendStr(" specialization-constant"); - if (qualifier.nonUniform) - appendStr(" nonuniform"); - if (qualifier.isNullInit()) - appendStr(" null-init"); - if (qualifier.isSpirvByReference()) - appendStr(" spirv_by_reference"); - if (qualifier.isSpirvLiteral()) - appendStr(" spirv_literal"); - appendStr(" "); - appendStr(getStorageQualifierString()); - } - if (getType) { - if (syntactic) { - if (getPrecision && qualifier.precision != EpqNone) { - appendStr(" "); - appendStr(getPrecisionQualifierString()); - } - if (isVector() || isMatrix()) { - appendStr(" "); - switch (basicType) { - case EbtDouble: - appendStr("d"); - break; - case EbtInt: - appendStr("i"); - break; - case EbtUint: - appendStr("u"); - break; - case EbtBool: - appendStr("b"); - break; - case EbtFloat: - default: - break; - } - if (isVector()) { - appendStr("vec"); - appendInt(vectorSize); - } else { - appendStr("mat"); - appendInt(matrixCols); - appendStr("x"); - appendInt(matrixRows); - } - } else if (isStruct() && structure) { - appendStr(" "); - appendStr(structName.c_str()); - appendStr("{"); - bool hasHiddenMember = true; - for (size_t i = 0; i < structure->size(); ++i) { - if (!(*structure)[i].type->hiddenMember()) { - if (!hasHiddenMember) - appendStr(", "); - typeString.append((*structure)[i].type->getCompleteString(syntactic, getQualifiers, getPrecision, getType, (*structure)[i].type->getFieldName())); - hasHiddenMember = false; - } - } - appendStr("}"); - } else { - appendStr(" "); - switch (basicType) { - case EbtDouble: - appendStr("double"); - break; - case EbtInt: - appendStr("int"); - break; - case EbtUint: - appendStr("uint"); - break; - case EbtBool: - appendStr("bool"); - break; - case EbtFloat: - appendStr("float"); - break; - default: - appendStr("unexpected"); - break; - } - } - if (name.length() > 0) { - appendStr(" "); - appendStr(name.c_str()); - } - if (isArray()) { - for (int i = 0; i < (int)arraySizes->getNumDims(); ++i) { - int size = arraySizes->getDimSize(i); - if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed()) - appendStr("[]"); - else { - if (size == UnsizedArraySize) { - appendStr("["); - if (i == 0) - appendInt(arraySizes->getImplicitSize()); - appendStr("]"); - } - else { - appendStr("["); - appendInt(arraySizes->getDimSize(i)); - appendStr("]"); - } - } - } - } - } - else { - if (isArray()) { - for (int i = 0; i < (int)arraySizes->getNumDims(); ++i) { - int size = arraySizes->getDimSize(i); - if (size == UnsizedArraySize && i == 0 && arraySizes->isVariablyIndexed()) - appendStr(" runtime-sized array of"); - else { - if (size == UnsizedArraySize) { - appendStr(" unsized"); - if (i == 0) { - appendStr(" "); - appendInt(arraySizes->getImplicitSize()); - } - } - else { - appendStr(" "); - appendInt(arraySizes->getDimSize(i)); - } - appendStr("-element array of"); - } - } - } - if (isParameterized()) { - if (isCoopMatKHR()) { - appendStr(" "); - appendStr("coopmat"); - } - - appendStr("<"); - for (int i = 0; i < (int)typeParameters->arraySizes->getNumDims(); ++i) { - appendInt(typeParameters->arraySizes->getDimSize(i)); - if (i != (int)typeParameters->arraySizes->getNumDims() - 1) - appendStr(", "); - } - if (coopmatKHRUseValid) { - appendStr(", "); - appendInt(coopmatKHRuse); - } - appendStr(">"); - } - if (getPrecision && qualifier.precision != EpqNone) { - appendStr(" "); - appendStr(getPrecisionQualifierString()); - } - if (isMatrix()) { - appendStr(" "); - appendInt(matrixCols); - appendStr("X"); - appendInt(matrixRows); - appendStr(" matrix of"); - } - else if (isVector()) { - appendStr(" "); - appendInt(vectorSize); - appendStr("-component vector of"); - } - - appendStr(" "); - typeString.append(getBasicTypeString()); - - if (qualifier.builtIn != EbvNone) { - appendStr(" "); - appendStr(getBuiltInVariableString()); - } - - // Add struct/block members - if (isStruct() && structure) { - appendStr("{"); - bool hasHiddenMember = true; - for (size_t i = 0; i < structure->size(); ++i) { - if (!(*structure)[i].type->hiddenMember()) { - if (!hasHiddenMember) - appendStr(", "); - typeString.append((*structure)[i].type->getCompleteString()); - typeString.append(" "); - typeString.append((*structure)[i].type->getFieldName()); - hasHiddenMember = false; - } - } - appendStr("}"); - } - } - } - - return typeString; - } - - TString getBasicTypeString() const - { - if (basicType == EbtSampler) - return sampler.getString(); - else - return getBasicString(); - } - - const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); } - const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); } - const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); } - - const TTypeList* getStruct() const { assert(isStruct()); return structure; } - void setStruct(TTypeList* s) { assert(isStruct()); structure = s; } - TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads - void setBasicType(const TBasicType& t) { basicType = t; } - void setVectorSize(int s) { - assert(s >= 0); - vectorSize = static_cast(s) & 0b1111; - } - - int computeNumComponents() const - { - uint32_t components = 0; - - if (getBasicType() == EbtStruct || getBasicType() == EbtBlock) { - for (TTypeList::const_iterator tl = getStruct()->begin(); tl != getStruct()->end(); tl++) - components += ((*tl).type)->computeNumComponents(); - } else if (matrixCols) - components = matrixCols * matrixRows; - else - components = vectorSize; - - if (arraySizes != nullptr) { - components *= arraySizes->getCumulativeSize(); - } - - return static_cast(components); - } - - // append this type's mangled name to the passed in 'name' - void appendMangledName(TString& name) const - { - buildMangledName(name); - name += ';' ; - } - - // These variables are inconsistently declared inside and outside of gl_PerVertex in glslang right now. - // They are declared inside of 'in gl_PerVertex', but sitting as standalone when they are 'out'puts. - bool isInconsistentGLPerVertexMember(const TString& name) const - { - if (name == "gl_SecondaryPositionNV" || - name == "gl_PositionPerViewNV") - return true; - return false; - } - - - // Do two structure types match? They could be declared independently, - // in different places, but still might satisfy the definition of matching. - // From the spec: - // - // "Structures must have the same name, sequence of type names, and - // type definitions, and member names to be considered the same type. - // This rule applies recursively for nested or embedded types." - // - // If type mismatch in structure, return member indices through lpidx and rpidx. - // If matching members for either block are exhausted, return -1 for exhausted - // block and the index of the unmatched member. Otherwise return {-1,-1}. - // - bool sameStructType(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const - { - // Initialize error to general type mismatch. - if (lpidx != nullptr) { - *lpidx = -1; - *rpidx = -1; - } - - // Most commonly, they are both nullptr, or the same pointer to the same actual structure - // TODO: Why return true when neither types are structures? - if ((!isStruct() && !right.isStruct()) || - (isStruct() && right.isStruct() && structure == right.structure)) - return true; - - if (!isStruct() || !right.isStruct()) - return false; - - // Structure names have to match - if (*typeName != *right.typeName) - return false; - - // There are inconsistencies with how gl_PerVertex is setup. For now ignore those as errors if they - // are known inconsistencies. - bool isGLPerVertex = *typeName == "gl_PerVertex"; - - // Both being nullptr was caught above, now they both have to be structures of the same number of elements - if (lpidx == nullptr && - (structure->size() != right.structure->size() && !isGLPerVertex)) { - return false; - } - - // Compare the names and types of all the members, which have to match - for (size_t li = 0, ri = 0; li < structure->size() || ri < right.structure->size(); ++li, ++ri) { - if (lpidx != nullptr) { - *lpidx = static_cast(li); - *rpidx = static_cast(ri); - } - if (li < structure->size() && ri < right.structure->size()) { - if ((*structure)[li].type->getFieldName() == (*right.structure)[ri].type->getFieldName()) { - if (*(*structure)[li].type != *(*right.structure)[ri].type) - return false; - } else { - // Skip hidden members - if ((*structure)[li].type->hiddenMember()) { - ri--; - continue; - } else if ((*right.structure)[ri].type->hiddenMember()) { - li--; - continue; - } - // If one of the members is something that's inconsistently declared, skip over it - // for now. - if (isGLPerVertex) { - if (isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) { - ri--; - continue; - } else if (isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) { - li--; - continue; - } - } else { - return false; - } - } - // If we get here, then there should only be inconsistently declared members left - } else if (li < structure->size()) { - if (!(*structure)[li].type->hiddenMember() && !isInconsistentGLPerVertexMember((*structure)[li].type->getFieldName())) { - if (lpidx != nullptr) { - *rpidx = -1; - } - return false; - } - } else { - if (!(*right.structure)[ri].type->hiddenMember() && !isInconsistentGLPerVertexMember((*right.structure)[ri].type->getFieldName())) { - if (lpidx != nullptr) { - *lpidx = -1; - } - return false; - } - } - } - - return true; - } - - bool sameReferenceType(const TType& right) const - { - if (isReference() != right.isReference()) - return false; - - if (!isReference() && !right.isReference()) - return true; - - assert(referentType != nullptr); - assert(right.referentType != nullptr); - - if (referentType == right.referentType) - return true; - - return *referentType == *right.referentType; - } - - // See if two types match, in all aspects except arrayness - // If mismatch in structure members, return member indices in lpidx and rpidx. - bool sameElementType(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const - { - if (lpidx != nullptr) { - *lpidx = -1; - *rpidx = -1; - } - return basicType == right.basicType && sameElementShape(right, lpidx, rpidx); - } - - // See if two type's arrayness match - bool sameArrayness(const TType& right) const - { - return ((arraySizes == nullptr && right.arraySizes == nullptr) || - (arraySizes != nullptr && right.arraySizes != nullptr && - (*arraySizes == *right.arraySizes || - (arraySizes->isImplicitlySized() && right.arraySizes->isDefaultImplicitlySized()) || - (right.arraySizes->isImplicitlySized() && arraySizes->isDefaultImplicitlySized())))); - } - - // See if two type's arrayness match in everything except their outer dimension - bool sameInnerArrayness(const TType& right) const - { - assert(arraySizes != nullptr && right.arraySizes != nullptr); - return arraySizes->sameInnerArrayness(*right.arraySizes); - } - - // See if two type's parameters match - bool sameTypeParameters(const TType& right) const - { - return ((typeParameters == nullptr && right.typeParameters == nullptr) || - (typeParameters != nullptr && right.typeParameters != nullptr && *typeParameters == *right.typeParameters)); - } - - // See if two type's SPIR-V type contents match - bool sameSpirvType(const TType& right) const - { - return ((spirvType == nullptr && right.spirvType == nullptr) || - (spirvType != nullptr && right.spirvType != nullptr && *spirvType == *right.spirvType)); - } - - // See if two type's elements match in all ways except basic type - // If mismatch in structure members, return member indices in lpidx and rpidx. - bool sameElementShape(const TType& right, int* lpidx = nullptr, int* rpidx = nullptr) const - { - if (lpidx != nullptr) { - *lpidx = -1; - *rpidx = -1; - } - return ((basicType != EbtSampler && right.basicType != EbtSampler) || sampler == right.sampler) && - vectorSize == right.vectorSize && - matrixCols == right.matrixCols && - matrixRows == right.matrixRows && - vector1 == right.vector1 && - isCoopMatNV() == right.isCoopMatNV() && - isCoopMatKHR() == right.isCoopMatKHR() && - sameStructType(right, lpidx, rpidx) && - sameReferenceType(right); - } - - // See if a cooperative matrix type parameter with unspecified parameters is - // an OK function parameter - bool coopMatParameterOK(const TType& right) const - { - if (isCoopMatNV()) { - return right.isCoopMatNV() && (getBasicType() == right.getBasicType()) && typeParameters == nullptr && - right.typeParameters != nullptr; - } - if (isCoopMatKHR() && right.isCoopMatKHR()) { - return ((getBasicType() == right.getBasicType()) || (getBasicType() == EbtCoopmat) || - (right.getBasicType() == EbtCoopmat)) && - typeParameters == nullptr && right.typeParameters != nullptr; - } - return false; - } - - bool sameCoopMatBaseType(const TType &right) const { - bool rv = false; - - if (isCoopMatNV()) { - rv = isCoopMatNV() && right.isCoopMatNV(); - if (getBasicType() == EbtFloat || getBasicType() == EbtFloat16) - rv = right.getBasicType() == EbtFloat || right.getBasicType() == EbtFloat16; - else if (getBasicType() == EbtUint || getBasicType() == EbtUint8 || getBasicType() == EbtUint16) - rv = right.getBasicType() == EbtUint || right.getBasicType() == EbtUint8 || right.getBasicType() == EbtUint16; - else if (getBasicType() == EbtInt || getBasicType() == EbtInt8 || getBasicType() == EbtInt16) - rv = right.getBasicType() == EbtInt || right.getBasicType() == EbtInt8 || right.getBasicType() == EbtInt16; - else - rv = false; - } else if (isCoopMatKHR() && right.isCoopMatKHR()) { - if (getBasicType() == EbtFloat || getBasicType() == EbtFloat16) - rv = right.getBasicType() == EbtFloat || right.getBasicType() == EbtFloat16 || right.getBasicType() == EbtCoopmat; - else if (getBasicType() == EbtUint || getBasicType() == EbtUint8 || getBasicType() == EbtUint16) - rv = right.getBasicType() == EbtUint || right.getBasicType() == EbtUint8 || right.getBasicType() == EbtUint16 || right.getBasicType() == EbtCoopmat; - else if (getBasicType() == EbtInt || getBasicType() == EbtInt8 || getBasicType() == EbtInt16) - rv = right.getBasicType() == EbtInt || right.getBasicType() == EbtInt8 || right.getBasicType() == EbtInt16 || right.getBasicType() == EbtCoopmat; - else - rv = false; - } - return rv; - } - - bool sameCoopMatUse(const TType &right) const { - return coopmatKHRuse == right.coopmatKHRuse; - } - - bool sameCoopMatShapeAndUse(const TType &right) const - { - if (!isCoopMat() || !right.isCoopMat() || isCoopMatKHR() != right.isCoopMatKHR()) - return false; - - if (coopmatKHRuse != right.coopmatKHRuse) - return false; - - // Skip bit width type parameter (first array size) for coopmatNV - int firstArrayDimToCompare = isCoopMatNV() ? 1 : 0; - for (int i = firstArrayDimToCompare; i < typeParameters->arraySizes->getNumDims(); ++i) { - if (typeParameters->arraySizes->getDimSize(i) != right.typeParameters->arraySizes->getDimSize(i)) - return false; - } - return true; - } - - // See if two types match in all ways (just the actual type, not qualification) - bool operator==(const TType& right) const - { - return sameElementType(right) && sameArrayness(right) && sameTypeParameters(right) && sameCoopMatUse(right) && sameSpirvType(right); - } - - bool operator!=(const TType& right) const - { - return ! operator==(right); - } - - unsigned int getBufferReferenceAlignment() const - { - if (getBasicType() == glslang::EbtReference) { - return getReferentType()->getQualifier().hasBufferReferenceAlign() ? - (1u << getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u; - } - return 0; - } - - const TSpirvType& getSpirvType() const { assert(spirvType); return *spirvType; } - -protected: - // Require consumer to pick between deep copy and shallow copy. - TType(const TType& type); - TType& operator=(const TType& type); - - // Recursively copy a type graph, while preserving the graph-like - // quality. That is, don't make more than one copy of a structure that - // gets reused multiple times in the type graph. - void deepCopy(const TType& copyOf, TMap& copiedMap) - { - shallowCopy(copyOf); - - // GL_EXT_spirv_intrinsics - if (copyOf.qualifier.spirvDecorate) { - qualifier.spirvDecorate = new TSpirvDecorate; - *qualifier.spirvDecorate = *copyOf.qualifier.spirvDecorate; - } - - if (copyOf.spirvType) { - spirvType = new TSpirvType; - *spirvType = *copyOf.spirvType; - } - - if (copyOf.arraySizes) { - arraySizes = new TArraySizes; - *arraySizes = *copyOf.arraySizes; - } - - if (copyOf.typeParameters) { - typeParameters = new TTypeParameters; - typeParameters->arraySizes = new TArraySizes; - *typeParameters->arraySizes = *copyOf.typeParameters->arraySizes; - typeParameters->basicType = copyOf.basicType; - } - - if (copyOf.isStruct() && copyOf.structure) { - auto prevCopy = copiedMap.find(copyOf.structure); - if (prevCopy != copiedMap.end()) - structure = prevCopy->second; - else { - structure = new TTypeList; - copiedMap[copyOf.structure] = structure; - for (unsigned int i = 0; i < copyOf.structure->size(); ++i) { - TTypeLoc typeLoc; - typeLoc.loc = (*copyOf.structure)[i].loc; - typeLoc.type = new TType(); - typeLoc.type->deepCopy(*(*copyOf.structure)[i].type, copiedMap); - structure->push_back(typeLoc); - } - } - } - - if (copyOf.fieldName) - fieldName = NewPoolTString(copyOf.fieldName->c_str()); - if (copyOf.typeName) - typeName = NewPoolTString(copyOf.typeName->c_str()); - } - - - void buildMangledName(TString&) const; - - TBasicType basicType : 8; - uint32_t vectorSize : 4; // 1 means either scalar or 1-component vector; see vector1 to disambiguate. - uint32_t matrixCols : 4; - uint32_t matrixRows : 4; - bool vector1 : 1; // Backward-compatible tracking of a 1-component vector distinguished from a scalar. - // GLSL 4.5 never has a 1-component vector; so this will always be false until such - // functionality is added. - // HLSL does have a 1-component vectors, so this will be true to disambiguate - // from a scalar. - bool coopmatNV : 1; - bool coopmatKHR : 1; - uint32_t coopmatKHRuse : 3; // Accepts one of three values: 0, 1, 2 (gl_MatrixUseA, gl_MatrixUseB, gl_MatrixUseAccumulator) - bool coopmatKHRUseValid : 1; // True if coopmatKHRuse has been set - TQualifier qualifier; - - TArraySizes* arraySizes; // nullptr unless an array; can be shared across types - // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so - // conserve space by making these a union - union { - TTypeList* structure; // invalid unless this is a struct; can be shared across types - TType *referentType; // invalid unless this is an EbtReference - }; - TString *fieldName; // for structure field names - TString *typeName; // for structure type name - TSampler sampler; - TTypeParameters *typeParameters;// nullptr unless a parameterized type; can be shared across types - TSpirvType* spirvType; // SPIR-V type defined by spirv_type directive -}; - -} // end namespace glslang - -#endif // _TYPES_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Include/arrays.h b/3rdparty/glslang/glslang/Include/arrays.h deleted file mode 100644 index 91e19083..00000000 --- a/3rdparty/glslang/glslang/Include/arrays.h +++ /dev/null @@ -1,362 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Implement types for tracking GLSL arrays, arrays of arrays, etc. -// - -#ifndef _ARRAYS_INCLUDED -#define _ARRAYS_INCLUDED - -#include - -namespace glslang { - -// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else. -const int UnsizedArraySize = 0; - -class TIntermTyped; -extern bool SameSpecializationConstants(TIntermTyped*, TIntermTyped*); - -// Specialization constants need both a nominal size and a node that defines -// the specialization constant being used. Array types are the same when their -// size and specialization constant nodes are the same. -struct TArraySize { - unsigned int size; - TIntermTyped* node; // nullptr means no specialization constant node - bool operator==(const TArraySize& rhs) const - { - if (size != rhs.size) - return false; - if (node == nullptr || rhs.node == nullptr) - return node == rhs.node; - - return SameSpecializationConstants(node, rhs.node); - } -}; - -// -// TSmallArrayVector is used as the container for the set of sizes in TArraySizes. -// It has generic-container semantics, while TArraySizes has array-of-array semantics. -// That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy. -// -struct TSmallArrayVector { - // - // TODO: memory: TSmallArrayVector is intended to be smaller. - // Almost all arrays could be handled by two sizes each fitting - // in 16 bits, needing a real vector only in the cases where there - // are more than 3 sizes or a size needing more than 16 bits. - // - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - TSmallArrayVector() : sizes(nullptr) { } - virtual ~TSmallArrayVector() { dealloc(); } - - // For breaking into two non-shared copies, independently modifiable. - TSmallArrayVector& operator=(const TSmallArrayVector& from) - { - if (from.sizes == nullptr) - sizes = nullptr; - else { - alloc(); - *sizes = *from.sizes; - } - - return *this; - } - - int size() const - { - if (sizes == nullptr) - return 0; - return (int)sizes->size(); - } - - unsigned int frontSize() const - { - assert(sizes != nullptr && sizes->size() > 0); - return sizes->front().size; - } - - TIntermTyped* frontNode() const - { - assert(sizes != nullptr && sizes->size() > 0); - return sizes->front().node; - } - - void changeFront(unsigned int s) - { - assert(sizes != nullptr); - // this should only happen for implicitly sized arrays, not specialization constants - assert(sizes->front().node == nullptr); - sizes->front().size = s; - } - - void push_back(unsigned int e, TIntermTyped* n) - { - alloc(); - TArraySize pair = { e, n }; - sizes->push_back(pair); - } - - void push_back(const TSmallArrayVector& newDims) - { - alloc(); - sizes->insert(sizes->end(), newDims.sizes->begin(), newDims.sizes->end()); - } - - void pop_front() - { - assert(sizes != nullptr && sizes->size() > 0); - if (sizes->size() == 1) - dealloc(); - else - sizes->erase(sizes->begin()); - } - - void pop_back() - { - assert(sizes != nullptr && sizes->size() > 0); - if (sizes->size() == 1) - dealloc(); - else - sizes->resize(sizes->size() - 1); - } - - // 'this' should currently not be holding anything, and copyNonFront - // will make it hold a copy of all but the first element of rhs. - // (This would be useful for making a type that is dereferenced by - // one dimension.) - void copyNonFront(const TSmallArrayVector& rhs) - { - assert(sizes == nullptr); - if (rhs.size() > 1) { - alloc(); - sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end()); - } - } - - unsigned int getDimSize(int i) const - { - assert(sizes != nullptr && (int)sizes->size() > i); - return (*sizes)[i].size; - } - - void setDimSize(int i, unsigned int size) const - { - assert(sizes != nullptr && (int)sizes->size() > i); - assert((*sizes)[i].node == nullptr); - (*sizes)[i].size = size; - } - - TIntermTyped* getDimNode(int i) const - { - assert(sizes != nullptr && (int)sizes->size() > i); - return (*sizes)[i].node; - } - - bool operator==(const TSmallArrayVector& rhs) const - { - if (sizes == nullptr && rhs.sizes == nullptr) - return true; - if (sizes == nullptr || rhs.sizes == nullptr) - return false; - return *sizes == *rhs.sizes; - } - bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); } - -protected: - TSmallArrayVector(const TSmallArrayVector&); - - void alloc() - { - if (sizes == nullptr) - sizes = new TVector; - } - void dealloc() - { - delete sizes; - sizes = nullptr; - } - - TVector* sizes; // will either hold such a pointer, or in the future, hold the two array sizes -}; - -// -// Represent an array, or array of arrays, to arbitrary depth. This is not -// done through a hierarchy of types in a type tree, rather all contiguous arrayness -// in the type hierarchy is localized into this single cumulative object. -// -// The arrayness in TTtype is a pointer, so that it can be non-allocated and zero -// for the vast majority of types that are non-array types. -// -// Order Policy: these are all identical: -// - left to right order within a contiguous set of ...[..][..][..]... in the source language -// - index order 0, 1, 2, ... within the 'sizes' member below -// - outer-most to inner-most -// -struct TArraySizes { - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - - TArraySizes() : implicitArraySize(0), implicitlySized(true), variablyIndexed(false){ } - - // For breaking into two non-shared copies, independently modifiable. - TArraySizes& operator=(const TArraySizes& from) - { - implicitArraySize = from.implicitArraySize; - variablyIndexed = from.variablyIndexed; - sizes = from.sizes; - implicitlySized = from.implicitlySized; - - return *this; - } - - // translate from array-of-array semantics to container semantics - int getNumDims() const { return sizes.size(); } - int getDimSize(int dim) const { return sizes.getDimSize(dim); } - TIntermTyped* getDimNode(int dim) const { return sizes.getDimNode(dim); } - void setDimSize(int dim, int size) { sizes.setDimSize(dim, size); } - int getOuterSize() const { return sizes.frontSize(); } - TIntermTyped* getOuterNode() const { return sizes.frontNode(); } - int getCumulativeSize() const - { - int size = 1; - for (int d = 0; d < sizes.size(); ++d) { - // this only makes sense in paths that have a known array size - assert(sizes.getDimSize(d) != UnsizedArraySize); - size *= sizes.getDimSize(d); - } - return size; - } - void addInnerSize() { addInnerSize((unsigned)UnsizedArraySize); } - void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); } - void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); } - void addInnerSize(TArraySize pair) { - sizes.push_back(pair.size, pair.node); - implicitlySized = false; - } - void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); } - void changeOuterSize(int s) { - sizes.changeFront((unsigned)s); - implicitlySized = false; - } - int getImplicitSize() const { return implicitArraySize > 0 ? implicitArraySize : 1; } - void updateImplicitSize(int s) { - implicitArraySize = (std::max)(implicitArraySize, s); - } - bool isInnerUnsized() const - { - for (int d = 1; d < sizes.size(); ++d) { - if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) - return true; - } - - return false; - } - bool clearInnerUnsized() - { - for (int d = 1; d < sizes.size(); ++d) { - if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize) - setDimSize(d, 1); - } - - return false; - } - bool isInnerSpecialization() const - { - for (int d = 1; d < sizes.size(); ++d) { - if (sizes.getDimNode(d) != nullptr) - return true; - } - - return false; - } - bool isOuterSpecialization() - { - return sizes.getDimNode(0) != nullptr; - } - - bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); } - bool isSized() const { return getOuterSize() != UnsizedArraySize; } - bool isImplicitlySized() const { return implicitlySized; } - bool isDefaultImplicitlySized() const { return implicitlySized && implicitArraySize == 0; } - void setImplicitlySized(bool isImplicitSizing) { implicitlySized = isImplicitSizing; } - void dereference() { sizes.pop_front(); } - void removeLastSize() { sizes.pop_back(); } - void copyDereferenced(const TArraySizes& rhs) - { - assert(sizes.size() == 0); - if (rhs.sizes.size() > 1) - sizes.copyNonFront(rhs.sizes); - } - - bool sameInnerArrayness(const TArraySizes& rhs) const - { - if (sizes.size() != rhs.sizes.size()) - return false; - - for (int d = 1; d < sizes.size(); ++d) { - if (sizes.getDimSize(d) != rhs.sizes.getDimSize(d) || - sizes.getDimNode(d) != rhs.sizes.getDimNode(d)) - return false; - } - - return true; - } - - void setVariablyIndexed() { variablyIndexed = true; } - bool isVariablyIndexed() const { return variablyIndexed; } - - bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; } - bool operator!=(const TArraySizes& rhs) const { return sizes != rhs.sizes; } - -protected: - TSmallArrayVector sizes; - - TArraySizes(const TArraySizes&); - - // For tracking maximum referenced compile-time constant index. - // Applies only to the outer-most dimension. Potentially becomes - // the implicit size of the array, if not variably indexed and - // otherwise legal. - int implicitArraySize; - bool implicitlySized; - bool variablyIndexed; // true if array is indexed with a non compile-time constant -}; - -} // end namespace glslang - -#endif // _ARRAYS_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Include/glslang_c_interface.h b/3rdparty/glslang/glslang/Include/glslang_c_interface.h deleted file mode 100644 index 7fa1a05d..00000000 --- a/3rdparty/glslang/glslang/Include/glslang_c_interface.h +++ /dev/null @@ -1,288 +0,0 @@ -/** - This code is based on the glslang_c_interface implementation by Viktor Latypov -**/ - -/** -BSD 2-Clause License - -Copyright (c) 2019, Viktor Latypov -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**/ - -#ifndef GLSLANG_C_IFACE_H_INCLUDED -#define GLSLANG_C_IFACE_H_INCLUDED - -#include -#include - -#include "glslang_c_shader_types.h" - -typedef struct glslang_shader_s glslang_shader_t; -typedef struct glslang_program_s glslang_program_t; - -/* TLimits counterpart */ -typedef struct glslang_limits_s { - bool non_inductive_for_loops; - bool while_loops; - bool do_while_loops; - bool general_uniform_indexing; - bool general_attribute_matrix_vector_indexing; - bool general_varying_indexing; - bool general_sampler_indexing; - bool general_variable_indexing; - bool general_constant_matrix_vector_indexing; -} glslang_limits_t; - -/* TBuiltInResource counterpart */ -typedef struct glslang_resource_s { - int max_lights; - int max_clip_planes; - int max_texture_units; - int max_texture_coords; - int max_vertex_attribs; - int max_vertex_uniform_components; - int max_varying_floats; - int max_vertex_texture_image_units; - int max_combined_texture_image_units; - int max_texture_image_units; - int max_fragment_uniform_components; - int max_draw_buffers; - int max_vertex_uniform_vectors; - int max_varying_vectors; - int max_fragment_uniform_vectors; - int max_vertex_output_vectors; - int max_fragment_input_vectors; - int min_program_texel_offset; - int max_program_texel_offset; - int max_clip_distances; - int max_compute_work_group_count_x; - int max_compute_work_group_count_y; - int max_compute_work_group_count_z; - int max_compute_work_group_size_x; - int max_compute_work_group_size_y; - int max_compute_work_group_size_z; - int max_compute_uniform_components; - int max_compute_texture_image_units; - int max_compute_image_uniforms; - int max_compute_atomic_counters; - int max_compute_atomic_counter_buffers; - int max_varying_components; - int max_vertex_output_components; - int max_geometry_input_components; - int max_geometry_output_components; - int max_fragment_input_components; - int max_image_units; - int max_combined_image_units_and_fragment_outputs; - int max_combined_shader_output_resources; - int max_image_samples; - int max_vertex_image_uniforms; - int max_tess_control_image_uniforms; - int max_tess_evaluation_image_uniforms; - int max_geometry_image_uniforms; - int max_fragment_image_uniforms; - int max_combined_image_uniforms; - int max_geometry_texture_image_units; - int max_geometry_output_vertices; - int max_geometry_total_output_components; - int max_geometry_uniform_components; - int max_geometry_varying_components; - int max_tess_control_input_components; - int max_tess_control_output_components; - int max_tess_control_texture_image_units; - int max_tess_control_uniform_components; - int max_tess_control_total_output_components; - int max_tess_evaluation_input_components; - int max_tess_evaluation_output_components; - int max_tess_evaluation_texture_image_units; - int max_tess_evaluation_uniform_components; - int max_tess_patch_components; - int max_patch_vertices; - int max_tess_gen_level; - int max_viewports; - int max_vertex_atomic_counters; - int max_tess_control_atomic_counters; - int max_tess_evaluation_atomic_counters; - int max_geometry_atomic_counters; - int max_fragment_atomic_counters; - int max_combined_atomic_counters; - int max_atomic_counter_bindings; - int max_vertex_atomic_counter_buffers; - int max_tess_control_atomic_counter_buffers; - int max_tess_evaluation_atomic_counter_buffers; - int max_geometry_atomic_counter_buffers; - int max_fragment_atomic_counter_buffers; - int max_combined_atomic_counter_buffers; - int max_atomic_counter_buffer_size; - int max_transform_feedback_buffers; - int max_transform_feedback_interleaved_components; - int max_cull_distances; - int max_combined_clip_and_cull_distances; - int max_samples; - int max_mesh_output_vertices_nv; - int max_mesh_output_primitives_nv; - int max_mesh_work_group_size_x_nv; - int max_mesh_work_group_size_y_nv; - int max_mesh_work_group_size_z_nv; - int max_task_work_group_size_x_nv; - int max_task_work_group_size_y_nv; - int max_task_work_group_size_z_nv; - int max_mesh_view_count_nv; - int max_mesh_output_vertices_ext; - int max_mesh_output_primitives_ext; - int max_mesh_work_group_size_x_ext; - int max_mesh_work_group_size_y_ext; - int max_mesh_work_group_size_z_ext; - int max_task_work_group_size_x_ext; - int max_task_work_group_size_y_ext; - int max_task_work_group_size_z_ext; - int max_mesh_view_count_ext; - union - { - int max_dual_source_draw_buffers_ext; - - /* Incorrectly capitalized name retained for backward compatibility */ - int maxDualSourceDrawBuffersEXT; - }; - - glslang_limits_t limits; -} glslang_resource_t; - -/* Inclusion result structure allocated by C include_local/include_system callbacks */ -typedef struct glsl_include_result_s { - /* Header file name or NULL if inclusion failed */ - const char* header_name; - - /* Header contents or NULL */ - const char* header_data; - size_t header_length; - -} glsl_include_result_t; - -/* Callback for local file inclusion */ -typedef glsl_include_result_t* (*glsl_include_local_func)(void* ctx, const char* header_name, const char* includer_name, - size_t include_depth); - -/* Callback for system file inclusion */ -typedef glsl_include_result_t* (*glsl_include_system_func)(void* ctx, const char* header_name, - const char* includer_name, size_t include_depth); - -/* Callback for include result destruction */ -typedef int (*glsl_free_include_result_func)(void* ctx, glsl_include_result_t* result); - -/* Collection of callbacks for GLSL preprocessor */ -typedef struct glsl_include_callbacks_s { - glsl_include_system_func include_system; - glsl_include_local_func include_local; - glsl_free_include_result_func free_include_result; -} glsl_include_callbacks_t; - -typedef struct glslang_input_s { - glslang_source_t language; - glslang_stage_t stage; - glslang_client_t client; - glslang_target_client_version_t client_version; - glslang_target_language_t target_language; - glslang_target_language_version_t target_language_version; - /** Shader source code */ - const char* code; - int default_version; - glslang_profile_t default_profile; - int force_default_version_and_profile; - int forward_compatible; - glslang_messages_t messages; - const glslang_resource_t* resource; - glsl_include_callbacks_t callbacks; - void* callbacks_ctx; -} glslang_input_t; - -/* SpvOptions counterpart */ -typedef struct glslang_spv_options_s { - bool generate_debug_info; - bool strip_debug_info; - bool disable_optimizer; - bool optimize_size; - bool disassemble; - bool validate; - bool emit_nonsemantic_shader_debug_info; - bool emit_nonsemantic_shader_debug_source; - bool compile_only; -} glslang_spv_options_t; - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef GLSLANG_IS_SHARED_LIBRARY - #ifdef _WIN32 - #ifdef GLSLANG_EXPORTING - #define GLSLANG_EXPORT __declspec(dllexport) - #else - #define GLSLANG_EXPORT __declspec(dllimport) - #endif - #elif __GNUC__ >= 4 - #define GLSLANG_EXPORT __attribute__((visibility("default"))) - #endif -#endif // GLSLANG_IS_SHARED_LIBRARY - -#ifndef GLSLANG_EXPORT -#define GLSLANG_EXPORT -#endif - -GLSLANG_EXPORT int glslang_initialize_process(void); -GLSLANG_EXPORT void glslang_finalize_process(void); - -GLSLANG_EXPORT glslang_shader_t* glslang_shader_create(const glslang_input_t* input); -GLSLANG_EXPORT void glslang_shader_delete(glslang_shader_t* shader); -GLSLANG_EXPORT void glslang_shader_set_preamble(glslang_shader_t* shader, const char* s); -GLSLANG_EXPORT void glslang_shader_shift_binding(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base); -GLSLANG_EXPORT void glslang_shader_shift_binding_for_set(glslang_shader_t* shader, glslang_resource_type_t res, unsigned int base, unsigned int set); -GLSLANG_EXPORT void glslang_shader_set_options(glslang_shader_t* shader, int options); // glslang_shader_options_t -GLSLANG_EXPORT void glslang_shader_set_glsl_version(glslang_shader_t* shader, int version); -GLSLANG_EXPORT int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input); -GLSLANG_EXPORT int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input); -GLSLANG_EXPORT const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader); -GLSLANG_EXPORT const char* glslang_shader_get_info_log(glslang_shader_t* shader); -GLSLANG_EXPORT const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader); - -GLSLANG_EXPORT glslang_program_t* glslang_program_create(void); -GLSLANG_EXPORT void glslang_program_delete(glslang_program_t* program); -GLSLANG_EXPORT void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader); -GLSLANG_EXPORT int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t -GLSLANG_EXPORT void glslang_program_add_source_text(glslang_program_t* program, glslang_stage_t stage, const char* text, size_t len); -GLSLANG_EXPORT void glslang_program_set_source_file(glslang_program_t* program, glslang_stage_t stage, const char* file); -GLSLANG_EXPORT int glslang_program_map_io(glslang_program_t* program); -GLSLANG_EXPORT void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage); -GLSLANG_EXPORT void glslang_program_SPIRV_generate_with_options(glslang_program_t* program, glslang_stage_t stage, glslang_spv_options_t* spv_options); -GLSLANG_EXPORT size_t glslang_program_SPIRV_get_size(glslang_program_t* program); -GLSLANG_EXPORT void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*); -GLSLANG_EXPORT unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program); -GLSLANG_EXPORT const char* glslang_program_SPIRV_get_messages(glslang_program_t* program); -GLSLANG_EXPORT const char* glslang_program_get_info_log(glslang_program_t* program); -GLSLANG_EXPORT const char* glslang_program_get_info_debug_log(glslang_program_t* program); - -#ifdef __cplusplus -} -#endif - -#endif /* #ifdef GLSLANG_C_IFACE_INCLUDED */ diff --git a/3rdparty/glslang/glslang/Include/glslang_c_shader_types.h b/3rdparty/glslang/glslang/Include/glslang_c_shader_types.h deleted file mode 100644 index 9bc21149..00000000 --- a/3rdparty/glslang/glslang/Include/glslang_c_shader_types.h +++ /dev/null @@ -1,227 +0,0 @@ -/** - This code is based on the glslang_c_interface implementation by Viktor Latypov -**/ - -/** -BSD 2-Clause License - -Copyright (c) 2019, Viktor Latypov -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**/ - -#ifndef C_SHADER_TYPES_H_INCLUDED -#define C_SHADER_TYPES_H_INCLUDED - -#define LAST_ELEMENT_MARKER(x) x - -/* EShLanguage counterpart */ -typedef enum { - GLSLANG_STAGE_VERTEX, - GLSLANG_STAGE_TESSCONTROL, - GLSLANG_STAGE_TESSEVALUATION, - GLSLANG_STAGE_GEOMETRY, - GLSLANG_STAGE_FRAGMENT, - GLSLANG_STAGE_COMPUTE, - GLSLANG_STAGE_RAYGEN, - GLSLANG_STAGE_RAYGEN_NV = GLSLANG_STAGE_RAYGEN, - GLSLANG_STAGE_INTERSECT, - GLSLANG_STAGE_INTERSECT_NV = GLSLANG_STAGE_INTERSECT, - GLSLANG_STAGE_ANYHIT, - GLSLANG_STAGE_ANYHIT_NV = GLSLANG_STAGE_ANYHIT, - GLSLANG_STAGE_CLOSESTHIT, - GLSLANG_STAGE_CLOSESTHIT_NV = GLSLANG_STAGE_CLOSESTHIT, - GLSLANG_STAGE_MISS, - GLSLANG_STAGE_MISS_NV = GLSLANG_STAGE_MISS, - GLSLANG_STAGE_CALLABLE, - GLSLANG_STAGE_CALLABLE_NV = GLSLANG_STAGE_CALLABLE, - GLSLANG_STAGE_TASK, - GLSLANG_STAGE_TASK_NV = GLSLANG_STAGE_TASK, - GLSLANG_STAGE_MESH, - GLSLANG_STAGE_MESH_NV = GLSLANG_STAGE_MESH, - LAST_ELEMENT_MARKER(GLSLANG_STAGE_COUNT), -} glslang_stage_t; // would be better as stage, but this is ancient now - -/* EShLanguageMask counterpart */ -typedef enum { - GLSLANG_STAGE_VERTEX_MASK = (1 << GLSLANG_STAGE_VERTEX), - GLSLANG_STAGE_TESSCONTROL_MASK = (1 << GLSLANG_STAGE_TESSCONTROL), - GLSLANG_STAGE_TESSEVALUATION_MASK = (1 << GLSLANG_STAGE_TESSEVALUATION), - GLSLANG_STAGE_GEOMETRY_MASK = (1 << GLSLANG_STAGE_GEOMETRY), - GLSLANG_STAGE_FRAGMENT_MASK = (1 << GLSLANG_STAGE_FRAGMENT), - GLSLANG_STAGE_COMPUTE_MASK = (1 << GLSLANG_STAGE_COMPUTE), - GLSLANG_STAGE_RAYGEN_MASK = (1 << GLSLANG_STAGE_RAYGEN), - GLSLANG_STAGE_RAYGEN_NV_MASK = GLSLANG_STAGE_RAYGEN_MASK, - GLSLANG_STAGE_INTERSECT_MASK = (1 << GLSLANG_STAGE_INTERSECT), - GLSLANG_STAGE_INTERSECT_NV_MASK = GLSLANG_STAGE_INTERSECT_MASK, - GLSLANG_STAGE_ANYHIT_MASK = (1 << GLSLANG_STAGE_ANYHIT), - GLSLANG_STAGE_ANYHIT_NV_MASK = GLSLANG_STAGE_ANYHIT_MASK, - GLSLANG_STAGE_CLOSESTHIT_MASK = (1 << GLSLANG_STAGE_CLOSESTHIT), - GLSLANG_STAGE_CLOSESTHIT_NV_MASK = GLSLANG_STAGE_CLOSESTHIT_MASK, - GLSLANG_STAGE_MISS_MASK = (1 << GLSLANG_STAGE_MISS), - GLSLANG_STAGE_MISS_NV_MASK = GLSLANG_STAGE_MISS_MASK, - GLSLANG_STAGE_CALLABLE_MASK = (1 << GLSLANG_STAGE_CALLABLE), - GLSLANG_STAGE_CALLABLE_NV_MASK = GLSLANG_STAGE_CALLABLE_MASK, - GLSLANG_STAGE_TASK_MASK = (1 << GLSLANG_STAGE_TASK), - GLSLANG_STAGE_TASK_NV_MASK = GLSLANG_STAGE_TASK_MASK, - GLSLANG_STAGE_MESH_MASK = (1 << GLSLANG_STAGE_MESH), - GLSLANG_STAGE_MESH_NV_MASK = GLSLANG_STAGE_MESH_MASK, - LAST_ELEMENT_MARKER(GLSLANG_STAGE_MASK_COUNT), -} glslang_stage_mask_t; - -/* EShSource counterpart */ -typedef enum { - GLSLANG_SOURCE_NONE, - GLSLANG_SOURCE_GLSL, - GLSLANG_SOURCE_HLSL, - LAST_ELEMENT_MARKER(GLSLANG_SOURCE_COUNT), -} glslang_source_t; - -/* EShClient counterpart */ -typedef enum { - GLSLANG_CLIENT_NONE, - GLSLANG_CLIENT_VULKAN, - GLSLANG_CLIENT_OPENGL, - LAST_ELEMENT_MARKER(GLSLANG_CLIENT_COUNT), -} glslang_client_t; - -/* EShTargetLanguage counterpart */ -typedef enum { - GLSLANG_TARGET_NONE, - GLSLANG_TARGET_SPV, - LAST_ELEMENT_MARKER(GLSLANG_TARGET_COUNT), -} glslang_target_language_t; - -/* SH_TARGET_ClientVersion counterpart */ -typedef enum { - GLSLANG_TARGET_VULKAN_1_0 = (1 << 22), - GLSLANG_TARGET_VULKAN_1_1 = (1 << 22) | (1 << 12), - GLSLANG_TARGET_VULKAN_1_2 = (1 << 22) | (2 << 12), - GLSLANG_TARGET_VULKAN_1_3 = (1 << 22) | (3 << 12), - GLSLANG_TARGET_OPENGL_450 = 450, - LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT = 5), -} glslang_target_client_version_t; - -/* SH_TARGET_LanguageVersion counterpart */ -typedef enum { - GLSLANG_TARGET_SPV_1_0 = (1 << 16), - GLSLANG_TARGET_SPV_1_1 = (1 << 16) | (1 << 8), - GLSLANG_TARGET_SPV_1_2 = (1 << 16) | (2 << 8), - GLSLANG_TARGET_SPV_1_3 = (1 << 16) | (3 << 8), - GLSLANG_TARGET_SPV_1_4 = (1 << 16) | (4 << 8), - GLSLANG_TARGET_SPV_1_5 = (1 << 16) | (5 << 8), - GLSLANG_TARGET_SPV_1_6 = (1 << 16) | (6 << 8), - LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT = 7), -} glslang_target_language_version_t; - -/* EShExecutable counterpart */ -typedef enum { GLSLANG_EX_VERTEX_FRAGMENT, GLSLANG_EX_FRAGMENT } glslang_executable_t; - -// EShOptimizationLevel counterpart -// This enum is not used in the current C interface, but could be added at a later date. -// GLSLANG_OPT_NONE is the current default. -typedef enum { - GLSLANG_OPT_NO_GENERATION, - GLSLANG_OPT_NONE, - GLSLANG_OPT_SIMPLE, - GLSLANG_OPT_FULL, - LAST_ELEMENT_MARKER(GLSLANG_OPT_LEVEL_COUNT), -} glslang_optimization_level_t; - -/* EShTextureSamplerTransformMode counterpart */ -typedef enum { - GLSLANG_TEX_SAMP_TRANS_KEEP, - GLSLANG_TEX_SAMP_TRANS_UPGRADE_TEXTURE_REMOVE_SAMPLER, - LAST_ELEMENT_MARKER(GLSLANG_TEX_SAMP_TRANS_COUNT), -} glslang_texture_sampler_transform_mode_t; - -/* EShMessages counterpart */ -typedef enum { - GLSLANG_MSG_DEFAULT_BIT = 0, - GLSLANG_MSG_RELAXED_ERRORS_BIT = (1 << 0), - GLSLANG_MSG_SUPPRESS_WARNINGS_BIT = (1 << 1), - GLSLANG_MSG_AST_BIT = (1 << 2), - GLSLANG_MSG_SPV_RULES_BIT = (1 << 3), - GLSLANG_MSG_VULKAN_RULES_BIT = (1 << 4), - GLSLANG_MSG_ONLY_PREPROCESSOR_BIT = (1 << 5), - GLSLANG_MSG_READ_HLSL_BIT = (1 << 6), - GLSLANG_MSG_CASCADING_ERRORS_BIT = (1 << 7), - GLSLANG_MSG_KEEP_UNCALLED_BIT = (1 << 8), - GLSLANG_MSG_HLSL_OFFSETS_BIT = (1 << 9), - GLSLANG_MSG_DEBUG_INFO_BIT = (1 << 10), - GLSLANG_MSG_HLSL_ENABLE_16BIT_TYPES_BIT = (1 << 11), - GLSLANG_MSG_HLSL_LEGALIZATION_BIT = (1 << 12), - GLSLANG_MSG_HLSL_DX9_COMPATIBLE_BIT = (1 << 13), - GLSLANG_MSG_BUILTIN_SYMBOL_TABLE_BIT = (1 << 14), - GLSLANG_MSG_ENHANCED = (1 << 15), - LAST_ELEMENT_MARKER(GLSLANG_MSG_COUNT), -} glslang_messages_t; - -/* EShReflectionOptions counterpart */ -typedef enum { - GLSLANG_REFLECTION_DEFAULT_BIT = 0, - GLSLANG_REFLECTION_STRICT_ARRAY_SUFFIX_BIT = (1 << 0), - GLSLANG_REFLECTION_BASIC_ARRAY_SUFFIX_BIT = (1 << 1), - GLSLANG_REFLECTION_INTERMEDIATE_IOO_BIT = (1 << 2), - GLSLANG_REFLECTION_SEPARATE_BUFFERS_BIT = (1 << 3), - GLSLANG_REFLECTION_ALL_BLOCK_VARIABLES_BIT = (1 << 4), - GLSLANG_REFLECTION_UNWRAP_IO_BLOCKS_BIT = (1 << 5), - GLSLANG_REFLECTION_ALL_IO_VARIABLES_BIT = (1 << 6), - GLSLANG_REFLECTION_SHARED_STD140_SSBO_BIT = (1 << 7), - GLSLANG_REFLECTION_SHARED_STD140_UBO_BIT = (1 << 8), - LAST_ELEMENT_MARKER(GLSLANG_REFLECTION_COUNT), -} glslang_reflection_options_t; - -/* EProfile counterpart (from Versions.h) */ -typedef enum { - GLSLANG_BAD_PROFILE = 0, - GLSLANG_NO_PROFILE = (1 << 0), - GLSLANG_CORE_PROFILE = (1 << 1), - GLSLANG_COMPATIBILITY_PROFILE = (1 << 2), - GLSLANG_ES_PROFILE = (1 << 3), - LAST_ELEMENT_MARKER(GLSLANG_PROFILE_COUNT), -} glslang_profile_t; - -/* Shader options */ -typedef enum { - GLSLANG_SHADER_DEFAULT_BIT = 0, - GLSLANG_SHADER_AUTO_MAP_BINDINGS = (1 << 0), - GLSLANG_SHADER_AUTO_MAP_LOCATIONS = (1 << 1), - GLSLANG_SHADER_VULKAN_RULES_RELAXED = (1 << 2), - LAST_ELEMENT_MARKER(GLSLANG_SHADER_COUNT), -} glslang_shader_options_t; - -/* TResourceType counterpart */ -typedef enum { - GLSLANG_RESOURCE_TYPE_SAMPLER, - GLSLANG_RESOURCE_TYPE_TEXTURE, - GLSLANG_RESOURCE_TYPE_IMAGE, - GLSLANG_RESOURCE_TYPE_UBO, - GLSLANG_RESOURCE_TYPE_SSBO, - GLSLANG_RESOURCE_TYPE_UAV, - LAST_ELEMENT_MARKER(GLSLANG_RESOURCE_TYPE_COUNT), -} glslang_resource_type_t; - -#undef LAST_ELEMENT_MARKER - -#endif diff --git a/3rdparty/glslang/glslang/Include/intermediate.h b/3rdparty/glslang/glslang/Include/intermediate.h deleted file mode 100644 index b0e154e9..00000000 --- a/3rdparty/glslang/glslang/Include/intermediate.h +++ /dev/null @@ -1,1887 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2016 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Definition of the in-memory high-level intermediate representation -// of shaders. This is a tree that parser creates. -// -// Nodes in the tree are defined as a hierarchy of classes derived from -// TIntermNode. Each is a node in a tree. There is no preset branching factor; -// each node can have it's own type of list of children. -// - -#ifndef __INTERMEDIATE_H -#define __INTERMEDIATE_H - -#include "Common.h" -#include "Types.h" -#include "ConstantUnion.h" - -namespace glslang { - -class TIntermediate; - -// -// Operators used by the high-level (parse tree) representation. -// -enum TOperator { - EOpNull, // if in a node, should only mean a node is still being built - EOpSequence, // denotes a list of statements, or parameters, etc. - EOpScope, // Used by debugging to denote a scoped list of statements - EOpLinkerObjects, // for aggregate node of objects the linker may need, if not reference by the rest of the AST - EOpFunctionCall, - EOpFunction, // For function definition - EOpParameters, // an aggregate listing the parameters to a function - EOpSpirvInst, - - // - // Unary operators - // - - EOpNegative, - EOpLogicalNot, - EOpVectorLogicalNot, - EOpBitwiseNot, - - EOpPostIncrement, - EOpPostDecrement, - EOpPreIncrement, - EOpPreDecrement, - - EOpCopyObject, - - EOpDeclare, // Used by debugging to force declaration of variable in correct scope - - // (u)int* -> bool - EOpConvInt8ToBool, - EOpConvUint8ToBool, - EOpConvInt16ToBool, - EOpConvUint16ToBool, - EOpConvIntToBool, - EOpConvUintToBool, - EOpConvInt64ToBool, - EOpConvUint64ToBool, - - // float* -> bool - EOpConvFloat16ToBool, - EOpConvFloatToBool, - EOpConvDoubleToBool, - - // bool -> (u)int* - EOpConvBoolToInt8, - EOpConvBoolToUint8, - EOpConvBoolToInt16, - EOpConvBoolToUint16, - EOpConvBoolToInt, - EOpConvBoolToUint, - EOpConvBoolToInt64, - EOpConvBoolToUint64, - - // bool -> float* - EOpConvBoolToFloat16, - EOpConvBoolToFloat, - EOpConvBoolToDouble, - - // int8_t -> (u)int* - EOpConvInt8ToInt16, - EOpConvInt8ToInt, - EOpConvInt8ToInt64, - EOpConvInt8ToUint8, - EOpConvInt8ToUint16, - EOpConvInt8ToUint, - EOpConvInt8ToUint64, - - // uint8_t -> (u)int* - EOpConvUint8ToInt8, - EOpConvUint8ToInt16, - EOpConvUint8ToInt, - EOpConvUint8ToInt64, - EOpConvUint8ToUint16, - EOpConvUint8ToUint, - EOpConvUint8ToUint64, - - // int8_t -> float* - EOpConvInt8ToFloat16, - EOpConvInt8ToFloat, - EOpConvInt8ToDouble, - - // uint8_t -> float* - EOpConvUint8ToFloat16, - EOpConvUint8ToFloat, - EOpConvUint8ToDouble, - - // int16_t -> (u)int* - EOpConvInt16ToInt8, - EOpConvInt16ToInt, - EOpConvInt16ToInt64, - EOpConvInt16ToUint8, - EOpConvInt16ToUint16, - EOpConvInt16ToUint, - EOpConvInt16ToUint64, - - // uint16_t -> (u)int* - EOpConvUint16ToInt8, - EOpConvUint16ToInt16, - EOpConvUint16ToInt, - EOpConvUint16ToInt64, - EOpConvUint16ToUint8, - EOpConvUint16ToUint, - EOpConvUint16ToUint64, - - // int16_t -> float* - EOpConvInt16ToFloat16, - EOpConvInt16ToFloat, - EOpConvInt16ToDouble, - - // uint16_t -> float* - EOpConvUint16ToFloat16, - EOpConvUint16ToFloat, - EOpConvUint16ToDouble, - - // int32_t -> (u)int* - EOpConvIntToInt8, - EOpConvIntToInt16, - EOpConvIntToInt64, - EOpConvIntToUint8, - EOpConvIntToUint16, - EOpConvIntToUint, - EOpConvIntToUint64, - - // uint32_t -> (u)int* - EOpConvUintToInt8, - EOpConvUintToInt16, - EOpConvUintToInt, - EOpConvUintToInt64, - EOpConvUintToUint8, - EOpConvUintToUint16, - EOpConvUintToUint64, - - // int32_t -> float* - EOpConvIntToFloat16, - EOpConvIntToFloat, - EOpConvIntToDouble, - - // uint32_t -> float* - EOpConvUintToFloat16, - EOpConvUintToFloat, - EOpConvUintToDouble, - - // int64_t -> (u)int* - EOpConvInt64ToInt8, - EOpConvInt64ToInt16, - EOpConvInt64ToInt, - EOpConvInt64ToUint8, - EOpConvInt64ToUint16, - EOpConvInt64ToUint, - EOpConvInt64ToUint64, - - // uint64_t -> (u)int* - EOpConvUint64ToInt8, - EOpConvUint64ToInt16, - EOpConvUint64ToInt, - EOpConvUint64ToInt64, - EOpConvUint64ToUint8, - EOpConvUint64ToUint16, - EOpConvUint64ToUint, - - // int64_t -> float* - EOpConvInt64ToFloat16, - EOpConvInt64ToFloat, - EOpConvInt64ToDouble, - - // uint64_t -> float* - EOpConvUint64ToFloat16, - EOpConvUint64ToFloat, - EOpConvUint64ToDouble, - - // float16_t -> (u)int* - EOpConvFloat16ToInt8, - EOpConvFloat16ToInt16, - EOpConvFloat16ToInt, - EOpConvFloat16ToInt64, - EOpConvFloat16ToUint8, - EOpConvFloat16ToUint16, - EOpConvFloat16ToUint, - EOpConvFloat16ToUint64, - - // float16_t -> float* - EOpConvFloat16ToFloat, - EOpConvFloat16ToDouble, - - // float -> (u)int* - EOpConvFloatToInt8, - EOpConvFloatToInt16, - EOpConvFloatToInt, - EOpConvFloatToInt64, - EOpConvFloatToUint8, - EOpConvFloatToUint16, - EOpConvFloatToUint, - EOpConvFloatToUint64, - - // float -> float* - EOpConvFloatToFloat16, - EOpConvFloatToDouble, - - // float64 _t-> (u)int* - EOpConvDoubleToInt8, - EOpConvDoubleToInt16, - EOpConvDoubleToInt, - EOpConvDoubleToInt64, - EOpConvDoubleToUint8, - EOpConvDoubleToUint16, - EOpConvDoubleToUint, - EOpConvDoubleToUint64, - - // float64_t -> float* - EOpConvDoubleToFloat16, - EOpConvDoubleToFloat, - - // uint64_t <-> pointer - EOpConvUint64ToPtr, - EOpConvPtrToUint64, - - // uvec2 <-> pointer - EOpConvUvec2ToPtr, - EOpConvPtrToUvec2, - - // uint64_t -> accelerationStructureEXT - EOpConvUint64ToAccStruct, - - // uvec2 -> accelerationStructureEXT - EOpConvUvec2ToAccStruct, - - // - // binary operations - // - - EOpAdd, - EOpSub, - EOpMul, - EOpDiv, - EOpMod, - EOpRightShift, - EOpLeftShift, - EOpAnd, - EOpInclusiveOr, - EOpExclusiveOr, - EOpEqual, - EOpNotEqual, - EOpVectorEqual, - EOpVectorNotEqual, - EOpLessThan, - EOpGreaterThan, - EOpLessThanEqual, - EOpGreaterThanEqual, - EOpComma, - - EOpVectorTimesScalar, - EOpVectorTimesMatrix, - EOpMatrixTimesVector, - EOpMatrixTimesScalar, - - EOpLogicalOr, - EOpLogicalXor, - EOpLogicalAnd, - - EOpIndexDirect, - EOpIndexIndirect, - EOpIndexDirectStruct, - - EOpVectorSwizzle, - - EOpMethod, - EOpScoping, - - // - // Built-in functions mapped to operators - // - - EOpRadians, - EOpDegrees, - EOpSin, - EOpCos, - EOpTan, - EOpAsin, - EOpAcos, - EOpAtan, - EOpSinh, - EOpCosh, - EOpTanh, - EOpAsinh, - EOpAcosh, - EOpAtanh, - - EOpPow, - EOpExp, - EOpLog, - EOpExp2, - EOpLog2, - EOpSqrt, - EOpInverseSqrt, - - EOpAbs, - EOpSign, - EOpFloor, - EOpTrunc, - EOpRound, - EOpRoundEven, - EOpCeil, - EOpFract, - EOpModf, - EOpMin, - EOpMax, - EOpClamp, - EOpMix, - EOpStep, - EOpSmoothStep, - - EOpIsNan, - EOpIsInf, - - EOpFma, - - EOpFrexp, - EOpLdexp, - - EOpFloatBitsToInt, - EOpFloatBitsToUint, - EOpIntBitsToFloat, - EOpUintBitsToFloat, - EOpDoubleBitsToInt64, - EOpDoubleBitsToUint64, - EOpInt64BitsToDouble, - EOpUint64BitsToDouble, - EOpFloat16BitsToInt16, - EOpFloat16BitsToUint16, - EOpInt16BitsToFloat16, - EOpUint16BitsToFloat16, - EOpPackSnorm2x16, - EOpUnpackSnorm2x16, - EOpPackUnorm2x16, - EOpUnpackUnorm2x16, - EOpPackSnorm4x8, - EOpUnpackSnorm4x8, - EOpPackUnorm4x8, - EOpUnpackUnorm4x8, - EOpPackHalf2x16, - EOpUnpackHalf2x16, - EOpPackDouble2x32, - EOpUnpackDouble2x32, - EOpPackInt2x32, - EOpUnpackInt2x32, - EOpPackUint2x32, - EOpUnpackUint2x32, - EOpPackFloat2x16, - EOpUnpackFloat2x16, - EOpPackInt2x16, - EOpUnpackInt2x16, - EOpPackUint2x16, - EOpUnpackUint2x16, - EOpPackInt4x16, - EOpUnpackInt4x16, - EOpPackUint4x16, - EOpUnpackUint4x16, - EOpPack16, - EOpPack32, - EOpPack64, - EOpUnpack32, - EOpUnpack16, - EOpUnpack8, - - EOpLength, - EOpDistance, - EOpDot, - EOpCross, - EOpNormalize, - EOpFaceForward, - EOpReflect, - EOpRefract, - - EOpMin3, - EOpMax3, - EOpMid3, - - EOpDPdx, // Fragment only - EOpDPdy, // Fragment only - EOpFwidth, // Fragment only - EOpDPdxFine, // Fragment only - EOpDPdyFine, // Fragment only - EOpFwidthFine, // Fragment only - EOpDPdxCoarse, // Fragment only - EOpDPdyCoarse, // Fragment only - EOpFwidthCoarse, // Fragment only - - EOpInterpolateAtCentroid, // Fragment only - EOpInterpolateAtSample, // Fragment only - EOpInterpolateAtOffset, // Fragment only - EOpInterpolateAtVertex, - - EOpMatrixTimesMatrix, - EOpOuterProduct, - EOpDeterminant, - EOpMatrixInverse, - EOpTranspose, - - EOpFtransform, - - EOpNoise, - - EOpEmitVertex, // geometry only - EOpEndPrimitive, // geometry only - EOpEmitStreamVertex, // geometry only - EOpEndStreamPrimitive, // geometry only - - EOpBarrier, - EOpMemoryBarrier, - EOpMemoryBarrierAtomicCounter, - EOpMemoryBarrierBuffer, - EOpMemoryBarrierImage, - EOpMemoryBarrierShared, // compute only - EOpGroupMemoryBarrier, // compute only - - EOpBallot, - EOpReadInvocation, - EOpReadFirstInvocation, - - EOpAnyInvocation, - EOpAllInvocations, - EOpAllInvocationsEqual, - - EOpSubgroupGuardStart, - EOpSubgroupBarrier, - EOpSubgroupMemoryBarrier, - EOpSubgroupMemoryBarrierBuffer, - EOpSubgroupMemoryBarrierImage, - EOpSubgroupMemoryBarrierShared, // compute only - EOpSubgroupElect, - EOpSubgroupAll, - EOpSubgroupAny, - EOpSubgroupAllEqual, - EOpSubgroupBroadcast, - EOpSubgroupBroadcastFirst, - EOpSubgroupBallot, - EOpSubgroupInverseBallot, - EOpSubgroupBallotBitExtract, - EOpSubgroupBallotBitCount, - EOpSubgroupBallotInclusiveBitCount, - EOpSubgroupBallotExclusiveBitCount, - EOpSubgroupBallotFindLSB, - EOpSubgroupBallotFindMSB, - EOpSubgroupShuffle, - EOpSubgroupShuffleXor, - EOpSubgroupShuffleUp, - EOpSubgroupShuffleDown, - EOpSubgroupAdd, - EOpSubgroupMul, - EOpSubgroupMin, - EOpSubgroupMax, - EOpSubgroupAnd, - EOpSubgroupOr, - EOpSubgroupXor, - EOpSubgroupInclusiveAdd, - EOpSubgroupInclusiveMul, - EOpSubgroupInclusiveMin, - EOpSubgroupInclusiveMax, - EOpSubgroupInclusiveAnd, - EOpSubgroupInclusiveOr, - EOpSubgroupInclusiveXor, - EOpSubgroupExclusiveAdd, - EOpSubgroupExclusiveMul, - EOpSubgroupExclusiveMin, - EOpSubgroupExclusiveMax, - EOpSubgroupExclusiveAnd, - EOpSubgroupExclusiveOr, - EOpSubgroupExclusiveXor, - EOpSubgroupClusteredAdd, - EOpSubgroupClusteredMul, - EOpSubgroupClusteredMin, - EOpSubgroupClusteredMax, - EOpSubgroupClusteredAnd, - EOpSubgroupClusteredOr, - EOpSubgroupClusteredXor, - EOpSubgroupQuadBroadcast, - EOpSubgroupQuadSwapHorizontal, - EOpSubgroupQuadSwapVertical, - EOpSubgroupQuadSwapDiagonal, - - EOpSubgroupPartition, - EOpSubgroupPartitionedAdd, - EOpSubgroupPartitionedMul, - EOpSubgroupPartitionedMin, - EOpSubgroupPartitionedMax, - EOpSubgroupPartitionedAnd, - EOpSubgroupPartitionedOr, - EOpSubgroupPartitionedXor, - EOpSubgroupPartitionedInclusiveAdd, - EOpSubgroupPartitionedInclusiveMul, - EOpSubgroupPartitionedInclusiveMin, - EOpSubgroupPartitionedInclusiveMax, - EOpSubgroupPartitionedInclusiveAnd, - EOpSubgroupPartitionedInclusiveOr, - EOpSubgroupPartitionedInclusiveXor, - EOpSubgroupPartitionedExclusiveAdd, - EOpSubgroupPartitionedExclusiveMul, - EOpSubgroupPartitionedExclusiveMin, - EOpSubgroupPartitionedExclusiveMax, - EOpSubgroupPartitionedExclusiveAnd, - EOpSubgroupPartitionedExclusiveOr, - EOpSubgroupPartitionedExclusiveXor, - - EOpSubgroupGuardStop, - - EOpMinInvocations, - EOpMaxInvocations, - EOpAddInvocations, - EOpMinInvocationsNonUniform, - EOpMaxInvocationsNonUniform, - EOpAddInvocationsNonUniform, - EOpMinInvocationsInclusiveScan, - EOpMaxInvocationsInclusiveScan, - EOpAddInvocationsInclusiveScan, - EOpMinInvocationsInclusiveScanNonUniform, - EOpMaxInvocationsInclusiveScanNonUniform, - EOpAddInvocationsInclusiveScanNonUniform, - EOpMinInvocationsExclusiveScan, - EOpMaxInvocationsExclusiveScan, - EOpAddInvocationsExclusiveScan, - EOpMinInvocationsExclusiveScanNonUniform, - EOpMaxInvocationsExclusiveScanNonUniform, - EOpAddInvocationsExclusiveScanNonUniform, - EOpSwizzleInvocations, - EOpSwizzleInvocationsMasked, - EOpWriteInvocation, - EOpMbcnt, - - EOpCubeFaceIndex, - EOpCubeFaceCoord, - EOpTime, - - EOpAtomicAdd, - EOpAtomicSubtract, - EOpAtomicMin, - EOpAtomicMax, - EOpAtomicAnd, - EOpAtomicOr, - EOpAtomicXor, - EOpAtomicExchange, - EOpAtomicCompSwap, - EOpAtomicLoad, - EOpAtomicStore, - - EOpAtomicCounterIncrement, // results in pre-increment value - EOpAtomicCounterDecrement, // results in post-decrement value - EOpAtomicCounter, - EOpAtomicCounterAdd, - EOpAtomicCounterSubtract, - EOpAtomicCounterMin, - EOpAtomicCounterMax, - EOpAtomicCounterAnd, - EOpAtomicCounterOr, - EOpAtomicCounterXor, - EOpAtomicCounterExchange, - EOpAtomicCounterCompSwap, - - EOpAny, - EOpAll, - - EOpCooperativeMatrixLoad, - EOpCooperativeMatrixStore, - EOpCooperativeMatrixMulAdd, - EOpCooperativeMatrixLoadNV, - EOpCooperativeMatrixStoreNV, - EOpCooperativeMatrixMulAddNV, - - EOpBeginInvocationInterlock, // Fragment only - EOpEndInvocationInterlock, // Fragment only - - EOpIsHelperInvocation, - - EOpDebugPrintf, - - // - // Branch - // - - EOpKill, // Fragment only - EOpTerminateInvocation, // Fragment only - EOpDemote, // Fragment only - EOpTerminateRayKHR, // Any-hit only - EOpIgnoreIntersectionKHR, // Any-hit only - EOpReturn, - EOpBreak, - EOpContinue, - EOpCase, - EOpDefault, - - // - // Constructors - // - - EOpConstructGuardStart, - EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed - EOpConstructUint, - EOpConstructInt8, - EOpConstructUint8, - EOpConstructInt16, - EOpConstructUint16, - EOpConstructInt64, - EOpConstructUint64, - EOpConstructBool, - EOpConstructFloat, - EOpConstructDouble, - // Keep vector and matrix constructors in a consistent relative order for - // TParseContext::constructBuiltIn, which converts between 8/16/32 bit - // vector constructors - EOpConstructVec2, - EOpConstructVec3, - EOpConstructVec4, - EOpConstructMat2x2, - EOpConstructMat2x3, - EOpConstructMat2x4, - EOpConstructMat3x2, - EOpConstructMat3x3, - EOpConstructMat3x4, - EOpConstructMat4x2, - EOpConstructMat4x3, - EOpConstructMat4x4, - EOpConstructDVec2, - EOpConstructDVec3, - EOpConstructDVec4, - EOpConstructBVec2, - EOpConstructBVec3, - EOpConstructBVec4, - EOpConstructI8Vec2, - EOpConstructI8Vec3, - EOpConstructI8Vec4, - EOpConstructU8Vec2, - EOpConstructU8Vec3, - EOpConstructU8Vec4, - EOpConstructI16Vec2, - EOpConstructI16Vec3, - EOpConstructI16Vec4, - EOpConstructU16Vec2, - EOpConstructU16Vec3, - EOpConstructU16Vec4, - EOpConstructIVec2, - EOpConstructIVec3, - EOpConstructIVec4, - EOpConstructUVec2, - EOpConstructUVec3, - EOpConstructUVec4, - EOpConstructI64Vec2, - EOpConstructI64Vec3, - EOpConstructI64Vec4, - EOpConstructU64Vec2, - EOpConstructU64Vec3, - EOpConstructU64Vec4, - EOpConstructDMat2x2, - EOpConstructDMat2x3, - EOpConstructDMat2x4, - EOpConstructDMat3x2, - EOpConstructDMat3x3, - EOpConstructDMat3x4, - EOpConstructDMat4x2, - EOpConstructDMat4x3, - EOpConstructDMat4x4, - EOpConstructIMat2x2, - EOpConstructIMat2x3, - EOpConstructIMat2x4, - EOpConstructIMat3x2, - EOpConstructIMat3x3, - EOpConstructIMat3x4, - EOpConstructIMat4x2, - EOpConstructIMat4x3, - EOpConstructIMat4x4, - EOpConstructUMat2x2, - EOpConstructUMat2x3, - EOpConstructUMat2x4, - EOpConstructUMat3x2, - EOpConstructUMat3x3, - EOpConstructUMat3x4, - EOpConstructUMat4x2, - EOpConstructUMat4x3, - EOpConstructUMat4x4, - EOpConstructBMat2x2, - EOpConstructBMat2x3, - EOpConstructBMat2x4, - EOpConstructBMat3x2, - EOpConstructBMat3x3, - EOpConstructBMat3x4, - EOpConstructBMat4x2, - EOpConstructBMat4x3, - EOpConstructBMat4x4, - EOpConstructFloat16, - EOpConstructF16Vec2, - EOpConstructF16Vec3, - EOpConstructF16Vec4, - EOpConstructF16Mat2x2, - EOpConstructF16Mat2x3, - EOpConstructF16Mat2x4, - EOpConstructF16Mat3x2, - EOpConstructF16Mat3x3, - EOpConstructF16Mat3x4, - EOpConstructF16Mat4x2, - EOpConstructF16Mat4x3, - EOpConstructF16Mat4x4, - EOpConstructStruct, - EOpConstructTextureSampler, - EOpConstructNonuniform, // expected to be transformed away, not present in final AST - EOpConstructReference, - EOpConstructCooperativeMatrixNV, - EOpConstructCooperativeMatrixKHR, - EOpConstructAccStruct, - EOpConstructGuardEnd, - - // - // moves - // - - EOpAssign, - EOpAddAssign, - EOpSubAssign, - EOpMulAssign, - EOpVectorTimesMatrixAssign, - EOpVectorTimesScalarAssign, - EOpMatrixTimesScalarAssign, - EOpMatrixTimesMatrixAssign, - EOpDivAssign, - EOpModAssign, - EOpAndAssign, - EOpInclusiveOrAssign, - EOpExclusiveOrAssign, - EOpLeftShiftAssign, - EOpRightShiftAssign, - - // - // Array operators - // - - // Can apply to arrays, vectors, or matrices. - // Can be decomposed to a constant at compile time, but this does not always happen, - // due to link-time effects. So, consumer can expect either a link-time sized or - // run-time sized array. - EOpArrayLength, - - // - // Image operations - // - - EOpImageGuardBegin, - - EOpImageQuerySize, - EOpImageQuerySamples, - EOpImageLoad, - EOpImageStore, - EOpImageLoadLod, - EOpImageStoreLod, - EOpImageAtomicAdd, - EOpImageAtomicMin, - EOpImageAtomicMax, - EOpImageAtomicAnd, - EOpImageAtomicOr, - EOpImageAtomicXor, - EOpImageAtomicExchange, - EOpImageAtomicCompSwap, - EOpImageAtomicLoad, - EOpImageAtomicStore, - - EOpSubpassLoad, - EOpSubpassLoadMS, - EOpSparseImageLoad, - EOpSparseImageLoadLod, - EOpColorAttachmentReadEXT, // Fragment only - - EOpImageGuardEnd, - - // - // Texture operations - // - - EOpTextureGuardBegin, - - EOpTextureQuerySize, - EOpTextureQueryLod, - EOpTextureQueryLevels, - EOpTextureQuerySamples, - - EOpSamplingGuardBegin, - - EOpTexture, - EOpTextureProj, - EOpTextureLod, - EOpTextureOffset, - EOpTextureFetch, - EOpTextureFetchOffset, - EOpTextureProjOffset, - EOpTextureLodOffset, - EOpTextureProjLod, - EOpTextureProjLodOffset, - EOpTextureGrad, - EOpTextureGradOffset, - EOpTextureProjGrad, - EOpTextureProjGradOffset, - EOpTextureGather, - EOpTextureGatherOffset, - EOpTextureGatherOffsets, - EOpTextureClamp, - EOpTextureOffsetClamp, - EOpTextureGradClamp, - EOpTextureGradOffsetClamp, - EOpTextureGatherLod, - EOpTextureGatherLodOffset, - EOpTextureGatherLodOffsets, - EOpFragmentMaskFetch, - EOpFragmentFetch, - - EOpSparseTextureGuardBegin, - - EOpSparseTexture, - EOpSparseTextureLod, - EOpSparseTextureOffset, - EOpSparseTextureFetch, - EOpSparseTextureFetchOffset, - EOpSparseTextureLodOffset, - EOpSparseTextureGrad, - EOpSparseTextureGradOffset, - EOpSparseTextureGather, - EOpSparseTextureGatherOffset, - EOpSparseTextureGatherOffsets, - EOpSparseTexelsResident, - EOpSparseTextureClamp, - EOpSparseTextureOffsetClamp, - EOpSparseTextureGradClamp, - EOpSparseTextureGradOffsetClamp, - EOpSparseTextureGatherLod, - EOpSparseTextureGatherLodOffset, - EOpSparseTextureGatherLodOffsets, - - EOpSparseTextureGuardEnd, - - EOpImageFootprintGuardBegin, - EOpImageSampleFootprintNV, - EOpImageSampleFootprintClampNV, - EOpImageSampleFootprintLodNV, - EOpImageSampleFootprintGradNV, - EOpImageSampleFootprintGradClampNV, - EOpImageFootprintGuardEnd, - EOpSamplingGuardEnd, - EOpTextureGuardEnd, - - // - // Integer operations - // - - EOpAddCarry, - EOpSubBorrow, - EOpUMulExtended, - EOpIMulExtended, - EOpBitfieldExtract, - EOpBitfieldInsert, - EOpBitFieldReverse, - EOpBitCount, - EOpFindLSB, - EOpFindMSB, - - EOpCountLeadingZeros, - EOpCountTrailingZeros, - EOpAbsDifference, - EOpAddSaturate, - EOpSubSaturate, - EOpAverage, - EOpAverageRounded, - EOpMul32x16, - - EOpTraceNV, - EOpTraceRayMotionNV, - EOpTraceKHR, - EOpReportIntersection, - EOpIgnoreIntersectionNV, - EOpTerminateRayNV, - EOpExecuteCallableNV, - EOpExecuteCallableKHR, - EOpWritePackedPrimitiveIndices4x8NV, - EOpEmitMeshTasksEXT, - EOpSetMeshOutputsEXT, - - // - // GL_EXT_ray_query operations - // - - EOpRayQueryInitialize, - EOpRayQueryTerminate, - EOpRayQueryGenerateIntersection, - EOpRayQueryConfirmIntersection, - EOpRayQueryProceed, - EOpRayQueryGetIntersectionType, - EOpRayQueryGetRayTMin, - EOpRayQueryGetRayFlags, - EOpRayQueryGetIntersectionT, - EOpRayQueryGetIntersectionInstanceCustomIndex, - EOpRayQueryGetIntersectionInstanceId, - EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset, - EOpRayQueryGetIntersectionGeometryIndex, - EOpRayQueryGetIntersectionPrimitiveIndex, - EOpRayQueryGetIntersectionBarycentrics, - EOpRayQueryGetIntersectionFrontFace, - EOpRayQueryGetIntersectionCandidateAABBOpaque, - EOpRayQueryGetIntersectionObjectRayDirection, - EOpRayQueryGetIntersectionObjectRayOrigin, - EOpRayQueryGetWorldRayDirection, - EOpRayQueryGetWorldRayOrigin, - EOpRayQueryGetIntersectionObjectToWorld, - EOpRayQueryGetIntersectionWorldToObject, - - // - // GL_NV_shader_invocation_reorder - // - - EOpHitObjectTraceRayNV, - EOpHitObjectTraceRayMotionNV, - EOpHitObjectRecordHitNV, - EOpHitObjectRecordHitMotionNV, - EOpHitObjectRecordHitWithIndexNV, - EOpHitObjectRecordHitWithIndexMotionNV, - EOpHitObjectRecordMissNV, - EOpHitObjectRecordMissMotionNV, - EOpHitObjectRecordEmptyNV, - EOpHitObjectExecuteShaderNV, - EOpHitObjectIsEmptyNV, - EOpHitObjectIsMissNV, - EOpHitObjectIsHitNV, - EOpHitObjectGetRayTMinNV, - EOpHitObjectGetRayTMaxNV, - EOpHitObjectGetObjectRayOriginNV, - EOpHitObjectGetObjectRayDirectionNV, - EOpHitObjectGetWorldRayOriginNV, - EOpHitObjectGetWorldRayDirectionNV, - EOpHitObjectGetWorldToObjectNV, - EOpHitObjectGetObjectToWorldNV, - EOpHitObjectGetInstanceCustomIndexNV, - EOpHitObjectGetInstanceIdNV, - EOpHitObjectGetGeometryIndexNV, - EOpHitObjectGetPrimitiveIndexNV, - EOpHitObjectGetHitKindNV, - EOpHitObjectGetShaderBindingTableRecordIndexNV, - EOpHitObjectGetShaderRecordBufferHandleNV, - EOpHitObjectGetAttributesNV, - EOpHitObjectGetCurrentTimeNV, - EOpReorderThreadNV, - EOpFetchMicroTriangleVertexPositionNV, - EOpFetchMicroTriangleVertexBarycentricNV, - - // HLSL operations - // - - EOpClip, // discard if input value < 0 - EOpIsFinite, - EOpLog10, // base 10 log - EOpRcp, // 1/x - EOpSaturate, // clamp from 0 to 1 - EOpSinCos, // sin and cos in out parameters - EOpGenMul, // mul(x,y) on any of mat/vec/scalars - EOpDst, // x = 1, y=src0.y * src1.y, z=src0.z, w=src1.w - EOpInterlockedAdd, // atomic ops, but uses [optional] out arg instead of return - EOpInterlockedAnd, // ... - EOpInterlockedCompareExchange, // ... - EOpInterlockedCompareStore, // ... - EOpInterlockedExchange, // ... - EOpInterlockedMax, // ... - EOpInterlockedMin, // ... - EOpInterlockedOr, // ... - EOpInterlockedXor, // ... - EOpAllMemoryBarrierWithGroupSync, // memory barriers without non-hlsl AST equivalents - EOpDeviceMemoryBarrier, // ... - EOpDeviceMemoryBarrierWithGroupSync, // ... - EOpWorkgroupMemoryBarrier, // ... - EOpWorkgroupMemoryBarrierWithGroupSync, // ... - EOpEvaluateAttributeSnapped, // InterpolateAtOffset with int position on 16x16 grid - EOpF32tof16, // HLSL conversion: half of a PackHalf2x16 - EOpF16tof32, // HLSL conversion: half of an UnpackHalf2x16 - EOpLit, // HLSL lighting coefficient vector - EOpTextureBias, // HLSL texture bias: will be lowered to EOpTexture - EOpAsDouble, // slightly different from EOpUint64BitsToDouble - EOpD3DCOLORtoUBYTE4, // convert and swizzle 4-component color to UBYTE4 range - - EOpMethodSample, // Texture object methods. These are translated to existing - EOpMethodSampleBias, // AST methods, and exist to represent HLSL semantics until that - EOpMethodSampleCmp, // translation is performed. See HlslParseContext::decomposeSampleMethods(). - EOpMethodSampleCmpLevelZero, // ... - EOpMethodSampleGrad, // ... - EOpMethodSampleLevel, // ... - EOpMethodLoad, // ... - EOpMethodGetDimensions, // ... - EOpMethodGetSamplePosition, // ... - EOpMethodGather, // ... - EOpMethodCalculateLevelOfDetail, // ... - EOpMethodCalculateLevelOfDetailUnclamped, // ... - - // Load already defined above for textures - EOpMethodLoad2, // Structure buffer object methods. These are translated to existing - EOpMethodLoad3, // AST methods, and exist to represent HLSL semantics until that - EOpMethodLoad4, // translation is performed. See HlslParseContext::decomposeSampleMethods(). - EOpMethodStore, // ... - EOpMethodStore2, // ... - EOpMethodStore3, // ... - EOpMethodStore4, // ... - EOpMethodIncrementCounter, // ... - EOpMethodDecrementCounter, // ... - // EOpMethodAppend is defined for geo shaders below - EOpMethodConsume, - - // SM5 texture methods - EOpMethodGatherRed, // These are covered under the above EOpMethodSample comment about - EOpMethodGatherGreen, // translation to existing AST opcodes. They exist temporarily - EOpMethodGatherBlue, // because HLSL arguments are slightly different. - EOpMethodGatherAlpha, // ... - EOpMethodGatherCmp, // ... - EOpMethodGatherCmpRed, // ... - EOpMethodGatherCmpGreen, // ... - EOpMethodGatherCmpBlue, // ... - EOpMethodGatherCmpAlpha, // ... - - // geometry methods - EOpMethodAppend, // Geometry shader methods - EOpMethodRestartStrip, // ... - - // matrix - EOpMatrixSwizzle, // select multiple matrix components (non-column) - - // SM6 wave ops - EOpWaveGetLaneCount, // Will decompose to gl_SubgroupSize. - EOpWaveGetLaneIndex, // Will decompose to gl_SubgroupInvocationID. - EOpWaveActiveCountBits, // Will decompose to subgroupBallotBitCount(subgroupBallot()). - EOpWavePrefixCountBits, // Will decompose to subgroupBallotInclusiveBitCount(subgroupBallot()). - - // Shader Clock Ops - EOpReadClockSubgroupKHR, - EOpReadClockDeviceKHR, - - // GL_EXT_ray_tracing_position_fetch - EOpRayQueryGetIntersectionTriangleVertexPositionsEXT, - - // Shader tile image ops - EOpStencilAttachmentReadEXT, // Fragment only - EOpDepthAttachmentReadEXT, // Fragment only - - // Image processing - EOpImageSampleWeightedQCOM, - EOpImageBoxFilterQCOM, - EOpImageBlockMatchSADQCOM, - EOpImageBlockMatchSSDQCOM, -}; - -enum TLinkType { - ELinkNone, - ELinkExport, -}; - -class TIntermTraverser; -class TIntermOperator; -class TIntermAggregate; -class TIntermUnary; -class TIntermBinary; -class TIntermConstantUnion; -class TIntermSelection; -class TIntermSwitch; -class TIntermBranch; -class TIntermTyped; -class TIntermMethod; -class TIntermSymbol; -class TIntermLoop; - -} // end namespace glslang - -// -// Base class for the tree nodes -// -// (Put outside the glslang namespace, as it's used as part of the external interface.) -// -class TIntermNode { -public: - POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) - - TIntermNode() { loc.init(); } - virtual const glslang::TSourceLoc& getLoc() const { return loc; } - virtual void setLoc(const glslang::TSourceLoc& l) { loc = l; } - virtual void traverse(glslang::TIntermTraverser*) = 0; - virtual glslang::TIntermTyped* getAsTyped() { return nullptr; } - virtual glslang::TIntermOperator* getAsOperator() { return nullptr; } - virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return nullptr; } - virtual glslang::TIntermAggregate* getAsAggregate() { return nullptr; } - virtual glslang::TIntermUnary* getAsUnaryNode() { return nullptr; } - virtual glslang::TIntermBinary* getAsBinaryNode() { return nullptr; } - virtual glslang::TIntermSelection* getAsSelectionNode() { return nullptr; } - virtual glslang::TIntermSwitch* getAsSwitchNode() { return nullptr; } - virtual glslang::TIntermMethod* getAsMethodNode() { return nullptr; } - virtual glslang::TIntermSymbol* getAsSymbolNode() { return nullptr; } - virtual glslang::TIntermBranch* getAsBranchNode() { return nullptr; } - virtual glslang::TIntermLoop* getAsLoopNode() { return nullptr; } - - virtual const glslang::TIntermTyped* getAsTyped() const { return nullptr; } - virtual const glslang::TIntermOperator* getAsOperator() const { return nullptr; } - virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return nullptr; } - virtual const glslang::TIntermAggregate* getAsAggregate() const { return nullptr; } - virtual const glslang::TIntermUnary* getAsUnaryNode() const { return nullptr; } - virtual const glslang::TIntermBinary* getAsBinaryNode() const { return nullptr; } - virtual const glslang::TIntermSelection* getAsSelectionNode() const { return nullptr; } - virtual const glslang::TIntermSwitch* getAsSwitchNode() const { return nullptr; } - virtual const glslang::TIntermMethod* getAsMethodNode() const { return nullptr; } - virtual const glslang::TIntermSymbol* getAsSymbolNode() const { return nullptr; } - virtual const glslang::TIntermBranch* getAsBranchNode() const { return nullptr; } - virtual const glslang::TIntermLoop* getAsLoopNode() const { return nullptr; } - virtual ~TIntermNode() { } - -protected: - TIntermNode(const TIntermNode&); - TIntermNode& operator=(const TIntermNode&); - glslang::TSourceLoc loc; -}; - -namespace glslang { - -// -// This is just to help yacc. -// -struct TIntermNodePair { - TIntermNode* node1; - TIntermNode* node2; -}; - -// -// Intermediate class for nodes that have a type. -// -class TIntermTyped : public TIntermNode { -public: - TIntermTyped(const TType& t) { type.shallowCopy(t); } - TIntermTyped(TBasicType basicType) { TType bt(basicType); type.shallowCopy(bt); } - virtual TIntermTyped* getAsTyped() { return this; } - virtual const TIntermTyped* getAsTyped() const { return this; } - virtual void setType(const TType& t) { type.shallowCopy(t); } - virtual const TType& getType() const { return type; } - virtual TType& getWritableType() { return type; } - - virtual TBasicType getBasicType() const { return type.getBasicType(); } - virtual TQualifier& getQualifier() { return type.getQualifier(); } - virtual const TQualifier& getQualifier() const { return type.getQualifier(); } - virtual TArraySizes* getArraySizes() { return type.getArraySizes(); } - virtual const TArraySizes* getArraySizes() const { return type.getArraySizes(); } - virtual void propagatePrecision(TPrecisionQualifier); - virtual int getVectorSize() const { return type.getVectorSize(); } - virtual int getMatrixCols() const { return type.getMatrixCols(); } - virtual int getMatrixRows() const { return type.getMatrixRows(); } - virtual bool isMatrix() const { return type.isMatrix(); } - virtual bool isArray() const { return type.isArray(); } - virtual bool isVector() const { return type.isVector(); } - virtual bool isScalar() const { return type.isScalar(); } - virtual bool isStruct() const { return type.isStruct(); } - virtual bool isFloatingDomain() const { return type.isFloatingDomain(); } - virtual bool isIntegerDomain() const { return type.isIntegerDomain(); } - bool isAtomic() const { return type.isAtomic(); } - bool isReference() const { return type.isReference(); } - TString getCompleteString(bool enhanced = false) const { return type.getCompleteString(enhanced); } - -protected: - TIntermTyped& operator=(const TIntermTyped&); - TType type; -}; - -// -// Handle for, do-while, and while loops. -// -class TIntermLoop : public TIntermNode { -public: - TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : - body(aBody), - test(aTest), - terminal(aTerminal), - first(testFirst), - unroll(false), - dontUnroll(false), - dependency(0), - minIterations(0), - maxIterations(iterationsInfinite), - iterationMultiple(1), - peelCount(0), - partialCount(0) - { } - - virtual TIntermLoop* getAsLoopNode() { return this; } - virtual const TIntermLoop* getAsLoopNode() const { return this; } - virtual void traverse(TIntermTraverser*); - TIntermNode* getBody() const { return body; } - TIntermTyped* getTest() const { return test; } - TIntermTyped* getTerminal() const { return terminal; } - bool testFirst() const { return first; } - - void setUnroll() { unroll = true; } - void setDontUnroll() { - dontUnroll = true; - peelCount = 0; - partialCount = 0; - } - bool getUnroll() const { return unroll; } - bool getDontUnroll() const { return dontUnroll; } - - static const unsigned int dependencyInfinite = 0xFFFFFFFF; - static const unsigned int iterationsInfinite = 0xFFFFFFFF; - void setLoopDependency(int d) { dependency = d; } - int getLoopDependency() const { return dependency; } - - void setMinIterations(unsigned int v) { minIterations = v; } - unsigned int getMinIterations() const { return minIterations; } - void setMaxIterations(unsigned int v) { maxIterations = v; } - unsigned int getMaxIterations() const { return maxIterations; } - void setIterationMultiple(unsigned int v) { iterationMultiple = v; } - unsigned int getIterationMultiple() const { return iterationMultiple; } - void setPeelCount(unsigned int v) { - peelCount = v; - dontUnroll = false; - } - unsigned int getPeelCount() const { return peelCount; } - void setPartialCount(unsigned int v) { - partialCount = v; - dontUnroll = false; - } - unsigned int getPartialCount() const { return partialCount; } - -protected: - TIntermNode* body; // code to loop over - TIntermTyped* test; // exit condition associated with loop, could be 0 for 'for' loops - TIntermTyped* terminal; // exists for for-loops - bool first; // true for while and for, not for do-while - bool unroll; // true if unroll requested - bool dontUnroll; // true if request to not unroll - unsigned int dependency; // loop dependency hint; 0 means not set or unknown - unsigned int minIterations; // as per the SPIR-V specification - unsigned int maxIterations; // as per the SPIR-V specification - unsigned int iterationMultiple; // as per the SPIR-V specification - unsigned int peelCount; // as per the SPIR-V specification - unsigned int partialCount; // as per the SPIR-V specification -}; - -// -// Handle case, break, continue, return, and kill. -// -class TIntermBranch : public TIntermNode { -public: - TIntermBranch(TOperator op, TIntermTyped* e) : - flowOp(op), - expression(e) { } - virtual TIntermBranch* getAsBranchNode() { return this; } - virtual const TIntermBranch* getAsBranchNode() const { return this; } - virtual void traverse(TIntermTraverser*); - TOperator getFlowOp() const { return flowOp; } - TIntermTyped* getExpression() const { return expression; } - void setExpression(TIntermTyped* pExpression) { expression = pExpression; } - void updatePrecision(TPrecisionQualifier parentPrecision); -protected: - TOperator flowOp; - TIntermTyped* expression; -}; - -// -// Represent method names before seeing their calling signature -// or resolving them to operations. Just an expression as the base object -// and a textural name. -// -class TIntermMethod : public TIntermTyped { -public: - TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { } - virtual TIntermMethod* getAsMethodNode() { return this; } - virtual const TIntermMethod* getAsMethodNode() const { return this; } - virtual const TString& getMethodName() const { return method; } - virtual TIntermTyped* getObject() const { return object; } - virtual void traverse(TIntermTraverser*); - void setExport() { linkType = ELinkExport; } -protected: - TIntermTyped* object; - TString method; - TLinkType linkType; -}; - -// -// Nodes that correspond to symbols or constants in the source code. -// -class TIntermSymbol : public TIntermTyped { -public: - // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from - // per process threadPoolAllocator, then it causes increased memory usage per compile - // it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(long long i, const TString& n, const TType& t) - : TIntermTyped(t), id(i), flattenSubset(-1), constSubtree(nullptr) { name = n; } - virtual long long getId() const { return id; } - virtual void changeId(long long i) { id = i; } - virtual const TString& getName() const { return name; } - virtual void traverse(TIntermTraverser*); - virtual TIntermSymbol* getAsSymbolNode() { return this; } - virtual const TIntermSymbol* getAsSymbolNode() const { return this; } - void setConstArray(const TConstUnionArray& c) { constArray = c; } - const TConstUnionArray& getConstArray() const { return constArray; } - void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } - TIntermTyped* getConstSubtree() const { return constSubtree; } - void setFlattenSubset(int subset) { flattenSubset = subset; } - virtual const TString& getAccessName() const; - - int getFlattenSubset() const { return flattenSubset; } // -1 means full object - - // This is meant for cases where a node has already been constructed, and - // later on, it becomes necessary to switch to a different symbol. - virtual void switchId(long long newId) { id = newId; } - -protected: - long long id; // the unique id of the symbol this node represents - int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced - TString name; // the name of the symbol this node represents - TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value - TIntermTyped* constSubtree; -}; - -class TIntermConstantUnion : public TIntermTyped { -public: - TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { } - const TConstUnionArray& getConstArray() const { return constArray; } - virtual TIntermConstantUnion* getAsConstantUnion() { return this; } - virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; } - virtual void traverse(TIntermTraverser*); - virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const; - virtual TIntermTyped* fold(TOperator, const TType&) const; - void setLiteral() { literal = true; } - void setExpression() { literal = false; } - bool isLiteral() const { return literal; } - -protected: - TIntermConstantUnion& operator=(const TIntermConstantUnion&); - - const TConstUnionArray constArray; - bool literal; // true if node represents a literal in the source code -}; - -// Represent the independent aspects of a texturing TOperator -struct TCrackedTextureOp { - bool query; - bool proj; - bool lod; - bool fetch; - bool offset; - bool offsets; - bool gather; - bool grad; - bool subpass; - bool lodClamp; - bool fragMask; - bool attachmentEXT; -}; - -// -// Intermediate class for node types that hold operators. -// -class TIntermOperator : public TIntermTyped { -public: - virtual TIntermOperator* getAsOperator() { return this; } - virtual const TIntermOperator* getAsOperator() const { return this; } - TOperator getOp() const { return op; } - void setOp(TOperator newOp) { op = newOp; } - bool modifiesState() const; - bool isConstructor() const; - bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; } - bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; } - bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; } - bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; } - bool isImageFootprint() const { return op > EOpImageFootprintGuardBegin && op < EOpImageFootprintGuardEnd; } - bool isSparseImage() const { return op == EOpSparseImageLoad; } - bool isSubgroup() const { return op > EOpSubgroupGuardStart && op < EOpSubgroupGuardStop; } - - void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; } - TPrecisionQualifier getOperationPrecision() const { return operationPrecision != EpqNone ? - operationPrecision : - type.getQualifier().precision; } - TString getCompleteString() const - { - TString cs = type.getCompleteString(); - if (getOperationPrecision() != type.getQualifier().precision) { - cs += ", operation at "; - cs += GetPrecisionQualifierString(getOperationPrecision()); - } - - return cs; - } - - // Crack the op into the individual dimensions of texturing operation. - void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const - { - cracked.query = false; - cracked.proj = false; - cracked.lod = false; - cracked.fetch = false; - cracked.offset = false; - cracked.offsets = false; - cracked.gather = false; - cracked.grad = false; - cracked.subpass = false; - cracked.attachmentEXT = false; - cracked.lodClamp = false; - cracked.fragMask = false; - - switch (op) { - case EOpImageQuerySize: - case EOpImageQuerySamples: - case EOpTextureQuerySize: - case EOpTextureQueryLod: - case EOpTextureQueryLevels: - case EOpTextureQuerySamples: - case EOpSparseTexelsResident: - cracked.query = true; - break; - case EOpTexture: - case EOpSparseTexture: - break; - case EOpTextureProj: - cracked.proj = true; - break; - case EOpTextureLod: - case EOpSparseTextureLod: - cracked.lod = true; - break; - case EOpTextureOffset: - case EOpSparseTextureOffset: - cracked.offset = true; - break; - case EOpTextureFetch: - case EOpSparseTextureFetch: - cracked.fetch = true; - if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) - cracked.lod = true; - break; - case EOpTextureFetchOffset: - case EOpSparseTextureFetchOffset: - cracked.fetch = true; - cracked.offset = true; - if (sampler.is1D() || (sampler.dim == Esd2D && ! sampler.isMultiSample()) || sampler.dim == Esd3D) - cracked.lod = true; - break; - case EOpTextureProjOffset: - cracked.offset = true; - cracked.proj = true; - break; - case EOpTextureLodOffset: - case EOpSparseTextureLodOffset: - cracked.offset = true; - cracked.lod = true; - break; - case EOpTextureProjLod: - cracked.lod = true; - cracked.proj = true; - break; - case EOpTextureProjLodOffset: - cracked.offset = true; - cracked.lod = true; - cracked.proj = true; - break; - case EOpTextureGrad: - case EOpSparseTextureGrad: - cracked.grad = true; - break; - case EOpTextureGradOffset: - case EOpSparseTextureGradOffset: - cracked.grad = true; - cracked.offset = true; - break; - case EOpTextureProjGrad: - cracked.grad = true; - cracked.proj = true; - break; - case EOpTextureProjGradOffset: - cracked.grad = true; - cracked.offset = true; - cracked.proj = true; - break; - case EOpTextureClamp: - case EOpSparseTextureClamp: - cracked.lodClamp = true; - break; - case EOpTextureOffsetClamp: - case EOpSparseTextureOffsetClamp: - cracked.offset = true; - cracked.lodClamp = true; - break; - case EOpTextureGradClamp: - case EOpSparseTextureGradClamp: - cracked.grad = true; - cracked.lodClamp = true; - break; - case EOpTextureGradOffsetClamp: - case EOpSparseTextureGradOffsetClamp: - cracked.grad = true; - cracked.offset = true; - cracked.lodClamp = true; - break; - case EOpTextureGather: - case EOpSparseTextureGather: - cracked.gather = true; - break; - case EOpTextureGatherOffset: - case EOpSparseTextureGatherOffset: - cracked.gather = true; - cracked.offset = true; - break; - case EOpTextureGatherOffsets: - case EOpSparseTextureGatherOffsets: - cracked.gather = true; - cracked.offsets = true; - break; - case EOpTextureGatherLod: - case EOpSparseTextureGatherLod: - cracked.gather = true; - cracked.lod = true; - break; - case EOpTextureGatherLodOffset: - case EOpSparseTextureGatherLodOffset: - cracked.gather = true; - cracked.offset = true; - cracked.lod = true; - break; - case EOpTextureGatherLodOffsets: - case EOpSparseTextureGatherLodOffsets: - cracked.gather = true; - cracked.offsets = true; - cracked.lod = true; - break; - case EOpImageLoadLod: - case EOpImageStoreLod: - case EOpSparseImageLoadLod: - cracked.lod = true; - break; - case EOpFragmentMaskFetch: - cracked.subpass = sampler.dim == EsdSubpass; - cracked.fragMask = true; - break; - case EOpFragmentFetch: - cracked.subpass = sampler.dim == EsdSubpass; - cracked.fragMask = true; - break; - case EOpImageSampleFootprintNV: - break; - case EOpImageSampleFootprintClampNV: - cracked.lodClamp = true; - break; - case EOpImageSampleFootprintLodNV: - cracked.lod = true; - break; - case EOpImageSampleFootprintGradNV: - cracked.grad = true; - break; - case EOpImageSampleFootprintGradClampNV: - cracked.lodClamp = true; - cracked.grad = true; - break; - case EOpSubpassLoad: - case EOpSubpassLoadMS: - cracked.subpass = true; - break; - case EOpColorAttachmentReadEXT: - cracked.attachmentEXT = true; - break; - default: - break; - } - } - -protected: - TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o), operationPrecision(EpqNone) {} - TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o), operationPrecision(EpqNone) {} - TOperator op; - // The result precision is in the inherited TType, and is usually meant to be both - // the operation precision and the result precision. However, some more complex things, - // like built-in function calls, distinguish between the two, in which case non-EqpNone - // 'operationPrecision' overrides the result precision as far as operation precision - // is concerned. - TPrecisionQualifier operationPrecision; -}; - -// -// Nodes for all the basic binary math operators. -// -class TIntermBinary : public TIntermOperator { -public: - TIntermBinary(TOperator o) : TIntermOperator(o) {} - virtual void traverse(TIntermTraverser*); - virtual void setLeft(TIntermTyped* n) { left = n; } - virtual void setRight(TIntermTyped* n) { right = n; } - virtual TIntermTyped* getLeft() const { return left; } - virtual TIntermTyped* getRight() const { return right; } - virtual TIntermBinary* getAsBinaryNode() { return this; } - virtual const TIntermBinary* getAsBinaryNode() const { return this; } - virtual void updatePrecision(); -protected: - TIntermTyped* left; - TIntermTyped* right; -}; - -// -// Nodes for unary math operators. -// -class TIntermUnary : public TIntermOperator { -public: - TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(nullptr) {} - TIntermUnary(TOperator o) : TIntermOperator(o), operand(nullptr) {} - virtual void traverse(TIntermTraverser*); - virtual void setOperand(TIntermTyped* o) { operand = o; } - virtual TIntermTyped* getOperand() { return operand; } - virtual const TIntermTyped* getOperand() const { return operand; } - virtual TIntermUnary* getAsUnaryNode() { return this; } - virtual const TIntermUnary* getAsUnaryNode() const { return this; } - virtual void updatePrecision(); - void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; } - const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; } -protected: - TIntermTyped* operand; - TSpirvInstruction spirvInst; -}; - -typedef TVector TIntermSequence; -typedef TVector TQualifierList; -// -// Nodes that operate on an arbitrary sized set of children. -// -class TIntermAggregate : public TIntermOperator { -public: - TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(nullptr) { } - TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(nullptr) { } - ~TIntermAggregate() { delete pragmaTable; } - virtual TIntermAggregate* getAsAggregate() { return this; } - virtual const TIntermAggregate* getAsAggregate() const { return this; } - virtual void updatePrecision(); - virtual void setOperator(TOperator o) { op = o; } - virtual TIntermSequence& getSequence() { return sequence; } - virtual const TIntermSequence& getSequence() const { return sequence; } - virtual void setName(const TString& n) { name = n; } - virtual const TString& getName() const { return name; } - virtual void traverse(TIntermTraverser*); - virtual void setUserDefined() { userDefined = true; } - virtual bool isUserDefined() { return userDefined; } - virtual TQualifierList& getQualifierList() { return qualifier; } - virtual const TQualifierList& getQualifierList() const { return qualifier; } - void setOptimize(bool o) { optimize = o; } - void setDebug(bool d) { debug = d; } - bool getOptimize() const { return optimize; } - bool getDebug() const { return debug; } - void setPragmaTable(const TPragmaTable& pTable); - const TPragmaTable& getPragmaTable() const { return *pragmaTable; } - void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; } - const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; } - - void setLinkType(TLinkType l) { linkType = l; } - TLinkType getLinkType() const { return linkType; } -protected: - TIntermAggregate(const TIntermAggregate&); // disallow copy constructor - TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator - TIntermSequence sequence; - TQualifierList qualifier; - TString name; - bool userDefined; // used for user defined function names - bool optimize; - bool debug; - TPragmaTable* pragmaTable; - TSpirvInstruction spirvInst; - TLinkType linkType = ELinkNone; -}; - -// -// For if tests. -// -class TIntermSelection : public TIntermTyped { -public: - TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : - TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB), - shortCircuit(true), - flatten(false), dontFlatten(false) {} - TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : - TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB), - shortCircuit(true), - flatten(false), dontFlatten(false) {} - virtual void traverse(TIntermTraverser*); - virtual TIntermTyped* getCondition() const { return condition; } - virtual void setCondition(TIntermTyped* c) { condition = c; } - virtual TIntermNode* getTrueBlock() const { return trueBlock; } - virtual void setTrueBlock(TIntermTyped* tb) { trueBlock = tb; } - virtual TIntermNode* getFalseBlock() const { return falseBlock; } - virtual void setFalseBlock(TIntermTyped* fb) { falseBlock = fb; } - virtual TIntermSelection* getAsSelectionNode() { return this; } - virtual const TIntermSelection* getAsSelectionNode() const { return this; } - - void setNoShortCircuit() { shortCircuit = false; } - bool getShortCircuit() const { return shortCircuit; } - - void setFlatten() { flatten = true; } - void setDontFlatten() { dontFlatten = true; } - bool getFlatten() const { return flatten; } - bool getDontFlatten() const { return dontFlatten; } - -protected: - TIntermTyped* condition; - TIntermNode* trueBlock; - TIntermNode* falseBlock; - bool shortCircuit; // normally all if-then-else and all GLSL ?: short-circuit, but HLSL ?: does not - bool flatten; // true if flatten requested - bool dontFlatten; // true if requested to not flatten -}; - -// -// For switch statements. Designed use is that a switch will have sequence of nodes -// that are either case/default nodes or a *single* node that represents all the code -// in between (if any) consecutive case/defaults. So, a traversal need only deal with -// 0 or 1 nodes per case/default statement. -// -class TIntermSwitch : public TIntermNode { -public: - TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b), - flatten(false), dontFlatten(false) {} - virtual void traverse(TIntermTraverser*); - virtual TIntermNode* getCondition() const { return condition; } - virtual TIntermAggregate* getBody() const { return body; } - virtual TIntermSwitch* getAsSwitchNode() { return this; } - virtual const TIntermSwitch* getAsSwitchNode() const { return this; } - - void setFlatten() { flatten = true; } - void setDontFlatten() { dontFlatten = true; } - bool getFlatten() const { return flatten; } - bool getDontFlatten() const { return dontFlatten; } - -protected: - TIntermTyped* condition; - TIntermAggregate* body; - bool flatten; // true if flatten requested - bool dontFlatten; // true if requested to not flatten -}; - -enum TVisit -{ - EvPreVisit, - EvInVisit, - EvPostVisit -}; - -// -// For traversing the tree. User should derive from this, -// put their traversal specific data in it, and then pass -// it to a Traverse method. -// -// When using this, just fill in the methods for nodes you want visited. -// Return false from a pre-visit to skip visiting that node's subtree. -// -// Explicitly set postVisit to true if you want post visiting, otherwise, -// filled in methods will only be called at pre-visit time (before processing -// the subtree). Similarly for inVisit for in-order visiting of nodes with -// multiple children. -// -// If you only want post-visits, explicitly turn off preVisit (and inVisit) -// and turn on postVisit. -// -// In general, for the visit*() methods, return true from interior nodes -// to have the traversal continue on to children. -// -// If you process children yourself, or don't want them processed, return false. -// -class TIntermTraverser { -public: - POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator()) - TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : - preVisit(preVisit), - inVisit(inVisit), - postVisit(postVisit), - rightToLeft(rightToLeft), - depth(0), - maxDepth(0) { } - virtual ~TIntermTraverser() { } - - virtual void visitSymbol(TIntermSymbol*) { } - virtual void visitConstantUnion(TIntermConstantUnion*) { } - virtual bool visitBinary(TVisit, TIntermBinary*) { return true; } - virtual bool visitUnary(TVisit, TIntermUnary*) { return true; } - virtual bool visitSelection(TVisit, TIntermSelection*) { return true; } - virtual bool visitAggregate(TVisit, TIntermAggregate*) { return true; } - virtual bool visitLoop(TVisit, TIntermLoop*) { return true; } - virtual bool visitBranch(TVisit, TIntermBranch*) { return true; } - virtual bool visitSwitch(TVisit, TIntermSwitch*) { return true; } - - int getMaxDepth() const { return maxDepth; } - - void incrementDepth(TIntermNode *current) - { - depth++; - maxDepth = (std::max)(maxDepth, depth); - path.push_back(current); - } - - void decrementDepth() - { - depth--; - path.pop_back(); - } - - TIntermNode *getParentNode() - { - return path.size() == 0 ? nullptr : path.back(); - } - - const bool preVisit; - const bool inVisit; - const bool postVisit; - const bool rightToLeft; - -protected: - TIntermTraverser& operator=(TIntermTraverser&); - - int depth; - int maxDepth; - - // All the nodes from root to the current node's parent during traversing. - TVector path; -}; - -// KHR_vulkan_glsl says "Two arrays sized with specialization constants are the same type only if -// sized with the same symbol, involving no operations" -inline bool SameSpecializationConstants(TIntermTyped* node1, TIntermTyped* node2) -{ - return node1->getAsSymbolNode() && node2->getAsSymbolNode() && - node1->getAsSymbolNode()->getId() == node2->getAsSymbolNode()->getId(); -} - -} // end namespace glslang - -#endif // __INTERMEDIATE_H diff --git a/3rdparty/glslang/glslang/MachineIndependent/Constant.cpp b/3rdparty/glslang/glslang/MachineIndependent/Constant.cpp deleted file mode 100644 index 4f706cad..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/Constant.cpp +++ /dev/null @@ -1,1384 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Copyright (C) 2018-2020 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "localintermediate.h" -#include -#include -#include -#include - -namespace { - -using namespace glslang; - -const double pi = 3.1415926535897932384626433832795; - -} // end anonymous namespace - - -namespace glslang { - -// -// The fold functions see if an operation on a constant can be done in place, -// without generating run-time code. -// -// Returns the node to keep using, which may or may not be the node passed in. -// -// Note: As of version 1.2, all constant operations must be folded. It is -// not opportunistic, but rather a semantic requirement. -// - -// -// Do folding between a pair of nodes. -// 'this' is the left-hand operand and 'rightConstantNode' is the right-hand operand. -// -// Returns a new node representing the result. -// -TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* rightConstantNode) const -{ - // For most cases, the return type matches the argument type, so set that - // up and just code to exceptions below. - TType returnType; - returnType.shallowCopy(getType()); - - // - // A pair of nodes is to be folded together - // - - const TIntermConstantUnion *rightNode = rightConstantNode->getAsConstantUnion(); - TConstUnionArray leftUnionArray = getConstArray(); - TConstUnionArray rightUnionArray = rightNode->getConstArray(); - - // Figure out the size of the result - int newComps; - int constComps; - switch(op) { - case EOpMatrixTimesMatrix: - newComps = rightNode->getMatrixCols() * getMatrixRows(); - break; - case EOpMatrixTimesVector: - newComps = getMatrixRows(); - break; - case EOpVectorTimesMatrix: - newComps = rightNode->getMatrixCols(); - break; - default: - newComps = getType().computeNumComponents(); - constComps = rightConstantNode->getType().computeNumComponents(); - if (constComps == 1 && newComps > 1) { - // for a case like vec4 f = vec4(2,3,4,5) + 1.2; - TConstUnionArray smearedArray(newComps, rightNode->getConstArray()[0]); - rightUnionArray = smearedArray; - } else if (constComps > 1 && newComps == 1) { - // for a case like vec4 f = 1.2 + vec4(2,3,4,5); - newComps = constComps; - rightUnionArray = rightNode->getConstArray(); - TConstUnionArray smearedArray(newComps, getConstArray()[0]); - leftUnionArray = smearedArray; - returnType.shallowCopy(rightNode->getType()); - } - break; - } - - TConstUnionArray newConstArray(newComps); - TType constBool(EbtBool, EvqConst); - - switch(op) { - case EOpAdd: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] + rightUnionArray[i]; - break; - case EOpSub: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] - rightUnionArray[i]; - break; - - case EOpMul: - case EOpVectorTimesScalar: - case EOpMatrixTimesScalar: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] * rightUnionArray[i]; - break; - case EOpMatrixTimesMatrix: - for (int row = 0; row < getMatrixRows(); row++) { - for (int column = 0; column < rightNode->getMatrixCols(); column++) { - double sum = 0.0f; - for (int i = 0; i < rightNode->getMatrixRows(); i++) - sum += leftUnionArray[i * getMatrixRows() + row].getDConst() * rightUnionArray[column * rightNode->getMatrixRows() + i].getDConst(); - newConstArray[column * getMatrixRows() + row].setDConst(sum); - } - } - returnType.shallowCopy(TType(getType().getBasicType(), EvqConst, 0, rightNode->getMatrixCols(), getMatrixRows())); - break; - case EOpDiv: - for (int i = 0; i < newComps; i++) { - switch (getType().getBasicType()) { - case EbtDouble: - case EbtFloat: - case EbtFloat16: - if (rightUnionArray[i].getDConst() != 0.0) - newConstArray[i].setDConst(leftUnionArray[i].getDConst() / rightUnionArray[i].getDConst()); - else if (leftUnionArray[i].getDConst() > 0.0) - newConstArray[i].setDConst((double)INFINITY); - else if (leftUnionArray[i].getDConst() < 0.0) - newConstArray[i].setDConst(-(double)INFINITY); - else - newConstArray[i].setDConst((double)NAN); - break; - - case EbtInt: - if (rightUnionArray[i] == 0) - newConstArray[i].setIConst(0x7FFFFFFF); - else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)-0x80000000ll) - newConstArray[i].setIConst((int)-0x80000000ll); - else - newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst()); - break; - - case EbtUint: - if (rightUnionArray[i] == 0u) - newConstArray[i].setUConst(0xFFFFFFFFu); - else - newConstArray[i].setUConst(leftUnionArray[i].getUConst() / rightUnionArray[i].getUConst()); - break; - - case EbtInt8: - if (rightUnionArray[i] == (signed char)0) - newConstArray[i].setI8Const((signed char)0x7F); - else if (rightUnionArray[i].getI8Const() == (signed char)-1 && leftUnionArray[i].getI8Const() == (signed char)-0x80) - newConstArray[i].setI8Const((signed char)-0x80); - else - newConstArray[i].setI8Const(leftUnionArray[i].getI8Const() / rightUnionArray[i].getI8Const()); - break; - - case EbtUint8: - if (rightUnionArray[i] == (unsigned char)0u) - newConstArray[i].setU8Const((unsigned char)0xFFu); - else - newConstArray[i].setU8Const(leftUnionArray[i].getU8Const() / rightUnionArray[i].getU8Const()); - break; - - case EbtInt16: - if (rightUnionArray[i] == (signed short)0) - newConstArray[i].setI16Const((signed short)0x7FFF); - else if (rightUnionArray[i].getI16Const() == (signed short)-1 && leftUnionArray[i].getI16Const() == (signed short)-0x8000) - newConstArray[i].setI16Const((signed short)-0x8000); - else - newConstArray[i].setI16Const(leftUnionArray[i].getI16Const() / rightUnionArray[i].getI16Const()); - break; - - case EbtUint16: - if (rightUnionArray[i] == (unsigned short)0u) - newConstArray[i].setU16Const((unsigned short)0xFFFFu); - else - newConstArray[i].setU16Const(leftUnionArray[i].getU16Const() / rightUnionArray[i].getU16Const()); - break; - - case EbtInt64: - if (rightUnionArray[i] == 0ll) - newConstArray[i].setI64Const(LLONG_MAX); - else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) - newConstArray[i].setI64Const(LLONG_MIN); - else - newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const()); - break; - - case EbtUint64: - if (rightUnionArray[i] == 0ull) - newConstArray[i].setU64Const(0xFFFFFFFFFFFFFFFFull); - else - newConstArray[i].setU64Const(leftUnionArray[i].getU64Const() / rightUnionArray[i].getU64Const()); - break; - default: - return nullptr; - } - } - break; - - case EOpMatrixTimesVector: - for (int i = 0; i < getMatrixRows(); i++) { - double sum = 0.0f; - for (int j = 0; j < rightNode->getVectorSize(); j++) { - sum += leftUnionArray[j*getMatrixRows() + i].getDConst() * rightUnionArray[j].getDConst(); - } - newConstArray[i].setDConst(sum); - } - - returnType.shallowCopy(TType(getBasicType(), EvqConst, getMatrixRows())); - break; - - case EOpVectorTimesMatrix: - for (int i = 0; i < rightNode->getMatrixCols(); i++) { - double sum = 0.0f; - for (int j = 0; j < getVectorSize(); j++) - sum += leftUnionArray[j].getDConst() * rightUnionArray[i*rightNode->getMatrixRows() + j].getDConst(); - newConstArray[i].setDConst(sum); - } - - returnType.shallowCopy(TType(getBasicType(), EvqConst, rightNode->getMatrixCols())); - break; - - case EOpMod: - for (int i = 0; i < newComps; i++) { - if (rightUnionArray[i] == 0) - newConstArray[i] = leftUnionArray[i]; - else { - switch (getType().getBasicType()) { - case EbtInt: - if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == INT_MIN) { - newConstArray[i].setIConst(0); - break; - } else goto modulo_default; - case EbtInt64: - if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == LLONG_MIN) { - newConstArray[i].setI64Const(0); - break; - } else goto modulo_default; - case EbtInt16: - if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == SHRT_MIN) { - newConstArray[i].setIConst(0); - break; - } else goto modulo_default; - default: - modulo_default: - newConstArray[i] = leftUnionArray[i] % rightUnionArray[i]; - } - } - } - break; - - case EOpRightShift: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] >> rightUnionArray[i]; - break; - - case EOpLeftShift: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] << rightUnionArray[i]; - break; - - case EOpAnd: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] & rightUnionArray[i]; - break; - case EOpInclusiveOr: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] | rightUnionArray[i]; - break; - case EOpExclusiveOr: - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] ^ rightUnionArray[i]; - break; - - case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] && rightUnionArray[i]; - break; - - case EOpLogicalOr: // this code is written for possible future use, will not get executed currently - for (int i = 0; i < newComps; i++) - newConstArray[i] = leftUnionArray[i] || rightUnionArray[i]; - break; - - case EOpLogicalXor: - for (int i = 0; i < newComps; i++) { - switch (getType().getBasicType()) { - case EbtBool: newConstArray[i].setBConst((leftUnionArray[i] == rightUnionArray[i]) ? false : true); break; - default: assert(false && "Default missing"); - } - } - break; - - case EOpLessThan: - newConstArray[0].setBConst(leftUnionArray[0] < rightUnionArray[0]); - returnType.shallowCopy(constBool); - break; - case EOpGreaterThan: - newConstArray[0].setBConst(leftUnionArray[0] > rightUnionArray[0]); - returnType.shallowCopy(constBool); - break; - case EOpLessThanEqual: - newConstArray[0].setBConst(! (leftUnionArray[0] > rightUnionArray[0])); - returnType.shallowCopy(constBool); - break; - case EOpGreaterThanEqual: - newConstArray[0].setBConst(! (leftUnionArray[0] < rightUnionArray[0])); - returnType.shallowCopy(constBool); - break; - case EOpEqual: - newConstArray[0].setBConst(rightNode->getConstArray() == leftUnionArray); - returnType.shallowCopy(constBool); - break; - case EOpNotEqual: - newConstArray[0].setBConst(rightNode->getConstArray() != leftUnionArray); - returnType.shallowCopy(constBool); - break; - - default: - return nullptr; - } - - TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType); - newNode->setLoc(getLoc()); - - return newNode; -} - -// -// Do single unary node folding -// -// Returns a new node representing the result. -// -TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType) const -{ - // First, size the result, which is mostly the same as the argument's size, - // but not always, and classify what is componentwise. - // Also, eliminate cases that can't be compile-time constant. - int resultSize; - bool componentWise = true; - - int objectSize = getType().computeNumComponents(); - switch (op) { - case EOpDeterminant: - case EOpAny: - case EOpAll: - case EOpLength: - componentWise = false; - resultSize = 1; - break; - - case EOpEmitStreamVertex: - case EOpEndStreamPrimitive: - // These don't fold - return nullptr; - - case EOpPackSnorm2x16: - case EOpPackUnorm2x16: - case EOpPackHalf2x16: - componentWise = false; - resultSize = 1; - break; - - case EOpUnpackSnorm2x16: - case EOpUnpackUnorm2x16: - case EOpUnpackHalf2x16: - componentWise = false; - resultSize = 2; - break; - - case EOpPack16: - case EOpPack32: - case EOpPack64: - case EOpUnpack32: - case EOpUnpack16: - case EOpUnpack8: - case EOpNormalize: - componentWise = false; - resultSize = objectSize; - break; - - default: - resultSize = objectSize; - break; - } - - // Set up for processing - TConstUnionArray newConstArray(resultSize); - const TConstUnionArray& unionArray = getConstArray(); - - // Process non-component-wise operations - switch (op) { - case EOpLength: - case EOpNormalize: - { - double sum = 0; - for (int i = 0; i < objectSize; i++) - sum += unionArray[i].getDConst() * unionArray[i].getDConst(); - double length = sqrt(sum); - if (op == EOpLength) - newConstArray[0].setDConst(length); - else { - for (int i = 0; i < objectSize; i++) - newConstArray[i].setDConst(unionArray[i].getDConst() / length); - } - break; - } - - case EOpAny: - { - bool result = false; - for (int i = 0; i < objectSize; i++) { - if (unionArray[i].getBConst()) - result = true; - } - newConstArray[0].setBConst(result); - break; - } - case EOpAll: - { - bool result = true; - for (int i = 0; i < objectSize; i++) { - if (! unionArray[i].getBConst()) - result = false; - } - newConstArray[0].setBConst(result); - break; - } - - case EOpPackSnorm2x16: - case EOpPackUnorm2x16: - case EOpPackHalf2x16: - case EOpPack16: - case EOpPack32: - case EOpPack64: - case EOpUnpack32: - case EOpUnpack16: - case EOpUnpack8: - - case EOpUnpackSnorm2x16: - case EOpUnpackUnorm2x16: - case EOpUnpackHalf2x16: - - case EOpDeterminant: - case EOpMatrixInverse: - case EOpTranspose: - return nullptr; - - default: - assert(componentWise); - break; - } - - // Turn off the componentwise loop - if (! componentWise) - objectSize = 0; - - // Process component-wise operations - for (int i = 0; i < objectSize; i++) { - switch (op) { - case EOpNegative: - switch (getType().getBasicType()) { - case EbtDouble: - case EbtFloat16: - case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break; - // Note: avoid UBSAN error regarding negating 0x80000000 - case EbtInt: newConstArray[i].setIConst( - static_cast(unionArray[i].getIConst()) == 0x80000000 - ? -0x7FFFFFFF - 1 - : -unionArray[i].getIConst()); - break; - case EbtUint: newConstArray[i].setUConst(static_cast(-static_cast(unionArray[i].getUConst()))); break; - case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break; - case EbtUint8: newConstArray[i].setU8Const(static_cast(-static_cast(unionArray[i].getU8Const()))); break; - case EbtInt16: newConstArray[i].setI16Const(-unionArray[i].getI16Const()); break; - case EbtUint16:newConstArray[i].setU16Const(static_cast(-static_cast(unionArray[i].getU16Const()))); break; - case EbtInt64: newConstArray[i].setI64Const(-unionArray[i].getI64Const()); break; - case EbtUint64: newConstArray[i].setU64Const(static_cast(-static_cast(unionArray[i].getU64Const()))); break; - default: - return nullptr; - } - break; - case EOpLogicalNot: - case EOpVectorLogicalNot: - switch (getType().getBasicType()) { - case EbtBool: newConstArray[i].setBConst(!unionArray[i].getBConst()); break; - default: - return nullptr; - } - break; - case EOpBitwiseNot: - newConstArray[i] = ~unionArray[i]; - break; - case EOpRadians: - newConstArray[i].setDConst(unionArray[i].getDConst() * pi / 180.0); - break; - case EOpDegrees: - newConstArray[i].setDConst(unionArray[i].getDConst() * 180.0 / pi); - break; - case EOpSin: - newConstArray[i].setDConst(sin(unionArray[i].getDConst())); - break; - case EOpCos: - newConstArray[i].setDConst(cos(unionArray[i].getDConst())); - break; - case EOpTan: - newConstArray[i].setDConst(tan(unionArray[i].getDConst())); - break; - case EOpAsin: - newConstArray[i].setDConst(asin(unionArray[i].getDConst())); - break; - case EOpAcos: - newConstArray[i].setDConst(acos(unionArray[i].getDConst())); - break; - case EOpAtan: - newConstArray[i].setDConst(atan(unionArray[i].getDConst())); - break; - - case EOpDPdx: - case EOpDPdy: - case EOpFwidth: - case EOpDPdxFine: - case EOpDPdyFine: - case EOpFwidthFine: - case EOpDPdxCoarse: - case EOpDPdyCoarse: - case EOpFwidthCoarse: - // The derivatives are all mandated to create a constant 0. - newConstArray[i].setDConst(0.0); - break; - - case EOpExp: - newConstArray[i].setDConst(exp(unionArray[i].getDConst())); - break; - case EOpLog: - newConstArray[i].setDConst(log(unionArray[i].getDConst())); - break; - case EOpExp2: - newConstArray[i].setDConst(exp2(unionArray[i].getDConst())); - break; - case EOpLog2: - newConstArray[i].setDConst(log2(unionArray[i].getDConst())); - break; - case EOpSqrt: - newConstArray[i].setDConst(sqrt(unionArray[i].getDConst())); - break; - case EOpInverseSqrt: - newConstArray[i].setDConst(1.0 / sqrt(unionArray[i].getDConst())); - break; - - case EOpAbs: - if (unionArray[i].getType() == EbtDouble) - newConstArray[i].setDConst(fabs(unionArray[i].getDConst())); - else if (unionArray[i].getType() == EbtInt) - newConstArray[i].setIConst(abs(unionArray[i].getIConst())); - else - newConstArray[i] = unionArray[i]; - break; - case EOpSign: - #define SIGN(X) (X == 0 ? 0 : (X < 0 ? -1 : 1)) - if (unionArray[i].getType() == EbtDouble) - newConstArray[i].setDConst(SIGN(unionArray[i].getDConst())); - else - newConstArray[i].setIConst(SIGN(unionArray[i].getIConst())); - break; - case EOpFloor: - newConstArray[i].setDConst(floor(unionArray[i].getDConst())); - break; - case EOpTrunc: - if (unionArray[i].getDConst() > 0) - newConstArray[i].setDConst(floor(unionArray[i].getDConst())); - else - newConstArray[i].setDConst(ceil(unionArray[i].getDConst())); - break; - case EOpRound: - newConstArray[i].setDConst(floor(0.5 + unionArray[i].getDConst())); - break; - case EOpRoundEven: - { - double flr = floor(unionArray[i].getDConst()); - bool even = flr / 2.0 == floor(flr / 2.0); - double rounded = even ? ceil(unionArray[i].getDConst() - 0.5) : floor(unionArray[i].getDConst() + 0.5); - newConstArray[i].setDConst(rounded); - break; - } - case EOpCeil: - newConstArray[i].setDConst(ceil(unionArray[i].getDConst())); - break; - case EOpFract: - { - double x = unionArray[i].getDConst(); - newConstArray[i].setDConst(x - floor(x)); - break; - } - - case EOpIsNan: - { - newConstArray[i].setBConst(std::isnan(unionArray[i].getDConst())); - break; - } - case EOpIsInf: - { - newConstArray[i].setBConst(std::isinf(unionArray[i].getDConst())); - break; - } - - case EOpConvIntToBool: - newConstArray[i].setBConst(unionArray[i].getIConst() != 0); break; - case EOpConvUintToBool: - newConstArray[i].setBConst(unionArray[i].getUConst() != 0); break; - case EOpConvBoolToInt: - newConstArray[i].setIConst(unionArray[i].getBConst()); break; - case EOpConvBoolToUint: - newConstArray[i].setUConst(unionArray[i].getBConst()); break; - case EOpConvIntToUint: - newConstArray[i].setUConst(unionArray[i].getIConst()); break; - case EOpConvUintToInt: - newConstArray[i].setIConst(unionArray[i].getUConst()); break; - - case EOpConvFloatToBool: - case EOpConvDoubleToBool: - newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break; - - case EOpConvBoolToFloat: - case EOpConvBoolToDouble: - newConstArray[i].setDConst(unionArray[i].getBConst()); break; - - case EOpConvIntToFloat: - case EOpConvIntToDouble: - newConstArray[i].setDConst(unionArray[i].getIConst()); break; - - case EOpConvUintToFloat: - case EOpConvUintToDouble: - newConstArray[i].setDConst(unionArray[i].getUConst()); break; - - case EOpConvDoubleToFloat: - case EOpConvFloatToDouble: - newConstArray[i].setDConst(unionArray[i].getDConst()); break; - - case EOpConvFloatToUint: - case EOpConvDoubleToUint: - newConstArray[i].setUConst(static_cast(unionArray[i].getDConst())); break; - - case EOpConvFloatToInt: - case EOpConvDoubleToInt: - newConstArray[i].setIConst(static_cast(unionArray[i].getDConst())); break; - - case EOpConvInt8ToBool: - newConstArray[i].setBConst(unionArray[i].getI8Const() != 0); break; - case EOpConvUint8ToBool: - newConstArray[i].setBConst(unionArray[i].getU8Const() != 0); break; - case EOpConvInt16ToBool: - newConstArray[i].setBConst(unionArray[i].getI16Const() != 0); break; - case EOpConvUint16ToBool: - newConstArray[i].setBConst(unionArray[i].getU16Const() != 0); break; - case EOpConvInt64ToBool: - newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break; - case EOpConvUint64ToBool: - newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break; - case EOpConvFloat16ToBool: - newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break; - - case EOpConvBoolToInt8: - newConstArray[i].setI8Const(unionArray[i].getBConst()); break; - case EOpConvBoolToUint8: - newConstArray[i].setU8Const(unionArray[i].getBConst()); break; - case EOpConvBoolToInt16: - newConstArray[i].setI16Const(unionArray[i].getBConst()); break; - case EOpConvBoolToUint16: - newConstArray[i].setU16Const(unionArray[i].getBConst()); break; - case EOpConvBoolToInt64: - newConstArray[i].setI64Const(unionArray[i].getBConst()); break; - case EOpConvBoolToUint64: - newConstArray[i].setU64Const(unionArray[i].getBConst()); break; - case EOpConvBoolToFloat16: - newConstArray[i].setDConst(unionArray[i].getBConst()); break; - - case EOpConvInt8ToInt16: - newConstArray[i].setI16Const(unionArray[i].getI8Const()); break; - case EOpConvInt8ToInt: - newConstArray[i].setIConst(unionArray[i].getI8Const()); break; - case EOpConvInt8ToInt64: - newConstArray[i].setI64Const(unionArray[i].getI8Const()); break; - case EOpConvInt8ToUint8: - newConstArray[i].setU8Const(unionArray[i].getI8Const()); break; - case EOpConvInt8ToUint16: - newConstArray[i].setU16Const(unionArray[i].getI8Const()); break; - case EOpConvInt8ToUint: - newConstArray[i].setUConst(unionArray[i].getI8Const()); break; - case EOpConvInt8ToUint64: - newConstArray[i].setU64Const(unionArray[i].getI8Const()); break; - case EOpConvUint8ToInt8: - newConstArray[i].setI8Const(unionArray[i].getU8Const()); break; - case EOpConvUint8ToInt16: - newConstArray[i].setI16Const(unionArray[i].getU8Const()); break; - case EOpConvUint8ToInt: - newConstArray[i].setIConst(unionArray[i].getU8Const()); break; - case EOpConvUint8ToInt64: - newConstArray[i].setI64Const(unionArray[i].getU8Const()); break; - case EOpConvUint8ToUint16: - newConstArray[i].setU16Const(unionArray[i].getU8Const()); break; - case EOpConvUint8ToUint: - newConstArray[i].setUConst(unionArray[i].getU8Const()); break; - case EOpConvUint8ToUint64: - newConstArray[i].setU64Const(unionArray[i].getU8Const()); break; - case EOpConvInt8ToFloat16: - newConstArray[i].setDConst(unionArray[i].getI8Const()); break; - case EOpConvInt8ToFloat: - newConstArray[i].setDConst(unionArray[i].getI8Const()); break; - case EOpConvInt8ToDouble: - newConstArray[i].setDConst(unionArray[i].getI8Const()); break; - case EOpConvUint8ToFloat16: - newConstArray[i].setDConst(unionArray[i].getU8Const()); break; - case EOpConvUint8ToFloat: - newConstArray[i].setDConst(unionArray[i].getU8Const()); break; - case EOpConvUint8ToDouble: - newConstArray[i].setDConst(unionArray[i].getU8Const()); break; - - case EOpConvInt16ToInt8: - newConstArray[i].setI8Const(static_cast(unionArray[i].getI16Const())); break; - case EOpConvInt16ToInt: - newConstArray[i].setIConst(unionArray[i].getI16Const()); break; - case EOpConvInt16ToInt64: - newConstArray[i].setI64Const(unionArray[i].getI16Const()); break; - case EOpConvInt16ToUint8: - newConstArray[i].setU8Const(static_cast(unionArray[i].getI16Const())); break; - case EOpConvInt16ToUint16: - newConstArray[i].setU16Const(unionArray[i].getI16Const()); break; - case EOpConvInt16ToUint: - newConstArray[i].setUConst(unionArray[i].getI16Const()); break; - case EOpConvInt16ToUint64: - newConstArray[i].setU64Const(unionArray[i].getI16Const()); break; - case EOpConvUint16ToInt8: - newConstArray[i].setI8Const(static_cast(unionArray[i].getU16Const())); break; - case EOpConvUint16ToInt16: - newConstArray[i].setI16Const(unionArray[i].getU16Const()); break; - case EOpConvUint16ToInt: - newConstArray[i].setIConst(unionArray[i].getU16Const()); break; - case EOpConvUint16ToInt64: - newConstArray[i].setI64Const(unionArray[i].getU16Const()); break; - case EOpConvUint16ToUint8: - newConstArray[i].setU8Const(static_cast(unionArray[i].getU16Const())); break; - - case EOpConvUint16ToUint: - newConstArray[i].setUConst(unionArray[i].getU16Const()); break; - case EOpConvUint16ToUint64: - newConstArray[i].setU64Const(unionArray[i].getU16Const()); break; - case EOpConvInt16ToFloat16: - newConstArray[i].setDConst(unionArray[i].getI16Const()); break; - case EOpConvInt16ToFloat: - newConstArray[i].setDConst(unionArray[i].getI16Const()); break; - case EOpConvInt16ToDouble: - newConstArray[i].setDConst(unionArray[i].getI16Const()); break; - case EOpConvUint16ToFloat16: - newConstArray[i].setDConst(unionArray[i].getU16Const()); break; - case EOpConvUint16ToFloat: - newConstArray[i].setDConst(unionArray[i].getU16Const()); break; - case EOpConvUint16ToDouble: - newConstArray[i].setDConst(unionArray[i].getU16Const()); break; - - case EOpConvIntToInt8: - newConstArray[i].setI8Const((signed char)unionArray[i].getIConst()); break; - case EOpConvIntToInt16: - newConstArray[i].setI16Const((signed short)unionArray[i].getIConst()); break; - case EOpConvIntToInt64: - newConstArray[i].setI64Const(unionArray[i].getIConst()); break; - case EOpConvIntToUint8: - newConstArray[i].setU8Const((unsigned char)unionArray[i].getIConst()); break; - case EOpConvIntToUint16: - newConstArray[i].setU16Const((unsigned char)unionArray[i].getIConst()); break; - case EOpConvIntToUint64: - newConstArray[i].setU64Const(unionArray[i].getIConst()); break; - - case EOpConvUintToInt8: - newConstArray[i].setI8Const((signed char)unionArray[i].getUConst()); break; - case EOpConvUintToInt16: - newConstArray[i].setI16Const((signed short)unionArray[i].getUConst()); break; - case EOpConvUintToInt64: - newConstArray[i].setI64Const(unionArray[i].getUConst()); break; - case EOpConvUintToUint8: - newConstArray[i].setU8Const((unsigned char)unionArray[i].getUConst()); break; - case EOpConvUintToUint16: - newConstArray[i].setU16Const((unsigned short)unionArray[i].getUConst()); break; - case EOpConvUintToUint64: - newConstArray[i].setU64Const(unionArray[i].getUConst()); break; - case EOpConvIntToFloat16: - newConstArray[i].setDConst(unionArray[i].getIConst()); break; - case EOpConvUintToFloat16: - newConstArray[i].setDConst(unionArray[i].getUConst()); break; - case EOpConvInt64ToInt8: - newConstArray[i].setI8Const(static_cast(unionArray[i].getI64Const())); break; - case EOpConvInt64ToInt16: - newConstArray[i].setI16Const(static_cast(unionArray[i].getI64Const())); break; - case EOpConvInt64ToInt: - newConstArray[i].setIConst(static_cast(unionArray[i].getI64Const())); break; - case EOpConvInt64ToUint8: - newConstArray[i].setU8Const(static_cast(unionArray[i].getI64Const())); break; - case EOpConvInt64ToUint16: - newConstArray[i].setU16Const(static_cast(unionArray[i].getI64Const())); break; - case EOpConvInt64ToUint: - newConstArray[i].setUConst(static_cast(unionArray[i].getI64Const())); break; - case EOpConvInt64ToUint64: - newConstArray[i].setU64Const(unionArray[i].getI64Const()); break; - case EOpConvUint64ToInt8: - newConstArray[i].setI8Const(static_cast(unionArray[i].getU64Const())); break; - case EOpConvUint64ToInt16: - newConstArray[i].setI16Const(static_cast(unionArray[i].getU64Const())); break; - case EOpConvUint64ToInt: - newConstArray[i].setIConst(static_cast(unionArray[i].getU64Const())); break; - case EOpConvUint64ToInt64: - newConstArray[i].setI64Const(unionArray[i].getU64Const()); break; - case EOpConvUint64ToUint8: - newConstArray[i].setU8Const(static_cast(unionArray[i].getU64Const())); break; - case EOpConvUint64ToUint16: - newConstArray[i].setU16Const(static_cast(unionArray[i].getU64Const())); break; - case EOpConvUint64ToUint: - newConstArray[i].setUConst(static_cast(unionArray[i].getU64Const())); break; - case EOpConvInt64ToFloat16: - newConstArray[i].setDConst(static_cast(unionArray[i].getI64Const())); break; - case EOpConvInt64ToFloat: - newConstArray[i].setDConst(static_cast(unionArray[i].getI64Const())); break; - case EOpConvInt64ToDouble: - newConstArray[i].setDConst(static_cast(unionArray[i].getI64Const())); break; - case EOpConvUint64ToFloat16: - newConstArray[i].setDConst(static_cast(unionArray[i].getU64Const())); break; - case EOpConvUint64ToFloat: - newConstArray[i].setDConst(static_cast(unionArray[i].getU64Const())); break; - case EOpConvUint64ToDouble: - newConstArray[i].setDConst(static_cast(unionArray[i].getU64Const())); break; - case EOpConvFloat16ToInt8: - newConstArray[i].setI8Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloat16ToInt16: - newConstArray[i].setI16Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloat16ToInt: - newConstArray[i].setIConst(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloat16ToInt64: - newConstArray[i].setI64Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloat16ToUint8: - newConstArray[i].setU8Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloat16ToUint16: - newConstArray[i].setU16Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloat16ToUint: - newConstArray[i].setUConst(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloat16ToUint64: - newConstArray[i].setU64Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloat16ToFloat: - newConstArray[i].setDConst(unionArray[i].getDConst()); break; - case EOpConvFloat16ToDouble: - newConstArray[i].setDConst(unionArray[i].getDConst()); break; - case EOpConvFloatToInt8: - newConstArray[i].setI8Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloatToInt16: - newConstArray[i].setI16Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloatToInt64: - newConstArray[i].setI64Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloatToUint8: - newConstArray[i].setU8Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloatToUint16: - newConstArray[i].setU16Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloatToUint64: - newConstArray[i].setU64Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvFloatToFloat16: - newConstArray[i].setDConst(unionArray[i].getDConst()); break; - case EOpConvDoubleToInt8: - newConstArray[i].setI8Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvDoubleToInt16: - newConstArray[i].setI16Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvDoubleToInt64: - newConstArray[i].setI64Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvDoubleToUint8: - newConstArray[i].setU8Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvDoubleToUint16: - newConstArray[i].setU16Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvDoubleToUint64: - newConstArray[i].setU64Const(static_cast(unionArray[i].getDConst())); break; - case EOpConvDoubleToFloat16: - newConstArray[i].setDConst(unionArray[i].getDConst()); break; - case EOpConvPtrToUint64: - case EOpConvUint64ToPtr: - case EOpConstructReference: - newConstArray[i].setU64Const(unionArray[i].getU64Const()); break; - - // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out - - case EOpSinh: - case EOpCosh: - case EOpTanh: - case EOpAsinh: - case EOpAcosh: - case EOpAtanh: - - case EOpFloatBitsToInt: - case EOpFloatBitsToUint: - case EOpIntBitsToFloat: - case EOpUintBitsToFloat: - case EOpDoubleBitsToInt64: - case EOpDoubleBitsToUint64: - case EOpInt64BitsToDouble: - case EOpUint64BitsToDouble: - case EOpFloat16BitsToInt16: - case EOpFloat16BitsToUint16: - case EOpInt16BitsToFloat16: - case EOpUint16BitsToFloat16: - default: - return nullptr; - } - } - - TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, returnType); - newNode->getWritableType().getQualifier().storage = EvqConst; - newNode->setLoc(getLoc()); - - return newNode; -} - -// -// Do constant folding for an aggregate node that has all its children -// as constants and an operator that requires constant folding. -// -TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode) -{ - if (aggrNode == nullptr) - return aggrNode; - - if (! areAllChildConst(aggrNode)) - return aggrNode; - - if (aggrNode->isConstructor()) - return foldConstructor(aggrNode); - - TIntermSequence& children = aggrNode->getSequence(); - - // First, see if this is an operation to constant fold, kick out if not, - // see what size the result is if so. - - bool componentwise = false; // will also say componentwise if a scalar argument gets repeated to make per-component results - int objectSize; - switch (aggrNode->getOp()) { - case EOpAtan: - case EOpPow: - case EOpMin: - case EOpMax: - case EOpMix: - case EOpMod: - case EOpClamp: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - case EOpVectorEqual: - case EOpVectorNotEqual: - componentwise = true; - objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents(); - break; - case EOpCross: - case EOpReflect: - case EOpRefract: - case EOpFaceForward: - objectSize = children[0]->getAsConstantUnion()->getType().computeNumComponents(); - break; - case EOpDistance: - case EOpDot: - objectSize = 1; - break; - case EOpOuterProduct: - objectSize = children[0]->getAsTyped()->getType().getVectorSize() * - children[1]->getAsTyped()->getType().getVectorSize(); - break; - case EOpStep: - componentwise = true; - objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(), - children[1]->getAsTyped()->getType().getVectorSize()); - break; - case EOpSmoothStep: - componentwise = true; - objectSize = std::max(children[0]->getAsTyped()->getType().getVectorSize(), - children[2]->getAsTyped()->getType().getVectorSize()); - break; - default: - return aggrNode; - } - TConstUnionArray newConstArray(objectSize); - - TVector childConstUnions; - for (unsigned int arg = 0; arg < children.size(); ++arg) - childConstUnions.push_back(children[arg]->getAsConstantUnion()->getConstArray()); - - if (componentwise) { - for (int comp = 0; comp < objectSize; comp++) { - - // some arguments are scalars instead of matching vectors; simulate a smear - int arg0comp = std::min(comp, children[0]->getAsTyped()->getType().getVectorSize() - 1); - int arg1comp = 0; - if (children.size() > 1) - arg1comp = std::min(comp, children[1]->getAsTyped()->getType().getVectorSize() - 1); - int arg2comp = 0; - if (children.size() > 2) - arg2comp = std::min(comp, children[2]->getAsTyped()->getType().getVectorSize() - 1); - - switch (aggrNode->getOp()) { - case EOpAtan: - newConstArray[comp].setDConst(atan2(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst())); - break; - case EOpPow: - newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst())); - break; - case EOpMod: - { - double arg0 = childConstUnions[0][arg0comp].getDConst(); - double arg1 = childConstUnions[1][arg1comp].getDConst(); - double result = arg0 - arg1 * floor(arg0 / arg1); - newConstArray[comp].setDConst(result); - break; - } - case EOpMin: - switch(children[0]->getAsTyped()->getBasicType()) { - case EbtFloat16: - case EbtFloat: - case EbtDouble: - newConstArray[comp].setDConst(std::min(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst())); - break; - case EbtInt: - newConstArray[comp].setIConst(std::min(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst())); - break; - case EbtUint: - newConstArray[comp].setUConst(std::min(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst())); - break; - case EbtInt8: - newConstArray[comp].setI8Const(std::min(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const())); - break; - case EbtUint8: - newConstArray[comp].setU8Const(std::min(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const())); - break; - case EbtInt16: - newConstArray[comp].setI16Const(std::min(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const())); - break; - case EbtUint16: - newConstArray[comp].setU16Const(std::min(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const())); - break; - case EbtInt64: - newConstArray[comp].setI64Const(std::min(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const())); - break; - case EbtUint64: - newConstArray[comp].setU64Const(std::min(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const())); - break; - default: assert(false && "Default missing"); - } - break; - case EOpMax: - switch(children[0]->getAsTyped()->getBasicType()) { - case EbtFloat16: - case EbtFloat: - case EbtDouble: - newConstArray[comp].setDConst(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst())); - break; - case EbtInt: - newConstArray[comp].setIConst(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst())); - break; - case EbtUint: - newConstArray[comp].setUConst(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst())); - break; - case EbtInt8: - newConstArray[comp].setI8Const(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const())); - break; - case EbtUint8: - newConstArray[comp].setU8Const(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const())); - break; - case EbtInt16: - newConstArray[comp].setI16Const(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const())); - break; - case EbtUint16: - newConstArray[comp].setU16Const(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const())); - break; - case EbtInt64: - newConstArray[comp].setI64Const(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const())); - break; - case EbtUint64: - newConstArray[comp].setU64Const(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const())); - break; - default: assert(false && "Default missing"); - } - break; - case EOpClamp: - switch(children[0]->getAsTyped()->getBasicType()) { - case EbtFloat16: - case EbtFloat: - case EbtDouble: - newConstArray[comp].setDConst(std::min(std::max(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()), - childConstUnions[2][arg2comp].getDConst())); - break; - case EbtUint: - newConstArray[comp].setUConst(std::min(std::max(childConstUnions[0][arg0comp].getUConst(), childConstUnions[1][arg1comp].getUConst()), - childConstUnions[2][arg2comp].getUConst())); - break; - case EbtInt8: - newConstArray[comp].setI8Const(std::min(std::max(childConstUnions[0][arg0comp].getI8Const(), childConstUnions[1][arg1comp].getI8Const()), - childConstUnions[2][arg2comp].getI8Const())); - break; - case EbtUint8: - newConstArray[comp].setU8Const(std::min(std::max(childConstUnions[0][arg0comp].getU8Const(), childConstUnions[1][arg1comp].getU8Const()), - childConstUnions[2][arg2comp].getU8Const())); - break; - case EbtInt16: - newConstArray[comp].setI16Const(std::min(std::max(childConstUnions[0][arg0comp].getI16Const(), childConstUnions[1][arg1comp].getI16Const()), - childConstUnions[2][arg2comp].getI16Const())); - break; - case EbtUint16: - newConstArray[comp].setU16Const(std::min(std::max(childConstUnions[0][arg0comp].getU16Const(), childConstUnions[1][arg1comp].getU16Const()), - childConstUnions[2][arg2comp].getU16Const())); - break; - case EbtInt: - newConstArray[comp].setIConst(std::min(std::max(childConstUnions[0][arg0comp].getIConst(), childConstUnions[1][arg1comp].getIConst()), - childConstUnions[2][arg2comp].getIConst())); - break; - case EbtInt64: - newConstArray[comp].setI64Const(std::min(std::max(childConstUnions[0][arg0comp].getI64Const(), childConstUnions[1][arg1comp].getI64Const()), - childConstUnions[2][arg2comp].getI64Const())); - break; - case EbtUint64: - newConstArray[comp].setU64Const(std::min(std::max(childConstUnions[0][arg0comp].getU64Const(), childConstUnions[1][arg1comp].getU64Const()), - childConstUnions[2][arg2comp].getU64Const())); - break; - default: assert(false && "Default missing"); - } - break; - case EOpLessThan: - newConstArray[comp].setBConst(childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp]); - break; - case EOpGreaterThan: - newConstArray[comp].setBConst(childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp]); - break; - case EOpLessThanEqual: - newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] > childConstUnions[1][arg1comp])); - break; - case EOpGreaterThanEqual: - newConstArray[comp].setBConst(! (childConstUnions[0][arg0comp] < childConstUnions[1][arg1comp])); - break; - case EOpVectorEqual: - newConstArray[comp].setBConst(childConstUnions[0][arg0comp] == childConstUnions[1][arg1comp]); - break; - case EOpVectorNotEqual: - newConstArray[comp].setBConst(childConstUnions[0][arg0comp] != childConstUnions[1][arg1comp]); - break; - case EOpMix: - if (!children[0]->getAsTyped()->isFloatingDomain()) - return aggrNode; - if (children[2]->getAsTyped()->getBasicType() == EbtBool) { - newConstArray[comp].setDConst(childConstUnions[2][arg2comp].getBConst() - ? childConstUnions[1][arg1comp].getDConst() - : childConstUnions[0][arg0comp].getDConst()); - } else { - newConstArray[comp].setDConst( - childConstUnions[0][arg0comp].getDConst() * (1.0 - childConstUnions[2][arg2comp].getDConst()) + - childConstUnions[1][arg1comp].getDConst() * childConstUnions[2][arg2comp].getDConst()); - } - break; - case EOpStep: - newConstArray[comp].setDConst(childConstUnions[1][arg1comp].getDConst() < childConstUnions[0][arg0comp].getDConst() ? 0.0 : 1.0); - break; - case EOpSmoothStep: - { - double t = (childConstUnions[2][arg2comp].getDConst() - childConstUnions[0][arg0comp].getDConst()) / - (childConstUnions[1][arg1comp].getDConst() - childConstUnions[0][arg0comp].getDConst()); - if (t < 0.0) - t = 0.0; - if (t > 1.0) - t = 1.0; - newConstArray[comp].setDConst(t * t * (3.0 - 2.0 * t)); - break; - } - default: - return aggrNode; - } - } - } else { - // Non-componentwise... - - int numComps = children[0]->getAsConstantUnion()->getType().computeNumComponents(); - double dot; - - switch (aggrNode->getOp()) { - case EOpDistance: - { - double sum = 0.0; - for (int comp = 0; comp < numComps; ++comp) { - double diff = childConstUnions[1][comp].getDConst() - childConstUnions[0][comp].getDConst(); - sum += diff * diff; - } - newConstArray[0].setDConst(sqrt(sum)); - break; - } - case EOpDot: - newConstArray[0].setDConst(childConstUnions[0].dot(childConstUnions[1])); - break; - case EOpCross: - newConstArray[0] = childConstUnions[0][1] * childConstUnions[1][2] - childConstUnions[0][2] * childConstUnions[1][1]; - newConstArray[1] = childConstUnions[0][2] * childConstUnions[1][0] - childConstUnions[0][0] * childConstUnions[1][2]; - newConstArray[2] = childConstUnions[0][0] * childConstUnions[1][1] - childConstUnions[0][1] * childConstUnions[1][0]; - break; - case EOpFaceForward: - // If dot(Nref, I) < 0 return N, otherwise return -N: Arguments are (N, I, Nref). - dot = childConstUnions[1].dot(childConstUnions[2]); - for (int comp = 0; comp < numComps; ++comp) { - if (dot < 0.0) - newConstArray[comp] = childConstUnions[0][comp]; - else - newConstArray[comp].setDConst(-childConstUnions[0][comp].getDConst()); - } - break; - case EOpReflect: - // I - 2 * dot(N, I) * N: Arguments are (I, N). - dot = childConstUnions[0].dot(childConstUnions[1]); - dot *= 2.0; - for (int comp = 0; comp < numComps; ++comp) - newConstArray[comp].setDConst(childConstUnions[0][comp].getDConst() - dot * childConstUnions[1][comp].getDConst()); - break; - case EOpRefract: - { - // Arguments are (I, N, eta). - // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) - // if (k < 0.0) - // return dvec(0.0) - // else - // return eta * I - (eta * dot(N, I) + sqrt(k)) * N - dot = childConstUnions[0].dot(childConstUnions[1]); - double eta = childConstUnions[2][0].getDConst(); - double k = 1.0 - eta * eta * (1.0 - dot * dot); - if (k < 0.0) { - for (int comp = 0; comp < numComps; ++comp) - newConstArray[comp].setDConst(0.0); - } else { - for (int comp = 0; comp < numComps; ++comp) - newConstArray[comp].setDConst(eta * childConstUnions[0][comp].getDConst() - (eta * dot + sqrt(k)) * childConstUnions[1][comp].getDConst()); - } - break; - } - case EOpOuterProduct: - { - int numRows = numComps; - int numCols = children[1]->getAsConstantUnion()->getType().computeNumComponents(); - for (int row = 0; row < numRows; ++row) - for (int col = 0; col < numCols; ++col) - newConstArray[col * numRows + row] = childConstUnions[0][row] * childConstUnions[1][col]; - break; - } - default: - return aggrNode; - } - } - - TIntermConstantUnion *newNode = new TIntermConstantUnion(newConstArray, aggrNode->getType()); - newNode->getWritableType().getQualifier().storage = EvqConst; - newNode->setLoc(aggrNode->getLoc()); - - return newNode; -} - -bool TIntermediate::areAllChildConst(TIntermAggregate* aggrNode) -{ - bool allConstant = true; - - // check if all the child nodes are constants so that they can be inserted into - // the parent node - if (aggrNode) { - TIntermSequence& childSequenceVector = aggrNode->getSequence(); - for (TIntermSequence::iterator p = childSequenceVector.begin(); - p != childSequenceVector.end(); p++) { - if (!(*p)->getAsTyped()->getAsConstantUnion()) - return false; - } - } - - return allConstant; -} - -TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode) -{ - bool error = false; - - TConstUnionArray unionArray(aggrNode->getType().computeNumComponents()); - if (aggrNode->getSequence().size() == 1) - error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true); - else - error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType()); - - if (error) - return aggrNode; - - return addConstantUnion(unionArray, aggrNode->getType(), aggrNode->getLoc()); -} - -// -// Constant folding of a bracket (array-style) dereference or struct-like dot -// dereference. Can handle anything except a multi-character swizzle, though -// all swizzles may go to foldSwizzle(). -// -TIntermTyped* TIntermediate::foldDereference(TIntermTyped* node, int index, const TSourceLoc& loc) -{ - TType dereferencedType(node->getType(), index); - dereferencedType.getQualifier().storage = EvqConst; - TIntermTyped* result = nullptr; - int size = dereferencedType.computeNumComponents(); - - // arrays, vectors, matrices, all use simple multiplicative math - // while structures need to add up heterogeneous members - int start; - if (node->getType().isCoopMat()) - start = 0; - else if (node->isArray() || ! node->isStruct()) - start = size * index; - else { - // it is a structure - assert(node->isStruct()); - start = 0; - for (int i = 0; i < index; ++i) - start += (*node->getType().getStruct())[i].type->computeNumComponents(); - } - - result = addConstantUnion(TConstUnionArray(node->getAsConstantUnion()->getConstArray(), start, size), node->getType(), loc); - - if (result == nullptr) - result = node; - else - result->setType(dereferencedType); - - return result; -} - -// -// Make a constant vector node or constant scalar node, representing a given -// constant vector and constant swizzle into it. -// -TIntermTyped* TIntermediate::foldSwizzle(TIntermTyped* node, TSwizzleSelectors& selectors, const TSourceLoc& loc) -{ - const TConstUnionArray& unionArray = node->getAsConstantUnion()->getConstArray(); - TConstUnionArray constArray(selectors.size()); - - for (int i = 0; i < selectors.size(); i++) - constArray[i] = unionArray[selectors[i]]; - - TIntermTyped* result = addConstantUnion(constArray, node->getType(), loc); - - if (result == nullptr) - result = node; - else - result->setType(TType(node->getBasicType(), EvqConst, selectors.size())); - - return result; -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/InfoSink.cpp b/3rdparty/glslang/glslang/MachineIndependent/InfoSink.cpp deleted file mode 100644 index d00c4225..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/InfoSink.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/InfoSink.h" - -#include - -namespace glslang { - -void TInfoSinkBase::append(const char* s) -{ - if (outputStream & EString) { - if (s == nullptr) - sink.append("(null)"); - else { - checkMem(strlen(s)); - sink.append(s); - } - } - -//#ifdef _WIN32 -// if (outputStream & EDebugger) -// OutputDebugString(s); -//#endif - - if (outputStream & EStdOut) - fprintf(stdout, "%s", s); -} - -void TInfoSinkBase::append(int count, char c) -{ - if (outputStream & EString) { - checkMem(count); - sink.append(count, c); - } - -//#ifdef _WIN32 -// if (outputStream & EDebugger) { -// char str[2]; -// str[0] = c; -// str[1] = '\0'; -// OutputDebugString(str); -// } -//#endif - - if (outputStream & EStdOut) - fprintf(stdout, "%c", c); -} - -void TInfoSinkBase::append(const TPersistString& t) -{ - if (outputStream & EString) { - checkMem(t.size()); - sink.append(t); - } - -//#ifdef _WIN32 -// if (outputStream & EDebugger) -// OutputDebugString(t.c_str()); -//#endif - - if (outputStream & EStdOut) - fprintf(stdout, "%s", t.c_str()); -} - -void TInfoSinkBase::append(const TString& t) -{ - if (outputStream & EString) { - checkMem(t.size()); - sink.append(t.c_str()); - } - -//#ifdef _WIN32 -// if (outputStream & EDebugger) -// OutputDebugString(t.c_str()); -//#endif - - if (outputStream & EStdOut) - fprintf(stdout, "%s", t.c_str()); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp b/3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp deleted file mode 100644 index af333f3f..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/Initialize.cpp +++ /dev/null @@ -1,10287 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2016 LunarG, Inc. -// Copyright (C) 2015-2020 Google, Inc. -// Copyright (C) 2017 ARM Limited. -// Modifications Copyright (C) 2020-2021 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Create strings that declare built-in definitions, add built-ins programmatically -// that cannot be expressed in the strings, and establish mappings between -// built-in functions and operators. -// -// Where to put a built-in: -// TBuiltIns::initialize(version,profile) context-independent textual built-ins; add them to the right string -// TBuiltIns::initialize(resources,...) context-dependent textual built-ins; add them to the right string -// TBuiltIns::identifyBuiltIns(...,symbolTable) context-independent programmatic additions/mappings to the symbol table, -// including identifying what extensions are needed if a version does not allow a symbol -// TBuiltIns::identifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the symbol table, -// including identifying what extensions are needed if a version does not allow a symbol -// - -#include "Initialize.h" - -namespace glslang { - -// TODO: ARB_Compatability: do full extension support -const bool ARBCompatibility = true; - -const bool ForwardCompatibility = false; - -namespace { - -// -// A set of definitions for tabling of the built-in functions. -// - -// Order matters here, as does correlation with the subsequent -// "const int ..." declarations and the ArgType enumerants. -const char* TypeString[] = { - "bool", "bvec2", "bvec3", "bvec4", - "float", "vec2", "vec3", "vec4", - "int", "ivec2", "ivec3", "ivec4", - "uint", "uvec2", "uvec3", "uvec4", -}; -const int TypeStringCount = sizeof(TypeString) / sizeof(char*); // number of entries in 'TypeString' -const int TypeStringRowShift = 2; // shift amount to go downe one row in 'TypeString' -const int TypeStringColumnMask = (1 << TypeStringRowShift) - 1; // reduce type to its column number in 'TypeString' -const int TypeStringScalarMask = ~TypeStringColumnMask; // take type to its scalar column in 'TypeString' - -enum ArgType { - // numbers hardcoded to correspond to 'TypeString'; order and value matter - TypeB = 1 << 0, // Boolean - TypeF = 1 << 1, // float 32 - TypeI = 1 << 2, // int 32 - TypeU = 1 << 3, // uint 32 - TypeF16 = 1 << 4, // float 16 - TypeF64 = 1 << 5, // float 64 - TypeI8 = 1 << 6, // int 8 - TypeI16 = 1 << 7, // int 16 - TypeI64 = 1 << 8, // int 64 - TypeU8 = 1 << 9, // uint 8 - TypeU16 = 1 << 10, // uint 16 - TypeU64 = 1 << 11, // uint 64 -}; -// Mixtures of the above, to help the function tables -const ArgType TypeFI = static_cast(TypeF | TypeI); -const ArgType TypeFIB = static_cast(TypeF | TypeI | TypeB); -const ArgType TypeIU = static_cast(TypeI | TypeU); - -// The relationships between arguments and return type, whether anything is -// output, or other unusual situations. -enum ArgClass { - ClassRegular = 0, // nothing special, just all vector widths with matching return type; traditional arithmetic - ClassLS = 1 << 0, // the last argument is also held fixed as a (type-matched) scalar while the others cycle - ClassXLS = 1 << 1, // the last argument is exclusively a (type-matched) scalar while the others cycle - ClassLS2 = 1 << 2, // the last two arguments are held fixed as a (type-matched) scalar while the others cycle - ClassFS = 1 << 3, // the first argument is held fixed as a (type-matched) scalar while the others cycle - ClassFS2 = 1 << 4, // the first two arguments are held fixed as a (type-matched) scalar while the others cycle - ClassLO = 1 << 5, // the last argument is an output - ClassB = 1 << 6, // return type cycles through only bool/bvec, matching vector width of args - ClassLB = 1 << 7, // last argument cycles through only bool/bvec, matching vector width of args - ClassV1 = 1 << 8, // scalar only - ClassFIO = 1 << 9, // first argument is inout - ClassRS = 1 << 10, // the return is held scalar as the arguments cycle - ClassNS = 1 << 11, // no scalar prototype - ClassCV = 1 << 12, // first argument is 'coherent volatile' - ClassFO = 1 << 13, // first argument is output - ClassV3 = 1 << 14, // vec3 only -}; -// Mixtures of the above, to help the function tables -const ArgClass ClassV1FIOCV = (ArgClass)(ClassV1 | ClassFIO | ClassCV); -const ArgClass ClassBNS = (ArgClass)(ClassB | ClassNS); -const ArgClass ClassRSNS = (ArgClass)(ClassRS | ClassNS); - -// A descriptor, for a single profile, of when something is available. -// If the current profile does not match 'profile' mask below, the other fields -// do not apply (nor validate). -// profiles == EBadProfile is the end of an array of these -struct Versioning { - EProfile profiles; // the profile(s) (mask) that the following fields are valid for - int minExtendedVersion; // earliest version when extensions are enabled; ignored if numExtensions is 0 - int minCoreVersion; // earliest version function is in core; 0 means never - int numExtensions; // how many extensions are in the 'extensions' list - const char** extensions; // list of extension names enabling the function -}; - -EProfile EDesktopProfile = static_cast(ENoProfile | ECoreProfile | ECompatibilityProfile); - -// Declare pointers to put into the table for versioning. - const Versioning Es300Desktop130Version[] = { { EEsProfile, 0, 300, 0, nullptr }, - { EDesktopProfile, 0, 130, 0, nullptr }, - { EBadProfile } }; - const Versioning* Es300Desktop130 = &Es300Desktop130Version[0]; - - const Versioning Es310Desktop400Version[] = { { EEsProfile, 0, 310, 0, nullptr }, - { EDesktopProfile, 0, 400, 0, nullptr }, - { EBadProfile } }; - const Versioning* Es310Desktop400 = &Es310Desktop400Version[0]; - - const Versioning Es310Desktop450Version[] = { { EEsProfile, 0, 310, 0, nullptr }, - { EDesktopProfile, 0, 450, 0, nullptr }, - { EBadProfile } }; - const Versioning* Es310Desktop450 = &Es310Desktop450Version[0]; - -// The main descriptor of what a set of function prototypes can look like, and -// a pointer to extra versioning information, when needed. -struct BuiltInFunction { - TOperator op; // operator to map the name to - const char* name; // function name - int numArguments; // number of arguments (overloads with varying arguments need different entries) - ArgType types; // ArgType mask - ArgClass classes; // the ways this particular function entry manifests - const Versioning* versioning; // nullptr means always a valid version -}; - -// The tables can have the same built-in function name more than one time, -// but the exact same prototype must be indicated at most once. -// The prototypes that get declared are the union of all those indicated. -// This is important when different releases add new prototypes for the same name. -// It also also congnitively simpler tiling of the prototype space. -// In practice, most names can be fully represented with one entry. -// -// Table is terminated by an OpNull TOperator. - -const BuiltInFunction BaseFunctions[] = { -// TOperator, name, arg-count, ArgType, ArgClass, versioning -// --------- ---- --------- ------- -------- ---------- - { EOpRadians, "radians", 1, TypeF, ClassRegular, nullptr }, - { EOpDegrees, "degrees", 1, TypeF, ClassRegular, nullptr }, - { EOpSin, "sin", 1, TypeF, ClassRegular, nullptr }, - { EOpCos, "cos", 1, TypeF, ClassRegular, nullptr }, - { EOpTan, "tan", 1, TypeF, ClassRegular, nullptr }, - { EOpAsin, "asin", 1, TypeF, ClassRegular, nullptr }, - { EOpAcos, "acos", 1, TypeF, ClassRegular, nullptr }, - { EOpAtan, "atan", 2, TypeF, ClassRegular, nullptr }, - { EOpAtan, "atan", 1, TypeF, ClassRegular, nullptr }, - { EOpPow, "pow", 2, TypeF, ClassRegular, nullptr }, - { EOpExp, "exp", 1, TypeF, ClassRegular, nullptr }, - { EOpLog, "log", 1, TypeF, ClassRegular, nullptr }, - { EOpExp2, "exp2", 1, TypeF, ClassRegular, nullptr }, - { EOpLog2, "log2", 1, TypeF, ClassRegular, nullptr }, - { EOpSqrt, "sqrt", 1, TypeF, ClassRegular, nullptr }, - { EOpInverseSqrt, "inversesqrt", 1, TypeF, ClassRegular, nullptr }, - { EOpAbs, "abs", 1, TypeF, ClassRegular, nullptr }, - { EOpSign, "sign", 1, TypeF, ClassRegular, nullptr }, - { EOpFloor, "floor", 1, TypeF, ClassRegular, nullptr }, - { EOpCeil, "ceil", 1, TypeF, ClassRegular, nullptr }, - { EOpFract, "fract", 1, TypeF, ClassRegular, nullptr }, - { EOpMod, "mod", 2, TypeF, ClassLS, nullptr }, - { EOpMin, "min", 2, TypeF, ClassLS, nullptr }, - { EOpMax, "max", 2, TypeF, ClassLS, nullptr }, - { EOpClamp, "clamp", 3, TypeF, ClassLS2, nullptr }, - { EOpMix, "mix", 3, TypeF, ClassLS, nullptr }, - { EOpStep, "step", 2, TypeF, ClassFS, nullptr }, - { EOpSmoothStep, "smoothstep", 3, TypeF, ClassFS2, nullptr }, - { EOpNormalize, "normalize", 1, TypeF, ClassRegular, nullptr }, - { EOpFaceForward, "faceforward", 3, TypeF, ClassRegular, nullptr }, - { EOpReflect, "reflect", 2, TypeF, ClassRegular, nullptr }, - { EOpRefract, "refract", 3, TypeF, ClassXLS, nullptr }, - { EOpLength, "length", 1, TypeF, ClassRS, nullptr }, - { EOpDistance, "distance", 2, TypeF, ClassRS, nullptr }, - { EOpDot, "dot", 2, TypeF, ClassRS, nullptr }, - { EOpCross, "cross", 2, TypeF, ClassV3, nullptr }, - { EOpLessThan, "lessThan", 2, TypeFI, ClassBNS, nullptr }, - { EOpLessThanEqual, "lessThanEqual", 2, TypeFI, ClassBNS, nullptr }, - { EOpGreaterThan, "greaterThan", 2, TypeFI, ClassBNS, nullptr }, - { EOpGreaterThanEqual, "greaterThanEqual", 2, TypeFI, ClassBNS, nullptr }, - { EOpVectorEqual, "equal", 2, TypeFIB, ClassBNS, nullptr }, - { EOpVectorNotEqual, "notEqual", 2, TypeFIB, ClassBNS, nullptr }, - { EOpAny, "any", 1, TypeB, ClassRSNS, nullptr }, - { EOpAll, "all", 1, TypeB, ClassRSNS, nullptr }, - { EOpVectorLogicalNot, "not", 1, TypeB, ClassNS, nullptr }, - { EOpSinh, "sinh", 1, TypeF, ClassRegular, Es300Desktop130 }, - { EOpCosh, "cosh", 1, TypeF, ClassRegular, Es300Desktop130 }, - { EOpTanh, "tanh", 1, TypeF, ClassRegular, Es300Desktop130 }, - { EOpAsinh, "asinh", 1, TypeF, ClassRegular, Es300Desktop130 }, - { EOpAcosh, "acosh", 1, TypeF, ClassRegular, Es300Desktop130 }, - { EOpAtanh, "atanh", 1, TypeF, ClassRegular, Es300Desktop130 }, - { EOpAbs, "abs", 1, TypeI, ClassRegular, Es300Desktop130 }, - { EOpSign, "sign", 1, TypeI, ClassRegular, Es300Desktop130 }, - { EOpTrunc, "trunc", 1, TypeF, ClassRegular, Es300Desktop130 }, - { EOpRound, "round", 1, TypeF, ClassRegular, Es300Desktop130 }, - { EOpRoundEven, "roundEven", 1, TypeF, ClassRegular, Es300Desktop130 }, - { EOpModf, "modf", 2, TypeF, ClassLO, Es300Desktop130 }, - { EOpMin, "min", 2, TypeIU, ClassLS, Es300Desktop130 }, - { EOpMax, "max", 2, TypeIU, ClassLS, Es300Desktop130 }, - { EOpClamp, "clamp", 3, TypeIU, ClassLS2, Es300Desktop130 }, - { EOpMix, "mix", 3, TypeF, ClassLB, Es300Desktop130 }, - { EOpIsInf, "isinf", 1, TypeF, ClassB, Es300Desktop130 }, - { EOpIsNan, "isnan", 1, TypeF, ClassB, Es300Desktop130 }, - { EOpLessThan, "lessThan", 2, TypeU, ClassBNS, Es300Desktop130 }, - { EOpLessThanEqual, "lessThanEqual", 2, TypeU, ClassBNS, Es300Desktop130 }, - { EOpGreaterThan, "greaterThan", 2, TypeU, ClassBNS, Es300Desktop130 }, - { EOpGreaterThanEqual, "greaterThanEqual", 2, TypeU, ClassBNS, Es300Desktop130 }, - { EOpVectorEqual, "equal", 2, TypeU, ClassBNS, Es300Desktop130 }, - { EOpVectorNotEqual, "notEqual", 2, TypeU, ClassBNS, Es300Desktop130 }, - { EOpAtomicAdd, "atomicAdd", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, - { EOpAtomicMin, "atomicMin", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, - { EOpAtomicMax, "atomicMax", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, - { EOpAtomicAnd, "atomicAnd", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, - { EOpAtomicOr, "atomicOr", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, - { EOpAtomicXor, "atomicXor", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, - { EOpAtomicExchange, "atomicExchange", 2, TypeIU, ClassV1FIOCV, Es310Desktop400 }, - { EOpAtomicCompSwap, "atomicCompSwap", 3, TypeIU, ClassV1FIOCV, Es310Desktop400 }, - { EOpMix, "mix", 3, TypeB, ClassRegular, Es310Desktop450 }, - { EOpMix, "mix", 3, TypeIU, ClassLB, Es310Desktop450 }, - - { EOpNull } -}; - -const BuiltInFunction DerivativeFunctions[] = { - { EOpDPdx, "dFdx", 1, TypeF, ClassRegular, nullptr }, - { EOpDPdy, "dFdy", 1, TypeF, ClassRegular, nullptr }, - { EOpFwidth, "fwidth", 1, TypeF, ClassRegular, nullptr }, - { EOpNull } -}; - -// For functions declared some other way, but still use the table to relate to operator. -struct CustomFunction { - TOperator op; // operator to map the name to - const char* name; // function name - const Versioning* versioning; // nullptr means always a valid version -}; - -const CustomFunction CustomFunctions[] = { - { EOpBarrier, "barrier", nullptr }, - { EOpMemoryBarrierShared, "memoryBarrierShared", nullptr }, - { EOpGroupMemoryBarrier, "groupMemoryBarrier", nullptr }, - { EOpMemoryBarrier, "memoryBarrier", nullptr }, - { EOpMemoryBarrierBuffer, "memoryBarrierBuffer", nullptr }, - - { EOpPackSnorm2x16, "packSnorm2x16", nullptr }, - { EOpUnpackSnorm2x16, "unpackSnorm2x16", nullptr }, - { EOpPackUnorm2x16, "packUnorm2x16", nullptr }, - { EOpUnpackUnorm2x16, "unpackUnorm2x16", nullptr }, - { EOpPackHalf2x16, "packHalf2x16", nullptr }, - { EOpUnpackHalf2x16, "unpackHalf2x16", nullptr }, - - { EOpMul, "matrixCompMult", nullptr }, - { EOpOuterProduct, "outerProduct", nullptr }, - { EOpTranspose, "transpose", nullptr }, - { EOpDeterminant, "determinant", nullptr }, - { EOpMatrixInverse, "inverse", nullptr }, - { EOpFloatBitsToInt, "floatBitsToInt", nullptr }, - { EOpFloatBitsToUint, "floatBitsToUint", nullptr }, - { EOpIntBitsToFloat, "intBitsToFloat", nullptr }, - { EOpUintBitsToFloat, "uintBitsToFloat", nullptr }, - - { EOpTextureQuerySize, "textureSize", nullptr }, - { EOpTextureQueryLod, "textureQueryLod", nullptr }, - { EOpTextureQueryLod, "textureQueryLOD", nullptr }, // extension GL_ARB_texture_query_lod - { EOpTextureQueryLevels, "textureQueryLevels", nullptr }, - { EOpTextureQuerySamples, "textureSamples", nullptr }, - { EOpTexture, "texture", nullptr }, - { EOpTextureProj, "textureProj", nullptr }, - { EOpTextureLod, "textureLod", nullptr }, - { EOpTextureOffset, "textureOffset", nullptr }, - { EOpTextureFetch, "texelFetch", nullptr }, - { EOpTextureFetchOffset, "texelFetchOffset", nullptr }, - { EOpTextureProjOffset, "textureProjOffset", nullptr }, - { EOpTextureLodOffset, "textureLodOffset", nullptr }, - { EOpTextureProjLod, "textureProjLod", nullptr }, - { EOpTextureProjLodOffset, "textureProjLodOffset", nullptr }, - { EOpTextureGrad, "textureGrad", nullptr }, - { EOpTextureGradOffset, "textureGradOffset", nullptr }, - { EOpTextureProjGrad, "textureProjGrad", nullptr }, - { EOpTextureProjGradOffset, "textureProjGradOffset", nullptr }, - - { EOpNull } -}; - -// For the given table of functions, add all the indicated prototypes for each -// one, to be returned in the passed in decls. -void AddTabledBuiltin(TString& decls, const BuiltInFunction& function) -{ - const auto isScalarType = [](int type) { return (type & TypeStringColumnMask) == 0; }; - - // loop across these two: - // 0: the varying arg set, and - // 1: the fixed scalar args - const ArgClass ClassFixed = (ArgClass)(ClassLS | ClassXLS | ClassLS2 | ClassFS | ClassFS2); - for (int fixed = 0; fixed < ((function.classes & ClassFixed) > 0 ? 2 : 1); ++fixed) { - - if (fixed == 0 && (function.classes & ClassXLS)) - continue; - - // walk the type strings in TypeString[] - for (int type = 0; type < TypeStringCount; ++type) { - // skip types not selected: go from type to row number to type bit - if ((function.types & (1 << (type >> TypeStringRowShift))) == 0) - continue; - - // if we aren't on a scalar, and should be, skip - if ((function.classes & ClassV1) && !isScalarType(type)) - continue; - - // if we aren't on a 3-vector, and should be, skip - if ((function.classes & ClassV3) && (type & TypeStringColumnMask) != 2) - continue; - - // skip replication of all arg scalars between the varying arg set and the fixed args - if (fixed == 1 && type == (type & TypeStringScalarMask) && (function.classes & ClassXLS) == 0) - continue; - - // skip scalars when we are told to - if ((function.classes & ClassNS) && isScalarType(type)) - continue; - - // return type - if (function.classes & ClassB) - decls.append(TypeString[type & TypeStringColumnMask]); - else if (function.classes & ClassRS) - decls.append(TypeString[type & TypeStringScalarMask]); - else - decls.append(TypeString[type]); - decls.append(" "); - decls.append(function.name); - decls.append("("); - - // arguments - for (int arg = 0; arg < function.numArguments; ++arg) { - if (arg == function.numArguments - 1 && (function.classes & ClassLO)) - decls.append("out "); - if (arg == 0) { - if (function.classes & ClassCV) - decls.append("coherent volatile "); - if (function.classes & ClassFIO) - decls.append("inout "); - if (function.classes & ClassFO) - decls.append("out "); - } - if ((function.classes & ClassLB) && arg == function.numArguments - 1) - decls.append(TypeString[type & TypeStringColumnMask]); - else if (fixed && ((arg == function.numArguments - 1 && (function.classes & (ClassLS | ClassXLS | - ClassLS2))) || - (arg == function.numArguments - 2 && (function.classes & ClassLS2)) || - (arg == 0 && (function.classes & (ClassFS | ClassFS2))) || - (arg == 1 && (function.classes & ClassFS2)))) - decls.append(TypeString[type & TypeStringScalarMask]); - else - decls.append(TypeString[type]); - if (arg < function.numArguments - 1) - decls.append(","); - } - decls.append(");\n"); - } - } -} - -// See if the tabled versioning information allows the current version. -bool ValidVersion(const BuiltInFunction& function, int version, EProfile profile, const SpvVersion& /* spVersion */) -{ - // nullptr means always valid - if (function.versioning == nullptr) - return true; - - // check for what is said about our current profile - for (const Versioning* v = function.versioning; v->profiles != EBadProfile; ++v) { - if ((v->profiles & profile) != 0) { - if (v->minCoreVersion <= version || (v->numExtensions > 0 && v->minExtendedVersion <= version)) - return true; - } - } - - return false; -} - -// Relate a single table of built-ins to their AST operator. -// This can get called redundantly (especially for the common built-ins, when -// called once per stage). This is a performance issue only, not a correctness -// concern. It is done for quality arising from simplicity, as there are subtleties -// to get correct if instead trying to do it surgically. -template -void RelateTabledBuiltins(const FunctionT* functions, TSymbolTable& symbolTable) -{ - while (functions->op != EOpNull) { - symbolTable.relateToOperator(functions->name, functions->op); - ++functions; - } -} - -} // end anonymous namespace - -// Add declarations for all tables of built-in functions. -void TBuiltIns::addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion) -{ - const auto forEachFunction = [&](TString& decls, const BuiltInFunction* function) { - while (function->op != EOpNull) { - if (ValidVersion(*function, version, profile, spvVersion)) - AddTabledBuiltin(decls, *function); - ++function; - } - }; - - forEachFunction(commonBuiltins, BaseFunctions); - forEachFunction(stageBuiltins[EShLangFragment], DerivativeFunctions); - - if ((profile == EEsProfile && version >= 320) || (profile != EEsProfile && version >= 450)) - forEachFunction(stageBuiltins[EShLangCompute], DerivativeFunctions); -} - -// Relate all tables of built-ins to the AST operators. -void TBuiltIns::relateTabledBuiltins(int /* version */, EProfile /* profile */, const SpvVersion& /* spvVersion */, EShLanguage /* stage */, TSymbolTable& symbolTable) -{ - RelateTabledBuiltins(BaseFunctions, symbolTable); - RelateTabledBuiltins(DerivativeFunctions, symbolTable); - RelateTabledBuiltins(CustomFunctions, symbolTable); -} - -inline bool IncludeLegacy(int version, EProfile profile, const SpvVersion& spvVersion) -{ - return profile != EEsProfile && (version <= 130 || (spvVersion.spv == 0 && version == 140 && ARBCompatibility) || - profile == ECompatibilityProfile); -} - -// Construct TBuiltInParseables base class. This can be used for language-common constructs. -TBuiltInParseables::TBuiltInParseables() -{ -} - -// Destroy TBuiltInParseables. -TBuiltInParseables::~TBuiltInParseables() -{ -} - -TBuiltIns::TBuiltIns() -{ - // Set up textual representations for making all the permutations - // of texturing/imaging functions. - prefixes[EbtFloat] = ""; - prefixes[EbtInt] = "i"; - prefixes[EbtUint] = "u"; - prefixes[EbtFloat16] = "f16"; - prefixes[EbtInt8] = "i8"; - prefixes[EbtUint8] = "u8"; - prefixes[EbtInt16] = "i16"; - prefixes[EbtUint16] = "u16"; - prefixes[EbtInt64] = "i64"; - prefixes[EbtUint64] = "u64"; - - postfixes[2] = "2"; - postfixes[3] = "3"; - postfixes[4] = "4"; - - // Map from symbolic class of texturing dimension to numeric dimensions. - dimMap[Esd2D] = 2; - dimMap[Esd3D] = 3; - dimMap[EsdCube] = 3; - dimMap[Esd1D] = 1; - dimMap[EsdRect] = 2; - dimMap[EsdBuffer] = 1; - dimMap[EsdSubpass] = 2; // potentially unused for now - dimMap[EsdAttachmentEXT] = 2; // potentially unused for now -} - -TBuiltIns::~TBuiltIns() -{ -} - - -// -// Add all context-independent built-in functions and variables that are present -// for the given version and profile. Share common ones across stages, otherwise -// make stage-specific entries. -// -// Most built-ins variables can be added as simple text strings. Some need to -// be added programmatically, which is done later in IdentifyBuiltIns() below. -// -void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvVersion) -{ - addTabledBuiltins(version, profile, spvVersion); - - //============================================================================ - // - // Prototypes for built-in functions used repeatly by different shaders - // - //============================================================================ - - // - // Derivatives Functions. - // - TString derivativeControls ( - "float dFdxFine(float p);" - "vec2 dFdxFine(vec2 p);" - "vec3 dFdxFine(vec3 p);" - "vec4 dFdxFine(vec4 p);" - - "float dFdyFine(float p);" - "vec2 dFdyFine(vec2 p);" - "vec3 dFdyFine(vec3 p);" - "vec4 dFdyFine(vec4 p);" - - "float fwidthFine(float p);" - "vec2 fwidthFine(vec2 p);" - "vec3 fwidthFine(vec3 p);" - "vec4 fwidthFine(vec4 p);" - - "float dFdxCoarse(float p);" - "vec2 dFdxCoarse(vec2 p);" - "vec3 dFdxCoarse(vec3 p);" - "vec4 dFdxCoarse(vec4 p);" - - "float dFdyCoarse(float p);" - "vec2 dFdyCoarse(vec2 p);" - "vec3 dFdyCoarse(vec3 p);" - "vec4 dFdyCoarse(vec4 p);" - - "float fwidthCoarse(float p);" - "vec2 fwidthCoarse(vec2 p);" - "vec3 fwidthCoarse(vec3 p);" - "vec4 fwidthCoarse(vec4 p);" - ); - - TString derivativesAndControl16bits ( - "float16_t dFdx(float16_t);" - "f16vec2 dFdx(f16vec2);" - "f16vec3 dFdx(f16vec3);" - "f16vec4 dFdx(f16vec4);" - - "float16_t dFdy(float16_t);" - "f16vec2 dFdy(f16vec2);" - "f16vec3 dFdy(f16vec3);" - "f16vec4 dFdy(f16vec4);" - - "float16_t dFdxFine(float16_t);" - "f16vec2 dFdxFine(f16vec2);" - "f16vec3 dFdxFine(f16vec3);" - "f16vec4 dFdxFine(f16vec4);" - - "float16_t dFdyFine(float16_t);" - "f16vec2 dFdyFine(f16vec2);" - "f16vec3 dFdyFine(f16vec3);" - "f16vec4 dFdyFine(f16vec4);" - - "float16_t dFdxCoarse(float16_t);" - "f16vec2 dFdxCoarse(f16vec2);" - "f16vec3 dFdxCoarse(f16vec3);" - "f16vec4 dFdxCoarse(f16vec4);" - - "float16_t dFdyCoarse(float16_t);" - "f16vec2 dFdyCoarse(f16vec2);" - "f16vec3 dFdyCoarse(f16vec3);" - "f16vec4 dFdyCoarse(f16vec4);" - - "float16_t fwidth(float16_t);" - "f16vec2 fwidth(f16vec2);" - "f16vec3 fwidth(f16vec3);" - "f16vec4 fwidth(f16vec4);" - - "float16_t fwidthFine(float16_t);" - "f16vec2 fwidthFine(f16vec2);" - "f16vec3 fwidthFine(f16vec3);" - "f16vec4 fwidthFine(f16vec4);" - - "float16_t fwidthCoarse(float16_t);" - "f16vec2 fwidthCoarse(f16vec2);" - "f16vec3 fwidthCoarse(f16vec3);" - "f16vec4 fwidthCoarse(f16vec4);" - ); - - TString derivativesAndControl64bits ( - "float64_t dFdx(float64_t);" - "f64vec2 dFdx(f64vec2);" - "f64vec3 dFdx(f64vec3);" - "f64vec4 dFdx(f64vec4);" - - "float64_t dFdy(float64_t);" - "f64vec2 dFdy(f64vec2);" - "f64vec3 dFdy(f64vec3);" - "f64vec4 dFdy(f64vec4);" - - "float64_t dFdxFine(float64_t);" - "f64vec2 dFdxFine(f64vec2);" - "f64vec3 dFdxFine(f64vec3);" - "f64vec4 dFdxFine(f64vec4);" - - "float64_t dFdyFine(float64_t);" - "f64vec2 dFdyFine(f64vec2);" - "f64vec3 dFdyFine(f64vec3);" - "f64vec4 dFdyFine(f64vec4);" - - "float64_t dFdxCoarse(float64_t);" - "f64vec2 dFdxCoarse(f64vec2);" - "f64vec3 dFdxCoarse(f64vec3);" - "f64vec4 dFdxCoarse(f64vec4);" - - "float64_t dFdyCoarse(float64_t);" - "f64vec2 dFdyCoarse(f64vec2);" - "f64vec3 dFdyCoarse(f64vec3);" - "f64vec4 dFdyCoarse(f64vec4);" - - "float64_t fwidth(float64_t);" - "f64vec2 fwidth(f64vec2);" - "f64vec3 fwidth(f64vec3);" - "f64vec4 fwidth(f64vec4);" - - "float64_t fwidthFine(float64_t);" - "f64vec2 fwidthFine(f64vec2);" - "f64vec3 fwidthFine(f64vec3);" - "f64vec4 fwidthFine(f64vec4);" - - "float64_t fwidthCoarse(float64_t);" - "f64vec2 fwidthCoarse(f64vec2);" - "f64vec3 fwidthCoarse(f64vec3);" - "f64vec4 fwidthCoarse(f64vec4);" - ); - - //============================================================================ - // - // Prototypes for built-in functions seen by both vertex and fragment shaders. - // - //============================================================================ - - // - // double functions added to desktop 4.00, but not fma, frexp, ldexp, or pack/unpack - // - if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64 - commonBuiltins.append( - - "double sqrt(double);" - "dvec2 sqrt(dvec2);" - "dvec3 sqrt(dvec3);" - "dvec4 sqrt(dvec4);" - - "double inversesqrt(double);" - "dvec2 inversesqrt(dvec2);" - "dvec3 inversesqrt(dvec3);" - "dvec4 inversesqrt(dvec4);" - - "double abs(double);" - "dvec2 abs(dvec2);" - "dvec3 abs(dvec3);" - "dvec4 abs(dvec4);" - - "double sign(double);" - "dvec2 sign(dvec2);" - "dvec3 sign(dvec3);" - "dvec4 sign(dvec4);" - - "double floor(double);" - "dvec2 floor(dvec2);" - "dvec3 floor(dvec3);" - "dvec4 floor(dvec4);" - - "double trunc(double);" - "dvec2 trunc(dvec2);" - "dvec3 trunc(dvec3);" - "dvec4 trunc(dvec4);" - - "double round(double);" - "dvec2 round(dvec2);" - "dvec3 round(dvec3);" - "dvec4 round(dvec4);" - - "double roundEven(double);" - "dvec2 roundEven(dvec2);" - "dvec3 roundEven(dvec3);" - "dvec4 roundEven(dvec4);" - - "double ceil(double);" - "dvec2 ceil(dvec2);" - "dvec3 ceil(dvec3);" - "dvec4 ceil(dvec4);" - - "double fract(double);" - "dvec2 fract(dvec2);" - "dvec3 fract(dvec3);" - "dvec4 fract(dvec4);" - - "double mod(double, double);" - "dvec2 mod(dvec2 , double);" - "dvec3 mod(dvec3 , double);" - "dvec4 mod(dvec4 , double);" - "dvec2 mod(dvec2 , dvec2);" - "dvec3 mod(dvec3 , dvec3);" - "dvec4 mod(dvec4 , dvec4);" - - "double modf(double, out double);" - "dvec2 modf(dvec2, out dvec2);" - "dvec3 modf(dvec3, out dvec3);" - "dvec4 modf(dvec4, out dvec4);" - - "double min(double, double);" - "dvec2 min(dvec2, double);" - "dvec3 min(dvec3, double);" - "dvec4 min(dvec4, double);" - "dvec2 min(dvec2, dvec2);" - "dvec3 min(dvec3, dvec3);" - "dvec4 min(dvec4, dvec4);" - - "double max(double, double);" - "dvec2 max(dvec2 , double);" - "dvec3 max(dvec3 , double);" - "dvec4 max(dvec4 , double);" - "dvec2 max(dvec2 , dvec2);" - "dvec3 max(dvec3 , dvec3);" - "dvec4 max(dvec4 , dvec4);" - - "double clamp(double, double, double);" - "dvec2 clamp(dvec2 , double, double);" - "dvec3 clamp(dvec3 , double, double);" - "dvec4 clamp(dvec4 , double, double);" - "dvec2 clamp(dvec2 , dvec2 , dvec2);" - "dvec3 clamp(dvec3 , dvec3 , dvec3);" - "dvec4 clamp(dvec4 , dvec4 , dvec4);" - - "double mix(double, double, double);" - "dvec2 mix(dvec2, dvec2, double);" - "dvec3 mix(dvec3, dvec3, double);" - "dvec4 mix(dvec4, dvec4, double);" - "dvec2 mix(dvec2, dvec2, dvec2);" - "dvec3 mix(dvec3, dvec3, dvec3);" - "dvec4 mix(dvec4, dvec4, dvec4);" - "double mix(double, double, bool);" - "dvec2 mix(dvec2, dvec2, bvec2);" - "dvec3 mix(dvec3, dvec3, bvec3);" - "dvec4 mix(dvec4, dvec4, bvec4);" - - "double step(double, double);" - "dvec2 step(dvec2 , dvec2);" - "dvec3 step(dvec3 , dvec3);" - "dvec4 step(dvec4 , dvec4);" - "dvec2 step(double, dvec2);" - "dvec3 step(double, dvec3);" - "dvec4 step(double, dvec4);" - - "double smoothstep(double, double, double);" - "dvec2 smoothstep(dvec2 , dvec2 , dvec2);" - "dvec3 smoothstep(dvec3 , dvec3 , dvec3);" - "dvec4 smoothstep(dvec4 , dvec4 , dvec4);" - "dvec2 smoothstep(double, double, dvec2);" - "dvec3 smoothstep(double, double, dvec3);" - "dvec4 smoothstep(double, double, dvec4);" - - "bool isnan(double);" - "bvec2 isnan(dvec2);" - "bvec3 isnan(dvec3);" - "bvec4 isnan(dvec4);" - - "bool isinf(double);" - "bvec2 isinf(dvec2);" - "bvec3 isinf(dvec3);" - "bvec4 isinf(dvec4);" - - "double length(double);" - "double length(dvec2);" - "double length(dvec3);" - "double length(dvec4);" - - "double distance(double, double);" - "double distance(dvec2 , dvec2);" - "double distance(dvec3 , dvec3);" - "double distance(dvec4 , dvec4);" - - "double dot(double, double);" - "double dot(dvec2 , dvec2);" - "double dot(dvec3 , dvec3);" - "double dot(dvec4 , dvec4);" - - "dvec3 cross(dvec3, dvec3);" - - "double normalize(double);" - "dvec2 normalize(dvec2);" - "dvec3 normalize(dvec3);" - "dvec4 normalize(dvec4);" - - "double faceforward(double, double, double);" - "dvec2 faceforward(dvec2, dvec2, dvec2);" - "dvec3 faceforward(dvec3, dvec3, dvec3);" - "dvec4 faceforward(dvec4, dvec4, dvec4);" - - "double reflect(double, double);" - "dvec2 reflect(dvec2 , dvec2 );" - "dvec3 reflect(dvec3 , dvec3 );" - "dvec4 reflect(dvec4 , dvec4 );" - - "double refract(double, double, double);" - "dvec2 refract(dvec2 , dvec2 , double);" - "dvec3 refract(dvec3 , dvec3 , double);" - "dvec4 refract(dvec4 , dvec4 , double);" - - "dmat2 matrixCompMult(dmat2, dmat2);" - "dmat3 matrixCompMult(dmat3, dmat3);" - "dmat4 matrixCompMult(dmat4, dmat4);" - "dmat2x3 matrixCompMult(dmat2x3, dmat2x3);" - "dmat2x4 matrixCompMult(dmat2x4, dmat2x4);" - "dmat3x2 matrixCompMult(dmat3x2, dmat3x2);" - "dmat3x4 matrixCompMult(dmat3x4, dmat3x4);" - "dmat4x2 matrixCompMult(dmat4x2, dmat4x2);" - "dmat4x3 matrixCompMult(dmat4x3, dmat4x3);" - - "dmat2 outerProduct(dvec2, dvec2);" - "dmat3 outerProduct(dvec3, dvec3);" - "dmat4 outerProduct(dvec4, dvec4);" - "dmat2x3 outerProduct(dvec3, dvec2);" - "dmat3x2 outerProduct(dvec2, dvec3);" - "dmat2x4 outerProduct(dvec4, dvec2);" - "dmat4x2 outerProduct(dvec2, dvec4);" - "dmat3x4 outerProduct(dvec4, dvec3);" - "dmat4x3 outerProduct(dvec3, dvec4);" - - "dmat2 transpose(dmat2);" - "dmat3 transpose(dmat3);" - "dmat4 transpose(dmat4);" - "dmat2x3 transpose(dmat3x2);" - "dmat3x2 transpose(dmat2x3);" - "dmat2x4 transpose(dmat4x2);" - "dmat4x2 transpose(dmat2x4);" - "dmat3x4 transpose(dmat4x3);" - "dmat4x3 transpose(dmat3x4);" - - "double determinant(dmat2);" - "double determinant(dmat3);" - "double determinant(dmat4);" - - "dmat2 inverse(dmat2);" - "dmat3 inverse(dmat3);" - "dmat4 inverse(dmat4);" - - "bvec2 lessThan(dvec2, dvec2);" - "bvec3 lessThan(dvec3, dvec3);" - "bvec4 lessThan(dvec4, dvec4);" - - "bvec2 lessThanEqual(dvec2, dvec2);" - "bvec3 lessThanEqual(dvec3, dvec3);" - "bvec4 lessThanEqual(dvec4, dvec4);" - - "bvec2 greaterThan(dvec2, dvec2);" - "bvec3 greaterThan(dvec3, dvec3);" - "bvec4 greaterThan(dvec4, dvec4);" - - "bvec2 greaterThanEqual(dvec2, dvec2);" - "bvec3 greaterThanEqual(dvec3, dvec3);" - "bvec4 greaterThanEqual(dvec4, dvec4);" - - "bvec2 equal(dvec2, dvec2);" - "bvec3 equal(dvec3, dvec3);" - "bvec4 equal(dvec4, dvec4);" - - "bvec2 notEqual(dvec2, dvec2);" - "bvec3 notEqual(dvec3, dvec3);" - "bvec4 notEqual(dvec4, dvec4);" - - "\n"); - } - - if (profile == EEsProfile && version >= 310) { // Explicit Types - commonBuiltins.append( - - "float64_t sqrt(float64_t);" - "f64vec2 sqrt(f64vec2);" - "f64vec3 sqrt(f64vec3);" - "f64vec4 sqrt(f64vec4);" - - "float64_t inversesqrt(float64_t);" - "f64vec2 inversesqrt(f64vec2);" - "f64vec3 inversesqrt(f64vec3);" - "f64vec4 inversesqrt(f64vec4);" - - "float64_t abs(float64_t);" - "f64vec2 abs(f64vec2);" - "f64vec3 abs(f64vec3);" - "f64vec4 abs(f64vec4);" - - "float64_t sign(float64_t);" - "f64vec2 sign(f64vec2);" - "f64vec3 sign(f64vec3);" - "f64vec4 sign(f64vec4);" - - "float64_t floor(float64_t);" - "f64vec2 floor(f64vec2);" - "f64vec3 floor(f64vec3);" - "f64vec4 floor(f64vec4);" - - "float64_t trunc(float64_t);" - "f64vec2 trunc(f64vec2);" - "f64vec3 trunc(f64vec3);" - "f64vec4 trunc(f64vec4);" - - "float64_t round(float64_t);" - "f64vec2 round(f64vec2);" - "f64vec3 round(f64vec3);" - "f64vec4 round(f64vec4);" - - "float64_t roundEven(float64_t);" - "f64vec2 roundEven(f64vec2);" - "f64vec3 roundEven(f64vec3);" - "f64vec4 roundEven(f64vec4);" - - "float64_t ceil(float64_t);" - "f64vec2 ceil(f64vec2);" - "f64vec3 ceil(f64vec3);" - "f64vec4 ceil(f64vec4);" - - "float64_t fract(float64_t);" - "f64vec2 fract(f64vec2);" - "f64vec3 fract(f64vec3);" - "f64vec4 fract(f64vec4);" - - "float64_t mod(float64_t, float64_t);" - "f64vec2 mod(f64vec2 , float64_t);" - "f64vec3 mod(f64vec3 , float64_t);" - "f64vec4 mod(f64vec4 , float64_t);" - "f64vec2 mod(f64vec2 , f64vec2);" - "f64vec3 mod(f64vec3 , f64vec3);" - "f64vec4 mod(f64vec4 , f64vec4);" - - "float64_t modf(float64_t, out float64_t);" - "f64vec2 modf(f64vec2, out f64vec2);" - "f64vec3 modf(f64vec3, out f64vec3);" - "f64vec4 modf(f64vec4, out f64vec4);" - - "float64_t min(float64_t, float64_t);" - "f64vec2 min(f64vec2, float64_t);" - "f64vec3 min(f64vec3, float64_t);" - "f64vec4 min(f64vec4, float64_t);" - "f64vec2 min(f64vec2, f64vec2);" - "f64vec3 min(f64vec3, f64vec3);" - "f64vec4 min(f64vec4, f64vec4);" - - "float64_t max(float64_t, float64_t);" - "f64vec2 max(f64vec2 , float64_t);" - "f64vec3 max(f64vec3 , float64_t);" - "f64vec4 max(f64vec4 , float64_t);" - "f64vec2 max(f64vec2 , f64vec2);" - "f64vec3 max(f64vec3 , f64vec3);" - "f64vec4 max(f64vec4 , f64vec4);" - - "float64_t clamp(float64_t, float64_t, float64_t);" - "f64vec2 clamp(f64vec2 , float64_t, float64_t);" - "f64vec3 clamp(f64vec3 , float64_t, float64_t);" - "f64vec4 clamp(f64vec4 , float64_t, float64_t);" - "f64vec2 clamp(f64vec2 , f64vec2 , f64vec2);" - "f64vec3 clamp(f64vec3 , f64vec3 , f64vec3);" - "f64vec4 clamp(f64vec4 , f64vec4 , f64vec4);" - - "float64_t mix(float64_t, float64_t, float64_t);" - "f64vec2 mix(f64vec2, f64vec2, float64_t);" - "f64vec3 mix(f64vec3, f64vec3, float64_t);" - "f64vec4 mix(f64vec4, f64vec4, float64_t);" - "f64vec2 mix(f64vec2, f64vec2, f64vec2);" - "f64vec3 mix(f64vec3, f64vec3, f64vec3);" - "f64vec4 mix(f64vec4, f64vec4, f64vec4);" - "float64_t mix(float64_t, float64_t, bool);" - "f64vec2 mix(f64vec2, f64vec2, bvec2);" - "f64vec3 mix(f64vec3, f64vec3, bvec3);" - "f64vec4 mix(f64vec4, f64vec4, bvec4);" - - "float64_t step(float64_t, float64_t);" - "f64vec2 step(f64vec2 , f64vec2);" - "f64vec3 step(f64vec3 , f64vec3);" - "f64vec4 step(f64vec4 , f64vec4);" - "f64vec2 step(float64_t, f64vec2);" - "f64vec3 step(float64_t, f64vec3);" - "f64vec4 step(float64_t, f64vec4);" - - "float64_t smoothstep(float64_t, float64_t, float64_t);" - "f64vec2 smoothstep(f64vec2 , f64vec2 , f64vec2);" - "f64vec3 smoothstep(f64vec3 , f64vec3 , f64vec3);" - "f64vec4 smoothstep(f64vec4 , f64vec4 , f64vec4);" - "f64vec2 smoothstep(float64_t, float64_t, f64vec2);" - "f64vec3 smoothstep(float64_t, float64_t, f64vec3);" - "f64vec4 smoothstep(float64_t, float64_t, f64vec4);" - - "float64_t length(float64_t);" - "float64_t length(f64vec2);" - "float64_t length(f64vec3);" - "float64_t length(f64vec4);" - - "float64_t distance(float64_t, float64_t);" - "float64_t distance(f64vec2 , f64vec2);" - "float64_t distance(f64vec3 , f64vec3);" - "float64_t distance(f64vec4 , f64vec4);" - - "float64_t dot(float64_t, float64_t);" - "float64_t dot(f64vec2 , f64vec2);" - "float64_t dot(f64vec3 , f64vec3);" - "float64_t dot(f64vec4 , f64vec4);" - - "f64vec3 cross(f64vec3, f64vec3);" - - "float64_t normalize(float64_t);" - "f64vec2 normalize(f64vec2);" - "f64vec3 normalize(f64vec3);" - "f64vec4 normalize(f64vec4);" - - "float64_t faceforward(float64_t, float64_t, float64_t);" - "f64vec2 faceforward(f64vec2, f64vec2, f64vec2);" - "f64vec3 faceforward(f64vec3, f64vec3, f64vec3);" - "f64vec4 faceforward(f64vec4, f64vec4, f64vec4);" - - "float64_t reflect(float64_t, float64_t);" - "f64vec2 reflect(f64vec2 , f64vec2 );" - "f64vec3 reflect(f64vec3 , f64vec3 );" - "f64vec4 reflect(f64vec4 , f64vec4 );" - - "float64_t refract(float64_t, float64_t, float64_t);" - "f64vec2 refract(f64vec2 , f64vec2 , float64_t);" - "f64vec3 refract(f64vec3 , f64vec3 , float64_t);" - "f64vec4 refract(f64vec4 , f64vec4 , float64_t);" - - "f64mat2 matrixCompMult(f64mat2, f64mat2);" - "f64mat3 matrixCompMult(f64mat3, f64mat3);" - "f64mat4 matrixCompMult(f64mat4, f64mat4);" - "f64mat2x3 matrixCompMult(f64mat2x3, f64mat2x3);" - "f64mat2x4 matrixCompMult(f64mat2x4, f64mat2x4);" - "f64mat3x2 matrixCompMult(f64mat3x2, f64mat3x2);" - "f64mat3x4 matrixCompMult(f64mat3x4, f64mat3x4);" - "f64mat4x2 matrixCompMult(f64mat4x2, f64mat4x2);" - "f64mat4x3 matrixCompMult(f64mat4x3, f64mat4x3);" - - "f64mat2 outerProduct(f64vec2, f64vec2);" - "f64mat3 outerProduct(f64vec3, f64vec3);" - "f64mat4 outerProduct(f64vec4, f64vec4);" - "f64mat2x3 outerProduct(f64vec3, f64vec2);" - "f64mat3x2 outerProduct(f64vec2, f64vec3);" - "f64mat2x4 outerProduct(f64vec4, f64vec2);" - "f64mat4x2 outerProduct(f64vec2, f64vec4);" - "f64mat3x4 outerProduct(f64vec4, f64vec3);" - "f64mat4x3 outerProduct(f64vec3, f64vec4);" - - "f64mat2 transpose(f64mat2);" - "f64mat3 transpose(f64mat3);" - "f64mat4 transpose(f64mat4);" - "f64mat2x3 transpose(f64mat3x2);" - "f64mat3x2 transpose(f64mat2x3);" - "f64mat2x4 transpose(f64mat4x2);" - "f64mat4x2 transpose(f64mat2x4);" - "f64mat3x4 transpose(f64mat4x3);" - "f64mat4x3 transpose(f64mat3x4);" - - "float64_t determinant(f64mat2);" - "float64_t determinant(f64mat3);" - "float64_t determinant(f64mat4);" - - "f64mat2 inverse(f64mat2);" - "f64mat3 inverse(f64mat3);" - "f64mat4 inverse(f64mat4);" - - "\n"); - } - - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { - commonBuiltins.append( - - "int64_t abs(int64_t);" - "i64vec2 abs(i64vec2);" - "i64vec3 abs(i64vec3);" - "i64vec4 abs(i64vec4);" - - "int64_t sign(int64_t);" - "i64vec2 sign(i64vec2);" - "i64vec3 sign(i64vec3);" - "i64vec4 sign(i64vec4);" - - "int64_t min(int64_t, int64_t);" - "i64vec2 min(i64vec2, int64_t);" - "i64vec3 min(i64vec3, int64_t);" - "i64vec4 min(i64vec4, int64_t);" - "i64vec2 min(i64vec2, i64vec2);" - "i64vec3 min(i64vec3, i64vec3);" - "i64vec4 min(i64vec4, i64vec4);" - "uint64_t min(uint64_t, uint64_t);" - "u64vec2 min(u64vec2, uint64_t);" - "u64vec3 min(u64vec3, uint64_t);" - "u64vec4 min(u64vec4, uint64_t);" - "u64vec2 min(u64vec2, u64vec2);" - "u64vec3 min(u64vec3, u64vec3);" - "u64vec4 min(u64vec4, u64vec4);" - - "int64_t max(int64_t, int64_t);" - "i64vec2 max(i64vec2, int64_t);" - "i64vec3 max(i64vec3, int64_t);" - "i64vec4 max(i64vec4, int64_t);" - "i64vec2 max(i64vec2, i64vec2);" - "i64vec3 max(i64vec3, i64vec3);" - "i64vec4 max(i64vec4, i64vec4);" - "uint64_t max(uint64_t, uint64_t);" - "u64vec2 max(u64vec2, uint64_t);" - "u64vec3 max(u64vec3, uint64_t);" - "u64vec4 max(u64vec4, uint64_t);" - "u64vec2 max(u64vec2, u64vec2);" - "u64vec3 max(u64vec3, u64vec3);" - "u64vec4 max(u64vec4, u64vec4);" - - "int64_t clamp(int64_t, int64_t, int64_t);" - "i64vec2 clamp(i64vec2, int64_t, int64_t);" - "i64vec3 clamp(i64vec3, int64_t, int64_t);" - "i64vec4 clamp(i64vec4, int64_t, int64_t);" - "i64vec2 clamp(i64vec2, i64vec2, i64vec2);" - "i64vec3 clamp(i64vec3, i64vec3, i64vec3);" - "i64vec4 clamp(i64vec4, i64vec4, i64vec4);" - "uint64_t clamp(uint64_t, uint64_t, uint64_t);" - "u64vec2 clamp(u64vec2, uint64_t, uint64_t);" - "u64vec3 clamp(u64vec3, uint64_t, uint64_t);" - "u64vec4 clamp(u64vec4, uint64_t, uint64_t);" - "u64vec2 clamp(u64vec2, u64vec2, u64vec2);" - "u64vec3 clamp(u64vec3, u64vec3, u64vec3);" - "u64vec4 clamp(u64vec4, u64vec4, u64vec4);" - - "int64_t mix(int64_t, int64_t, bool);" - "i64vec2 mix(i64vec2, i64vec2, bvec2);" - "i64vec3 mix(i64vec3, i64vec3, bvec3);" - "i64vec4 mix(i64vec4, i64vec4, bvec4);" - "uint64_t mix(uint64_t, uint64_t, bool);" - "u64vec2 mix(u64vec2, u64vec2, bvec2);" - "u64vec3 mix(u64vec3, u64vec3, bvec3);" - "u64vec4 mix(u64vec4, u64vec4, bvec4);" - - "int64_t doubleBitsToInt64(float64_t);" - "i64vec2 doubleBitsToInt64(f64vec2);" - "i64vec3 doubleBitsToInt64(f64vec3);" - "i64vec4 doubleBitsToInt64(f64vec4);" - - "uint64_t doubleBitsToUint64(float64_t);" - "u64vec2 doubleBitsToUint64(f64vec2);" - "u64vec3 doubleBitsToUint64(f64vec3);" - "u64vec4 doubleBitsToUint64(f64vec4);" - - "float64_t int64BitsToDouble(int64_t);" - "f64vec2 int64BitsToDouble(i64vec2);" - "f64vec3 int64BitsToDouble(i64vec3);" - "f64vec4 int64BitsToDouble(i64vec4);" - - "float64_t uint64BitsToDouble(uint64_t);" - "f64vec2 uint64BitsToDouble(u64vec2);" - "f64vec3 uint64BitsToDouble(u64vec3);" - "f64vec4 uint64BitsToDouble(u64vec4);" - - "int64_t packInt2x32(ivec2);" - "uint64_t packUint2x32(uvec2);" - "ivec2 unpackInt2x32(int64_t);" - "uvec2 unpackUint2x32(uint64_t);" - - "bvec2 lessThan(i64vec2, i64vec2);" - "bvec3 lessThan(i64vec3, i64vec3);" - "bvec4 lessThan(i64vec4, i64vec4);" - "bvec2 lessThan(u64vec2, u64vec2);" - "bvec3 lessThan(u64vec3, u64vec3);" - "bvec4 lessThan(u64vec4, u64vec4);" - - "bvec2 lessThanEqual(i64vec2, i64vec2);" - "bvec3 lessThanEqual(i64vec3, i64vec3);" - "bvec4 lessThanEqual(i64vec4, i64vec4);" - "bvec2 lessThanEqual(u64vec2, u64vec2);" - "bvec3 lessThanEqual(u64vec3, u64vec3);" - "bvec4 lessThanEqual(u64vec4, u64vec4);" - - "bvec2 greaterThan(i64vec2, i64vec2);" - "bvec3 greaterThan(i64vec3, i64vec3);" - "bvec4 greaterThan(i64vec4, i64vec4);" - "bvec2 greaterThan(u64vec2, u64vec2);" - "bvec3 greaterThan(u64vec3, u64vec3);" - "bvec4 greaterThan(u64vec4, u64vec4);" - - "bvec2 greaterThanEqual(i64vec2, i64vec2);" - "bvec3 greaterThanEqual(i64vec3, i64vec3);" - "bvec4 greaterThanEqual(i64vec4, i64vec4);" - "bvec2 greaterThanEqual(u64vec2, u64vec2);" - "bvec3 greaterThanEqual(u64vec3, u64vec3);" - "bvec4 greaterThanEqual(u64vec4, u64vec4);" - - "bvec2 equal(i64vec2, i64vec2);" - "bvec3 equal(i64vec3, i64vec3);" - "bvec4 equal(i64vec4, i64vec4);" - "bvec2 equal(u64vec2, u64vec2);" - "bvec3 equal(u64vec3, u64vec3);" - "bvec4 equal(u64vec4, u64vec4);" - - "bvec2 notEqual(i64vec2, i64vec2);" - "bvec3 notEqual(i64vec3, i64vec3);" - "bvec4 notEqual(i64vec4, i64vec4);" - "bvec2 notEqual(u64vec2, u64vec2);" - "bvec3 notEqual(u64vec3, u64vec3);" - "bvec4 notEqual(u64vec4, u64vec4);" - - "int64_t bitCount(int64_t);" - "i64vec2 bitCount(i64vec2);" - "i64vec3 bitCount(i64vec3);" - "i64vec4 bitCount(i64vec4);" - - "int64_t bitCount(uint64_t);" - "i64vec2 bitCount(u64vec2);" - "i64vec3 bitCount(u64vec3);" - "i64vec4 bitCount(u64vec4);" - - "int64_t findLSB(int64_t);" - "i64vec2 findLSB(i64vec2);" - "i64vec3 findLSB(i64vec3);" - "i64vec4 findLSB(i64vec4);" - - "int64_t findLSB(uint64_t);" - "i64vec2 findLSB(u64vec2);" - "i64vec3 findLSB(u64vec3);" - "i64vec4 findLSB(u64vec4);" - - "int64_t findMSB(int64_t);" - "i64vec2 findMSB(i64vec2);" - "i64vec3 findMSB(i64vec3);" - "i64vec4 findMSB(i64vec4);" - - "int64_t findMSB(uint64_t);" - "i64vec2 findMSB(u64vec2);" - "i64vec3 findMSB(u64vec3);" - "i64vec4 findMSB(u64vec4);" - - "\n" - ); - } - - // GL_AMD_shader_trinary_minmax - if (profile != EEsProfile && version >= 430) { - commonBuiltins.append( - "float min3(float, float, float);" - "vec2 min3(vec2, vec2, vec2);" - "vec3 min3(vec3, vec3, vec3);" - "vec4 min3(vec4, vec4, vec4);" - - "int min3(int, int, int);" - "ivec2 min3(ivec2, ivec2, ivec2);" - "ivec3 min3(ivec3, ivec3, ivec3);" - "ivec4 min3(ivec4, ivec4, ivec4);" - - "uint min3(uint, uint, uint);" - "uvec2 min3(uvec2, uvec2, uvec2);" - "uvec3 min3(uvec3, uvec3, uvec3);" - "uvec4 min3(uvec4, uvec4, uvec4);" - - "float max3(float, float, float);" - "vec2 max3(vec2, vec2, vec2);" - "vec3 max3(vec3, vec3, vec3);" - "vec4 max3(vec4, vec4, vec4);" - - "int max3(int, int, int);" - "ivec2 max3(ivec2, ivec2, ivec2);" - "ivec3 max3(ivec3, ivec3, ivec3);" - "ivec4 max3(ivec4, ivec4, ivec4);" - - "uint max3(uint, uint, uint);" - "uvec2 max3(uvec2, uvec2, uvec2);" - "uvec3 max3(uvec3, uvec3, uvec3);" - "uvec4 max3(uvec4, uvec4, uvec4);" - - "float mid3(float, float, float);" - "vec2 mid3(vec2, vec2, vec2);" - "vec3 mid3(vec3, vec3, vec3);" - "vec4 mid3(vec4, vec4, vec4);" - - "int mid3(int, int, int);" - "ivec2 mid3(ivec2, ivec2, ivec2);" - "ivec3 mid3(ivec3, ivec3, ivec3);" - "ivec4 mid3(ivec4, ivec4, ivec4);" - - "uint mid3(uint, uint, uint);" - "uvec2 mid3(uvec2, uvec2, uvec2);" - "uvec3 mid3(uvec3, uvec3, uvec3);" - "uvec4 mid3(uvec4, uvec4, uvec4);" - - "float16_t min3(float16_t, float16_t, float16_t);" - "f16vec2 min3(f16vec2, f16vec2, f16vec2);" - "f16vec3 min3(f16vec3, f16vec3, f16vec3);" - "f16vec4 min3(f16vec4, f16vec4, f16vec4);" - - "float16_t max3(float16_t, float16_t, float16_t);" - "f16vec2 max3(f16vec2, f16vec2, f16vec2);" - "f16vec3 max3(f16vec3, f16vec3, f16vec3);" - "f16vec4 max3(f16vec4, f16vec4, f16vec4);" - - "float16_t mid3(float16_t, float16_t, float16_t);" - "f16vec2 mid3(f16vec2, f16vec2, f16vec2);" - "f16vec3 mid3(f16vec3, f16vec3, f16vec3);" - "f16vec4 mid3(f16vec4, f16vec4, f16vec4);" - - "int16_t min3(int16_t, int16_t, int16_t);" - "i16vec2 min3(i16vec2, i16vec2, i16vec2);" - "i16vec3 min3(i16vec3, i16vec3, i16vec3);" - "i16vec4 min3(i16vec4, i16vec4, i16vec4);" - - "int16_t max3(int16_t, int16_t, int16_t);" - "i16vec2 max3(i16vec2, i16vec2, i16vec2);" - "i16vec3 max3(i16vec3, i16vec3, i16vec3);" - "i16vec4 max3(i16vec4, i16vec4, i16vec4);" - - "int16_t mid3(int16_t, int16_t, int16_t);" - "i16vec2 mid3(i16vec2, i16vec2, i16vec2);" - "i16vec3 mid3(i16vec3, i16vec3, i16vec3);" - "i16vec4 mid3(i16vec4, i16vec4, i16vec4);" - - "uint16_t min3(uint16_t, uint16_t, uint16_t);" - "u16vec2 min3(u16vec2, u16vec2, u16vec2);" - "u16vec3 min3(u16vec3, u16vec3, u16vec3);" - "u16vec4 min3(u16vec4, u16vec4, u16vec4);" - - "uint16_t max3(uint16_t, uint16_t, uint16_t);" - "u16vec2 max3(u16vec2, u16vec2, u16vec2);" - "u16vec3 max3(u16vec3, u16vec3, u16vec3);" - "u16vec4 max3(u16vec4, u16vec4, u16vec4);" - - "uint16_t mid3(uint16_t, uint16_t, uint16_t);" - "u16vec2 mid3(u16vec2, u16vec2, u16vec2);" - "u16vec3 mid3(u16vec3, u16vec3, u16vec3);" - "u16vec4 mid3(u16vec4, u16vec4, u16vec4);" - - "\n" - ); - } - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 430)) { - commonBuiltins.append( - "uint atomicAdd(coherent volatile inout uint, uint, int, int, int);" - " int atomicAdd(coherent volatile inout int, int, int, int, int);" - - "uint atomicMin(coherent volatile inout uint, uint, int, int, int);" - " int atomicMin(coherent volatile inout int, int, int, int, int);" - - "uint atomicMax(coherent volatile inout uint, uint, int, int, int);" - " int atomicMax(coherent volatile inout int, int, int, int, int);" - - "uint atomicAnd(coherent volatile inout uint, uint, int, int, int);" - " int atomicAnd(coherent volatile inout int, int, int, int, int);" - - "uint atomicOr (coherent volatile inout uint, uint, int, int, int);" - " int atomicOr (coherent volatile inout int, int, int, int, int);" - - "uint atomicXor(coherent volatile inout uint, uint, int, int, int);" - " int atomicXor(coherent volatile inout int, int, int, int, int);" - - "uint atomicExchange(coherent volatile inout uint, uint, int, int, int);" - " int atomicExchange(coherent volatile inout int, int, int, int, int);" - - "uint atomicCompSwap(coherent volatile inout uint, uint, uint, int, int, int, int, int);" - " int atomicCompSwap(coherent volatile inout int, int, int, int, int, int, int, int);" - - "uint atomicLoad(coherent volatile in uint, int, int, int);" - " int atomicLoad(coherent volatile in int, int, int, int);" - - "void atomicStore(coherent volatile out uint, uint, int, int, int);" - "void atomicStore(coherent volatile out int, int, int, int, int);" - - "\n"); - } - - if (profile != EEsProfile && version >= 440) { - commonBuiltins.append( - "uint64_t atomicMin(coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicMin(coherent volatile inout int64_t, int64_t);" - "uint64_t atomicMin(coherent volatile inout uint64_t, uint64_t, int, int, int);" - " int64_t atomicMin(coherent volatile inout int64_t, int64_t, int, int, int);" - "float16_t atomicMin(coherent volatile inout float16_t, float16_t);" - "float16_t atomicMin(coherent volatile inout float16_t, float16_t, int, int, int);" - " float atomicMin(coherent volatile inout float, float);" - " float atomicMin(coherent volatile inout float, float, int, int, int);" - " double atomicMin(coherent volatile inout double, double);" - " double atomicMin(coherent volatile inout double, double, int, int, int);" - - "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicMax(coherent volatile inout int64_t, int64_t);" - "uint64_t atomicMax(coherent volatile inout uint64_t, uint64_t, int, int, int);" - " int64_t atomicMax(coherent volatile inout int64_t, int64_t, int, int, int);" - "float16_t atomicMax(coherent volatile inout float16_t, float16_t);" - "float16_t atomicMax(coherent volatile inout float16_t, float16_t, int, int, int);" - " float atomicMax(coherent volatile inout float, float);" - " float atomicMax(coherent volatile inout float, float, int, int, int);" - " double atomicMax(coherent volatile inout double, double);" - " double atomicMax(coherent volatile inout double, double, int, int, int);" - - "uint64_t atomicAnd(coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicAnd(coherent volatile inout int64_t, int64_t);" - "uint64_t atomicAnd(coherent volatile inout uint64_t, uint64_t, int, int, int);" - " int64_t atomicAnd(coherent volatile inout int64_t, int64_t, int, int, int);" - - "uint64_t atomicOr (coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicOr (coherent volatile inout int64_t, int64_t);" - "uint64_t atomicOr (coherent volatile inout uint64_t, uint64_t, int, int, int);" - " int64_t atomicOr (coherent volatile inout int64_t, int64_t, int, int, int);" - - "uint64_t atomicXor(coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicXor(coherent volatile inout int64_t, int64_t);" - "uint64_t atomicXor(coherent volatile inout uint64_t, uint64_t, int, int, int);" - " int64_t atomicXor(coherent volatile inout int64_t, int64_t, int, int, int);" - - "uint64_t atomicAdd(coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicAdd(coherent volatile inout int64_t, int64_t);" - "uint64_t atomicAdd(coherent volatile inout uint64_t, uint64_t, int, int, int);" - " int64_t atomicAdd(coherent volatile inout int64_t, int64_t, int, int, int);" - "float16_t atomicAdd(coherent volatile inout float16_t, float16_t);" - "float16_t atomicAdd(coherent volatile inout float16_t, float16_t, int, int, int);" - " float atomicAdd(coherent volatile inout float, float);" - " float atomicAdd(coherent volatile inout float, float, int, int, int);" - " double atomicAdd(coherent volatile inout double, double);" - " double atomicAdd(coherent volatile inout double, double, int, int, int);" - - "uint64_t atomicExchange(coherent volatile inout uint64_t, uint64_t);" - " int64_t atomicExchange(coherent volatile inout int64_t, int64_t);" - "uint64_t atomicExchange(coherent volatile inout uint64_t, uint64_t, int, int, int);" - " int64_t atomicExchange(coherent volatile inout int64_t, int64_t, int, int, int);" - "float16_t atomicExchange(coherent volatile inout float16_t, float16_t);" - "float16_t atomicExchange(coherent volatile inout float16_t, float16_t, int, int, int);" - " float atomicExchange(coherent volatile inout float, float);" - " float atomicExchange(coherent volatile inout float, float, int, int, int);" - " double atomicExchange(coherent volatile inout double, double);" - " double atomicExchange(coherent volatile inout double, double, int, int, int);" - - "uint64_t atomicCompSwap(coherent volatile inout uint64_t, uint64_t, uint64_t);" - " int64_t atomicCompSwap(coherent volatile inout int64_t, int64_t, int64_t);" - "uint64_t atomicCompSwap(coherent volatile inout uint64_t, uint64_t, uint64_t, int, int, int, int, int);" - " int64_t atomicCompSwap(coherent volatile inout int64_t, int64_t, int64_t, int, int, int, int, int);" - - "uint64_t atomicLoad(coherent volatile in uint64_t, int, int, int);" - " int64_t atomicLoad(coherent volatile in int64_t, int, int, int);" - "float16_t atomicLoad(coherent volatile in float16_t, int, int, int);" - " float atomicLoad(coherent volatile in float, int, int, int);" - " double atomicLoad(coherent volatile in double, int, int, int);" - - "void atomicStore(coherent volatile out uint64_t, uint64_t, int, int, int);" - "void atomicStore(coherent volatile out int64_t, int64_t, int, int, int);" - "void atomicStore(coherent volatile out float16_t, float16_t, int, int, int);" - "void atomicStore(coherent volatile out float, float, int, int, int);" - "void atomicStore(coherent volatile out double, double, int, int, int);" - "\n"); - } - - if ((profile == EEsProfile && version >= 300) || - (profile != EEsProfile && version >= 150)) { // GL_ARB_shader_bit_encoding - commonBuiltins.append( - "int floatBitsToInt(highp float value);" - "ivec2 floatBitsToInt(highp vec2 value);" - "ivec3 floatBitsToInt(highp vec3 value);" - "ivec4 floatBitsToInt(highp vec4 value);" - - "uint floatBitsToUint(highp float value);" - "uvec2 floatBitsToUint(highp vec2 value);" - "uvec3 floatBitsToUint(highp vec3 value);" - "uvec4 floatBitsToUint(highp vec4 value);" - - "float intBitsToFloat(highp int value);" - "vec2 intBitsToFloat(highp ivec2 value);" - "vec3 intBitsToFloat(highp ivec3 value);" - "vec4 intBitsToFloat(highp ivec4 value);" - - "float uintBitsToFloat(highp uint value);" - "vec2 uintBitsToFloat(highp uvec2 value);" - "vec3 uintBitsToFloat(highp uvec3 value);" - "vec4 uintBitsToFloat(highp uvec4 value);" - - "\n"); - } - - if ((profile != EEsProfile && version >= 400) || - (profile == EEsProfile && version >= 310)) { // GL_OES_gpu_shader5 - - commonBuiltins.append( - "float fma(float, float, float );" - "vec2 fma(vec2, vec2, vec2 );" - "vec3 fma(vec3, vec3, vec3 );" - "vec4 fma(vec4, vec4, vec4 );" - "\n"); - } - - if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64 - commonBuiltins.append( - "double fma(double, double, double);" - "dvec2 fma(dvec2, dvec2, dvec2 );" - "dvec3 fma(dvec3, dvec3, dvec3 );" - "dvec4 fma(dvec4, dvec4, dvec4 );" - "\n"); - } - - if (profile == EEsProfile && version >= 310) { // ARB_gpu_shader_fp64 - commonBuiltins.append( - "float64_t fma(float64_t, float64_t, float64_t);" - "f64vec2 fma(f64vec2, f64vec2, f64vec2 );" - "f64vec3 fma(f64vec3, f64vec3, f64vec3 );" - "f64vec4 fma(f64vec4, f64vec4, f64vec4 );" - "\n"); - } - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 400)) { - commonBuiltins.append( - "float frexp(highp float, out highp int);" - "vec2 frexp(highp vec2, out highp ivec2);" - "vec3 frexp(highp vec3, out highp ivec3);" - "vec4 frexp(highp vec4, out highp ivec4);" - - "float ldexp(highp float, highp int);" - "vec2 ldexp(highp vec2, highp ivec2);" - "vec3 ldexp(highp vec3, highp ivec3);" - "vec4 ldexp(highp vec4, highp ivec4);" - - "\n"); - } - - if (profile != EEsProfile && version >= 150) { // ARB_gpu_shader_fp64 - commonBuiltins.append( - "double frexp(double, out int);" - "dvec2 frexp( dvec2, out ivec2);" - "dvec3 frexp( dvec3, out ivec3);" - "dvec4 frexp( dvec4, out ivec4);" - - "double ldexp(double, int);" - "dvec2 ldexp( dvec2, ivec2);" - "dvec3 ldexp( dvec3, ivec3);" - "dvec4 ldexp( dvec4, ivec4);" - - "double packDouble2x32(uvec2);" - "uvec2 unpackDouble2x32(double);" - - "\n"); - } - - if (profile == EEsProfile && version >= 310) { // ARB_gpu_shader_fp64 - commonBuiltins.append( - "float64_t frexp(float64_t, out int);" - "f64vec2 frexp( f64vec2, out ivec2);" - "f64vec3 frexp( f64vec3, out ivec3);" - "f64vec4 frexp( f64vec4, out ivec4);" - - "float64_t ldexp(float64_t, int);" - "f64vec2 ldexp( f64vec2, ivec2);" - "f64vec3 ldexp( f64vec3, ivec3);" - "f64vec4 ldexp( f64vec4, ivec4);" - - "\n"); - } - - if ((profile == EEsProfile && version >= 300) || - (profile != EEsProfile && version >= 150)) { - commonBuiltins.append( - "highp uint packUnorm2x16(vec2);" - "vec2 unpackUnorm2x16(highp uint);" - "\n"); - } - - if ((profile == EEsProfile && version >= 300) || - (profile != EEsProfile && version >= 150)) { - commonBuiltins.append( - "highp uint packSnorm2x16(vec2);" - " vec2 unpackSnorm2x16(highp uint);" - "highp uint packHalf2x16(vec2);" - "\n"); - } - - if (profile == EEsProfile && version >= 300) { - commonBuiltins.append( - "mediump vec2 unpackHalf2x16(highp uint);" - "\n"); - } else if (profile != EEsProfile && version >= 150) { - commonBuiltins.append( - " vec2 unpackHalf2x16(highp uint);" - "\n"); - } - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 150)) { - commonBuiltins.append( - "highp uint packSnorm4x8(vec4);" - "highp uint packUnorm4x8(vec4);" - "\n"); - } - - if (profile == EEsProfile && version >= 310) { - commonBuiltins.append( - "mediump vec4 unpackSnorm4x8(highp uint);" - "mediump vec4 unpackUnorm4x8(highp uint);" - "\n"); - } else if (profile != EEsProfile && version >= 150) { - commonBuiltins.append( - "vec4 unpackSnorm4x8(highp uint);" - "vec4 unpackUnorm4x8(highp uint);" - "\n"); - } - - // - // Matrix Functions. - // - commonBuiltins.append( - "mat2 matrixCompMult(mat2 x, mat2 y);" - "mat3 matrixCompMult(mat3 x, mat3 y);" - "mat4 matrixCompMult(mat4 x, mat4 y);" - - "\n"); - - // 120 is correct for both ES and desktop - if (version >= 120) { - commonBuiltins.append( - "mat2 outerProduct(vec2 c, vec2 r);" - "mat3 outerProduct(vec3 c, vec3 r);" - "mat4 outerProduct(vec4 c, vec4 r);" - "mat2x3 outerProduct(vec3 c, vec2 r);" - "mat3x2 outerProduct(vec2 c, vec3 r);" - "mat2x4 outerProduct(vec4 c, vec2 r);" - "mat4x2 outerProduct(vec2 c, vec4 r);" - "mat3x4 outerProduct(vec4 c, vec3 r);" - "mat4x3 outerProduct(vec3 c, vec4 r);" - - "mat2 transpose(mat2 m);" - "mat3 transpose(mat3 m);" - "mat4 transpose(mat4 m);" - "mat2x3 transpose(mat3x2 m);" - "mat3x2 transpose(mat2x3 m);" - "mat2x4 transpose(mat4x2 m);" - "mat4x2 transpose(mat2x4 m);" - "mat3x4 transpose(mat4x3 m);" - "mat4x3 transpose(mat3x4 m);" - - "mat2x3 matrixCompMult(mat2x3, mat2x3);" - "mat2x4 matrixCompMult(mat2x4, mat2x4);" - "mat3x2 matrixCompMult(mat3x2, mat3x2);" - "mat3x4 matrixCompMult(mat3x4, mat3x4);" - "mat4x2 matrixCompMult(mat4x2, mat4x2);" - "mat4x3 matrixCompMult(mat4x3, mat4x3);" - - "\n"); - - // 150 is correct for both ES and desktop - if (version >= 150) { - commonBuiltins.append( - "float determinant(mat2 m);" - "float determinant(mat3 m);" - "float determinant(mat4 m);" - - "mat2 inverse(mat2 m);" - "mat3 inverse(mat3 m);" - "mat4 inverse(mat4 m);" - - "\n"); - } - } - - // - // Original-style texture functions existing in all stages. - // (Per-stage functions below.) - // - if ((profile == EEsProfile && version == 100) || - profile == ECompatibilityProfile || - (profile == ECoreProfile && version < 420) || - profile == ENoProfile) { - if (spvVersion.spv == 0) { - commonBuiltins.append( - "vec4 texture2D(sampler2D, vec2);" - - "vec4 texture2DProj(sampler2D, vec3);" - "vec4 texture2DProj(sampler2D, vec4);" - - "vec4 texture3D(sampler3D, vec3);" // OES_texture_3D, but caught by keyword check - "vec4 texture3DProj(sampler3D, vec4);" // OES_texture_3D, but caught by keyword check - - "vec4 textureCube(samplerCube, vec3);" - - "\n"); - } - } - - if ( profile == ECompatibilityProfile || - (profile == ECoreProfile && version < 420) || - profile == ENoProfile) { - if (spvVersion.spv == 0) { - commonBuiltins.append( - "vec4 texture1D(sampler1D, float);" - - "vec4 texture1DProj(sampler1D, vec2);" - "vec4 texture1DProj(sampler1D, vec4);" - - "vec4 shadow1D(sampler1DShadow, vec3);" - "vec4 shadow2D(sampler2DShadow, vec3);" - "vec4 shadow1DProj(sampler1DShadow, vec4);" - "vec4 shadow2DProj(sampler2DShadow, vec4);" - - "vec4 texture2DRect(sampler2DRect, vec2);" // GL_ARB_texture_rectangle, caught by keyword check - "vec4 texture2DRectProj(sampler2DRect, vec3);" // GL_ARB_texture_rectangle, caught by keyword check - "vec4 texture2DRectProj(sampler2DRect, vec4);" // GL_ARB_texture_rectangle, caught by keyword check - "vec4 shadow2DRect(sampler2DRectShadow, vec3);" // GL_ARB_texture_rectangle, caught by keyword check - "vec4 shadow2DRectProj(sampler2DRectShadow, vec4);" // GL_ARB_texture_rectangle, caught by keyword check - - "vec4 texture1DArray(sampler1DArray, vec2);" // GL_EXT_texture_array - "vec4 texture2DArray(sampler2DArray, vec3);" // GL_EXT_texture_array - "vec4 shadow1DArray(sampler1DArrayShadow, vec3);" // GL_EXT_texture_array - "vec4 shadow2DArray(sampler2DArrayShadow, vec4);" // GL_EXT_texture_array - "vec4 texture1DArray(sampler1DArray, vec2, float);" // GL_EXT_texture_array - "vec4 texture2DArray(sampler2DArray, vec3, float);" // GL_EXT_texture_array - "vec4 shadow1DArray(sampler1DArrayShadow, vec3, float);" // GL_EXT_texture_array - "vec4 texture1DArrayLod(sampler1DArray, vec2, float);" // GL_EXT_texture_array - "vec4 texture2DArrayLod(sampler2DArray, vec3, float);" // GL_EXT_texture_array - "vec4 shadow1DArrayLod(sampler1DArrayShadow, vec3, float);" // GL_EXT_texture_array - "\n"); - } - } - - if (profile == EEsProfile) { - if (spvVersion.spv == 0) { - if (version < 300) { - commonBuiltins.append( - "vec4 texture2D(samplerExternalOES, vec2 coord);" // GL_OES_EGL_image_external - "vec4 texture2DProj(samplerExternalOES, vec3);" // GL_OES_EGL_image_external - "vec4 texture2DProj(samplerExternalOES, vec4);" // GL_OES_EGL_image_external - "\n"); - } else { - commonBuiltins.append( - "highp ivec2 textureSize(samplerExternalOES, int lod);" // GL_OES_EGL_image_external_essl3 - "vec4 texture(samplerExternalOES, vec2);" // GL_OES_EGL_image_external_essl3 - "vec4 texture(samplerExternalOES, vec2, float bias);" // GL_OES_EGL_image_external_essl3 - "vec4 textureProj(samplerExternalOES, vec3);" // GL_OES_EGL_image_external_essl3 - "vec4 textureProj(samplerExternalOES, vec3, float bias);" // GL_OES_EGL_image_external_essl3 - "vec4 textureProj(samplerExternalOES, vec4);" // GL_OES_EGL_image_external_essl3 - "vec4 textureProj(samplerExternalOES, vec4, float bias);" // GL_OES_EGL_image_external_essl3 - "vec4 texelFetch(samplerExternalOES, ivec2, int lod);" // GL_OES_EGL_image_external_essl3 - "\n"); - } - commonBuiltins.append( - "highp ivec2 textureSize(__samplerExternal2DY2YEXT, int lod);" // GL_EXT_YUV_target - "vec4 texture(__samplerExternal2DY2YEXT, vec2);" // GL_EXT_YUV_target - "vec4 texture(__samplerExternal2DY2YEXT, vec2, float bias);" // GL_EXT_YUV_target - "vec4 textureProj(__samplerExternal2DY2YEXT, vec3);" // GL_EXT_YUV_target - "vec4 textureProj(__samplerExternal2DY2YEXT, vec3, float bias);" // GL_EXT_YUV_target - "vec4 textureProj(__samplerExternal2DY2YEXT, vec4);" // GL_EXT_YUV_target - "vec4 textureProj(__samplerExternal2DY2YEXT, vec4, float bias);" // GL_EXT_YUV_target - "vec4 texelFetch(__samplerExternal2DY2YEXT sampler, ivec2, int lod);" // GL_EXT_YUV_target - "\n"); - commonBuiltins.append( - "vec4 texture2DGradEXT(sampler2D, vec2, vec2, vec2);" // GL_EXT_shader_texture_lod - "vec4 texture2DProjGradEXT(sampler2D, vec3, vec2, vec2);" // GL_EXT_shader_texture_lod - "vec4 texture2DProjGradEXT(sampler2D, vec4, vec2, vec2);" // GL_EXT_shader_texture_lod - "vec4 textureCubeGradEXT(samplerCube, vec3, vec3, vec3);" // GL_EXT_shader_texture_lod - - "float shadow2DEXT(sampler2DShadow, vec3);" // GL_EXT_shadow_samplers - "float shadow2DProjEXT(sampler2DShadow, vec4);" // GL_EXT_shadow_samplers - - "\n"); - } - } - - // - // Noise functions. - // - if (spvVersion.spv == 0 && profile != EEsProfile) { - commonBuiltins.append( - "float noise1(float x);" - "float noise1(vec2 x);" - "float noise1(vec3 x);" - "float noise1(vec4 x);" - - "vec2 noise2(float x);" - "vec2 noise2(vec2 x);" - "vec2 noise2(vec3 x);" - "vec2 noise2(vec4 x);" - - "vec3 noise3(float x);" - "vec3 noise3(vec2 x);" - "vec3 noise3(vec3 x);" - "vec3 noise3(vec4 x);" - - "vec4 noise4(float x);" - "vec4 noise4(vec2 x);" - "vec4 noise4(vec3 x);" - "vec4 noise4(vec4 x);" - - "\n"); - } - - if (spvVersion.vulkan == 0) { - // - // Atomic counter functions. - // - if ((profile != EEsProfile && version >= 300) || - (profile == EEsProfile && version >= 310)) { - commonBuiltins.append( - "uint atomicCounterIncrement(atomic_uint);" - "uint atomicCounterDecrement(atomic_uint);" - "uint atomicCounter(atomic_uint);" - - "\n"); - } - if (profile != EEsProfile && version == 450) { - commonBuiltins.append( - "uint atomicCounterAddARB(atomic_uint, uint);" - "uint atomicCounterSubtractARB(atomic_uint, uint);" - "uint atomicCounterMinARB(atomic_uint, uint);" - "uint atomicCounterMaxARB(atomic_uint, uint);" - "uint atomicCounterAndARB(atomic_uint, uint);" - "uint atomicCounterOrARB(atomic_uint, uint);" - "uint atomicCounterXorARB(atomic_uint, uint);" - "uint atomicCounterExchangeARB(atomic_uint, uint);" - "uint atomicCounterCompSwapARB(atomic_uint, uint, uint);" - - "\n"); - } - - - if (profile != EEsProfile && version >= 460) { - commonBuiltins.append( - "uint atomicCounterAdd(atomic_uint, uint);" - "uint atomicCounterSubtract(atomic_uint, uint);" - "uint atomicCounterMin(atomic_uint, uint);" - "uint atomicCounterMax(atomic_uint, uint);" - "uint atomicCounterAnd(atomic_uint, uint);" - "uint atomicCounterOr(atomic_uint, uint);" - "uint atomicCounterXor(atomic_uint, uint);" - "uint atomicCounterExchange(atomic_uint, uint);" - "uint atomicCounterCompSwap(atomic_uint, uint, uint);" - - "\n"); - } - } - else if (spvVersion.vulkanRelaxed) { - // - // Atomic counter functions act as aliases to normal atomic functions. - // replace definitions to take 'volatile coherent uint' instead of 'atomic_uint' - // and map to equivalent non-counter atomic op - // - if ((profile != EEsProfile && version >= 300) || - (profile == EEsProfile && version >= 310)) { - commonBuiltins.append( - "uint atomicCounterIncrement(volatile coherent uint);" - "uint atomicCounterDecrement(volatile coherent uint);" - "uint atomicCounter(volatile coherent uint);" - - "\n"); - } - if (profile != EEsProfile && version >= 460) { - commonBuiltins.append( - "uint atomicCounterAdd(volatile coherent uint, uint);" - "uint atomicCounterSubtract(volatile coherent uint, uint);" - "uint atomicCounterMin(volatile coherent uint, uint);" - "uint atomicCounterMax(volatile coherent uint, uint);" - "uint atomicCounterAnd(volatile coherent uint, uint);" - "uint atomicCounterOr(volatile coherent uint, uint);" - "uint atomicCounterXor(volatile coherent uint, uint);" - "uint atomicCounterExchange(volatile coherent uint, uint);" - "uint atomicCounterCompSwap(volatile coherent uint, uint, uint);" - - "\n"); - } - } - - // Bitfield - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 400)) { - commonBuiltins.append( - " int bitfieldExtract( int, int, int);" - "ivec2 bitfieldExtract(ivec2, int, int);" - "ivec3 bitfieldExtract(ivec3, int, int);" - "ivec4 bitfieldExtract(ivec4, int, int);" - - " uint bitfieldExtract( uint, int, int);" - "uvec2 bitfieldExtract(uvec2, int, int);" - "uvec3 bitfieldExtract(uvec3, int, int);" - "uvec4 bitfieldExtract(uvec4, int, int);" - - " int bitfieldInsert( int base, int, int, int);" - "ivec2 bitfieldInsert(ivec2 base, ivec2, int, int);" - "ivec3 bitfieldInsert(ivec3 base, ivec3, int, int);" - "ivec4 bitfieldInsert(ivec4 base, ivec4, int, int);" - - " uint bitfieldInsert( uint base, uint, int, int);" - "uvec2 bitfieldInsert(uvec2 base, uvec2, int, int);" - "uvec3 bitfieldInsert(uvec3 base, uvec3, int, int);" - "uvec4 bitfieldInsert(uvec4 base, uvec4, int, int);" - - "\n"); - } - - if (profile != EEsProfile && version >= 400) { - commonBuiltins.append( - " int findLSB( int);" - "ivec2 findLSB(ivec2);" - "ivec3 findLSB(ivec3);" - "ivec4 findLSB(ivec4);" - - " int findLSB( uint);" - "ivec2 findLSB(uvec2);" - "ivec3 findLSB(uvec3);" - "ivec4 findLSB(uvec4);" - - "\n"); - } else if (profile == EEsProfile && version >= 310) { - commonBuiltins.append( - "lowp int findLSB( int);" - "lowp ivec2 findLSB(ivec2);" - "lowp ivec3 findLSB(ivec3);" - "lowp ivec4 findLSB(ivec4);" - - "lowp int findLSB( uint);" - "lowp ivec2 findLSB(uvec2);" - "lowp ivec3 findLSB(uvec3);" - "lowp ivec4 findLSB(uvec4);" - - "\n"); - } - - if (profile != EEsProfile && version >= 400) { - commonBuiltins.append( - " int bitCount( int);" - "ivec2 bitCount(ivec2);" - "ivec3 bitCount(ivec3);" - "ivec4 bitCount(ivec4);" - - " int bitCount( uint);" - "ivec2 bitCount(uvec2);" - "ivec3 bitCount(uvec3);" - "ivec4 bitCount(uvec4);" - - " int findMSB(highp int);" - "ivec2 findMSB(highp ivec2);" - "ivec3 findMSB(highp ivec3);" - "ivec4 findMSB(highp ivec4);" - - " int findMSB(highp uint);" - "ivec2 findMSB(highp uvec2);" - "ivec3 findMSB(highp uvec3);" - "ivec4 findMSB(highp uvec4);" - - "\n"); - } - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 400)) { - commonBuiltins.append( - " uint uaddCarry(highp uint, highp uint, out lowp uint carry);" - "uvec2 uaddCarry(highp uvec2, highp uvec2, out lowp uvec2 carry);" - "uvec3 uaddCarry(highp uvec3, highp uvec3, out lowp uvec3 carry);" - "uvec4 uaddCarry(highp uvec4, highp uvec4, out lowp uvec4 carry);" - - " uint usubBorrow(highp uint, highp uint, out lowp uint borrow);" - "uvec2 usubBorrow(highp uvec2, highp uvec2, out lowp uvec2 borrow);" - "uvec3 usubBorrow(highp uvec3, highp uvec3, out lowp uvec3 borrow);" - "uvec4 usubBorrow(highp uvec4, highp uvec4, out lowp uvec4 borrow);" - - "void umulExtended(highp uint, highp uint, out highp uint, out highp uint lsb);" - "void umulExtended(highp uvec2, highp uvec2, out highp uvec2, out highp uvec2 lsb);" - "void umulExtended(highp uvec3, highp uvec3, out highp uvec3, out highp uvec3 lsb);" - "void umulExtended(highp uvec4, highp uvec4, out highp uvec4, out highp uvec4 lsb);" - - "void imulExtended(highp int, highp int, out highp int, out highp int lsb);" - "void imulExtended(highp ivec2, highp ivec2, out highp ivec2, out highp ivec2 lsb);" - "void imulExtended(highp ivec3, highp ivec3, out highp ivec3, out highp ivec3 lsb);" - "void imulExtended(highp ivec4, highp ivec4, out highp ivec4, out highp ivec4 lsb);" - - " int bitfieldReverse(highp int);" - "ivec2 bitfieldReverse(highp ivec2);" - "ivec3 bitfieldReverse(highp ivec3);" - "ivec4 bitfieldReverse(highp ivec4);" - - " uint bitfieldReverse(highp uint);" - "uvec2 bitfieldReverse(highp uvec2);" - "uvec3 bitfieldReverse(highp uvec3);" - "uvec4 bitfieldReverse(highp uvec4);" - - "\n"); - } - - if (profile == EEsProfile && version >= 310) { - commonBuiltins.append( - "lowp int bitCount( int);" - "lowp ivec2 bitCount(ivec2);" - "lowp ivec3 bitCount(ivec3);" - "lowp ivec4 bitCount(ivec4);" - - "lowp int bitCount( uint);" - "lowp ivec2 bitCount(uvec2);" - "lowp ivec3 bitCount(uvec3);" - "lowp ivec4 bitCount(uvec4);" - - "lowp int findMSB(highp int);" - "lowp ivec2 findMSB(highp ivec2);" - "lowp ivec3 findMSB(highp ivec3);" - "lowp ivec4 findMSB(highp ivec4);" - - "lowp int findMSB(highp uint);" - "lowp ivec2 findMSB(highp uvec2);" - "lowp ivec3 findMSB(highp uvec3);" - "lowp ivec4 findMSB(highp uvec4);" - - "\n"); - } - - // GL_ARB_shader_ballot - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append( - "uint64_t ballotARB(bool);" - - "float readInvocationARB(float, uint);" - "vec2 readInvocationARB(vec2, uint);" - "vec3 readInvocationARB(vec3, uint);" - "vec4 readInvocationARB(vec4, uint);" - - "int readInvocationARB(int, uint);" - "ivec2 readInvocationARB(ivec2, uint);" - "ivec3 readInvocationARB(ivec3, uint);" - "ivec4 readInvocationARB(ivec4, uint);" - - "uint readInvocationARB(uint, uint);" - "uvec2 readInvocationARB(uvec2, uint);" - "uvec3 readInvocationARB(uvec3, uint);" - "uvec4 readInvocationARB(uvec4, uint);" - - "float readFirstInvocationARB(float);" - "vec2 readFirstInvocationARB(vec2);" - "vec3 readFirstInvocationARB(vec3);" - "vec4 readFirstInvocationARB(vec4);" - - "int readFirstInvocationARB(int);" - "ivec2 readFirstInvocationARB(ivec2);" - "ivec3 readFirstInvocationARB(ivec3);" - "ivec4 readFirstInvocationARB(ivec4);" - - "uint readFirstInvocationARB(uint);" - "uvec2 readFirstInvocationARB(uvec2);" - "uvec3 readFirstInvocationARB(uvec3);" - "uvec4 readFirstInvocationARB(uvec4);" - - "\n"); - } - - // GL_ARB_shader_group_vote - if (profile != EEsProfile && version >= 430) { - commonBuiltins.append( - "bool anyInvocationARB(bool);" - "bool allInvocationsARB(bool);" - "bool allInvocationsEqualARB(bool);" - - "\n"); - } - - // GL_KHR_shader_subgroup - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - commonBuiltins.append( - "void subgroupBarrier();" - "void subgroupMemoryBarrier();" - "void subgroupMemoryBarrierBuffer();" - "void subgroupMemoryBarrierImage();" - "bool subgroupElect();" - - "bool subgroupAll(bool);\n" - "bool subgroupAny(bool);\n" - "uvec4 subgroupBallot(bool);\n" - "bool subgroupInverseBallot(uvec4);\n" - "bool subgroupBallotBitExtract(uvec4, uint);\n" - "uint subgroupBallotBitCount(uvec4);\n" - "uint subgroupBallotInclusiveBitCount(uvec4);\n" - "uint subgroupBallotExclusiveBitCount(uvec4);\n" - "uint subgroupBallotFindLSB(uvec4);\n" - "uint subgroupBallotFindMSB(uvec4);\n" - ); - - // Generate all flavors of subgroup ops. - static const char *subgroupOps[] = - { - "bool subgroupAllEqual(%s);\n", - "%s subgroupBroadcast(%s, uint);\n", - "%s subgroupBroadcastFirst(%s);\n", - "%s subgroupShuffle(%s, uint);\n", - "%s subgroupShuffleXor(%s, uint);\n", - "%s subgroupShuffleUp(%s, uint delta);\n", - "%s subgroupShuffleDown(%s, uint delta);\n", - "%s subgroupAdd(%s);\n", - "%s subgroupMul(%s);\n", - "%s subgroupMin(%s);\n", - "%s subgroupMax(%s);\n", - "%s subgroupAnd(%s);\n", - "%s subgroupOr(%s);\n", - "%s subgroupXor(%s);\n", - "%s subgroupInclusiveAdd(%s);\n", - "%s subgroupInclusiveMul(%s);\n", - "%s subgroupInclusiveMin(%s);\n", - "%s subgroupInclusiveMax(%s);\n", - "%s subgroupInclusiveAnd(%s);\n", - "%s subgroupInclusiveOr(%s);\n", - "%s subgroupInclusiveXor(%s);\n", - "%s subgroupExclusiveAdd(%s);\n", - "%s subgroupExclusiveMul(%s);\n", - "%s subgroupExclusiveMin(%s);\n", - "%s subgroupExclusiveMax(%s);\n", - "%s subgroupExclusiveAnd(%s);\n", - "%s subgroupExclusiveOr(%s);\n", - "%s subgroupExclusiveXor(%s);\n", - "%s subgroupClusteredAdd(%s, uint);\n", - "%s subgroupClusteredMul(%s, uint);\n", - "%s subgroupClusteredMin(%s, uint);\n", - "%s subgroupClusteredMax(%s, uint);\n", - "%s subgroupClusteredAnd(%s, uint);\n", - "%s subgroupClusteredOr(%s, uint);\n", - "%s subgroupClusteredXor(%s, uint);\n", - "%s subgroupQuadBroadcast(%s, uint);\n", - "%s subgroupQuadSwapHorizontal(%s);\n", - "%s subgroupQuadSwapVertical(%s);\n", - "%s subgroupQuadSwapDiagonal(%s);\n", - "uvec4 subgroupPartitionNV(%s);\n", - "%s subgroupPartitionedAddNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedMulNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedMinNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedMaxNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedAndNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedOrNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedXorNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedInclusiveAddNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedInclusiveMulNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedInclusiveMinNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedInclusiveMaxNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedInclusiveAndNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedInclusiveOrNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedInclusiveXorNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedExclusiveAddNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedExclusiveMulNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedExclusiveMinNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedExclusiveMaxNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedExclusiveAndNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedExclusiveOrNV(%s, uvec4 ballot);\n", - "%s subgroupPartitionedExclusiveXorNV(%s, uvec4 ballot);\n", - }; - - static const char *floatTypes[] = { - "float", "vec2", "vec3", "vec4", - "float16_t", "f16vec2", "f16vec3", "f16vec4", - }; - static const char *doubleTypes[] = { - "double", "dvec2", "dvec3", "dvec4", - }; - static const char *intTypes[] = { - "int8_t", "i8vec2", "i8vec3", "i8vec4", - "int16_t", "i16vec2", "i16vec3", "i16vec4", - "int", "ivec2", "ivec3", "ivec4", - "int64_t", "i64vec2", "i64vec3", "i64vec4", - "uint8_t", "u8vec2", "u8vec3", "u8vec4", - "uint16_t", "u16vec2", "u16vec3", "u16vec4", - "uint", "uvec2", "uvec3", "uvec4", - "uint64_t", "u64vec2", "u64vec3", "u64vec4", - }; - static const char *boolTypes[] = { - "bool", "bvec2", "bvec3", "bvec4", - }; - - for (size_t i = 0; i < sizeof(subgroupOps)/sizeof(subgroupOps[0]); ++i) { - const char *op = subgroupOps[i]; - - // Logical operations don't support float - bool logicalOp = strstr(op, "Or") || strstr(op, "And") || - (strstr(op, "Xor") && !strstr(op, "ShuffleXor")); - // Math operations don't support bool - bool mathOp = strstr(op, "Add") || strstr(op, "Mul") || strstr(op, "Min") || strstr(op, "Max"); - - const int bufSize = 256; - char buf[bufSize]; - - if (!logicalOp) { - for (size_t j = 0; j < sizeof(floatTypes)/sizeof(floatTypes[0]); ++j) { - snprintf(buf, bufSize, op, floatTypes[j], floatTypes[j]); - commonBuiltins.append(buf); - } - if (profile != EEsProfile && version >= 400) { - for (size_t j = 0; j < sizeof(doubleTypes)/sizeof(doubleTypes[0]); ++j) { - snprintf(buf, bufSize, op, doubleTypes[j], doubleTypes[j]); - commonBuiltins.append(buf); - } - } - } - if (!mathOp) { - for (size_t j = 0; j < sizeof(boolTypes)/sizeof(boolTypes[0]); ++j) { - snprintf(buf, bufSize, op, boolTypes[j], boolTypes[j]); - commonBuiltins.append(buf); - } - } - for (size_t j = 0; j < sizeof(intTypes)/sizeof(intTypes[0]); ++j) { - snprintf(buf, bufSize, op, intTypes[j], intTypes[j]); - commonBuiltins.append(buf); - } - } - - stageBuiltins[EShLangCompute].append( - "void subgroupMemoryBarrierShared();" - - "\n" - ); - stageBuiltins[EShLangMesh].append( - "void subgroupMemoryBarrierShared();" - "\n" - ); - stageBuiltins[EShLangTask].append( - "void subgroupMemoryBarrierShared();" - "\n" - ); - } - - if (profile != EEsProfile && version >= 460) { - commonBuiltins.append( - "bool anyInvocation(bool);" - "bool allInvocations(bool);" - "bool allInvocationsEqual(bool);" - - "\n"); - } - - // GL_AMD_shader_ballot - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append( - "float minInvocationsAMD(float);" - "vec2 minInvocationsAMD(vec2);" - "vec3 minInvocationsAMD(vec3);" - "vec4 minInvocationsAMD(vec4);" - - "int minInvocationsAMD(int);" - "ivec2 minInvocationsAMD(ivec2);" - "ivec3 minInvocationsAMD(ivec3);" - "ivec4 minInvocationsAMD(ivec4);" - - "uint minInvocationsAMD(uint);" - "uvec2 minInvocationsAMD(uvec2);" - "uvec3 minInvocationsAMD(uvec3);" - "uvec4 minInvocationsAMD(uvec4);" - - "double minInvocationsAMD(double);" - "dvec2 minInvocationsAMD(dvec2);" - "dvec3 minInvocationsAMD(dvec3);" - "dvec4 minInvocationsAMD(dvec4);" - - "int64_t minInvocationsAMD(int64_t);" - "i64vec2 minInvocationsAMD(i64vec2);" - "i64vec3 minInvocationsAMD(i64vec3);" - "i64vec4 minInvocationsAMD(i64vec4);" - - "uint64_t minInvocationsAMD(uint64_t);" - "u64vec2 minInvocationsAMD(u64vec2);" - "u64vec3 minInvocationsAMD(u64vec3);" - "u64vec4 minInvocationsAMD(u64vec4);" - - "float16_t minInvocationsAMD(float16_t);" - "f16vec2 minInvocationsAMD(f16vec2);" - "f16vec3 minInvocationsAMD(f16vec3);" - "f16vec4 minInvocationsAMD(f16vec4);" - - "int16_t minInvocationsAMD(int16_t);" - "i16vec2 minInvocationsAMD(i16vec2);" - "i16vec3 minInvocationsAMD(i16vec3);" - "i16vec4 minInvocationsAMD(i16vec4);" - - "uint16_t minInvocationsAMD(uint16_t);" - "u16vec2 minInvocationsAMD(u16vec2);" - "u16vec3 minInvocationsAMD(u16vec3);" - "u16vec4 minInvocationsAMD(u16vec4);" - - "float minInvocationsInclusiveScanAMD(float);" - "vec2 minInvocationsInclusiveScanAMD(vec2);" - "vec3 minInvocationsInclusiveScanAMD(vec3);" - "vec4 minInvocationsInclusiveScanAMD(vec4);" - - "int minInvocationsInclusiveScanAMD(int);" - "ivec2 minInvocationsInclusiveScanAMD(ivec2);" - "ivec3 minInvocationsInclusiveScanAMD(ivec3);" - "ivec4 minInvocationsInclusiveScanAMD(ivec4);" - - "uint minInvocationsInclusiveScanAMD(uint);" - "uvec2 minInvocationsInclusiveScanAMD(uvec2);" - "uvec3 minInvocationsInclusiveScanAMD(uvec3);" - "uvec4 minInvocationsInclusiveScanAMD(uvec4);" - - "double minInvocationsInclusiveScanAMD(double);" - "dvec2 minInvocationsInclusiveScanAMD(dvec2);" - "dvec3 minInvocationsInclusiveScanAMD(dvec3);" - "dvec4 minInvocationsInclusiveScanAMD(dvec4);" - - "int64_t minInvocationsInclusiveScanAMD(int64_t);" - "i64vec2 minInvocationsInclusiveScanAMD(i64vec2);" - "i64vec3 minInvocationsInclusiveScanAMD(i64vec3);" - "i64vec4 minInvocationsInclusiveScanAMD(i64vec4);" - - "uint64_t minInvocationsInclusiveScanAMD(uint64_t);" - "u64vec2 minInvocationsInclusiveScanAMD(u64vec2);" - "u64vec3 minInvocationsInclusiveScanAMD(u64vec3);" - "u64vec4 minInvocationsInclusiveScanAMD(u64vec4);" - - "float16_t minInvocationsInclusiveScanAMD(float16_t);" - "f16vec2 minInvocationsInclusiveScanAMD(f16vec2);" - "f16vec3 minInvocationsInclusiveScanAMD(f16vec3);" - "f16vec4 minInvocationsInclusiveScanAMD(f16vec4);" - - "int16_t minInvocationsInclusiveScanAMD(int16_t);" - "i16vec2 minInvocationsInclusiveScanAMD(i16vec2);" - "i16vec3 minInvocationsInclusiveScanAMD(i16vec3);" - "i16vec4 minInvocationsInclusiveScanAMD(i16vec4);" - - "uint16_t minInvocationsInclusiveScanAMD(uint16_t);" - "u16vec2 minInvocationsInclusiveScanAMD(u16vec2);" - "u16vec3 minInvocationsInclusiveScanAMD(u16vec3);" - "u16vec4 minInvocationsInclusiveScanAMD(u16vec4);" - - "float minInvocationsExclusiveScanAMD(float);" - "vec2 minInvocationsExclusiveScanAMD(vec2);" - "vec3 minInvocationsExclusiveScanAMD(vec3);" - "vec4 minInvocationsExclusiveScanAMD(vec4);" - - "int minInvocationsExclusiveScanAMD(int);" - "ivec2 minInvocationsExclusiveScanAMD(ivec2);" - "ivec3 minInvocationsExclusiveScanAMD(ivec3);" - "ivec4 minInvocationsExclusiveScanAMD(ivec4);" - - "uint minInvocationsExclusiveScanAMD(uint);" - "uvec2 minInvocationsExclusiveScanAMD(uvec2);" - "uvec3 minInvocationsExclusiveScanAMD(uvec3);" - "uvec4 minInvocationsExclusiveScanAMD(uvec4);" - - "double minInvocationsExclusiveScanAMD(double);" - "dvec2 minInvocationsExclusiveScanAMD(dvec2);" - "dvec3 minInvocationsExclusiveScanAMD(dvec3);" - "dvec4 minInvocationsExclusiveScanAMD(dvec4);" - - "int64_t minInvocationsExclusiveScanAMD(int64_t);" - "i64vec2 minInvocationsExclusiveScanAMD(i64vec2);" - "i64vec3 minInvocationsExclusiveScanAMD(i64vec3);" - "i64vec4 minInvocationsExclusiveScanAMD(i64vec4);" - - "uint64_t minInvocationsExclusiveScanAMD(uint64_t);" - "u64vec2 minInvocationsExclusiveScanAMD(u64vec2);" - "u64vec3 minInvocationsExclusiveScanAMD(u64vec3);" - "u64vec4 minInvocationsExclusiveScanAMD(u64vec4);" - - "float16_t minInvocationsExclusiveScanAMD(float16_t);" - "f16vec2 minInvocationsExclusiveScanAMD(f16vec2);" - "f16vec3 minInvocationsExclusiveScanAMD(f16vec3);" - "f16vec4 minInvocationsExclusiveScanAMD(f16vec4);" - - "int16_t minInvocationsExclusiveScanAMD(int16_t);" - "i16vec2 minInvocationsExclusiveScanAMD(i16vec2);" - "i16vec3 minInvocationsExclusiveScanAMD(i16vec3);" - "i16vec4 minInvocationsExclusiveScanAMD(i16vec4);" - - "uint16_t minInvocationsExclusiveScanAMD(uint16_t);" - "u16vec2 minInvocationsExclusiveScanAMD(u16vec2);" - "u16vec3 minInvocationsExclusiveScanAMD(u16vec3);" - "u16vec4 minInvocationsExclusiveScanAMD(u16vec4);" - - "float maxInvocationsAMD(float);" - "vec2 maxInvocationsAMD(vec2);" - "vec3 maxInvocationsAMD(vec3);" - "vec4 maxInvocationsAMD(vec4);" - - "int maxInvocationsAMD(int);" - "ivec2 maxInvocationsAMD(ivec2);" - "ivec3 maxInvocationsAMD(ivec3);" - "ivec4 maxInvocationsAMD(ivec4);" - - "uint maxInvocationsAMD(uint);" - "uvec2 maxInvocationsAMD(uvec2);" - "uvec3 maxInvocationsAMD(uvec3);" - "uvec4 maxInvocationsAMD(uvec4);" - - "double maxInvocationsAMD(double);" - "dvec2 maxInvocationsAMD(dvec2);" - "dvec3 maxInvocationsAMD(dvec3);" - "dvec4 maxInvocationsAMD(dvec4);" - - "int64_t maxInvocationsAMD(int64_t);" - "i64vec2 maxInvocationsAMD(i64vec2);" - "i64vec3 maxInvocationsAMD(i64vec3);" - "i64vec4 maxInvocationsAMD(i64vec4);" - - "uint64_t maxInvocationsAMD(uint64_t);" - "u64vec2 maxInvocationsAMD(u64vec2);" - "u64vec3 maxInvocationsAMD(u64vec3);" - "u64vec4 maxInvocationsAMD(u64vec4);" - - "float16_t maxInvocationsAMD(float16_t);" - "f16vec2 maxInvocationsAMD(f16vec2);" - "f16vec3 maxInvocationsAMD(f16vec3);" - "f16vec4 maxInvocationsAMD(f16vec4);" - - "int16_t maxInvocationsAMD(int16_t);" - "i16vec2 maxInvocationsAMD(i16vec2);" - "i16vec3 maxInvocationsAMD(i16vec3);" - "i16vec4 maxInvocationsAMD(i16vec4);" - - "uint16_t maxInvocationsAMD(uint16_t);" - "u16vec2 maxInvocationsAMD(u16vec2);" - "u16vec3 maxInvocationsAMD(u16vec3);" - "u16vec4 maxInvocationsAMD(u16vec4);" - - "float maxInvocationsInclusiveScanAMD(float);" - "vec2 maxInvocationsInclusiveScanAMD(vec2);" - "vec3 maxInvocationsInclusiveScanAMD(vec3);" - "vec4 maxInvocationsInclusiveScanAMD(vec4);" - - "int maxInvocationsInclusiveScanAMD(int);" - "ivec2 maxInvocationsInclusiveScanAMD(ivec2);" - "ivec3 maxInvocationsInclusiveScanAMD(ivec3);" - "ivec4 maxInvocationsInclusiveScanAMD(ivec4);" - - "uint maxInvocationsInclusiveScanAMD(uint);" - "uvec2 maxInvocationsInclusiveScanAMD(uvec2);" - "uvec3 maxInvocationsInclusiveScanAMD(uvec3);" - "uvec4 maxInvocationsInclusiveScanAMD(uvec4);" - - "double maxInvocationsInclusiveScanAMD(double);" - "dvec2 maxInvocationsInclusiveScanAMD(dvec2);" - "dvec3 maxInvocationsInclusiveScanAMD(dvec3);" - "dvec4 maxInvocationsInclusiveScanAMD(dvec4);" - - "int64_t maxInvocationsInclusiveScanAMD(int64_t);" - "i64vec2 maxInvocationsInclusiveScanAMD(i64vec2);" - "i64vec3 maxInvocationsInclusiveScanAMD(i64vec3);" - "i64vec4 maxInvocationsInclusiveScanAMD(i64vec4);" - - "uint64_t maxInvocationsInclusiveScanAMD(uint64_t);" - "u64vec2 maxInvocationsInclusiveScanAMD(u64vec2);" - "u64vec3 maxInvocationsInclusiveScanAMD(u64vec3);" - "u64vec4 maxInvocationsInclusiveScanAMD(u64vec4);" - - "float16_t maxInvocationsInclusiveScanAMD(float16_t);" - "f16vec2 maxInvocationsInclusiveScanAMD(f16vec2);" - "f16vec3 maxInvocationsInclusiveScanAMD(f16vec3);" - "f16vec4 maxInvocationsInclusiveScanAMD(f16vec4);" - - "int16_t maxInvocationsInclusiveScanAMD(int16_t);" - "i16vec2 maxInvocationsInclusiveScanAMD(i16vec2);" - "i16vec3 maxInvocationsInclusiveScanAMD(i16vec3);" - "i16vec4 maxInvocationsInclusiveScanAMD(i16vec4);" - - "uint16_t maxInvocationsInclusiveScanAMD(uint16_t);" - "u16vec2 maxInvocationsInclusiveScanAMD(u16vec2);" - "u16vec3 maxInvocationsInclusiveScanAMD(u16vec3);" - "u16vec4 maxInvocationsInclusiveScanAMD(u16vec4);" - - "float maxInvocationsExclusiveScanAMD(float);" - "vec2 maxInvocationsExclusiveScanAMD(vec2);" - "vec3 maxInvocationsExclusiveScanAMD(vec3);" - "vec4 maxInvocationsExclusiveScanAMD(vec4);" - - "int maxInvocationsExclusiveScanAMD(int);" - "ivec2 maxInvocationsExclusiveScanAMD(ivec2);" - "ivec3 maxInvocationsExclusiveScanAMD(ivec3);" - "ivec4 maxInvocationsExclusiveScanAMD(ivec4);" - - "uint maxInvocationsExclusiveScanAMD(uint);" - "uvec2 maxInvocationsExclusiveScanAMD(uvec2);" - "uvec3 maxInvocationsExclusiveScanAMD(uvec3);" - "uvec4 maxInvocationsExclusiveScanAMD(uvec4);" - - "double maxInvocationsExclusiveScanAMD(double);" - "dvec2 maxInvocationsExclusiveScanAMD(dvec2);" - "dvec3 maxInvocationsExclusiveScanAMD(dvec3);" - "dvec4 maxInvocationsExclusiveScanAMD(dvec4);" - - "int64_t maxInvocationsExclusiveScanAMD(int64_t);" - "i64vec2 maxInvocationsExclusiveScanAMD(i64vec2);" - "i64vec3 maxInvocationsExclusiveScanAMD(i64vec3);" - "i64vec4 maxInvocationsExclusiveScanAMD(i64vec4);" - - "uint64_t maxInvocationsExclusiveScanAMD(uint64_t);" - "u64vec2 maxInvocationsExclusiveScanAMD(u64vec2);" - "u64vec3 maxInvocationsExclusiveScanAMD(u64vec3);" - "u64vec4 maxInvocationsExclusiveScanAMD(u64vec4);" - - "float16_t maxInvocationsExclusiveScanAMD(float16_t);" - "f16vec2 maxInvocationsExclusiveScanAMD(f16vec2);" - "f16vec3 maxInvocationsExclusiveScanAMD(f16vec3);" - "f16vec4 maxInvocationsExclusiveScanAMD(f16vec4);" - - "int16_t maxInvocationsExclusiveScanAMD(int16_t);" - "i16vec2 maxInvocationsExclusiveScanAMD(i16vec2);" - "i16vec3 maxInvocationsExclusiveScanAMD(i16vec3);" - "i16vec4 maxInvocationsExclusiveScanAMD(i16vec4);" - - "uint16_t maxInvocationsExclusiveScanAMD(uint16_t);" - "u16vec2 maxInvocationsExclusiveScanAMD(u16vec2);" - "u16vec3 maxInvocationsExclusiveScanAMD(u16vec3);" - "u16vec4 maxInvocationsExclusiveScanAMD(u16vec4);" - - "float addInvocationsAMD(float);" - "vec2 addInvocationsAMD(vec2);" - "vec3 addInvocationsAMD(vec3);" - "vec4 addInvocationsAMD(vec4);" - - "int addInvocationsAMD(int);" - "ivec2 addInvocationsAMD(ivec2);" - "ivec3 addInvocationsAMD(ivec3);" - "ivec4 addInvocationsAMD(ivec4);" - - "uint addInvocationsAMD(uint);" - "uvec2 addInvocationsAMD(uvec2);" - "uvec3 addInvocationsAMD(uvec3);" - "uvec4 addInvocationsAMD(uvec4);" - - "double addInvocationsAMD(double);" - "dvec2 addInvocationsAMD(dvec2);" - "dvec3 addInvocationsAMD(dvec3);" - "dvec4 addInvocationsAMD(dvec4);" - - "int64_t addInvocationsAMD(int64_t);" - "i64vec2 addInvocationsAMD(i64vec2);" - "i64vec3 addInvocationsAMD(i64vec3);" - "i64vec4 addInvocationsAMD(i64vec4);" - - "uint64_t addInvocationsAMD(uint64_t);" - "u64vec2 addInvocationsAMD(u64vec2);" - "u64vec3 addInvocationsAMD(u64vec3);" - "u64vec4 addInvocationsAMD(u64vec4);" - - "float16_t addInvocationsAMD(float16_t);" - "f16vec2 addInvocationsAMD(f16vec2);" - "f16vec3 addInvocationsAMD(f16vec3);" - "f16vec4 addInvocationsAMD(f16vec4);" - - "int16_t addInvocationsAMD(int16_t);" - "i16vec2 addInvocationsAMD(i16vec2);" - "i16vec3 addInvocationsAMD(i16vec3);" - "i16vec4 addInvocationsAMD(i16vec4);" - - "uint16_t addInvocationsAMD(uint16_t);" - "u16vec2 addInvocationsAMD(u16vec2);" - "u16vec3 addInvocationsAMD(u16vec3);" - "u16vec4 addInvocationsAMD(u16vec4);" - - "float addInvocationsInclusiveScanAMD(float);" - "vec2 addInvocationsInclusiveScanAMD(vec2);" - "vec3 addInvocationsInclusiveScanAMD(vec3);" - "vec4 addInvocationsInclusiveScanAMD(vec4);" - - "int addInvocationsInclusiveScanAMD(int);" - "ivec2 addInvocationsInclusiveScanAMD(ivec2);" - "ivec3 addInvocationsInclusiveScanAMD(ivec3);" - "ivec4 addInvocationsInclusiveScanAMD(ivec4);" - - "uint addInvocationsInclusiveScanAMD(uint);" - "uvec2 addInvocationsInclusiveScanAMD(uvec2);" - "uvec3 addInvocationsInclusiveScanAMD(uvec3);" - "uvec4 addInvocationsInclusiveScanAMD(uvec4);" - - "double addInvocationsInclusiveScanAMD(double);" - "dvec2 addInvocationsInclusiveScanAMD(dvec2);" - "dvec3 addInvocationsInclusiveScanAMD(dvec3);" - "dvec4 addInvocationsInclusiveScanAMD(dvec4);" - - "int64_t addInvocationsInclusiveScanAMD(int64_t);" - "i64vec2 addInvocationsInclusiveScanAMD(i64vec2);" - "i64vec3 addInvocationsInclusiveScanAMD(i64vec3);" - "i64vec4 addInvocationsInclusiveScanAMD(i64vec4);" - - "uint64_t addInvocationsInclusiveScanAMD(uint64_t);" - "u64vec2 addInvocationsInclusiveScanAMD(u64vec2);" - "u64vec3 addInvocationsInclusiveScanAMD(u64vec3);" - "u64vec4 addInvocationsInclusiveScanAMD(u64vec4);" - - "float16_t addInvocationsInclusiveScanAMD(float16_t);" - "f16vec2 addInvocationsInclusiveScanAMD(f16vec2);" - "f16vec3 addInvocationsInclusiveScanAMD(f16vec3);" - "f16vec4 addInvocationsInclusiveScanAMD(f16vec4);" - - "int16_t addInvocationsInclusiveScanAMD(int16_t);" - "i16vec2 addInvocationsInclusiveScanAMD(i16vec2);" - "i16vec3 addInvocationsInclusiveScanAMD(i16vec3);" - "i16vec4 addInvocationsInclusiveScanAMD(i16vec4);" - - "uint16_t addInvocationsInclusiveScanAMD(uint16_t);" - "u16vec2 addInvocationsInclusiveScanAMD(u16vec2);" - "u16vec3 addInvocationsInclusiveScanAMD(u16vec3);" - "u16vec4 addInvocationsInclusiveScanAMD(u16vec4);" - - "float addInvocationsExclusiveScanAMD(float);" - "vec2 addInvocationsExclusiveScanAMD(vec2);" - "vec3 addInvocationsExclusiveScanAMD(vec3);" - "vec4 addInvocationsExclusiveScanAMD(vec4);" - - "int addInvocationsExclusiveScanAMD(int);" - "ivec2 addInvocationsExclusiveScanAMD(ivec2);" - "ivec3 addInvocationsExclusiveScanAMD(ivec3);" - "ivec4 addInvocationsExclusiveScanAMD(ivec4);" - - "uint addInvocationsExclusiveScanAMD(uint);" - "uvec2 addInvocationsExclusiveScanAMD(uvec2);" - "uvec3 addInvocationsExclusiveScanAMD(uvec3);" - "uvec4 addInvocationsExclusiveScanAMD(uvec4);" - - "double addInvocationsExclusiveScanAMD(double);" - "dvec2 addInvocationsExclusiveScanAMD(dvec2);" - "dvec3 addInvocationsExclusiveScanAMD(dvec3);" - "dvec4 addInvocationsExclusiveScanAMD(dvec4);" - - "int64_t addInvocationsExclusiveScanAMD(int64_t);" - "i64vec2 addInvocationsExclusiveScanAMD(i64vec2);" - "i64vec3 addInvocationsExclusiveScanAMD(i64vec3);" - "i64vec4 addInvocationsExclusiveScanAMD(i64vec4);" - - "uint64_t addInvocationsExclusiveScanAMD(uint64_t);" - "u64vec2 addInvocationsExclusiveScanAMD(u64vec2);" - "u64vec3 addInvocationsExclusiveScanAMD(u64vec3);" - "u64vec4 addInvocationsExclusiveScanAMD(u64vec4);" - - "float16_t addInvocationsExclusiveScanAMD(float16_t);" - "f16vec2 addInvocationsExclusiveScanAMD(f16vec2);" - "f16vec3 addInvocationsExclusiveScanAMD(f16vec3);" - "f16vec4 addInvocationsExclusiveScanAMD(f16vec4);" - - "int16_t addInvocationsExclusiveScanAMD(int16_t);" - "i16vec2 addInvocationsExclusiveScanAMD(i16vec2);" - "i16vec3 addInvocationsExclusiveScanAMD(i16vec3);" - "i16vec4 addInvocationsExclusiveScanAMD(i16vec4);" - - "uint16_t addInvocationsExclusiveScanAMD(uint16_t);" - "u16vec2 addInvocationsExclusiveScanAMD(u16vec2);" - "u16vec3 addInvocationsExclusiveScanAMD(u16vec3);" - "u16vec4 addInvocationsExclusiveScanAMD(u16vec4);" - - "float minInvocationsNonUniformAMD(float);" - "vec2 minInvocationsNonUniformAMD(vec2);" - "vec3 minInvocationsNonUniformAMD(vec3);" - "vec4 minInvocationsNonUniformAMD(vec4);" - - "int minInvocationsNonUniformAMD(int);" - "ivec2 minInvocationsNonUniformAMD(ivec2);" - "ivec3 minInvocationsNonUniformAMD(ivec3);" - "ivec4 minInvocationsNonUniformAMD(ivec4);" - - "uint minInvocationsNonUniformAMD(uint);" - "uvec2 minInvocationsNonUniformAMD(uvec2);" - "uvec3 minInvocationsNonUniformAMD(uvec3);" - "uvec4 minInvocationsNonUniformAMD(uvec4);" - - "double minInvocationsNonUniformAMD(double);" - "dvec2 minInvocationsNonUniformAMD(dvec2);" - "dvec3 minInvocationsNonUniformAMD(dvec3);" - "dvec4 minInvocationsNonUniformAMD(dvec4);" - - "int64_t minInvocationsNonUniformAMD(int64_t);" - "i64vec2 minInvocationsNonUniformAMD(i64vec2);" - "i64vec3 minInvocationsNonUniformAMD(i64vec3);" - "i64vec4 minInvocationsNonUniformAMD(i64vec4);" - - "uint64_t minInvocationsNonUniformAMD(uint64_t);" - "u64vec2 minInvocationsNonUniformAMD(u64vec2);" - "u64vec3 minInvocationsNonUniformAMD(u64vec3);" - "u64vec4 minInvocationsNonUniformAMD(u64vec4);" - - "float16_t minInvocationsNonUniformAMD(float16_t);" - "f16vec2 minInvocationsNonUniformAMD(f16vec2);" - "f16vec3 minInvocationsNonUniformAMD(f16vec3);" - "f16vec4 minInvocationsNonUniformAMD(f16vec4);" - - "int16_t minInvocationsNonUniformAMD(int16_t);" - "i16vec2 minInvocationsNonUniformAMD(i16vec2);" - "i16vec3 minInvocationsNonUniformAMD(i16vec3);" - "i16vec4 minInvocationsNonUniformAMD(i16vec4);" - - "uint16_t minInvocationsNonUniformAMD(uint16_t);" - "u16vec2 minInvocationsNonUniformAMD(u16vec2);" - "u16vec3 minInvocationsNonUniformAMD(u16vec3);" - "u16vec4 minInvocationsNonUniformAMD(u16vec4);" - - "float minInvocationsInclusiveScanNonUniformAMD(float);" - "vec2 minInvocationsInclusiveScanNonUniformAMD(vec2);" - "vec3 minInvocationsInclusiveScanNonUniformAMD(vec3);" - "vec4 minInvocationsInclusiveScanNonUniformAMD(vec4);" - - "int minInvocationsInclusiveScanNonUniformAMD(int);" - "ivec2 minInvocationsInclusiveScanNonUniformAMD(ivec2);" - "ivec3 minInvocationsInclusiveScanNonUniformAMD(ivec3);" - "ivec4 minInvocationsInclusiveScanNonUniformAMD(ivec4);" - - "uint minInvocationsInclusiveScanNonUniformAMD(uint);" - "uvec2 minInvocationsInclusiveScanNonUniformAMD(uvec2);" - "uvec3 minInvocationsInclusiveScanNonUniformAMD(uvec3);" - "uvec4 minInvocationsInclusiveScanNonUniformAMD(uvec4);" - - "double minInvocationsInclusiveScanNonUniformAMD(double);" - "dvec2 minInvocationsInclusiveScanNonUniformAMD(dvec2);" - "dvec3 minInvocationsInclusiveScanNonUniformAMD(dvec3);" - "dvec4 minInvocationsInclusiveScanNonUniformAMD(dvec4);" - - "int64_t minInvocationsInclusiveScanNonUniformAMD(int64_t);" - "i64vec2 minInvocationsInclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 minInvocationsInclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 minInvocationsInclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t minInvocationsInclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 minInvocationsInclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 minInvocationsInclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 minInvocationsInclusiveScanNonUniformAMD(u64vec4);" - - "float16_t minInvocationsInclusiveScanNonUniformAMD(float16_t);" - "f16vec2 minInvocationsInclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 minInvocationsInclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 minInvocationsInclusiveScanNonUniformAMD(f16vec4);" - - "int16_t minInvocationsInclusiveScanNonUniformAMD(int16_t);" - "i16vec2 minInvocationsInclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 minInvocationsInclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 minInvocationsInclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t minInvocationsInclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 minInvocationsInclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 minInvocationsInclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 minInvocationsInclusiveScanNonUniformAMD(u16vec4);" - - "float minInvocationsExclusiveScanNonUniformAMD(float);" - "vec2 minInvocationsExclusiveScanNonUniformAMD(vec2);" - "vec3 minInvocationsExclusiveScanNonUniformAMD(vec3);" - "vec4 minInvocationsExclusiveScanNonUniformAMD(vec4);" - - "int minInvocationsExclusiveScanNonUniformAMD(int);" - "ivec2 minInvocationsExclusiveScanNonUniformAMD(ivec2);" - "ivec3 minInvocationsExclusiveScanNonUniformAMD(ivec3);" - "ivec4 minInvocationsExclusiveScanNonUniformAMD(ivec4);" - - "uint minInvocationsExclusiveScanNonUniformAMD(uint);" - "uvec2 minInvocationsExclusiveScanNonUniformAMD(uvec2);" - "uvec3 minInvocationsExclusiveScanNonUniformAMD(uvec3);" - "uvec4 minInvocationsExclusiveScanNonUniformAMD(uvec4);" - - "double minInvocationsExclusiveScanNonUniformAMD(double);" - "dvec2 minInvocationsExclusiveScanNonUniformAMD(dvec2);" - "dvec3 minInvocationsExclusiveScanNonUniformAMD(dvec3);" - "dvec4 minInvocationsExclusiveScanNonUniformAMD(dvec4);" - - "int64_t minInvocationsExclusiveScanNonUniformAMD(int64_t);" - "i64vec2 minInvocationsExclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 minInvocationsExclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 minInvocationsExclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t minInvocationsExclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 minInvocationsExclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 minInvocationsExclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 minInvocationsExclusiveScanNonUniformAMD(u64vec4);" - - "float16_t minInvocationsExclusiveScanNonUniformAMD(float16_t);" - "f16vec2 minInvocationsExclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 minInvocationsExclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 minInvocationsExclusiveScanNonUniformAMD(f16vec4);" - - "int16_t minInvocationsExclusiveScanNonUniformAMD(int16_t);" - "i16vec2 minInvocationsExclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 minInvocationsExclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 minInvocationsExclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t minInvocationsExclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 minInvocationsExclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 minInvocationsExclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 minInvocationsExclusiveScanNonUniformAMD(u16vec4);" - - "float maxInvocationsNonUniformAMD(float);" - "vec2 maxInvocationsNonUniformAMD(vec2);" - "vec3 maxInvocationsNonUniformAMD(vec3);" - "vec4 maxInvocationsNonUniformAMD(vec4);" - - "int maxInvocationsNonUniformAMD(int);" - "ivec2 maxInvocationsNonUniformAMD(ivec2);" - "ivec3 maxInvocationsNonUniformAMD(ivec3);" - "ivec4 maxInvocationsNonUniformAMD(ivec4);" - - "uint maxInvocationsNonUniformAMD(uint);" - "uvec2 maxInvocationsNonUniformAMD(uvec2);" - "uvec3 maxInvocationsNonUniformAMD(uvec3);" - "uvec4 maxInvocationsNonUniformAMD(uvec4);" - - "double maxInvocationsNonUniformAMD(double);" - "dvec2 maxInvocationsNonUniformAMD(dvec2);" - "dvec3 maxInvocationsNonUniformAMD(dvec3);" - "dvec4 maxInvocationsNonUniformAMD(dvec4);" - - "int64_t maxInvocationsNonUniformAMD(int64_t);" - "i64vec2 maxInvocationsNonUniformAMD(i64vec2);" - "i64vec3 maxInvocationsNonUniformAMD(i64vec3);" - "i64vec4 maxInvocationsNonUniformAMD(i64vec4);" - - "uint64_t maxInvocationsNonUniformAMD(uint64_t);" - "u64vec2 maxInvocationsNonUniformAMD(u64vec2);" - "u64vec3 maxInvocationsNonUniformAMD(u64vec3);" - "u64vec4 maxInvocationsNonUniformAMD(u64vec4);" - - "float16_t maxInvocationsNonUniformAMD(float16_t);" - "f16vec2 maxInvocationsNonUniformAMD(f16vec2);" - "f16vec3 maxInvocationsNonUniformAMD(f16vec3);" - "f16vec4 maxInvocationsNonUniformAMD(f16vec4);" - - "int16_t maxInvocationsNonUniformAMD(int16_t);" - "i16vec2 maxInvocationsNonUniformAMD(i16vec2);" - "i16vec3 maxInvocationsNonUniformAMD(i16vec3);" - "i16vec4 maxInvocationsNonUniformAMD(i16vec4);" - - "uint16_t maxInvocationsNonUniformAMD(uint16_t);" - "u16vec2 maxInvocationsNonUniformAMD(u16vec2);" - "u16vec3 maxInvocationsNonUniformAMD(u16vec3);" - "u16vec4 maxInvocationsNonUniformAMD(u16vec4);" - - "float maxInvocationsInclusiveScanNonUniformAMD(float);" - "vec2 maxInvocationsInclusiveScanNonUniformAMD(vec2);" - "vec3 maxInvocationsInclusiveScanNonUniformAMD(vec3);" - "vec4 maxInvocationsInclusiveScanNonUniformAMD(vec4);" - - "int maxInvocationsInclusiveScanNonUniformAMD(int);" - "ivec2 maxInvocationsInclusiveScanNonUniformAMD(ivec2);" - "ivec3 maxInvocationsInclusiveScanNonUniformAMD(ivec3);" - "ivec4 maxInvocationsInclusiveScanNonUniformAMD(ivec4);" - - "uint maxInvocationsInclusiveScanNonUniformAMD(uint);" - "uvec2 maxInvocationsInclusiveScanNonUniformAMD(uvec2);" - "uvec3 maxInvocationsInclusiveScanNonUniformAMD(uvec3);" - "uvec4 maxInvocationsInclusiveScanNonUniformAMD(uvec4);" - - "double maxInvocationsInclusiveScanNonUniformAMD(double);" - "dvec2 maxInvocationsInclusiveScanNonUniformAMD(dvec2);" - "dvec3 maxInvocationsInclusiveScanNonUniformAMD(dvec3);" - "dvec4 maxInvocationsInclusiveScanNonUniformAMD(dvec4);" - - "int64_t maxInvocationsInclusiveScanNonUniformAMD(int64_t);" - "i64vec2 maxInvocationsInclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 maxInvocationsInclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 maxInvocationsInclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t maxInvocationsInclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 maxInvocationsInclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 maxInvocationsInclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 maxInvocationsInclusiveScanNonUniformAMD(u64vec4);" - - "float16_t maxInvocationsInclusiveScanNonUniformAMD(float16_t);" - "f16vec2 maxInvocationsInclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 maxInvocationsInclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 maxInvocationsInclusiveScanNonUniformAMD(f16vec4);" - - "int16_t maxInvocationsInclusiveScanNonUniformAMD(int16_t);" - "i16vec2 maxInvocationsInclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 maxInvocationsInclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 maxInvocationsInclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t maxInvocationsInclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 maxInvocationsInclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 maxInvocationsInclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 maxInvocationsInclusiveScanNonUniformAMD(u16vec4);" - - "float maxInvocationsExclusiveScanNonUniformAMD(float);" - "vec2 maxInvocationsExclusiveScanNonUniformAMD(vec2);" - "vec3 maxInvocationsExclusiveScanNonUniformAMD(vec3);" - "vec4 maxInvocationsExclusiveScanNonUniformAMD(vec4);" - - "int maxInvocationsExclusiveScanNonUniformAMD(int);" - "ivec2 maxInvocationsExclusiveScanNonUniformAMD(ivec2);" - "ivec3 maxInvocationsExclusiveScanNonUniformAMD(ivec3);" - "ivec4 maxInvocationsExclusiveScanNonUniformAMD(ivec4);" - - "uint maxInvocationsExclusiveScanNonUniformAMD(uint);" - "uvec2 maxInvocationsExclusiveScanNonUniformAMD(uvec2);" - "uvec3 maxInvocationsExclusiveScanNonUniformAMD(uvec3);" - "uvec4 maxInvocationsExclusiveScanNonUniformAMD(uvec4);" - - "double maxInvocationsExclusiveScanNonUniformAMD(double);" - "dvec2 maxInvocationsExclusiveScanNonUniformAMD(dvec2);" - "dvec3 maxInvocationsExclusiveScanNonUniformAMD(dvec3);" - "dvec4 maxInvocationsExclusiveScanNonUniformAMD(dvec4);" - - "int64_t maxInvocationsExclusiveScanNonUniformAMD(int64_t);" - "i64vec2 maxInvocationsExclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 maxInvocationsExclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 maxInvocationsExclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t maxInvocationsExclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 maxInvocationsExclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 maxInvocationsExclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 maxInvocationsExclusiveScanNonUniformAMD(u64vec4);" - - "float16_t maxInvocationsExclusiveScanNonUniformAMD(float16_t);" - "f16vec2 maxInvocationsExclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 maxInvocationsExclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 maxInvocationsExclusiveScanNonUniformAMD(f16vec4);" - - "int16_t maxInvocationsExclusiveScanNonUniformAMD(int16_t);" - "i16vec2 maxInvocationsExclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 maxInvocationsExclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 maxInvocationsExclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t maxInvocationsExclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 maxInvocationsExclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 maxInvocationsExclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 maxInvocationsExclusiveScanNonUniformAMD(u16vec4);" - - "float addInvocationsNonUniformAMD(float);" - "vec2 addInvocationsNonUniformAMD(vec2);" - "vec3 addInvocationsNonUniformAMD(vec3);" - "vec4 addInvocationsNonUniformAMD(vec4);" - - "int addInvocationsNonUniformAMD(int);" - "ivec2 addInvocationsNonUniformAMD(ivec2);" - "ivec3 addInvocationsNonUniformAMD(ivec3);" - "ivec4 addInvocationsNonUniformAMD(ivec4);" - - "uint addInvocationsNonUniformAMD(uint);" - "uvec2 addInvocationsNonUniformAMD(uvec2);" - "uvec3 addInvocationsNonUniformAMD(uvec3);" - "uvec4 addInvocationsNonUniformAMD(uvec4);" - - "double addInvocationsNonUniformAMD(double);" - "dvec2 addInvocationsNonUniformAMD(dvec2);" - "dvec3 addInvocationsNonUniformAMD(dvec3);" - "dvec4 addInvocationsNonUniformAMD(dvec4);" - - "int64_t addInvocationsNonUniformAMD(int64_t);" - "i64vec2 addInvocationsNonUniformAMD(i64vec2);" - "i64vec3 addInvocationsNonUniformAMD(i64vec3);" - "i64vec4 addInvocationsNonUniformAMD(i64vec4);" - - "uint64_t addInvocationsNonUniformAMD(uint64_t);" - "u64vec2 addInvocationsNonUniformAMD(u64vec2);" - "u64vec3 addInvocationsNonUniformAMD(u64vec3);" - "u64vec4 addInvocationsNonUniformAMD(u64vec4);" - - "float16_t addInvocationsNonUniformAMD(float16_t);" - "f16vec2 addInvocationsNonUniformAMD(f16vec2);" - "f16vec3 addInvocationsNonUniformAMD(f16vec3);" - "f16vec4 addInvocationsNonUniformAMD(f16vec4);" - - "int16_t addInvocationsNonUniformAMD(int16_t);" - "i16vec2 addInvocationsNonUniformAMD(i16vec2);" - "i16vec3 addInvocationsNonUniformAMD(i16vec3);" - "i16vec4 addInvocationsNonUniformAMD(i16vec4);" - - "uint16_t addInvocationsNonUniformAMD(uint16_t);" - "u16vec2 addInvocationsNonUniformAMD(u16vec2);" - "u16vec3 addInvocationsNonUniformAMD(u16vec3);" - "u16vec4 addInvocationsNonUniformAMD(u16vec4);" - - "float addInvocationsInclusiveScanNonUniformAMD(float);" - "vec2 addInvocationsInclusiveScanNonUniformAMD(vec2);" - "vec3 addInvocationsInclusiveScanNonUniformAMD(vec3);" - "vec4 addInvocationsInclusiveScanNonUniformAMD(vec4);" - - "int addInvocationsInclusiveScanNonUniformAMD(int);" - "ivec2 addInvocationsInclusiveScanNonUniformAMD(ivec2);" - "ivec3 addInvocationsInclusiveScanNonUniformAMD(ivec3);" - "ivec4 addInvocationsInclusiveScanNonUniformAMD(ivec4);" - - "uint addInvocationsInclusiveScanNonUniformAMD(uint);" - "uvec2 addInvocationsInclusiveScanNonUniformAMD(uvec2);" - "uvec3 addInvocationsInclusiveScanNonUniformAMD(uvec3);" - "uvec4 addInvocationsInclusiveScanNonUniformAMD(uvec4);" - - "double addInvocationsInclusiveScanNonUniformAMD(double);" - "dvec2 addInvocationsInclusiveScanNonUniformAMD(dvec2);" - "dvec3 addInvocationsInclusiveScanNonUniformAMD(dvec3);" - "dvec4 addInvocationsInclusiveScanNonUniformAMD(dvec4);" - - "int64_t addInvocationsInclusiveScanNonUniformAMD(int64_t);" - "i64vec2 addInvocationsInclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 addInvocationsInclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 addInvocationsInclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t addInvocationsInclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 addInvocationsInclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 addInvocationsInclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 addInvocationsInclusiveScanNonUniformAMD(u64vec4);" - - "float16_t addInvocationsInclusiveScanNonUniformAMD(float16_t);" - "f16vec2 addInvocationsInclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 addInvocationsInclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 addInvocationsInclusiveScanNonUniformAMD(f16vec4);" - - "int16_t addInvocationsInclusiveScanNonUniformAMD(int16_t);" - "i16vec2 addInvocationsInclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 addInvocationsInclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 addInvocationsInclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t addInvocationsInclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 addInvocationsInclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 addInvocationsInclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 addInvocationsInclusiveScanNonUniformAMD(u16vec4);" - - "float addInvocationsExclusiveScanNonUniformAMD(float);" - "vec2 addInvocationsExclusiveScanNonUniformAMD(vec2);" - "vec3 addInvocationsExclusiveScanNonUniformAMD(vec3);" - "vec4 addInvocationsExclusiveScanNonUniformAMD(vec4);" - - "int addInvocationsExclusiveScanNonUniformAMD(int);" - "ivec2 addInvocationsExclusiveScanNonUniformAMD(ivec2);" - "ivec3 addInvocationsExclusiveScanNonUniformAMD(ivec3);" - "ivec4 addInvocationsExclusiveScanNonUniformAMD(ivec4);" - - "uint addInvocationsExclusiveScanNonUniformAMD(uint);" - "uvec2 addInvocationsExclusiveScanNonUniformAMD(uvec2);" - "uvec3 addInvocationsExclusiveScanNonUniformAMD(uvec3);" - "uvec4 addInvocationsExclusiveScanNonUniformAMD(uvec4);" - - "double addInvocationsExclusiveScanNonUniformAMD(double);" - "dvec2 addInvocationsExclusiveScanNonUniformAMD(dvec2);" - "dvec3 addInvocationsExclusiveScanNonUniformAMD(dvec3);" - "dvec4 addInvocationsExclusiveScanNonUniformAMD(dvec4);" - - "int64_t addInvocationsExclusiveScanNonUniformAMD(int64_t);" - "i64vec2 addInvocationsExclusiveScanNonUniformAMD(i64vec2);" - "i64vec3 addInvocationsExclusiveScanNonUniformAMD(i64vec3);" - "i64vec4 addInvocationsExclusiveScanNonUniformAMD(i64vec4);" - - "uint64_t addInvocationsExclusiveScanNonUniformAMD(uint64_t);" - "u64vec2 addInvocationsExclusiveScanNonUniformAMD(u64vec2);" - "u64vec3 addInvocationsExclusiveScanNonUniformAMD(u64vec3);" - "u64vec4 addInvocationsExclusiveScanNonUniformAMD(u64vec4);" - - "float16_t addInvocationsExclusiveScanNonUniformAMD(float16_t);" - "f16vec2 addInvocationsExclusiveScanNonUniformAMD(f16vec2);" - "f16vec3 addInvocationsExclusiveScanNonUniformAMD(f16vec3);" - "f16vec4 addInvocationsExclusiveScanNonUniformAMD(f16vec4);" - - "int16_t addInvocationsExclusiveScanNonUniformAMD(int16_t);" - "i16vec2 addInvocationsExclusiveScanNonUniformAMD(i16vec2);" - "i16vec3 addInvocationsExclusiveScanNonUniformAMD(i16vec3);" - "i16vec4 addInvocationsExclusiveScanNonUniformAMD(i16vec4);" - - "uint16_t addInvocationsExclusiveScanNonUniformAMD(uint16_t);" - "u16vec2 addInvocationsExclusiveScanNonUniformAMD(u16vec2);" - "u16vec3 addInvocationsExclusiveScanNonUniformAMD(u16vec3);" - "u16vec4 addInvocationsExclusiveScanNonUniformAMD(u16vec4);" - - "float swizzleInvocationsAMD(float, uvec4);" - "vec2 swizzleInvocationsAMD(vec2, uvec4);" - "vec3 swizzleInvocationsAMD(vec3, uvec4);" - "vec4 swizzleInvocationsAMD(vec4, uvec4);" - - "int swizzleInvocationsAMD(int, uvec4);" - "ivec2 swizzleInvocationsAMD(ivec2, uvec4);" - "ivec3 swizzleInvocationsAMD(ivec3, uvec4);" - "ivec4 swizzleInvocationsAMD(ivec4, uvec4);" - - "uint swizzleInvocationsAMD(uint, uvec4);" - "uvec2 swizzleInvocationsAMD(uvec2, uvec4);" - "uvec3 swizzleInvocationsAMD(uvec3, uvec4);" - "uvec4 swizzleInvocationsAMD(uvec4, uvec4);" - - "float swizzleInvocationsMaskedAMD(float, uvec3);" - "vec2 swizzleInvocationsMaskedAMD(vec2, uvec3);" - "vec3 swizzleInvocationsMaskedAMD(vec3, uvec3);" - "vec4 swizzleInvocationsMaskedAMD(vec4, uvec3);" - - "int swizzleInvocationsMaskedAMD(int, uvec3);" - "ivec2 swizzleInvocationsMaskedAMD(ivec2, uvec3);" - "ivec3 swizzleInvocationsMaskedAMD(ivec3, uvec3);" - "ivec4 swizzleInvocationsMaskedAMD(ivec4, uvec3);" - - "uint swizzleInvocationsMaskedAMD(uint, uvec3);" - "uvec2 swizzleInvocationsMaskedAMD(uvec2, uvec3);" - "uvec3 swizzleInvocationsMaskedAMD(uvec3, uvec3);" - "uvec4 swizzleInvocationsMaskedAMD(uvec4, uvec3);" - - "float writeInvocationAMD(float, float, uint);" - "vec2 writeInvocationAMD(vec2, vec2, uint);" - "vec3 writeInvocationAMD(vec3, vec3, uint);" - "vec4 writeInvocationAMD(vec4, vec4, uint);" - - "int writeInvocationAMD(int, int, uint);" - "ivec2 writeInvocationAMD(ivec2, ivec2, uint);" - "ivec3 writeInvocationAMD(ivec3, ivec3, uint);" - "ivec4 writeInvocationAMD(ivec4, ivec4, uint);" - - "uint writeInvocationAMD(uint, uint, uint);" - "uvec2 writeInvocationAMD(uvec2, uvec2, uint);" - "uvec3 writeInvocationAMD(uvec3, uvec3, uint);" - "uvec4 writeInvocationAMD(uvec4, uvec4, uint);" - - "uint mbcntAMD(uint64_t);" - - "\n"); - } - - // GL_AMD_gcn_shader - if (profile != EEsProfile && version >= 440) { - commonBuiltins.append( - "float cubeFaceIndexAMD(vec3);" - "vec2 cubeFaceCoordAMD(vec3);" - "uint64_t timeAMD();" - - "in int gl_SIMDGroupSizeAMD;" - "\n"); - } - - // GL_AMD_shader_fragment_mask - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append( - "uint fragmentMaskFetchAMD(sampler2DMS, ivec2);" - "uint fragmentMaskFetchAMD(isampler2DMS, ivec2);" - "uint fragmentMaskFetchAMD(usampler2DMS, ivec2);" - - "uint fragmentMaskFetchAMD(sampler2DMSArray, ivec3);" - "uint fragmentMaskFetchAMD(isampler2DMSArray, ivec3);" - "uint fragmentMaskFetchAMD(usampler2DMSArray, ivec3);" - - "vec4 fragmentFetchAMD(sampler2DMS, ivec2, uint);" - "ivec4 fragmentFetchAMD(isampler2DMS, ivec2, uint);" - "uvec4 fragmentFetchAMD(usampler2DMS, ivec2, uint);" - - "vec4 fragmentFetchAMD(sampler2DMSArray, ivec3, uint);" - "ivec4 fragmentFetchAMD(isampler2DMSArray, ivec3, uint);" - "uvec4 fragmentFetchAMD(usampler2DMSArray, ivec3, uint);" - - "\n"); - } - - if ((profile != EEsProfile && version >= 130) || - (profile == EEsProfile && version >= 300)) { - commonBuiltins.append( - "uint countLeadingZeros(uint);" - "uvec2 countLeadingZeros(uvec2);" - "uvec3 countLeadingZeros(uvec3);" - "uvec4 countLeadingZeros(uvec4);" - - "uint countTrailingZeros(uint);" - "uvec2 countTrailingZeros(uvec2);" - "uvec3 countTrailingZeros(uvec3);" - "uvec4 countTrailingZeros(uvec4);" - - "uint absoluteDifference(int, int);" - "uvec2 absoluteDifference(ivec2, ivec2);" - "uvec3 absoluteDifference(ivec3, ivec3);" - "uvec4 absoluteDifference(ivec4, ivec4);" - - "uint16_t absoluteDifference(int16_t, int16_t);" - "u16vec2 absoluteDifference(i16vec2, i16vec2);" - "u16vec3 absoluteDifference(i16vec3, i16vec3);" - "u16vec4 absoluteDifference(i16vec4, i16vec4);" - - "uint64_t absoluteDifference(int64_t, int64_t);" - "u64vec2 absoluteDifference(i64vec2, i64vec2);" - "u64vec3 absoluteDifference(i64vec3, i64vec3);" - "u64vec4 absoluteDifference(i64vec4, i64vec4);" - - "uint absoluteDifference(uint, uint);" - "uvec2 absoluteDifference(uvec2, uvec2);" - "uvec3 absoluteDifference(uvec3, uvec3);" - "uvec4 absoluteDifference(uvec4, uvec4);" - - "uint16_t absoluteDifference(uint16_t, uint16_t);" - "u16vec2 absoluteDifference(u16vec2, u16vec2);" - "u16vec3 absoluteDifference(u16vec3, u16vec3);" - "u16vec4 absoluteDifference(u16vec4, u16vec4);" - - "uint64_t absoluteDifference(uint64_t, uint64_t);" - "u64vec2 absoluteDifference(u64vec2, u64vec2);" - "u64vec3 absoluteDifference(u64vec3, u64vec3);" - "u64vec4 absoluteDifference(u64vec4, u64vec4);" - - "int addSaturate(int, int);" - "ivec2 addSaturate(ivec2, ivec2);" - "ivec3 addSaturate(ivec3, ivec3);" - "ivec4 addSaturate(ivec4, ivec4);" - - "int16_t addSaturate(int16_t, int16_t);" - "i16vec2 addSaturate(i16vec2, i16vec2);" - "i16vec3 addSaturate(i16vec3, i16vec3);" - "i16vec4 addSaturate(i16vec4, i16vec4);" - - "int64_t addSaturate(int64_t, int64_t);" - "i64vec2 addSaturate(i64vec2, i64vec2);" - "i64vec3 addSaturate(i64vec3, i64vec3);" - "i64vec4 addSaturate(i64vec4, i64vec4);" - - "uint addSaturate(uint, uint);" - "uvec2 addSaturate(uvec2, uvec2);" - "uvec3 addSaturate(uvec3, uvec3);" - "uvec4 addSaturate(uvec4, uvec4);" - - "uint16_t addSaturate(uint16_t, uint16_t);" - "u16vec2 addSaturate(u16vec2, u16vec2);" - "u16vec3 addSaturate(u16vec3, u16vec3);" - "u16vec4 addSaturate(u16vec4, u16vec4);" - - "uint64_t addSaturate(uint64_t, uint64_t);" - "u64vec2 addSaturate(u64vec2, u64vec2);" - "u64vec3 addSaturate(u64vec3, u64vec3);" - "u64vec4 addSaturate(u64vec4, u64vec4);" - - "int subtractSaturate(int, int);" - "ivec2 subtractSaturate(ivec2, ivec2);" - "ivec3 subtractSaturate(ivec3, ivec3);" - "ivec4 subtractSaturate(ivec4, ivec4);" - - "int16_t subtractSaturate(int16_t, int16_t);" - "i16vec2 subtractSaturate(i16vec2, i16vec2);" - "i16vec3 subtractSaturate(i16vec3, i16vec3);" - "i16vec4 subtractSaturate(i16vec4, i16vec4);" - - "int64_t subtractSaturate(int64_t, int64_t);" - "i64vec2 subtractSaturate(i64vec2, i64vec2);" - "i64vec3 subtractSaturate(i64vec3, i64vec3);" - "i64vec4 subtractSaturate(i64vec4, i64vec4);" - - "uint subtractSaturate(uint, uint);" - "uvec2 subtractSaturate(uvec2, uvec2);" - "uvec3 subtractSaturate(uvec3, uvec3);" - "uvec4 subtractSaturate(uvec4, uvec4);" - - "uint16_t subtractSaturate(uint16_t, uint16_t);" - "u16vec2 subtractSaturate(u16vec2, u16vec2);" - "u16vec3 subtractSaturate(u16vec3, u16vec3);" - "u16vec4 subtractSaturate(u16vec4, u16vec4);" - - "uint64_t subtractSaturate(uint64_t, uint64_t);" - "u64vec2 subtractSaturate(u64vec2, u64vec2);" - "u64vec3 subtractSaturate(u64vec3, u64vec3);" - "u64vec4 subtractSaturate(u64vec4, u64vec4);" - - "int average(int, int);" - "ivec2 average(ivec2, ivec2);" - "ivec3 average(ivec3, ivec3);" - "ivec4 average(ivec4, ivec4);" - - "int16_t average(int16_t, int16_t);" - "i16vec2 average(i16vec2, i16vec2);" - "i16vec3 average(i16vec3, i16vec3);" - "i16vec4 average(i16vec4, i16vec4);" - - "int64_t average(int64_t, int64_t);" - "i64vec2 average(i64vec2, i64vec2);" - "i64vec3 average(i64vec3, i64vec3);" - "i64vec4 average(i64vec4, i64vec4);" - - "uint average(uint, uint);" - "uvec2 average(uvec2, uvec2);" - "uvec3 average(uvec3, uvec3);" - "uvec4 average(uvec4, uvec4);" - - "uint16_t average(uint16_t, uint16_t);" - "u16vec2 average(u16vec2, u16vec2);" - "u16vec3 average(u16vec3, u16vec3);" - "u16vec4 average(u16vec4, u16vec4);" - - "uint64_t average(uint64_t, uint64_t);" - "u64vec2 average(u64vec2, u64vec2);" - "u64vec3 average(u64vec3, u64vec3);" - "u64vec4 average(u64vec4, u64vec4);" - - "int averageRounded(int, int);" - "ivec2 averageRounded(ivec2, ivec2);" - "ivec3 averageRounded(ivec3, ivec3);" - "ivec4 averageRounded(ivec4, ivec4);" - - "int16_t averageRounded(int16_t, int16_t);" - "i16vec2 averageRounded(i16vec2, i16vec2);" - "i16vec3 averageRounded(i16vec3, i16vec3);" - "i16vec4 averageRounded(i16vec4, i16vec4);" - - "int64_t averageRounded(int64_t, int64_t);" - "i64vec2 averageRounded(i64vec2, i64vec2);" - "i64vec3 averageRounded(i64vec3, i64vec3);" - "i64vec4 averageRounded(i64vec4, i64vec4);" - - "uint averageRounded(uint, uint);" - "uvec2 averageRounded(uvec2, uvec2);" - "uvec3 averageRounded(uvec3, uvec3);" - "uvec4 averageRounded(uvec4, uvec4);" - - "uint16_t averageRounded(uint16_t, uint16_t);" - "u16vec2 averageRounded(u16vec2, u16vec2);" - "u16vec3 averageRounded(u16vec3, u16vec3);" - "u16vec4 averageRounded(u16vec4, u16vec4);" - - "uint64_t averageRounded(uint64_t, uint64_t);" - "u64vec2 averageRounded(u64vec2, u64vec2);" - "u64vec3 averageRounded(u64vec3, u64vec3);" - "u64vec4 averageRounded(u64vec4, u64vec4);" - - "int multiply32x16(int, int);" - "ivec2 multiply32x16(ivec2, ivec2);" - "ivec3 multiply32x16(ivec3, ivec3);" - "ivec4 multiply32x16(ivec4, ivec4);" - - "uint multiply32x16(uint, uint);" - "uvec2 multiply32x16(uvec2, uvec2);" - "uvec3 multiply32x16(uvec3, uvec3);" - "uvec4 multiply32x16(uvec4, uvec4);" - "\n"); - } - - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 320)) { - commonBuiltins.append( - "struct gl_TextureFootprint2DNV {" - "uvec2 anchor;" - "uvec2 offset;" - "uvec2 mask;" - "uint lod;" - "uint granularity;" - "};" - - "struct gl_TextureFootprint3DNV {" - "uvec3 anchor;" - "uvec3 offset;" - "uvec2 mask;" - "uint lod;" - "uint granularity;" - "};" - "bool textureFootprintNV(sampler2D, vec2, int, bool, out gl_TextureFootprint2DNV);" - "bool textureFootprintNV(sampler3D, vec3, int, bool, out gl_TextureFootprint3DNV);" - "bool textureFootprintNV(sampler2D, vec2, int, bool, out gl_TextureFootprint2DNV, float);" - "bool textureFootprintNV(sampler3D, vec3, int, bool, out gl_TextureFootprint3DNV, float);" - "bool textureFootprintClampNV(sampler2D, vec2, float, int, bool, out gl_TextureFootprint2DNV);" - "bool textureFootprintClampNV(sampler3D, vec3, float, int, bool, out gl_TextureFootprint3DNV);" - "bool textureFootprintClampNV(sampler2D, vec2, float, int, bool, out gl_TextureFootprint2DNV, float);" - "bool textureFootprintClampNV(sampler3D, vec3, float, int, bool, out gl_TextureFootprint3DNV, float);" - "bool textureFootprintLodNV(sampler2D, vec2, float, int, bool, out gl_TextureFootprint2DNV);" - "bool textureFootprintLodNV(sampler3D, vec3, float, int, bool, out gl_TextureFootprint3DNV);" - "bool textureFootprintGradNV(sampler2D, vec2, vec2, vec2, int, bool, out gl_TextureFootprint2DNV);" - "bool textureFootprintGradClampNV(sampler2D, vec2, vec2, vec2, float, int, bool, out gl_TextureFootprint2DNV);" - "\n"); - } - - if ((profile == EEsProfile && version >= 300 && version < 310) || - (profile != EEsProfile && version >= 150 && version < 450)) { // GL_EXT_shader_integer_mix - commonBuiltins.append("int mix(int, int, bool);" - "ivec2 mix(ivec2, ivec2, bvec2);" - "ivec3 mix(ivec3, ivec3, bvec3);" - "ivec4 mix(ivec4, ivec4, bvec4);" - "uint mix(uint, uint, bool );" - "uvec2 mix(uvec2, uvec2, bvec2);" - "uvec3 mix(uvec3, uvec3, bvec3);" - "uvec4 mix(uvec4, uvec4, bvec4);" - "bool mix(bool, bool, bool );" - "bvec2 mix(bvec2, bvec2, bvec2);" - "bvec3 mix(bvec3, bvec3, bvec3);" - "bvec4 mix(bvec4, bvec4, bvec4);" - - "\n"); - } - - // GL_AMD_gpu_shader_half_float/Explicit types - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { - commonBuiltins.append( - "float16_t radians(float16_t);" - "f16vec2 radians(f16vec2);" - "f16vec3 radians(f16vec3);" - "f16vec4 radians(f16vec4);" - - "float16_t degrees(float16_t);" - "f16vec2 degrees(f16vec2);" - "f16vec3 degrees(f16vec3);" - "f16vec4 degrees(f16vec4);" - - "float16_t sin(float16_t);" - "f16vec2 sin(f16vec2);" - "f16vec3 sin(f16vec3);" - "f16vec4 sin(f16vec4);" - - "float16_t cos(float16_t);" - "f16vec2 cos(f16vec2);" - "f16vec3 cos(f16vec3);" - "f16vec4 cos(f16vec4);" - - "float16_t tan(float16_t);" - "f16vec2 tan(f16vec2);" - "f16vec3 tan(f16vec3);" - "f16vec4 tan(f16vec4);" - - "float16_t asin(float16_t);" - "f16vec2 asin(f16vec2);" - "f16vec3 asin(f16vec3);" - "f16vec4 asin(f16vec4);" - - "float16_t acos(float16_t);" - "f16vec2 acos(f16vec2);" - "f16vec3 acos(f16vec3);" - "f16vec4 acos(f16vec4);" - - "float16_t atan(float16_t, float16_t);" - "f16vec2 atan(f16vec2, f16vec2);" - "f16vec3 atan(f16vec3, f16vec3);" - "f16vec4 atan(f16vec4, f16vec4);" - - "float16_t atan(float16_t);" - "f16vec2 atan(f16vec2);" - "f16vec3 atan(f16vec3);" - "f16vec4 atan(f16vec4);" - - "float16_t sinh(float16_t);" - "f16vec2 sinh(f16vec2);" - "f16vec3 sinh(f16vec3);" - "f16vec4 sinh(f16vec4);" - - "float16_t cosh(float16_t);" - "f16vec2 cosh(f16vec2);" - "f16vec3 cosh(f16vec3);" - "f16vec4 cosh(f16vec4);" - - "float16_t tanh(float16_t);" - "f16vec2 tanh(f16vec2);" - "f16vec3 tanh(f16vec3);" - "f16vec4 tanh(f16vec4);" - - "float16_t asinh(float16_t);" - "f16vec2 asinh(f16vec2);" - "f16vec3 asinh(f16vec3);" - "f16vec4 asinh(f16vec4);" - - "float16_t acosh(float16_t);" - "f16vec2 acosh(f16vec2);" - "f16vec3 acosh(f16vec3);" - "f16vec4 acosh(f16vec4);" - - "float16_t atanh(float16_t);" - "f16vec2 atanh(f16vec2);" - "f16vec3 atanh(f16vec3);" - "f16vec4 atanh(f16vec4);" - - "float16_t pow(float16_t, float16_t);" - "f16vec2 pow(f16vec2, f16vec2);" - "f16vec3 pow(f16vec3, f16vec3);" - "f16vec4 pow(f16vec4, f16vec4);" - - "float16_t exp(float16_t);" - "f16vec2 exp(f16vec2);" - "f16vec3 exp(f16vec3);" - "f16vec4 exp(f16vec4);" - - "float16_t log(float16_t);" - "f16vec2 log(f16vec2);" - "f16vec3 log(f16vec3);" - "f16vec4 log(f16vec4);" - - "float16_t exp2(float16_t);" - "f16vec2 exp2(f16vec2);" - "f16vec3 exp2(f16vec3);" - "f16vec4 exp2(f16vec4);" - - "float16_t log2(float16_t);" - "f16vec2 log2(f16vec2);" - "f16vec3 log2(f16vec3);" - "f16vec4 log2(f16vec4);" - - "float16_t sqrt(float16_t);" - "f16vec2 sqrt(f16vec2);" - "f16vec3 sqrt(f16vec3);" - "f16vec4 sqrt(f16vec4);" - - "float16_t inversesqrt(float16_t);" - "f16vec2 inversesqrt(f16vec2);" - "f16vec3 inversesqrt(f16vec3);" - "f16vec4 inversesqrt(f16vec4);" - - "float16_t abs(float16_t);" - "f16vec2 abs(f16vec2);" - "f16vec3 abs(f16vec3);" - "f16vec4 abs(f16vec4);" - - "float16_t sign(float16_t);" - "f16vec2 sign(f16vec2);" - "f16vec3 sign(f16vec3);" - "f16vec4 sign(f16vec4);" - - "float16_t floor(float16_t);" - "f16vec2 floor(f16vec2);" - "f16vec3 floor(f16vec3);" - "f16vec4 floor(f16vec4);" - - "float16_t trunc(float16_t);" - "f16vec2 trunc(f16vec2);" - "f16vec3 trunc(f16vec3);" - "f16vec4 trunc(f16vec4);" - - "float16_t round(float16_t);" - "f16vec2 round(f16vec2);" - "f16vec3 round(f16vec3);" - "f16vec4 round(f16vec4);" - - "float16_t roundEven(float16_t);" - "f16vec2 roundEven(f16vec2);" - "f16vec3 roundEven(f16vec3);" - "f16vec4 roundEven(f16vec4);" - - "float16_t ceil(float16_t);" - "f16vec2 ceil(f16vec2);" - "f16vec3 ceil(f16vec3);" - "f16vec4 ceil(f16vec4);" - - "float16_t fract(float16_t);" - "f16vec2 fract(f16vec2);" - "f16vec3 fract(f16vec3);" - "f16vec4 fract(f16vec4);" - - "float16_t mod(float16_t, float16_t);" - "f16vec2 mod(f16vec2, float16_t);" - "f16vec3 mod(f16vec3, float16_t);" - "f16vec4 mod(f16vec4, float16_t);" - "f16vec2 mod(f16vec2, f16vec2);" - "f16vec3 mod(f16vec3, f16vec3);" - "f16vec4 mod(f16vec4, f16vec4);" - - "float16_t modf(float16_t, out float16_t);" - "f16vec2 modf(f16vec2, out f16vec2);" - "f16vec3 modf(f16vec3, out f16vec3);" - "f16vec4 modf(f16vec4, out f16vec4);" - - "float16_t min(float16_t, float16_t);" - "f16vec2 min(f16vec2, float16_t);" - "f16vec3 min(f16vec3, float16_t);" - "f16vec4 min(f16vec4, float16_t);" - "f16vec2 min(f16vec2, f16vec2);" - "f16vec3 min(f16vec3, f16vec3);" - "f16vec4 min(f16vec4, f16vec4);" - - "float16_t max(float16_t, float16_t);" - "f16vec2 max(f16vec2, float16_t);" - "f16vec3 max(f16vec3, float16_t);" - "f16vec4 max(f16vec4, float16_t);" - "f16vec2 max(f16vec2, f16vec2);" - "f16vec3 max(f16vec3, f16vec3);" - "f16vec4 max(f16vec4, f16vec4);" - - "float16_t clamp(float16_t, float16_t, float16_t);" - "f16vec2 clamp(f16vec2, float16_t, float16_t);" - "f16vec3 clamp(f16vec3, float16_t, float16_t);" - "f16vec4 clamp(f16vec4, float16_t, float16_t);" - "f16vec2 clamp(f16vec2, f16vec2, f16vec2);" - "f16vec3 clamp(f16vec3, f16vec3, f16vec3);" - "f16vec4 clamp(f16vec4, f16vec4, f16vec4);" - - "float16_t mix(float16_t, float16_t, float16_t);" - "f16vec2 mix(f16vec2, f16vec2, float16_t);" - "f16vec3 mix(f16vec3, f16vec3, float16_t);" - "f16vec4 mix(f16vec4, f16vec4, float16_t);" - "f16vec2 mix(f16vec2, f16vec2, f16vec2);" - "f16vec3 mix(f16vec3, f16vec3, f16vec3);" - "f16vec4 mix(f16vec4, f16vec4, f16vec4);" - "float16_t mix(float16_t, float16_t, bool);" - "f16vec2 mix(f16vec2, f16vec2, bvec2);" - "f16vec3 mix(f16vec3, f16vec3, bvec3);" - "f16vec4 mix(f16vec4, f16vec4, bvec4);" - - "float16_t step(float16_t, float16_t);" - "f16vec2 step(f16vec2, f16vec2);" - "f16vec3 step(f16vec3, f16vec3);" - "f16vec4 step(f16vec4, f16vec4);" - "f16vec2 step(float16_t, f16vec2);" - "f16vec3 step(float16_t, f16vec3);" - "f16vec4 step(float16_t, f16vec4);" - - "float16_t smoothstep(float16_t, float16_t, float16_t);" - "f16vec2 smoothstep(f16vec2, f16vec2, f16vec2);" - "f16vec3 smoothstep(f16vec3, f16vec3, f16vec3);" - "f16vec4 smoothstep(f16vec4, f16vec4, f16vec4);" - "f16vec2 smoothstep(float16_t, float16_t, f16vec2);" - "f16vec3 smoothstep(float16_t, float16_t, f16vec3);" - "f16vec4 smoothstep(float16_t, float16_t, f16vec4);" - - "bool isnan(float16_t);" - "bvec2 isnan(f16vec2);" - "bvec3 isnan(f16vec3);" - "bvec4 isnan(f16vec4);" - - "bool isinf(float16_t);" - "bvec2 isinf(f16vec2);" - "bvec3 isinf(f16vec3);" - "bvec4 isinf(f16vec4);" - - "float16_t fma(float16_t, float16_t, float16_t);" - "f16vec2 fma(f16vec2, f16vec2, f16vec2);" - "f16vec3 fma(f16vec3, f16vec3, f16vec3);" - "f16vec4 fma(f16vec4, f16vec4, f16vec4);" - - "float16_t frexp(float16_t, out int);" - "f16vec2 frexp(f16vec2, out ivec2);" - "f16vec3 frexp(f16vec3, out ivec3);" - "f16vec4 frexp(f16vec4, out ivec4);" - - "float16_t ldexp(float16_t, in int);" - "f16vec2 ldexp(f16vec2, in ivec2);" - "f16vec3 ldexp(f16vec3, in ivec3);" - "f16vec4 ldexp(f16vec4, in ivec4);" - - "uint packFloat2x16(f16vec2);" - "f16vec2 unpackFloat2x16(uint);" - - "float16_t length(float16_t);" - "float16_t length(f16vec2);" - "float16_t length(f16vec3);" - "float16_t length(f16vec4);" - - "float16_t distance(float16_t, float16_t);" - "float16_t distance(f16vec2, f16vec2);" - "float16_t distance(f16vec3, f16vec3);" - "float16_t distance(f16vec4, f16vec4);" - - "float16_t dot(float16_t, float16_t);" - "float16_t dot(f16vec2, f16vec2);" - "float16_t dot(f16vec3, f16vec3);" - "float16_t dot(f16vec4, f16vec4);" - - "f16vec3 cross(f16vec3, f16vec3);" - - "float16_t normalize(float16_t);" - "f16vec2 normalize(f16vec2);" - "f16vec3 normalize(f16vec3);" - "f16vec4 normalize(f16vec4);" - - "float16_t faceforward(float16_t, float16_t, float16_t);" - "f16vec2 faceforward(f16vec2, f16vec2, f16vec2);" - "f16vec3 faceforward(f16vec3, f16vec3, f16vec3);" - "f16vec4 faceforward(f16vec4, f16vec4, f16vec4);" - - "float16_t reflect(float16_t, float16_t);" - "f16vec2 reflect(f16vec2, f16vec2);" - "f16vec3 reflect(f16vec3, f16vec3);" - "f16vec4 reflect(f16vec4, f16vec4);" - - "float16_t refract(float16_t, float16_t, float16_t);" - "f16vec2 refract(f16vec2, f16vec2, float16_t);" - "f16vec3 refract(f16vec3, f16vec3, float16_t);" - "f16vec4 refract(f16vec4, f16vec4, float16_t);" - - "f16mat2 matrixCompMult(f16mat2, f16mat2);" - "f16mat3 matrixCompMult(f16mat3, f16mat3);" - "f16mat4 matrixCompMult(f16mat4, f16mat4);" - "f16mat2x3 matrixCompMult(f16mat2x3, f16mat2x3);" - "f16mat2x4 matrixCompMult(f16mat2x4, f16mat2x4);" - "f16mat3x2 matrixCompMult(f16mat3x2, f16mat3x2);" - "f16mat3x4 matrixCompMult(f16mat3x4, f16mat3x4);" - "f16mat4x2 matrixCompMult(f16mat4x2, f16mat4x2);" - "f16mat4x3 matrixCompMult(f16mat4x3, f16mat4x3);" - - "f16mat2 outerProduct(f16vec2, f16vec2);" - "f16mat3 outerProduct(f16vec3, f16vec3);" - "f16mat4 outerProduct(f16vec4, f16vec4);" - "f16mat2x3 outerProduct(f16vec3, f16vec2);" - "f16mat3x2 outerProduct(f16vec2, f16vec3);" - "f16mat2x4 outerProduct(f16vec4, f16vec2);" - "f16mat4x2 outerProduct(f16vec2, f16vec4);" - "f16mat3x4 outerProduct(f16vec4, f16vec3);" - "f16mat4x3 outerProduct(f16vec3, f16vec4);" - - "f16mat2 transpose(f16mat2);" - "f16mat3 transpose(f16mat3);" - "f16mat4 transpose(f16mat4);" - "f16mat2x3 transpose(f16mat3x2);" - "f16mat3x2 transpose(f16mat2x3);" - "f16mat2x4 transpose(f16mat4x2);" - "f16mat4x2 transpose(f16mat2x4);" - "f16mat3x4 transpose(f16mat4x3);" - "f16mat4x3 transpose(f16mat3x4);" - - "float16_t determinant(f16mat2);" - "float16_t determinant(f16mat3);" - "float16_t determinant(f16mat4);" - - "f16mat2 inverse(f16mat2);" - "f16mat3 inverse(f16mat3);" - "f16mat4 inverse(f16mat4);" - - "bvec2 lessThan(f16vec2, f16vec2);" - "bvec3 lessThan(f16vec3, f16vec3);" - "bvec4 lessThan(f16vec4, f16vec4);" - - "bvec2 lessThanEqual(f16vec2, f16vec2);" - "bvec3 lessThanEqual(f16vec3, f16vec3);" - "bvec4 lessThanEqual(f16vec4, f16vec4);" - - "bvec2 greaterThan(f16vec2, f16vec2);" - "bvec3 greaterThan(f16vec3, f16vec3);" - "bvec4 greaterThan(f16vec4, f16vec4);" - - "bvec2 greaterThanEqual(f16vec2, f16vec2);" - "bvec3 greaterThanEqual(f16vec3, f16vec3);" - "bvec4 greaterThanEqual(f16vec4, f16vec4);" - - "bvec2 equal(f16vec2, f16vec2);" - "bvec3 equal(f16vec3, f16vec3);" - "bvec4 equal(f16vec4, f16vec4);" - - "bvec2 notEqual(f16vec2, f16vec2);" - "bvec3 notEqual(f16vec3, f16vec3);" - "bvec4 notEqual(f16vec4, f16vec4);" - - "\n"); - } - - // Explicit types - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { - commonBuiltins.append( - "int8_t abs(int8_t);" - "i8vec2 abs(i8vec2);" - "i8vec3 abs(i8vec3);" - "i8vec4 abs(i8vec4);" - - "int8_t sign(int8_t);" - "i8vec2 sign(i8vec2);" - "i8vec3 sign(i8vec3);" - "i8vec4 sign(i8vec4);" - - "int8_t min(int8_t x, int8_t y);" - "i8vec2 min(i8vec2 x, int8_t y);" - "i8vec3 min(i8vec3 x, int8_t y);" - "i8vec4 min(i8vec4 x, int8_t y);" - "i8vec2 min(i8vec2 x, i8vec2 y);" - "i8vec3 min(i8vec3 x, i8vec3 y);" - "i8vec4 min(i8vec4 x, i8vec4 y);" - - "uint8_t min(uint8_t x, uint8_t y);" - "u8vec2 min(u8vec2 x, uint8_t y);" - "u8vec3 min(u8vec3 x, uint8_t y);" - "u8vec4 min(u8vec4 x, uint8_t y);" - "u8vec2 min(u8vec2 x, u8vec2 y);" - "u8vec3 min(u8vec3 x, u8vec3 y);" - "u8vec4 min(u8vec4 x, u8vec4 y);" - - "int8_t max(int8_t x, int8_t y);" - "i8vec2 max(i8vec2 x, int8_t y);" - "i8vec3 max(i8vec3 x, int8_t y);" - "i8vec4 max(i8vec4 x, int8_t y);" - "i8vec2 max(i8vec2 x, i8vec2 y);" - "i8vec3 max(i8vec3 x, i8vec3 y);" - "i8vec4 max(i8vec4 x, i8vec4 y);" - - "uint8_t max(uint8_t x, uint8_t y);" - "u8vec2 max(u8vec2 x, uint8_t y);" - "u8vec3 max(u8vec3 x, uint8_t y);" - "u8vec4 max(u8vec4 x, uint8_t y);" - "u8vec2 max(u8vec2 x, u8vec2 y);" - "u8vec3 max(u8vec3 x, u8vec3 y);" - "u8vec4 max(u8vec4 x, u8vec4 y);" - - "int8_t clamp(int8_t x, int8_t minVal, int8_t maxVal);" - "i8vec2 clamp(i8vec2 x, int8_t minVal, int8_t maxVal);" - "i8vec3 clamp(i8vec3 x, int8_t minVal, int8_t maxVal);" - "i8vec4 clamp(i8vec4 x, int8_t minVal, int8_t maxVal);" - "i8vec2 clamp(i8vec2 x, i8vec2 minVal, i8vec2 maxVal);" - "i8vec3 clamp(i8vec3 x, i8vec3 minVal, i8vec3 maxVal);" - "i8vec4 clamp(i8vec4 x, i8vec4 minVal, i8vec4 maxVal);" - - "uint8_t clamp(uint8_t x, uint8_t minVal, uint8_t maxVal);" - "u8vec2 clamp(u8vec2 x, uint8_t minVal, uint8_t maxVal);" - "u8vec3 clamp(u8vec3 x, uint8_t minVal, uint8_t maxVal);" - "u8vec4 clamp(u8vec4 x, uint8_t minVal, uint8_t maxVal);" - "u8vec2 clamp(u8vec2 x, u8vec2 minVal, u8vec2 maxVal);" - "u8vec3 clamp(u8vec3 x, u8vec3 minVal, u8vec3 maxVal);" - "u8vec4 clamp(u8vec4 x, u8vec4 minVal, u8vec4 maxVal);" - - "int8_t mix(int8_t, int8_t, bool);" - "i8vec2 mix(i8vec2, i8vec2, bvec2);" - "i8vec3 mix(i8vec3, i8vec3, bvec3);" - "i8vec4 mix(i8vec4, i8vec4, bvec4);" - "uint8_t mix(uint8_t, uint8_t, bool);" - "u8vec2 mix(u8vec2, u8vec2, bvec2);" - "u8vec3 mix(u8vec3, u8vec3, bvec3);" - "u8vec4 mix(u8vec4, u8vec4, bvec4);" - - "bvec2 lessThan(i8vec2, i8vec2);" - "bvec3 lessThan(i8vec3, i8vec3);" - "bvec4 lessThan(i8vec4, i8vec4);" - "bvec2 lessThan(u8vec2, u8vec2);" - "bvec3 lessThan(u8vec3, u8vec3);" - "bvec4 lessThan(u8vec4, u8vec4);" - - "bvec2 lessThanEqual(i8vec2, i8vec2);" - "bvec3 lessThanEqual(i8vec3, i8vec3);" - "bvec4 lessThanEqual(i8vec4, i8vec4);" - "bvec2 lessThanEqual(u8vec2, u8vec2);" - "bvec3 lessThanEqual(u8vec3, u8vec3);" - "bvec4 lessThanEqual(u8vec4, u8vec4);" - - "bvec2 greaterThan(i8vec2, i8vec2);" - "bvec3 greaterThan(i8vec3, i8vec3);" - "bvec4 greaterThan(i8vec4, i8vec4);" - "bvec2 greaterThan(u8vec2, u8vec2);" - "bvec3 greaterThan(u8vec3, u8vec3);" - "bvec4 greaterThan(u8vec4, u8vec4);" - - "bvec2 greaterThanEqual(i8vec2, i8vec2);" - "bvec3 greaterThanEqual(i8vec3, i8vec3);" - "bvec4 greaterThanEqual(i8vec4, i8vec4);" - "bvec2 greaterThanEqual(u8vec2, u8vec2);" - "bvec3 greaterThanEqual(u8vec3, u8vec3);" - "bvec4 greaterThanEqual(u8vec4, u8vec4);" - - "bvec2 equal(i8vec2, i8vec2);" - "bvec3 equal(i8vec3, i8vec3);" - "bvec4 equal(i8vec4, i8vec4);" - "bvec2 equal(u8vec2, u8vec2);" - "bvec3 equal(u8vec3, u8vec3);" - "bvec4 equal(u8vec4, u8vec4);" - - "bvec2 notEqual(i8vec2, i8vec2);" - "bvec3 notEqual(i8vec3, i8vec3);" - "bvec4 notEqual(i8vec4, i8vec4);" - "bvec2 notEqual(u8vec2, u8vec2);" - "bvec3 notEqual(u8vec3, u8vec3);" - "bvec4 notEqual(u8vec4, u8vec4);" - - " int8_t bitfieldExtract( int8_t, int8_t, int8_t);" - "i8vec2 bitfieldExtract(i8vec2, int8_t, int8_t);" - "i8vec3 bitfieldExtract(i8vec3, int8_t, int8_t);" - "i8vec4 bitfieldExtract(i8vec4, int8_t, int8_t);" - - " uint8_t bitfieldExtract( uint8_t, int8_t, int8_t);" - "u8vec2 bitfieldExtract(u8vec2, int8_t, int8_t);" - "u8vec3 bitfieldExtract(u8vec3, int8_t, int8_t);" - "u8vec4 bitfieldExtract(u8vec4, int8_t, int8_t);" - - " int8_t bitfieldInsert( int8_t base, int8_t, int8_t, int8_t);" - "i8vec2 bitfieldInsert(i8vec2 base, i8vec2, int8_t, int8_t);" - "i8vec3 bitfieldInsert(i8vec3 base, i8vec3, int8_t, int8_t);" - "i8vec4 bitfieldInsert(i8vec4 base, i8vec4, int8_t, int8_t);" - - " uint8_t bitfieldInsert( uint8_t base, uint8_t, int8_t, int8_t);" - "u8vec2 bitfieldInsert(u8vec2 base, u8vec2, int8_t, int8_t);" - "u8vec3 bitfieldInsert(u8vec3 base, u8vec3, int8_t, int8_t);" - "u8vec4 bitfieldInsert(u8vec4 base, u8vec4, int8_t, int8_t);" - - " int8_t bitCount( int8_t);" - "i8vec2 bitCount(i8vec2);" - "i8vec3 bitCount(i8vec3);" - "i8vec4 bitCount(i8vec4);" - - " int8_t bitCount( uint8_t);" - "i8vec2 bitCount(u8vec2);" - "i8vec3 bitCount(u8vec3);" - "i8vec4 bitCount(u8vec4);" - - " int8_t findLSB( int8_t);" - "i8vec2 findLSB(i8vec2);" - "i8vec3 findLSB(i8vec3);" - "i8vec4 findLSB(i8vec4);" - - " int8_t findLSB( uint8_t);" - "i8vec2 findLSB(u8vec2);" - "i8vec3 findLSB(u8vec3);" - "i8vec4 findLSB(u8vec4);" - - " int8_t findMSB( int8_t);" - "i8vec2 findMSB(i8vec2);" - "i8vec3 findMSB(i8vec3);" - "i8vec4 findMSB(i8vec4);" - - " int8_t findMSB( uint8_t);" - "i8vec2 findMSB(u8vec2);" - "i8vec3 findMSB(u8vec3);" - "i8vec4 findMSB(u8vec4);" - - "int16_t abs(int16_t);" - "i16vec2 abs(i16vec2);" - "i16vec3 abs(i16vec3);" - "i16vec4 abs(i16vec4);" - - "int16_t sign(int16_t);" - "i16vec2 sign(i16vec2);" - "i16vec3 sign(i16vec3);" - "i16vec4 sign(i16vec4);" - - "int16_t min(int16_t x, int16_t y);" - "i16vec2 min(i16vec2 x, int16_t y);" - "i16vec3 min(i16vec3 x, int16_t y);" - "i16vec4 min(i16vec4 x, int16_t y);" - "i16vec2 min(i16vec2 x, i16vec2 y);" - "i16vec3 min(i16vec3 x, i16vec3 y);" - "i16vec4 min(i16vec4 x, i16vec4 y);" - - "uint16_t min(uint16_t x, uint16_t y);" - "u16vec2 min(u16vec2 x, uint16_t y);" - "u16vec3 min(u16vec3 x, uint16_t y);" - "u16vec4 min(u16vec4 x, uint16_t y);" - "u16vec2 min(u16vec2 x, u16vec2 y);" - "u16vec3 min(u16vec3 x, u16vec3 y);" - "u16vec4 min(u16vec4 x, u16vec4 y);" - - "int16_t max(int16_t x, int16_t y);" - "i16vec2 max(i16vec2 x, int16_t y);" - "i16vec3 max(i16vec3 x, int16_t y);" - "i16vec4 max(i16vec4 x, int16_t y);" - "i16vec2 max(i16vec2 x, i16vec2 y);" - "i16vec3 max(i16vec3 x, i16vec3 y);" - "i16vec4 max(i16vec4 x, i16vec4 y);" - - "uint16_t max(uint16_t x, uint16_t y);" - "u16vec2 max(u16vec2 x, uint16_t y);" - "u16vec3 max(u16vec3 x, uint16_t y);" - "u16vec4 max(u16vec4 x, uint16_t y);" - "u16vec2 max(u16vec2 x, u16vec2 y);" - "u16vec3 max(u16vec3 x, u16vec3 y);" - "u16vec4 max(u16vec4 x, u16vec4 y);" - - "int16_t clamp(int16_t x, int16_t minVal, int16_t maxVal);" - "i16vec2 clamp(i16vec2 x, int16_t minVal, int16_t maxVal);" - "i16vec3 clamp(i16vec3 x, int16_t minVal, int16_t maxVal);" - "i16vec4 clamp(i16vec4 x, int16_t minVal, int16_t maxVal);" - "i16vec2 clamp(i16vec2 x, i16vec2 minVal, i16vec2 maxVal);" - "i16vec3 clamp(i16vec3 x, i16vec3 minVal, i16vec3 maxVal);" - "i16vec4 clamp(i16vec4 x, i16vec4 minVal, i16vec4 maxVal);" - - "uint16_t clamp(uint16_t x, uint16_t minVal, uint16_t maxVal);" - "u16vec2 clamp(u16vec2 x, uint16_t minVal, uint16_t maxVal);" - "u16vec3 clamp(u16vec3 x, uint16_t minVal, uint16_t maxVal);" - "u16vec4 clamp(u16vec4 x, uint16_t minVal, uint16_t maxVal);" - "u16vec2 clamp(u16vec2 x, u16vec2 minVal, u16vec2 maxVal);" - "u16vec3 clamp(u16vec3 x, u16vec3 minVal, u16vec3 maxVal);" - "u16vec4 clamp(u16vec4 x, u16vec4 minVal, u16vec4 maxVal);" - - "int16_t mix(int16_t, int16_t, bool);" - "i16vec2 mix(i16vec2, i16vec2, bvec2);" - "i16vec3 mix(i16vec3, i16vec3, bvec3);" - "i16vec4 mix(i16vec4, i16vec4, bvec4);" - "uint16_t mix(uint16_t, uint16_t, bool);" - "u16vec2 mix(u16vec2, u16vec2, bvec2);" - "u16vec3 mix(u16vec3, u16vec3, bvec3);" - "u16vec4 mix(u16vec4, u16vec4, bvec4);" - - "float16_t frexp(float16_t, out int16_t);" - "f16vec2 frexp(f16vec2, out i16vec2);" - "f16vec3 frexp(f16vec3, out i16vec3);" - "f16vec4 frexp(f16vec4, out i16vec4);" - - "float16_t ldexp(float16_t, int16_t);" - "f16vec2 ldexp(f16vec2, i16vec2);" - "f16vec3 ldexp(f16vec3, i16vec3);" - "f16vec4 ldexp(f16vec4, i16vec4);" - - "int16_t halfBitsToInt16(float16_t);" - "i16vec2 halfBitsToInt16(f16vec2);" - "i16vec3 halhBitsToInt16(f16vec3);" - "i16vec4 halfBitsToInt16(f16vec4);" - - "uint16_t halfBitsToUint16(float16_t);" - "u16vec2 halfBitsToUint16(f16vec2);" - "u16vec3 halfBitsToUint16(f16vec3);" - "u16vec4 halfBitsToUint16(f16vec4);" - - "int16_t float16BitsToInt16(float16_t);" - "i16vec2 float16BitsToInt16(f16vec2);" - "i16vec3 float16BitsToInt16(f16vec3);" - "i16vec4 float16BitsToInt16(f16vec4);" - - "uint16_t float16BitsToUint16(float16_t);" - "u16vec2 float16BitsToUint16(f16vec2);" - "u16vec3 float16BitsToUint16(f16vec3);" - "u16vec4 float16BitsToUint16(f16vec4);" - - "float16_t int16BitsToFloat16(int16_t);" - "f16vec2 int16BitsToFloat16(i16vec2);" - "f16vec3 int16BitsToFloat16(i16vec3);" - "f16vec4 int16BitsToFloat16(i16vec4);" - - "float16_t uint16BitsToFloat16(uint16_t);" - "f16vec2 uint16BitsToFloat16(u16vec2);" - "f16vec3 uint16BitsToFloat16(u16vec3);" - "f16vec4 uint16BitsToFloat16(u16vec4);" - - "float16_t int16BitsToHalf(int16_t);" - "f16vec2 int16BitsToHalf(i16vec2);" - "f16vec3 int16BitsToHalf(i16vec3);" - "f16vec4 int16BitsToHalf(i16vec4);" - - "float16_t uint16BitsToHalf(uint16_t);" - "f16vec2 uint16BitsToHalf(u16vec2);" - "f16vec3 uint16BitsToHalf(u16vec3);" - "f16vec4 uint16BitsToHalf(u16vec4);" - - "int packInt2x16(i16vec2);" - "uint packUint2x16(u16vec2);" - "int64_t packInt4x16(i16vec4);" - "uint64_t packUint4x16(u16vec4);" - "i16vec2 unpackInt2x16(int);" - "u16vec2 unpackUint2x16(uint);" - "i16vec4 unpackInt4x16(int64_t);" - "u16vec4 unpackUint4x16(uint64_t);" - - "bvec2 lessThan(i16vec2, i16vec2);" - "bvec3 lessThan(i16vec3, i16vec3);" - "bvec4 lessThan(i16vec4, i16vec4);" - "bvec2 lessThan(u16vec2, u16vec2);" - "bvec3 lessThan(u16vec3, u16vec3);" - "bvec4 lessThan(u16vec4, u16vec4);" - - "bvec2 lessThanEqual(i16vec2, i16vec2);" - "bvec3 lessThanEqual(i16vec3, i16vec3);" - "bvec4 lessThanEqual(i16vec4, i16vec4);" - "bvec2 lessThanEqual(u16vec2, u16vec2);" - "bvec3 lessThanEqual(u16vec3, u16vec3);" - "bvec4 lessThanEqual(u16vec4, u16vec4);" - - "bvec2 greaterThan(i16vec2, i16vec2);" - "bvec3 greaterThan(i16vec3, i16vec3);" - "bvec4 greaterThan(i16vec4, i16vec4);" - "bvec2 greaterThan(u16vec2, u16vec2);" - "bvec3 greaterThan(u16vec3, u16vec3);" - "bvec4 greaterThan(u16vec4, u16vec4);" - - "bvec2 greaterThanEqual(i16vec2, i16vec2);" - "bvec3 greaterThanEqual(i16vec3, i16vec3);" - "bvec4 greaterThanEqual(i16vec4, i16vec4);" - "bvec2 greaterThanEqual(u16vec2, u16vec2);" - "bvec3 greaterThanEqual(u16vec3, u16vec3);" - "bvec4 greaterThanEqual(u16vec4, u16vec4);" - - "bvec2 equal(i16vec2, i16vec2);" - "bvec3 equal(i16vec3, i16vec3);" - "bvec4 equal(i16vec4, i16vec4);" - "bvec2 equal(u16vec2, u16vec2);" - "bvec3 equal(u16vec3, u16vec3);" - "bvec4 equal(u16vec4, u16vec4);" - - "bvec2 notEqual(i16vec2, i16vec2);" - "bvec3 notEqual(i16vec3, i16vec3);" - "bvec4 notEqual(i16vec4, i16vec4);" - "bvec2 notEqual(u16vec2, u16vec2);" - "bvec3 notEqual(u16vec3, u16vec3);" - "bvec4 notEqual(u16vec4, u16vec4);" - - " int16_t bitfieldExtract( int16_t, int16_t, int16_t);" - "i16vec2 bitfieldExtract(i16vec2, int16_t, int16_t);" - "i16vec3 bitfieldExtract(i16vec3, int16_t, int16_t);" - "i16vec4 bitfieldExtract(i16vec4, int16_t, int16_t);" - - " uint16_t bitfieldExtract( uint16_t, int16_t, int16_t);" - "u16vec2 bitfieldExtract(u16vec2, int16_t, int16_t);" - "u16vec3 bitfieldExtract(u16vec3, int16_t, int16_t);" - "u16vec4 bitfieldExtract(u16vec4, int16_t, int16_t);" - - " int16_t bitfieldInsert( int16_t base, int16_t, int16_t, int16_t);" - "i16vec2 bitfieldInsert(i16vec2 base, i16vec2, int16_t, int16_t);" - "i16vec3 bitfieldInsert(i16vec3 base, i16vec3, int16_t, int16_t);" - "i16vec4 bitfieldInsert(i16vec4 base, i16vec4, int16_t, int16_t);" - - " uint16_t bitfieldInsert( uint16_t base, uint16_t, int16_t, int16_t);" - "u16vec2 bitfieldInsert(u16vec2 base, u16vec2, int16_t, int16_t);" - "u16vec3 bitfieldInsert(u16vec3 base, u16vec3, int16_t, int16_t);" - "u16vec4 bitfieldInsert(u16vec4 base, u16vec4, int16_t, int16_t);" - - " int16_t bitCount( int16_t);" - "i16vec2 bitCount(i16vec2);" - "i16vec3 bitCount(i16vec3);" - "i16vec4 bitCount(i16vec4);" - - " int16_t bitCount( uint16_t);" - "i16vec2 bitCount(u16vec2);" - "i16vec3 bitCount(u16vec3);" - "i16vec4 bitCount(u16vec4);" - - " int16_t findLSB( int16_t);" - "i16vec2 findLSB(i16vec2);" - "i16vec3 findLSB(i16vec3);" - "i16vec4 findLSB(i16vec4);" - - " int16_t findLSB( uint16_t);" - "i16vec2 findLSB(u16vec2);" - "i16vec3 findLSB(u16vec3);" - "i16vec4 findLSB(u16vec4);" - - " int16_t findMSB( int16_t);" - "i16vec2 findMSB(i16vec2);" - "i16vec3 findMSB(i16vec3);" - "i16vec4 findMSB(i16vec4);" - - " int16_t findMSB( uint16_t);" - "i16vec2 findMSB(u16vec2);" - "i16vec3 findMSB(u16vec3);" - "i16vec4 findMSB(u16vec4);" - - "int16_t pack16(i8vec2);" - "uint16_t pack16(u8vec2);" - "int32_t pack32(i8vec4);" - "uint32_t pack32(u8vec4);" - "int32_t pack32(i16vec2);" - "uint32_t pack32(u16vec2);" - "int64_t pack64(i16vec4);" - "uint64_t pack64(u16vec4);" - "int64_t pack64(i32vec2);" - "uint64_t pack64(u32vec2);" - - "i8vec2 unpack8(int16_t);" - "u8vec2 unpack8(uint16_t);" - "i8vec4 unpack8(int32_t);" - "u8vec4 unpack8(uint32_t);" - "i16vec2 unpack16(int32_t);" - "u16vec2 unpack16(uint32_t);" - "i16vec4 unpack16(int64_t);" - "u16vec4 unpack16(uint64_t);" - "i32vec2 unpack32(int64_t);" - "u32vec2 unpack32(uint64_t);" - "\n"); - } - - // Builtins for GL_EXT_texture_shadow_lod - if ((profile == EEsProfile && version >= 300) || ((profile != EEsProfile && version >= 130))) { - commonBuiltins.append( - "float texture(sampler2DArrayShadow, vec4, float);" - "float texture(samplerCubeArrayShadow, vec4, float, float);" - "float textureLod(sampler2DArrayShadow, vec4, float);" - "float textureLod(samplerCubeShadow, vec4, float);" - "float textureLod(samplerCubeArrayShadow, vec4, float, float);" - "float textureLodOffset(sampler2DArrayShadow, vec4, float, ivec2);" - "float textureOffset(sampler2DArrayShadow, vec4 , ivec2, float);" - "\n"); - } - - if (profile != EEsProfile && version >= 450) { - stageBuiltins[EShLangFragment].append(derivativesAndControl64bits); - stageBuiltins[EShLangFragment].append( - "float64_t interpolateAtCentroid(float64_t);" - "f64vec2 interpolateAtCentroid(f64vec2);" - "f64vec3 interpolateAtCentroid(f64vec3);" - "f64vec4 interpolateAtCentroid(f64vec4);" - - "float64_t interpolateAtSample(float64_t, int);" - "f64vec2 interpolateAtSample(f64vec2, int);" - "f64vec3 interpolateAtSample(f64vec3, int);" - "f64vec4 interpolateAtSample(f64vec4, int);" - - "float64_t interpolateAtOffset(float64_t, f64vec2);" - "f64vec2 interpolateAtOffset(f64vec2, f64vec2);" - "f64vec3 interpolateAtOffset(f64vec3, f64vec2);" - "f64vec4 interpolateAtOffset(f64vec4, f64vec2);" - - "\n"); - - } - - // QCOM_image_processing - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - commonBuiltins.append( - "vec4 textureWeightedQCOM(sampler2D, vec2, sampler2DArray);" - "vec4 textureWeightedQCOM(sampler2D, vec2, sampler1DArray);" - "vec4 textureBoxFilterQCOM(sampler2D, vec2, vec2);" - "vec4 textureBlockMatchSADQCOM(sampler2D, uvec2, sampler2D, uvec2, uvec2);" - "vec4 textureBlockMatchSSDQCOM(sampler2D, uvec2, sampler2D, uvec2, uvec2);" - "\n"); - } - - //============================================================================ - // - // Prototypes for built-in functions seen by vertex shaders only. - // (Except legacy lod functions, where it depends which release they are - // vertex only.) - // - //============================================================================ - - // - // Geometric Functions. - // - if (spvVersion.vulkan == 0 && IncludeLegacy(version, profile, spvVersion)) - stageBuiltins[EShLangVertex].append("vec4 ftransform();"); - - // - // Original-style texture Functions with lod. - // - TString* s; - if (version == 100) - s = &stageBuiltins[EShLangVertex]; - else - s = &commonBuiltins; - if ((profile == EEsProfile && version == 100) || - profile == ECompatibilityProfile || - (profile == ECoreProfile && version < 420) || - profile == ENoProfile) { - if (spvVersion.spv == 0) { - s->append( - "vec4 texture2DLod(sampler2D, vec2, float);" // GL_ARB_shader_texture_lod - "vec4 texture2DProjLod(sampler2D, vec3, float);" // GL_ARB_shader_texture_lod - "vec4 texture2DProjLod(sampler2D, vec4, float);" // GL_ARB_shader_texture_lod - "vec4 texture3DLod(sampler3D, vec3, float);" // GL_ARB_shader_texture_lod // OES_texture_3D, but caught by keyword check - "vec4 texture3DProjLod(sampler3D, vec4, float);" // GL_ARB_shader_texture_lod // OES_texture_3D, but caught by keyword check - "vec4 textureCubeLod(samplerCube, vec3, float);" // GL_ARB_shader_texture_lod - - "\n"); - } - } - if ( profile == ECompatibilityProfile || - (profile == ECoreProfile && version < 420) || - profile == ENoProfile) { - if (spvVersion.spv == 0) { - s->append( - "vec4 texture1DLod(sampler1D, float, float);" // GL_ARB_shader_texture_lod - "vec4 texture1DProjLod(sampler1D, vec2, float);" // GL_ARB_shader_texture_lod - "vec4 texture1DProjLod(sampler1D, vec4, float);" // GL_ARB_shader_texture_lod - "vec4 shadow1DLod(sampler1DShadow, vec3, float);" // GL_ARB_shader_texture_lod - "vec4 shadow2DLod(sampler2DShadow, vec3, float);" // GL_ARB_shader_texture_lod - "vec4 shadow1DProjLod(sampler1DShadow, vec4, float);" // GL_ARB_shader_texture_lod - "vec4 shadow2DProjLod(sampler2DShadow, vec4, float);" // GL_ARB_shader_texture_lod - - "vec4 texture1DGradARB(sampler1D, float, float, float);" // GL_ARB_shader_texture_lod - "vec4 texture1DProjGradARB(sampler1D, vec2, float, float);" // GL_ARB_shader_texture_lod - "vec4 texture1DProjGradARB(sampler1D, vec4, float, float);" // GL_ARB_shader_texture_lod - "vec4 texture2DGradARB(sampler2D, vec2, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture2DProjGradARB(sampler2D, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture2DProjGradARB(sampler2D, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture3DGradARB(sampler3D, vec3, vec3, vec3);" // GL_ARB_shader_texture_lod - "vec4 texture3DProjGradARB(sampler3D, vec4, vec3, vec3);" // GL_ARB_shader_texture_lod - "vec4 textureCubeGradARB(samplerCube, vec3, vec3, vec3);" // GL_ARB_shader_texture_lod - "vec4 shadow1DGradARB(sampler1DShadow, vec3, float, float);" // GL_ARB_shader_texture_lod - "vec4 shadow1DProjGradARB( sampler1DShadow, vec4, float, float);" // GL_ARB_shader_texture_lod - "vec4 shadow2DGradARB(sampler2DShadow, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 shadow2DProjGradARB( sampler2DShadow, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture2DRectGradARB(sampler2DRect, vec2, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture2DRectProjGradARB( sampler2DRect, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 texture2DRectProjGradARB( sampler2DRect, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 shadow2DRectGradARB( sampler2DRectShadow, vec3, vec2, vec2);" // GL_ARB_shader_texture_lod - "vec4 shadow2DRectProjGradARB(sampler2DRectShadow, vec4, vec2, vec2);" // GL_ARB_shader_texture_lod - - "\n"); - } - } - - if ((profile != EEsProfile && version >= 150) || - (profile == EEsProfile && version >= 310)) { - //============================================================================ - // - // Prototypes for built-in functions seen by geometry shaders only. - // - //============================================================================ - - if (profile != EEsProfile && (version >= 400 || version == 150)) { - stageBuiltins[EShLangGeometry].append( - "void EmitStreamVertex(int);" - "void EndStreamPrimitive(int);" - ); - } - stageBuiltins[EShLangGeometry].append( - "void EmitVertex();" - "void EndPrimitive();" - "\n"); - } - - //============================================================================ - // - // Prototypes for all control functions. - // - //============================================================================ - bool esBarrier = (profile == EEsProfile && version >= 310); - if ((profile != EEsProfile && version >= 150) || esBarrier) - stageBuiltins[EShLangTessControl].append( - "void barrier();" - ); - if ((profile != EEsProfile && version >= 420) || esBarrier) - stageBuiltins[EShLangCompute].append( - "void barrier();" - ); - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { - stageBuiltins[EShLangMesh].append( - "void barrier();" - ); - stageBuiltins[EShLangTask].append( - "void barrier();" - ); - } - if ((profile != EEsProfile && version >= 130) || esBarrier) - commonBuiltins.append( - "void memoryBarrier();" - ); - if ((profile != EEsProfile && version >= 420) || esBarrier) { - commonBuiltins.append( - "void memoryBarrierBuffer();" - ); - stageBuiltins[EShLangCompute].append( - "void memoryBarrierShared();" - "void groupMemoryBarrier();" - ); - } - if ((profile != EEsProfile && version >= 420) || esBarrier) { - if (spvVersion.vulkan == 0 || spvVersion.vulkanRelaxed) { - commonBuiltins.append("void memoryBarrierAtomicCounter();"); - } - commonBuiltins.append("void memoryBarrierImage();"); - } - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { - stageBuiltins[EShLangMesh].append( - "void memoryBarrierShared();" - "void groupMemoryBarrier();" - ); - stageBuiltins[EShLangTask].append( - "void memoryBarrierShared();" - "void groupMemoryBarrier();" - ); - } - - commonBuiltins.append("void controlBarrier(int, int, int, int);\n" - "void memoryBarrier(int, int, int);\n"); - - commonBuiltins.append("void debugPrintfEXT();\n"); - - if (profile != EEsProfile && version >= 450) { - // coopMatStoreNV perhaps ought to have "out" on the buf parameter, but - // adding it introduces undesirable tempArgs on the stack. What we want - // is more like "buf" thought of as a pointer value being an in parameter. - stageBuiltins[EShLangCompute].append( - "void coopMatLoadNV(out fcoopmatNV m, volatile coherent float16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out fcoopmatNV m, volatile coherent float[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out fcoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n" - - "void coopMatStoreNV(fcoopmatNV m, volatile coherent float16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(fcoopmatNV m, volatile coherent float[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(fcoopmatNV m, volatile coherent float64_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(fcoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(fcoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(fcoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(fcoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(fcoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(fcoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n" - - "fcoopmatNV coopMatMulAddNV(fcoopmatNV A, fcoopmatNV B, fcoopmatNV C);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent int8_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent int16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent int[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent int64_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent ivec2[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent ivec4[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out icoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n" - - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent int8_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent int16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent int[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent int64_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent ivec2[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent ivec4[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatLoadNV(out ucoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n" - - "void coopMatStoreNV(icoopmatNV m, volatile coherent int8_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(icoopmatNV m, volatile coherent int16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(icoopmatNV m, volatile coherent int[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(icoopmatNV m, volatile coherent int64_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(icoopmatNV m, volatile coherent ivec2[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(icoopmatNV m, volatile coherent ivec4[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(icoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(icoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(icoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(icoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(icoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(icoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n" - - "void coopMatStoreNV(ucoopmatNV m, volatile coherent int8_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(ucoopmatNV m, volatile coherent int16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(ucoopmatNV m, volatile coherent int[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(ucoopmatNV m, volatile coherent int64_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(ucoopmatNV m, volatile coherent ivec2[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(ucoopmatNV m, volatile coherent ivec4[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(ucoopmatNV m, volatile coherent uint8_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(ucoopmatNV m, volatile coherent uint16_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(ucoopmatNV m, volatile coherent uint[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(ucoopmatNV m, volatile coherent uint64_t[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(ucoopmatNV m, volatile coherent uvec2[] buf, uint element, uint stride, bool colMajor);\n" - "void coopMatStoreNV(ucoopmatNV m, volatile coherent uvec4[] buf, uint element, uint stride, bool colMajor);\n" - - "icoopmatNV coopMatMulAddNV(icoopmatNV A, icoopmatNV B, icoopmatNV C);\n" - "ucoopmatNV coopMatMulAddNV(ucoopmatNV A, ucoopmatNV B, ucoopmatNV C);\n" - ); - - std::string cooperativeMatrixFuncs = - "void coopMatLoad(out coopmat m, volatile coherent int8_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent int16_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent int32_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent int64_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent uint8_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent uint16_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent uint32_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent uint64_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent float16_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent float[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent float64_t[] buf, uint element, uint stride, int matrixLayout);\n" - - "void coopMatLoad(out coopmat m, volatile coherent i8vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent i16vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent i32vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent i64vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent u8vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent u16vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent u32vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent u64vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent f16vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent f32vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent f64vec2[] buf, uint element, uint stride, int matrixLayout);\n" - - "void coopMatLoad(out coopmat m, volatile coherent i8vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent i16vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent i32vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent i64vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent u8vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent u16vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent u32vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent u64vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent f16vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent f32vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatLoad(out coopmat m, volatile coherent f64vec4[] buf, uint element, uint stride, int matrixLayout);\n" - - "void coopMatStore(coopmat m, volatile coherent int8_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent int16_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent int32_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent int64_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent uint8_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent uint16_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent uint32_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent uint64_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent float16_t[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent float[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent float64_t[] buf, uint element, uint stride, int matrixLayout);\n" - - "void coopMatStore(coopmat m, volatile coherent i8vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent i16vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent i32vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent i64vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent u8vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent u16vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent u32vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent u64vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent f16vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent f32vec2[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent f64vec2[] buf, uint element, uint stride, int matrixLayout);\n" - - "void coopMatStore(coopmat m, volatile coherent i8vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent i16vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent i32vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent i64vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent u8vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent u16vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent u32vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent u64vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent f16vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent f32vec4[] buf, uint element, uint stride, int matrixLayout);\n" - "void coopMatStore(coopmat m, volatile coherent f64vec4[] buf, uint element, uint stride, int matrixLayout);\n" - - "coopmat coopMatMulAdd(coopmat A, coopmat B, coopmat C);\n" - "coopmat coopMatMulAdd(coopmat A, coopmat B, coopmat C, int matrixOperands);\n"; - - commonBuiltins.append(cooperativeMatrixFuncs.c_str()); - - commonBuiltins.append( - "const int gl_MatrixUseA = 0;\n" - "const int gl_MatrixUseB = 1;\n" - "const int gl_MatrixUseAccumulator = 2;\n" - "const int gl_MatrixOperandsSaturatingAccumulation = 0x10;\n" - "const int gl_CooperativeMatrixLayoutRowMajor = 0;\n" - "const int gl_CooperativeMatrixLayoutColumnMajor = 1;\n" - "\n" - ); - } - - //============================================================================ - // - // Prototypes for built-in functions seen by fragment shaders only. - // - //============================================================================ - - // - // Original-style texture Functions with bias. - // - if (spvVersion.spv == 0 && (profile != EEsProfile || version == 100)) { - stageBuiltins[EShLangFragment].append( - "vec4 texture2D(sampler2D, vec2, float);" - "vec4 texture2DProj(sampler2D, vec3, float);" - "vec4 texture2DProj(sampler2D, vec4, float);" - "vec4 texture3D(sampler3D, vec3, float);" // OES_texture_3D - "vec4 texture3DProj(sampler3D, vec4, float);" // OES_texture_3D - "vec4 textureCube(samplerCube, vec3, float);" - - "\n"); - } - if (spvVersion.spv == 0 && (profile != EEsProfile && version > 100)) { - stageBuiltins[EShLangFragment].append( - "vec4 texture1D(sampler1D, float, float);" - "vec4 texture1DProj(sampler1D, vec2, float);" - "vec4 texture1DProj(sampler1D, vec4, float);" - "vec4 shadow1D(sampler1DShadow, vec3, float);" - "vec4 shadow2D(sampler2DShadow, vec3, float);" - "vec4 shadow1DProj(sampler1DShadow, vec4, float);" - "vec4 shadow2DProj(sampler2DShadow, vec4, float);" - - "\n"); - } - if (spvVersion.spv == 0 && profile == EEsProfile) { - stageBuiltins[EShLangFragment].append( - "vec4 texture2DLodEXT(sampler2D, vec2, float);" // GL_EXT_shader_texture_lod - "vec4 texture2DProjLodEXT(sampler2D, vec3, float);" // GL_EXT_shader_texture_lod - "vec4 texture2DProjLodEXT(sampler2D, vec4, float);" // GL_EXT_shader_texture_lod - "vec4 textureCubeLodEXT(samplerCube, vec3, float);" // GL_EXT_shader_texture_lod - - "\n"); - } - - // GL_EXT_shader_tile_image - if (spvVersion.vulkan > 0) { - stageBuiltins[EShLangFragment].append( - "lowp uint stencilAttachmentReadEXT();" - "lowp uint stencilAttachmentReadEXT(int);" - "highp float depthAttachmentReadEXT();" - "highp float depthAttachmentReadEXT(int);" - "\n"); - stageBuiltins[EShLangFragment].append( - "vec4 colorAttachmentReadEXT(attachmentEXT);" - "vec4 colorAttachmentReadEXT(attachmentEXT, int);" - "ivec4 colorAttachmentReadEXT(iattachmentEXT);" - "ivec4 colorAttachmentReadEXT(iattachmentEXT, int);" - "uvec4 colorAttachmentReadEXT(uattachmentEXT);" - "uvec4 colorAttachmentReadEXT(uattachmentEXT, int);" - "\n"); - } - - // GL_ARB_derivative_control - if (profile != EEsProfile && version >= 400) { - stageBuiltins[EShLangFragment].append(derivativeControls); - stageBuiltins[EShLangFragment].append("\n"); - } - - // GL_OES_shader_multisample_interpolation - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 400)) { - stageBuiltins[EShLangFragment].append( - "float interpolateAtCentroid(float);" - "vec2 interpolateAtCentroid(vec2);" - "vec3 interpolateAtCentroid(vec3);" - "vec4 interpolateAtCentroid(vec4);" - - "float interpolateAtSample(float, int);" - "vec2 interpolateAtSample(vec2, int);" - "vec3 interpolateAtSample(vec3, int);" - "vec4 interpolateAtSample(vec4, int);" - - "float interpolateAtOffset(float, vec2);" - "vec2 interpolateAtOffset(vec2, vec2);" - "vec3 interpolateAtOffset(vec3, vec2);" - "vec4 interpolateAtOffset(vec4, vec2);" - - "\n"); - } - - stageBuiltins[EShLangFragment].append( - "void beginInvocationInterlockARB(void);" - "void endInvocationInterlockARB(void);"); - - stageBuiltins[EShLangFragment].append( - "bool helperInvocationEXT();" - "\n"); - - // GL_AMD_shader_explicit_vertex_parameter - if (profile != EEsProfile && version >= 450) { - stageBuiltins[EShLangFragment].append( - "float interpolateAtVertexAMD(float, uint);" - "vec2 interpolateAtVertexAMD(vec2, uint);" - "vec3 interpolateAtVertexAMD(vec3, uint);" - "vec4 interpolateAtVertexAMD(vec4, uint);" - - "int interpolateAtVertexAMD(int, uint);" - "ivec2 interpolateAtVertexAMD(ivec2, uint);" - "ivec3 interpolateAtVertexAMD(ivec3, uint);" - "ivec4 interpolateAtVertexAMD(ivec4, uint);" - - "uint interpolateAtVertexAMD(uint, uint);" - "uvec2 interpolateAtVertexAMD(uvec2, uint);" - "uvec3 interpolateAtVertexAMD(uvec3, uint);" - "uvec4 interpolateAtVertexAMD(uvec4, uint);" - - "float16_t interpolateAtVertexAMD(float16_t, uint);" - "f16vec2 interpolateAtVertexAMD(f16vec2, uint);" - "f16vec3 interpolateAtVertexAMD(f16vec3, uint);" - "f16vec4 interpolateAtVertexAMD(f16vec4, uint);" - - "\n"); - } - - // GL_AMD_gpu_shader_half_float - if (profile != EEsProfile && version >= 450) { - stageBuiltins[EShLangFragment].append(derivativesAndControl16bits); - stageBuiltins[EShLangFragment].append("\n"); - - stageBuiltins[EShLangFragment].append( - "float16_t interpolateAtCentroid(float16_t);" - "f16vec2 interpolateAtCentroid(f16vec2);" - "f16vec3 interpolateAtCentroid(f16vec3);" - "f16vec4 interpolateAtCentroid(f16vec4);" - - "float16_t interpolateAtSample(float16_t, int);" - "f16vec2 interpolateAtSample(f16vec2, int);" - "f16vec3 interpolateAtSample(f16vec3, int);" - "f16vec4 interpolateAtSample(f16vec4, int);" - - "float16_t interpolateAtOffset(float16_t, f16vec2);" - "f16vec2 interpolateAtOffset(f16vec2, f16vec2);" - "f16vec3 interpolateAtOffset(f16vec3, f16vec2);" - "f16vec4 interpolateAtOffset(f16vec4, f16vec2);" - - "\n"); - } - - // GL_ARB_shader_clock& GL_EXT_shader_realtime_clock - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append( - "uvec2 clock2x32ARB();" - "uint64_t clockARB();" - "uvec2 clockRealtime2x32EXT();" - "uint64_t clockRealtimeEXT();" - "\n"); - } - - // GL_AMD_shader_fragment_mask - if (profile != EEsProfile && version >= 450 && spvVersion.vulkan > 0) { - stageBuiltins[EShLangFragment].append( - "uint fragmentMaskFetchAMD(subpassInputMS);" - "uint fragmentMaskFetchAMD(isubpassInputMS);" - "uint fragmentMaskFetchAMD(usubpassInputMS);" - - "vec4 fragmentFetchAMD(subpassInputMS, uint);" - "ivec4 fragmentFetchAMD(isubpassInputMS, uint);" - "uvec4 fragmentFetchAMD(usubpassInputMS, uint);" - - "\n"); - } - - // Builtins for GL_NV_ray_tracing/GL_NV_ray_tracing_motion_blur/GL_EXT_ray_tracing/GL_EXT_ray_query/ - // GL_NV_shader_invocation_reorder/GL_KHR_ray_tracing_position_Fetch - if (profile != EEsProfile && version >= 460) { - commonBuiltins.append("void rayQueryInitializeEXT(rayQueryEXT, accelerationStructureEXT, uint, uint, vec3, float, vec3, float);" - "void rayQueryTerminateEXT(rayQueryEXT);" - "void rayQueryGenerateIntersectionEXT(rayQueryEXT, float);" - "void rayQueryConfirmIntersectionEXT(rayQueryEXT);" - "bool rayQueryProceedEXT(rayQueryEXT);" - "uint rayQueryGetIntersectionTypeEXT(rayQueryEXT, bool);" - "float rayQueryGetRayTMinEXT(rayQueryEXT);" - "uint rayQueryGetRayFlagsEXT(rayQueryEXT);" - "vec3 rayQueryGetWorldRayOriginEXT(rayQueryEXT);" - "vec3 rayQueryGetWorldRayDirectionEXT(rayQueryEXT);" - "float rayQueryGetIntersectionTEXT(rayQueryEXT, bool);" - "int rayQueryGetIntersectionInstanceCustomIndexEXT(rayQueryEXT, bool);" - "int rayQueryGetIntersectionInstanceIdEXT(rayQueryEXT, bool);" - "uint rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT(rayQueryEXT, bool);" - "int rayQueryGetIntersectionGeometryIndexEXT(rayQueryEXT, bool);" - "int rayQueryGetIntersectionPrimitiveIndexEXT(rayQueryEXT, bool);" - "vec2 rayQueryGetIntersectionBarycentricsEXT(rayQueryEXT, bool);" - "bool rayQueryGetIntersectionFrontFaceEXT(rayQueryEXT, bool);" - "bool rayQueryGetIntersectionCandidateAABBOpaqueEXT(rayQueryEXT);" - "vec3 rayQueryGetIntersectionObjectRayDirectionEXT(rayQueryEXT, bool);" - "vec3 rayQueryGetIntersectionObjectRayOriginEXT(rayQueryEXT, bool);" - "mat4x3 rayQueryGetIntersectionObjectToWorldEXT(rayQueryEXT, bool);" - "mat4x3 rayQueryGetIntersectionWorldToObjectEXT(rayQueryEXT, bool);" - "void rayQueryGetIntersectionTriangleVertexPositionsEXT(rayQueryEXT, bool, out vec3[3]);" - "\n"); - - stageBuiltins[EShLangRayGen].append( - "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" - "void traceRayMotionNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,float,int);" - "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" - "void executeCallableNV(uint, int);" - "void executeCallableEXT(uint, int);" - "void hitObjectTraceRayNV(hitObjectNV,accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" - "void hitObjectTraceRayMotionNV(hitObjectNV,accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,float,int);" - "void hitObjectRecordHitNV(hitObjectNV,accelerationStructureEXT,int,int,int,uint,uint,uint,vec3,float,vec3,float,int);" - "void hitObjectRecordHitMotionNV(hitObjectNV,accelerationStructureEXT,int,int,int,uint,uint,uint,vec3,float,vec3,float,float,int);" - "void hitObjectRecordHitWithIndexNV(hitObjectNV, accelerationStructureEXT,int,int,int,uint,uint,vec3,float,vec3,float,int);" - "void hitObjectRecordHitWithIndexMotionNV(hitObjectNV, accelerationStructureEXT,int,int,int,uint,uint,vec3,float,vec3,float,float,int);" - "void hitObjectRecordMissNV(hitObjectNV,uint,vec3,float,vec3,float);" - "void hitObjectRecordMissMotionNV(hitObjectNV,uint,vec3,float,vec3,float,float);" - "void hitObjectRecordEmptyNV(hitObjectNV);" - "void hitObjectExecuteShaderNV(hitObjectNV,int);" - "bool hitObjectIsEmptyNV(hitObjectNV);" - "bool hitObjectIsMissNV(hitObjectNV);" - "bool hitObjectIsHitNV(hitObjectNV);" - "float hitObjectGetRayTMinNV(hitObjectNV);" - "float hitObjectGetRayTMaxNV(hitObjectNV);" - "vec3 hitObjectGetWorldRayOriginNV(hitObjectNV);" - "vec3 hitObjectGetWorldRayDirectionNV(hitObjectNV);" - "vec3 hitObjectGetObjectRayOriginNV(hitObjectNV);" - "vec3 hitObjectGetObjectRayDirectionNV(hitObjectNV);" - "mat4x3 hitObjectGetWorldToObjectNV(hitObjectNV);" - "mat4x3 hitObjectGetObjectToWorldNV(hitObjectNV);" - "int hitObjectGetInstanceCustomIndexNV(hitObjectNV);" - "int hitObjectGetInstanceIdNV(hitObjectNV);" - "int hitObjectGetGeometryIndexNV(hitObjectNV);" - "int hitObjectGetPrimitiveIndexNV(hitObjectNV);" - "uint hitObjectGetHitKindNV(hitObjectNV);" - "void hitObjectGetAttributesNV(hitObjectNV,int);" - "float hitObjectGetCurrentTimeNV(hitObjectNV);" - "uint hitObjectGetShaderBindingTableRecordIndexNV(hitObjectNV);" - "uvec2 hitObjectGetShaderRecordBufferHandleNV(hitObjectNV);" - "void reorderThreadNV(uint, uint);" - "void reorderThreadNV(hitObjectNV);" - "void reorderThreadNV(hitObjectNV, uint, uint);" - "vec3 fetchMicroTriangleVertexPositionNV(accelerationStructureEXT, int, int, int, ivec2);" - "vec2 fetchMicroTriangleVertexBarycentricNV(accelerationStructureEXT, int, int, int, ivec2);" - "\n"); - stageBuiltins[EShLangIntersect].append( - "bool reportIntersectionNV(float, uint);" - "bool reportIntersectionEXT(float, uint);" - "\n"); - stageBuiltins[EShLangAnyHit].append( - "void ignoreIntersectionNV();" - "void terminateRayNV();" - "\n"); - stageBuiltins[EShLangClosestHit].append( - "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" - "void traceRayMotionNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,float,int);" - "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" - "void executeCallableNV(uint, int);" - "void executeCallableEXT(uint, int);" - "void hitObjectTraceRayNV(hitObjectNV,accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" - "void hitObjectTraceRayMotionNV(hitObjectNV,accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,float,int);" - "void hitObjectRecordHitNV(hitObjectNV,accelerationStructureEXT,int,int,int,uint,uint,uint,vec3,float,vec3,float,int);" - "void hitObjectRecordHitMotionNV(hitObjectNV,accelerationStructureEXT,int,int,int,uint,uint,uint,vec3,float,vec3,float,float,int);" - "void hitObjectRecordHitWithIndexNV(hitObjectNV,accelerationStructureEXT,int,int,int,uint,uint,vec3,float,vec3,float,int);" - "void hitObjectRecordHitWithIndexMotionNV(hitObjectNV, accelerationStructureEXT,int,int,int,uint,uint,vec3,float,vec3,float,float,int);" - "void hitObjectRecordMissNV(hitObjectNV, uint, vec3, float, vec3, float);" - "void hitObjectRecordMissMotionNV(hitObjectNV,uint,vec3,float,vec3,float,float);" - "void hitObjectRecordEmptyNV(hitObjectNV);" - "void hitObjectExecuteShaderNV(hitObjectNV, int);" - "bool hitObjectIsEmptyNV(hitObjectNV);" - "bool hitObjectIsMissNV(hitObjectNV);" - "bool hitObjectIsHitNV(hitObjectNV);" - "float hitObjectGetRayTMinNV(hitObjectNV);" - "float hitObjectGetRayTMaxNV(hitObjectNV);" - "vec3 hitObjectGetWorldRayOriginNV(hitObjectNV);" - "vec3 hitObjectGetWorldRayDirectionNV(hitObjectNV);" - "vec3 hitObjectGetObjectRayOriginNV(hitObjectNV);" - "vec3 hitObjectGetObjectRayDirectionNV(hitObjectNV);" - "mat4x3 hitObjectGetWorldToObjectNV(hitObjectNV);" - "mat4x3 hitObjectGetObjectToWorldNV(hitObjectNV);" - "int hitObjectGetInstanceCustomIndexNV(hitObjectNV);" - "int hitObjectGetInstanceIdNV(hitObjectNV);" - "int hitObjectGetGeometryIndexNV(hitObjectNV);" - "int hitObjectGetPrimitiveIndexNV(hitObjectNV);" - "uint hitObjectGetHitKindNV(hitObjectNV);" - "void hitObjectGetAttributesNV(hitObjectNV,int);" - "float hitObjectGetCurrentTimeNV(hitObjectNV);" - "uint hitObjectGetShaderBindingTableRecordIndexNV(hitObjectNV);" - "uvec2 hitObjectGetShaderRecordBufferHandleNV(hitObjectNV);" - "\n"); - stageBuiltins[EShLangMiss].append( - "void traceNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" - "void traceRayMotionNV(accelerationStructureNV,uint,uint,uint,uint,uint,vec3,float,vec3,float,float,int);" - "void traceRayEXT(accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" - "void executeCallableNV(uint, int);" - "void executeCallableEXT(uint, int);" - "void hitObjectTraceRayNV(hitObjectNV,accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,int);" - "void hitObjectTraceRayMotionNV(hitObjectNV,accelerationStructureEXT,uint,uint,uint,uint,uint,vec3,float,vec3,float,float,int);" - "void hitObjectRecordHitNV(hitObjectNV,accelerationStructureEXT,int,int,int,uint,uint,uint,vec3,float,vec3,float,int);" - "void hitObjectRecordHitMotionNV(hitObjectNV,accelerationStructureEXT,int,int,int,uint,uint,uint,vec3,float,vec3,float,float,int);" - "void hitObjectRecordHitWithIndexNV(hitObjectNV,accelerationStructureEXT,int,int,int,uint,uint,vec3,float,vec3,float,int);" - "void hitObjectRecordHitWithIndexMotionNV(hitObjectNV, accelerationStructureEXT,int,int,int,uint,uint,vec3,float,vec3,float,float,int);" - "void hitObjectRecordMissNV(hitObjectNV, uint, vec3, float, vec3, float);" - "void hitObjectRecordMissMotionNV(hitObjectNV,uint,vec3,float,vec3,float,float);" - "void hitObjectRecordEmptyNV(hitObjectNV);" - "void hitObjectExecuteShaderNV(hitObjectNV, int);" - "bool hitObjectIsEmptyNV(hitObjectNV);" - "bool hitObjectIsMissNV(hitObjectNV);" - "bool hitObjectIsHitNV(hitObjectNV);" - "float hitObjectGetRayTMinNV(hitObjectNV);" - "float hitObjectGetRayTMaxNV(hitObjectNV);" - "vec3 hitObjectGetWorldRayOriginNV(hitObjectNV);" - "vec3 hitObjectGetWorldRayDirectionNV(hitObjectNV);" - "vec3 hitObjectGetObjectRayOriginNV(hitObjectNV);" - "vec3 hitObjectGetObjectRayDirectionNV(hitObjectNV);" - "mat4x3 hitObjectGetWorldToObjectNV(hitObjectNV);" - "mat4x3 hitObjectGetObjectToWorldNV(hitObjectNV);" - "int hitObjectGetInstanceCustomIndexNV(hitObjectNV);" - "int hitObjectGetInstanceIdNV(hitObjectNV);" - "int hitObjectGetGeometryIndexNV(hitObjectNV);" - "int hitObjectGetPrimitiveIndexNV(hitObjectNV);" - "uint hitObjectGetHitKindNV(hitObjectNV);" - "void hitObjectGetAttributesNV(hitObjectNV,int);" - "float hitObjectGetCurrentTimeNV(hitObjectNV);" - "uint hitObjectGetShaderBindingTableRecordIndexNV(hitObjectNV);" - "uvec2 hitObjectGetShaderRecordBufferHandleNV(hitObjectNV);" - "\n"); - stageBuiltins[EShLangCallable].append( - "void executeCallableNV(uint, int);" - "void executeCallableEXT(uint, int);" - "\n"); - } - - //E_SPV_NV_compute_shader_derivatives - if ((profile == EEsProfile && version >= 320) || (profile != EEsProfile && version >= 450)) { - stageBuiltins[EShLangCompute].append(derivativeControls); - stageBuiltins[EShLangCompute].append("\n"); - } - if (profile != EEsProfile && version >= 450) { - stageBuiltins[EShLangCompute].append(derivativesAndControl16bits); - stageBuiltins[EShLangCompute].append(derivativesAndControl64bits); - stageBuiltins[EShLangCompute].append("\n"); - } - - // Builtins for GL_NV_mesh_shader - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { - stageBuiltins[EShLangMesh].append( - "void writePackedPrimitiveIndices4x8NV(uint, uint);" - "\n"); - } - // Builtins for GL_EXT_mesh_shader - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { - // Builtins for GL_EXT_mesh_shader - stageBuiltins[EShLangTask].append( - "void EmitMeshTasksEXT(uint, uint, uint);" - "\n"); - - stageBuiltins[EShLangMesh].append( - "void SetMeshOutputsEXT(uint, uint);" - "\n"); - } - // Builtins for GL_NV_displacement_micromap - if ((profile != EEsProfile && version >= 460) || (profile == EEsProfile && version >= 320)) { - stageBuiltins[EShLangMesh].append( - "vec3 fetchMicroTriangleVertexPositionNV(accelerationStructureEXT, int, int, int, ivec2);" - "vec2 fetchMicroTriangleVertexBarycentricNV(accelerationStructureEXT, int, int, int, ivec2);" - "\n"); - - stageBuiltins[EShLangCompute].append( - "vec3 fetchMicroTriangleVertexPositionNV(accelerationStructureEXT, int, int, int, ivec2);" - "vec2 fetchMicroTriangleVertexBarycentricNV(accelerationStructureEXT, int, int, int, ivec2);" - "\n"); - - } - - - //============================================================================ - // - // Standard Uniforms - // - //============================================================================ - - // - // Depth range in window coordinates, p. 33 - // - if (spvVersion.spv == 0) { - commonBuiltins.append( - "struct gl_DepthRangeParameters {" - ); - if (profile == EEsProfile) { - commonBuiltins.append( - "highp float near;" // n - "highp float far;" // f - "highp float diff;" // f - n - ); - } else { - commonBuiltins.append( - "float near;" // n - "float far;" // f - "float diff;" // f - n - ); - } - - commonBuiltins.append( - "};" - "uniform gl_DepthRangeParameters gl_DepthRange;" - "\n"); - } - - if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) { - // - // Matrix state. p. 31, 32, 37, 39, 40. - // - commonBuiltins.append( - "uniform mat4 gl_ModelViewMatrix;" - "uniform mat4 gl_ProjectionMatrix;" - "uniform mat4 gl_ModelViewProjectionMatrix;" - - // - // Derived matrix state that provides inverse and transposed versions - // of the matrices above. - // - "uniform mat3 gl_NormalMatrix;" - - "uniform mat4 gl_ModelViewMatrixInverse;" - "uniform mat4 gl_ProjectionMatrixInverse;" - "uniform mat4 gl_ModelViewProjectionMatrixInverse;" - - "uniform mat4 gl_ModelViewMatrixTranspose;" - "uniform mat4 gl_ProjectionMatrixTranspose;" - "uniform mat4 gl_ModelViewProjectionMatrixTranspose;" - - "uniform mat4 gl_ModelViewMatrixInverseTranspose;" - "uniform mat4 gl_ProjectionMatrixInverseTranspose;" - "uniform mat4 gl_ModelViewProjectionMatrixInverseTranspose;" - - // - // Normal scaling p. 39. - // - "uniform float gl_NormalScale;" - - // - // Point Size, p. 66, 67. - // - "struct gl_PointParameters {" - "float size;" - "float sizeMin;" - "float sizeMax;" - "float fadeThresholdSize;" - "float distanceConstantAttenuation;" - "float distanceLinearAttenuation;" - "float distanceQuadraticAttenuation;" - "};" - - "uniform gl_PointParameters gl_Point;" - - // - // Material State p. 50, 55. - // - "struct gl_MaterialParameters {" - "vec4 emission;" // Ecm - "vec4 ambient;" // Acm - "vec4 diffuse;" // Dcm - "vec4 specular;" // Scm - "float shininess;" // Srm - "};" - "uniform gl_MaterialParameters gl_FrontMaterial;" - "uniform gl_MaterialParameters gl_BackMaterial;" - - // - // Light State p 50, 53, 55. - // - "struct gl_LightSourceParameters {" - "vec4 ambient;" // Acli - "vec4 diffuse;" // Dcli - "vec4 specular;" // Scli - "vec4 position;" // Ppli - "vec4 halfVector;" // Derived: Hi - "vec3 spotDirection;" // Sdli - "float spotExponent;" // Srli - "float spotCutoff;" // Crli - // (range: [0.0,90.0], 180.0) - "float spotCosCutoff;" // Derived: cos(Crli) - // (range: [1.0,0.0],-1.0) - "float constantAttenuation;" // K0 - "float linearAttenuation;" // K1 - "float quadraticAttenuation;"// K2 - "};" - - "struct gl_LightModelParameters {" - "vec4 ambient;" // Acs - "};" - - "uniform gl_LightModelParameters gl_LightModel;" - - // - // Derived state from products of light and material. - // - "struct gl_LightModelProducts {" - "vec4 sceneColor;" // Derived. Ecm + Acm * Acs - "};" - - "uniform gl_LightModelProducts gl_FrontLightModelProduct;" - "uniform gl_LightModelProducts gl_BackLightModelProduct;" - - "struct gl_LightProducts {" - "vec4 ambient;" // Acm * Acli - "vec4 diffuse;" // Dcm * Dcli - "vec4 specular;" // Scm * Scli - "};" - - // - // Fog p. 161 - // - "struct gl_FogParameters {" - "vec4 color;" - "float density;" - "float start;" - "float end;" - "float scale;" // 1 / (gl_FogEnd - gl_FogStart) - "};" - - "uniform gl_FogParameters gl_Fog;" - - "\n"); - } - - //============================================================================ - // - // Define the interface to the compute shader. - // - //============================================================================ - - if ((profile != EEsProfile && version >= 420) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangCompute].append( - "in highp uvec3 gl_NumWorkGroups;" - "const highp uvec3 gl_WorkGroupSize = uvec3(1,1,1);" - - "in highp uvec3 gl_WorkGroupID;" - "in highp uvec3 gl_LocalInvocationID;" - - "in highp uvec3 gl_GlobalInvocationID;" - "in highp uint gl_LocalInvocationIndex;" - - "\n"); - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangCompute].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "\n"); - } - - //============================================================================ - // - // Define the interface to the mesh/task shader. - // - //============================================================================ - - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { - // per-vertex attributes - stageBuiltins[EShLangMesh].append( - "out gl_MeshPerVertexNV {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - "float gl_CullDistance[];" - "perviewNV vec4 gl_PositionPerViewNV[];" - "perviewNV float gl_ClipDistancePerViewNV[][];" - "perviewNV float gl_CullDistancePerViewNV[][];" - "} gl_MeshVerticesNV[];" - ); - - // per-primitive attributes - stageBuiltins[EShLangMesh].append( - "perprimitiveNV out gl_MeshPerPrimitiveNV {" - "int gl_PrimitiveID;" - "int gl_Layer;" - "int gl_ViewportIndex;" - "int gl_ViewportMask[];" - "perviewNV int gl_LayerPerViewNV[];" - "perviewNV int gl_ViewportMaskPerViewNV[][];" - "} gl_MeshPrimitivesNV[];" - ); - - stageBuiltins[EShLangMesh].append( - "out uint gl_PrimitiveCountNV;" - "out uint gl_PrimitiveIndicesNV[];" - - "in uint gl_MeshViewCountNV;" - "in uint gl_MeshViewIndicesNV[4];" - - "const highp uvec3 gl_WorkGroupSize = uvec3(1,1,1);" - - "in highp uvec3 gl_WorkGroupID;" - "in highp uvec3 gl_LocalInvocationID;" - - "in highp uvec3 gl_GlobalInvocationID;" - "in highp uint gl_LocalInvocationIndex;" - "\n"); - - // GL_EXT_mesh_shader - stageBuiltins[EShLangMesh].append( - "out uint gl_PrimitivePointIndicesEXT[];" - "out uvec2 gl_PrimitiveLineIndicesEXT[];" - "out uvec3 gl_PrimitiveTriangleIndicesEXT[];" - "in highp uvec3 gl_NumWorkGroups;" - "\n"); - - // per-vertex attributes - stageBuiltins[EShLangMesh].append( - "out gl_MeshPerVertexEXT {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - "float gl_CullDistance[];" - "} gl_MeshVerticesEXT[];" - ); - - // per-primitive attributes - stageBuiltins[EShLangMesh].append( - "perprimitiveEXT out gl_MeshPerPrimitiveEXT {" - "int gl_PrimitiveID;" - "int gl_Layer;" - "int gl_ViewportIndex;" - "bool gl_CullPrimitiveEXT;" - "int gl_PrimitiveShadingRateEXT;" - "} gl_MeshPrimitivesEXT[];" - ); - - stageBuiltins[EShLangTask].append( - "out uint gl_TaskCountNV;" - - "const highp uvec3 gl_WorkGroupSize = uvec3(1,1,1);" - - "in highp uvec3 gl_WorkGroupID;" - "in highp uvec3 gl_LocalInvocationID;" - - "in highp uvec3 gl_GlobalInvocationID;" - "in highp uint gl_LocalInvocationIndex;" - - "in uint gl_MeshViewCountNV;" - "in uint gl_MeshViewIndicesNV[4];" - "in highp uvec3 gl_NumWorkGroups;" - "\n"); - } - - if (profile != EEsProfile && version >= 450) { - stageBuiltins[EShLangMesh].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "in int gl_DrawIDARB;" // GL_ARB_shader_draw_parameters - "in int gl_ViewIndex;" // GL_EXT_multiview - "\n"); - - stageBuiltins[EShLangTask].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "in int gl_DrawIDARB;" // GL_ARB_shader_draw_parameters - "\n"); - - if (version >= 460) { - stageBuiltins[EShLangMesh].append( - "in int gl_DrawID;" - "\n"); - - stageBuiltins[EShLangTask].append( - "in int gl_DrawID;" - "\n"); - } - } - - //============================================================================ - // - // Define the interface to the vertex shader. - // - //============================================================================ - - if (profile != EEsProfile) { - if (version < 130) { - stageBuiltins[EShLangVertex].append( - "attribute vec4 gl_Color;" - "attribute vec4 gl_SecondaryColor;" - "attribute vec3 gl_Normal;" - "attribute vec4 gl_Vertex;" - "attribute vec4 gl_MultiTexCoord0;" - "attribute vec4 gl_MultiTexCoord1;" - "attribute vec4 gl_MultiTexCoord2;" - "attribute vec4 gl_MultiTexCoord3;" - "attribute vec4 gl_MultiTexCoord4;" - "attribute vec4 gl_MultiTexCoord5;" - "attribute vec4 gl_MultiTexCoord6;" - "attribute vec4 gl_MultiTexCoord7;" - "attribute float gl_FogCoord;" - "\n"); - } else if (IncludeLegacy(version, profile, spvVersion)) { - stageBuiltins[EShLangVertex].append( - "in vec4 gl_Color;" - "in vec4 gl_SecondaryColor;" - "in vec3 gl_Normal;" - "in vec4 gl_Vertex;" - "in vec4 gl_MultiTexCoord0;" - "in vec4 gl_MultiTexCoord1;" - "in vec4 gl_MultiTexCoord2;" - "in vec4 gl_MultiTexCoord3;" - "in vec4 gl_MultiTexCoord4;" - "in vec4 gl_MultiTexCoord5;" - "in vec4 gl_MultiTexCoord6;" - "in vec4 gl_MultiTexCoord7;" - "in float gl_FogCoord;" - "\n"); - } - - if (version < 150) { - if (version < 130) { - stageBuiltins[EShLangVertex].append( - " vec4 gl_ClipVertex;" // needs qualifier fixed later - "varying vec4 gl_FrontColor;" - "varying vec4 gl_BackColor;" - "varying vec4 gl_FrontSecondaryColor;" - "varying vec4 gl_BackSecondaryColor;" - "varying vec4 gl_TexCoord[];" - "varying float gl_FogFragCoord;" - "\n"); - } else if (IncludeLegacy(version, profile, spvVersion)) { - stageBuiltins[EShLangVertex].append( - " vec4 gl_ClipVertex;" // needs qualifier fixed later - "out vec4 gl_FrontColor;" - "out vec4 gl_BackColor;" - "out vec4 gl_FrontSecondaryColor;" - "out vec4 gl_BackSecondaryColor;" - "out vec4 gl_TexCoord[];" - "out float gl_FogFragCoord;" - "\n"); - } - stageBuiltins[EShLangVertex].append( - "vec4 gl_Position;" // needs qualifier fixed later - "float gl_PointSize;" // needs qualifier fixed later - ); - - if (version == 130 || version == 140) - stageBuiltins[EShLangVertex].append( - "out float gl_ClipDistance[];" - ); - } else { - // version >= 150 - stageBuiltins[EShLangVertex].append( - "out gl_PerVertex {" - "vec4 gl_Position;" // needs qualifier fixed later - "float gl_PointSize;" // needs qualifier fixed later - "float gl_ClipDistance[];" - ); - if (IncludeLegacy(version, profile, spvVersion)) - stageBuiltins[EShLangVertex].append( - "vec4 gl_ClipVertex;" // needs qualifier fixed later - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (version >= 450) - stageBuiltins[EShLangVertex].append( - "float gl_CullDistance[];" - ); - stageBuiltins[EShLangVertex].append( - "};" - "\n"); - } - if (version >= 130 && spvVersion.vulkan == 0) - stageBuiltins[EShLangVertex].append( - "int gl_VertexID;" // needs qualifier fixed later - ); - if (spvVersion.vulkan == 0) - stageBuiltins[EShLangVertex].append( - "int gl_InstanceID;" // needs qualifier fixed later - ); - if (spvVersion.vulkan > 0 && version >= 140) - stageBuiltins[EShLangVertex].append( - "in int gl_VertexIndex;" - "in int gl_InstanceIndex;" - ); - - if (spvVersion.vulkan > 0 && version >= 140 && spvVersion.vulkanRelaxed) - stageBuiltins[EShLangVertex].append( - "in int gl_VertexID;" // declare with 'in' qualifier - "in int gl_InstanceID;" - ); - - if (version >= 440) { - stageBuiltins[EShLangVertex].append( - "in int gl_BaseVertexARB;" - "in int gl_BaseInstanceARB;" - "in int gl_DrawIDARB;" - ); - } - if (version >= 410) { - stageBuiltins[EShLangVertex].append( - "out int gl_ViewportIndex;" - "out int gl_Layer;" - ); - } - if (version >= 460) { - stageBuiltins[EShLangVertex].append( - "in int gl_BaseVertex;" - "in int gl_BaseInstance;" - "in int gl_DrawID;" - ); - } - - if (version >= 430) - stageBuiltins[EShLangVertex].append( - "out int gl_ViewportMask[];" // GL_NV_viewport_array2 - ); - - if (version >= 450) - stageBuiltins[EShLangVertex].append( - "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering - "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes - "out int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes - ); - } else { - // ES profile - if (version == 100) { - stageBuiltins[EShLangVertex].append( - "highp vec4 gl_Position;" // needs qualifier fixed later - "mediump float gl_PointSize;" // needs qualifier fixed later - "highp int gl_InstanceID;" // needs qualifier fixed later - ); - } else { - if (spvVersion.vulkan == 0 || spvVersion.vulkanRelaxed) - stageBuiltins[EShLangVertex].append( - "in highp int gl_VertexID;" // needs qualifier fixed later - "in highp int gl_InstanceID;" // needs qualifier fixed later - ); - if (spvVersion.vulkan > 0) - stageBuiltins[EShLangVertex].append( - "in highp int gl_VertexIndex;" - "in highp int gl_InstanceIndex;" - ); - if (version < 310) - stageBuiltins[EShLangVertex].append( - "highp vec4 gl_Position;" // needs qualifier fixed later - "highp float gl_PointSize;" // needs qualifier fixed later - ); - else - stageBuiltins[EShLangVertex].append( - "out gl_PerVertex {" - "highp vec4 gl_Position;" // needs qualifier fixed later - "highp float gl_PointSize;" // needs qualifier fixed later - "};" - ); - } - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangVertex].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "in highp int gl_ViewIndex;" // GL_EXT_multiview - "\n"); - } - - if (version >= 300 /* both ES and non-ES */) { - stageBuiltins[EShLangVertex].append( - "in highp uint gl_ViewID_OVR;" // GL_OVR_multiview, GL_OVR_multiview2 - "\n"); - } - - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangVertex].append( - "out highp int gl_PrimitiveShadingRateEXT;" // GL_EXT_fragment_shading_rate - "\n"); - } - - //============================================================================ - // - // Define the interface to the geometry shader. - // - //============================================================================ - - if (profile == ECoreProfile || profile == ECompatibilityProfile) { - stageBuiltins[EShLangGeometry].append( - "in gl_PerVertex {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - ); - if (profile == ECompatibilityProfile) - stageBuiltins[EShLangGeometry].append( - "vec4 gl_ClipVertex;" - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (version >= 450) - stageBuiltins[EShLangGeometry].append( - "float gl_CullDistance[];" - "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes - ); - stageBuiltins[EShLangGeometry].append( - "} gl_in[];" - - "in int gl_PrimitiveIDIn;" - "out gl_PerVertex {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - "\n"); - if (profile == ECompatibilityProfile && version >= 400) - stageBuiltins[EShLangGeometry].append( - "vec4 gl_ClipVertex;" - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (version >= 450) - stageBuiltins[EShLangGeometry].append( - "float gl_CullDistance[];" - ); - stageBuiltins[EShLangGeometry].append( - "};" - - "out int gl_PrimitiveID;" - "out int gl_Layer;"); - - if (version >= 150) - stageBuiltins[EShLangGeometry].append( - "out int gl_ViewportIndex;" - ); - - if (profile == ECompatibilityProfile && version < 400) - stageBuiltins[EShLangGeometry].append( - "out vec4 gl_ClipVertex;" - ); - - if (version >= 400) - stageBuiltins[EShLangGeometry].append( - "in int gl_InvocationID;" - ); - - if (version >= 430) - stageBuiltins[EShLangGeometry].append( - "out int gl_ViewportMask[];" // GL_NV_viewport_array2 - ); - - if (version >= 450) - stageBuiltins[EShLangGeometry].append( - "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering - "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes - "out int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes - ); - - stageBuiltins[EShLangGeometry].append("\n"); - } else if (profile == EEsProfile && version >= 310) { - stageBuiltins[EShLangGeometry].append( - "in gl_PerVertex {" - "highp vec4 gl_Position;" - "highp float gl_PointSize;" - "} gl_in[];" - "\n" - "in highp int gl_PrimitiveIDIn;" - "in highp int gl_InvocationID;" - "\n" - "out gl_PerVertex {" - "highp vec4 gl_Position;" - "highp float gl_PointSize;" - "};" - "\n" - "out highp int gl_PrimitiveID;" - "out highp int gl_Layer;" - "\n" - ); - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangGeometry].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "in highp int gl_ViewIndex;" // GL_EXT_multiview - "\n"); - } - - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangGeometry].append( - "out highp int gl_PrimitiveShadingRateEXT;" // GL_EXT_fragment_shading_rate - "\n"); - } - - //============================================================================ - // - // Define the interface to the tessellation control shader. - // - //============================================================================ - - if (profile != EEsProfile && version >= 150) { - // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below, - // as it depends on the resource sizing of gl_MaxPatchVertices. - - stageBuiltins[EShLangTessControl].append( - "in int gl_PatchVerticesIn;" - "in int gl_PrimitiveID;" - "in int gl_InvocationID;" - - "out gl_PerVertex {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - ); - if (profile == ECompatibilityProfile) - stageBuiltins[EShLangTessControl].append( - "vec4 gl_ClipVertex;" - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (version >= 450) - stageBuiltins[EShLangTessControl].append( - "float gl_CullDistance[];" - ); - if (version >= 430) - stageBuiltins[EShLangTessControl].append( - "int gl_ViewportMask[];" // GL_NV_viewport_array2 - ); - if (version >= 450) - stageBuiltins[EShLangTessControl].append( - "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering - "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes - "int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes - ); - stageBuiltins[EShLangTessControl].append( - "} gl_out[];" - - "patch out float gl_TessLevelOuter[4];" - "patch out float gl_TessLevelInner[2];" - "\n"); - - if (version >= 410) - stageBuiltins[EShLangTessControl].append( - "out int gl_ViewportIndex;" - "out int gl_Layer;" - "\n"); - - } else { - // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below, - // as it depends on the resource sizing of gl_MaxPatchVertices. - - stageBuiltins[EShLangTessControl].append( - "in highp int gl_PatchVerticesIn;" - "in highp int gl_PrimitiveID;" - "in highp int gl_InvocationID;" - - "out gl_PerVertex {" - "highp vec4 gl_Position;" - "highp float gl_PointSize;" - ); - stageBuiltins[EShLangTessControl].append( - "} gl_out[];" - - "patch out highp float gl_TessLevelOuter[4];" - "patch out highp float gl_TessLevelInner[2];" - "patch out highp vec4 gl_BoundingBoxOES[2];" - "patch out highp vec4 gl_BoundingBoxEXT[2];" - "\n"); - if (profile == EEsProfile && version >= 320) { - stageBuiltins[EShLangTessControl].append( - "patch out highp vec4 gl_BoundingBox[2];" - "\n" - ); - } - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangTessControl].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "in highp int gl_ViewIndex;" // GL_EXT_multiview - "\n"); - } - - //============================================================================ - // - // Define the interface to the tessellation evaluation shader. - // - //============================================================================ - - if (profile != EEsProfile && version >= 150) { - // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below, - // as it depends on the resource sizing of gl_MaxPatchVertices. - - stageBuiltins[EShLangTessEvaluation].append( - "in int gl_PatchVerticesIn;" - "in int gl_PrimitiveID;" - "in vec3 gl_TessCoord;" - - "patch in float gl_TessLevelOuter[4];" - "patch in float gl_TessLevelInner[2];" - - "out gl_PerVertex {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - ); - if (version >= 400 && profile == ECompatibilityProfile) - stageBuiltins[EShLangTessEvaluation].append( - "vec4 gl_ClipVertex;" - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (version >= 450) - stageBuiltins[EShLangTessEvaluation].append( - "float gl_CullDistance[];" - ); - stageBuiltins[EShLangTessEvaluation].append( - "};" - "\n"); - - if (version >= 410) - stageBuiltins[EShLangTessEvaluation].append( - "out int gl_ViewportIndex;" - "out int gl_Layer;" - "\n"); - - if (version >= 430) - stageBuiltins[EShLangTessEvaluation].append( - "out int gl_ViewportMask[];" // GL_NV_viewport_array2 - ); - - if (version >= 450) - stageBuiltins[EShLangTessEvaluation].append( - "out vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "out int gl_SecondaryViewportMaskNV[];" // GL_NV_stereo_view_rendering - "out vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes - "out int gl_ViewportMaskPerViewNV[];" // GL_NVX_multiview_per_view_attributes - ); - - } else if (profile == EEsProfile && version >= 310) { - // Note: "in gl_PerVertex {...} gl_in[gl_MaxPatchVertices];" is declared in initialize() below, - // as it depends on the resource sizing of gl_MaxPatchVertices. - - stageBuiltins[EShLangTessEvaluation].append( - "in highp int gl_PatchVerticesIn;" - "in highp int gl_PrimitiveID;" - "in highp vec3 gl_TessCoord;" - - "patch in highp float gl_TessLevelOuter[4];" - "patch in highp float gl_TessLevelInner[2];" - - "out gl_PerVertex {" - "highp vec4 gl_Position;" - "highp float gl_PointSize;" - ); - stageBuiltins[EShLangTessEvaluation].append( - "};" - "\n"); - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangTessEvaluation].append( - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "in highp int gl_ViewIndex;" // GL_EXT_multiview - "\n"); - } - - //============================================================================ - // - // Define the interface to the fragment shader. - // - //============================================================================ - - if (profile != EEsProfile) { - - stageBuiltins[EShLangFragment].append( - "vec4 gl_FragCoord;" // needs qualifier fixed later - "bool gl_FrontFacing;" // needs qualifier fixed later - "float gl_FragDepth;" // needs qualifier fixed later - ); - if (version >= 120) - stageBuiltins[EShLangFragment].append( - "vec2 gl_PointCoord;" // needs qualifier fixed later - ); - if (version >= 140) - stageBuiltins[EShLangFragment].append( - "out int gl_FragStencilRefARB;" - ); - if (IncludeLegacy(version, profile, spvVersion) || (! ForwardCompatibility && version < 420)) - stageBuiltins[EShLangFragment].append( - "vec4 gl_FragColor;" // needs qualifier fixed later - ); - - if (version < 130) { - stageBuiltins[EShLangFragment].append( - "varying vec4 gl_Color;" - "varying vec4 gl_SecondaryColor;" - "varying vec4 gl_TexCoord[];" - "varying float gl_FogFragCoord;" - ); - } else { - stageBuiltins[EShLangFragment].append( - "in float gl_ClipDistance[];" - ); - - if (IncludeLegacy(version, profile, spvVersion)) { - if (version < 150) - stageBuiltins[EShLangFragment].append( - "in float gl_FogFragCoord;" - "in vec4 gl_TexCoord[];" - "in vec4 gl_Color;" - "in vec4 gl_SecondaryColor;" - ); - else - stageBuiltins[EShLangFragment].append( - "in gl_PerFragment {" - "in float gl_FogFragCoord;" - "in vec4 gl_TexCoord[];" - "in vec4 gl_Color;" - "in vec4 gl_SecondaryColor;" - "};" - ); - } - } - - if (version >= 150) - stageBuiltins[EShLangFragment].append( - "flat in int gl_PrimitiveID;" - ); - - if (version >= 130) { // ARB_sample_shading - stageBuiltins[EShLangFragment].append( - "flat in int gl_SampleID;" - " in vec2 gl_SamplePosition;" - " out int gl_SampleMask[];" - ); - - if (spvVersion.spv == 0) { - stageBuiltins[EShLangFragment].append( - "uniform int gl_NumSamples;" - ); - } - } - - if (version >= 400) - stageBuiltins[EShLangFragment].append( - "flat in int gl_SampleMaskIn[];" - ); - - if (version >= 430) - stageBuiltins[EShLangFragment].append( - "flat in int gl_Layer;" - "flat in int gl_ViewportIndex;" - ); - - if (version >= 450) - stageBuiltins[EShLangFragment].append( - "in float gl_CullDistance[];" - "bool gl_HelperInvocation;" // needs qualifier fixed later - ); - - if (version >= 450) - stageBuiltins[EShLangFragment].append( // GL_EXT_fragment_invocation_density - "flat in ivec2 gl_FragSizeEXT;" - "flat in int gl_FragInvocationCountEXT;" - ); - - if (version >= 450) - stageBuiltins[EShLangFragment].append( - "in vec2 gl_BaryCoordNoPerspAMD;" - "in vec2 gl_BaryCoordNoPerspCentroidAMD;" - "in vec2 gl_BaryCoordNoPerspSampleAMD;" - "in vec2 gl_BaryCoordSmoothAMD;" - "in vec2 gl_BaryCoordSmoothCentroidAMD;" - "in vec2 gl_BaryCoordSmoothSampleAMD;" - "in vec3 gl_BaryCoordPullModelAMD;" - ); - - if (version >= 430) - stageBuiltins[EShLangFragment].append( - "in bool gl_FragFullyCoveredNV;" - ); - if (version >= 450) - stageBuiltins[EShLangFragment].append( - "flat in ivec2 gl_FragmentSizeNV;" // GL_NV_shading_rate_image - "flat in int gl_InvocationsPerPixelNV;" - "in vec3 gl_BaryCoordNV;" // GL_NV_fragment_shader_barycentric - "in vec3 gl_BaryCoordNoPerspNV;" - "in vec3 gl_BaryCoordEXT;" // GL_EXT_fragment_shader_barycentric - "in vec3 gl_BaryCoordNoPerspEXT;" - ); - - if (version >= 450) - stageBuiltins[EShLangFragment].append( - "flat in int gl_ShadingRateEXT;" // GL_EXT_fragment_shading_rate - ); - - } else { - // ES profile - - if (version == 100) { - stageBuiltins[EShLangFragment].append( - "mediump vec4 gl_FragCoord;" // needs qualifier fixed later - " bool gl_FrontFacing;" // needs qualifier fixed later - "mediump vec4 gl_FragColor;" // needs qualifier fixed later - "mediump vec2 gl_PointCoord;" // needs qualifier fixed later - ); - } - if (version >= 300) { - stageBuiltins[EShLangFragment].append( - "highp vec4 gl_FragCoord;" // needs qualifier fixed later - " bool gl_FrontFacing;" // needs qualifier fixed later - "mediump vec2 gl_PointCoord;" // needs qualifier fixed later - "highp float gl_FragDepth;" // needs qualifier fixed later - ); - } - if (version >= 310) { - stageBuiltins[EShLangFragment].append( - "bool gl_HelperInvocation;" // needs qualifier fixed later - "flat in highp int gl_PrimitiveID;" // needs qualifier fixed later - "flat in highp int gl_Layer;" // needs qualifier fixed later - ); - - stageBuiltins[EShLangFragment].append( // GL_OES_sample_variables - "flat in lowp int gl_SampleID;" - " in mediump vec2 gl_SamplePosition;" - "flat in highp int gl_SampleMaskIn[];" - " out highp int gl_SampleMask[];" - ); - if (spvVersion.spv == 0) - stageBuiltins[EShLangFragment].append( // GL_OES_sample_variables - "uniform lowp int gl_NumSamples;" - ); - } - stageBuiltins[EShLangFragment].append( - "highp float gl_FragDepthEXT;" // GL_EXT_frag_depth - ); - - if (version >= 310) - stageBuiltins[EShLangFragment].append( // GL_EXT_fragment_invocation_density - "flat in ivec2 gl_FragSizeEXT;" - "flat in int gl_FragInvocationCountEXT;" - ); - if (version >= 320) - stageBuiltins[EShLangFragment].append( // GL_NV_shading_rate_image - "flat in ivec2 gl_FragmentSizeNV;" - "flat in int gl_InvocationsPerPixelNV;" - ); - if (version >= 320) - stageBuiltins[EShLangFragment].append( - "in vec3 gl_BaryCoordNV;" - "in vec3 gl_BaryCoordNoPerspNV;" - "in vec3 gl_BaryCoordEXT;" - "in vec3 gl_BaryCoordNoPerspEXT;" - ); - if (version >= 310) - stageBuiltins[EShLangFragment].append( - "flat in highp int gl_ShadingRateEXT;" // GL_EXT_fragment_shading_rate - ); - } - - stageBuiltins[EShLangFragment].append("\n"); - - if (version >= 130) - add2ndGenerationSamplingImaging(version, profile, spvVersion); - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - stageBuiltins[EShLangFragment].append( - "flat in highp int gl_DeviceIndex;" // GL_EXT_device_group - "flat in highp int gl_ViewIndex;" // GL_EXT_multiview - "\n"); - } - - if (version >= 300 /* both ES and non-ES */) { - stageBuiltins[EShLangFragment].append( - "flat in highp uint gl_ViewID_OVR;" // GL_OVR_multiview, GL_OVR_multiview2 - "\n"); - } - - // GL_ARB_shader_ballot - if (profile != EEsProfile && version >= 450) { - const char* ballotDecls = - "uniform uint gl_SubGroupSizeARB;" - "in uint gl_SubGroupInvocationARB;" - "in uint64_t gl_SubGroupEqMaskARB;" - "in uint64_t gl_SubGroupGeMaskARB;" - "in uint64_t gl_SubGroupGtMaskARB;" - "in uint64_t gl_SubGroupLeMaskARB;" - "in uint64_t gl_SubGroupLtMaskARB;" - "\n"; - const char* rtBallotDecls = - "uniform volatile uint gl_SubGroupSizeARB;" - "in volatile uint gl_SubGroupInvocationARB;" - "in volatile uint64_t gl_SubGroupEqMaskARB;" - "in volatile uint64_t gl_SubGroupGeMaskARB;" - "in volatile uint64_t gl_SubGroupGtMaskARB;" - "in volatile uint64_t gl_SubGroupLeMaskARB;" - "in volatile uint64_t gl_SubGroupLtMaskARB;" - "\n"; - const char* fragmentBallotDecls = - "uniform uint gl_SubGroupSizeARB;" - "flat in uint gl_SubGroupInvocationARB;" - "flat in uint64_t gl_SubGroupEqMaskARB;" - "flat in uint64_t gl_SubGroupGeMaskARB;" - "flat in uint64_t gl_SubGroupGtMaskARB;" - "flat in uint64_t gl_SubGroupLeMaskARB;" - "flat in uint64_t gl_SubGroupLtMaskARB;" - "\n"; - stageBuiltins[EShLangVertex] .append(ballotDecls); - stageBuiltins[EShLangTessControl] .append(ballotDecls); - stageBuiltins[EShLangTessEvaluation].append(ballotDecls); - stageBuiltins[EShLangGeometry] .append(ballotDecls); - stageBuiltins[EShLangCompute] .append(ballotDecls); - stageBuiltins[EShLangFragment] .append(fragmentBallotDecls); - stageBuiltins[EShLangMesh] .append(ballotDecls); - stageBuiltins[EShLangTask] .append(ballotDecls); - stageBuiltins[EShLangRayGen] .append(rtBallotDecls); - stageBuiltins[EShLangIntersect] .append(rtBallotDecls); - // No volatile qualifier on these builtins in any-hit - stageBuiltins[EShLangAnyHit] .append(ballotDecls); - stageBuiltins[EShLangClosestHit] .append(rtBallotDecls); - stageBuiltins[EShLangMiss] .append(rtBallotDecls); - stageBuiltins[EShLangCallable] .append(rtBallotDecls); - } - - // GL_KHR_shader_subgroup - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - const char* subgroupDecls = - "in mediump uint gl_SubgroupSize;" - "in mediump uint gl_SubgroupInvocationID;" - "in highp uvec4 gl_SubgroupEqMask;" - "in highp uvec4 gl_SubgroupGeMask;" - "in highp uvec4 gl_SubgroupGtMask;" - "in highp uvec4 gl_SubgroupLeMask;" - "in highp uvec4 gl_SubgroupLtMask;" - // GL_NV_shader_sm_builtins - "in highp uint gl_WarpsPerSMNV;" - "in highp uint gl_SMCountNV;" - "in highp uint gl_WarpIDNV;" - "in highp uint gl_SMIDNV;" - // GL_ARM_shader_core_builtins - "in highp uint gl_CoreIDARM;" - "in highp uint gl_CoreCountARM;" - "in highp uint gl_CoreMaxIDARM;" - "in highp uint gl_WarpIDARM;" - "in highp uint gl_WarpMaxIDARM;" - "\n"; - const char* fragmentSubgroupDecls = - "flat in mediump uint gl_SubgroupSize;" - "flat in mediump uint gl_SubgroupInvocationID;" - "flat in highp uvec4 gl_SubgroupEqMask;" - "flat in highp uvec4 gl_SubgroupGeMask;" - "flat in highp uvec4 gl_SubgroupGtMask;" - "flat in highp uvec4 gl_SubgroupLeMask;" - "flat in highp uvec4 gl_SubgroupLtMask;" - // GL_NV_shader_sm_builtins - "flat in highp uint gl_WarpsPerSMNV;" - "flat in highp uint gl_SMCountNV;" - "flat in highp uint gl_WarpIDNV;" - "flat in highp uint gl_SMIDNV;" - // GL_ARM_shader_core_builtins - "flat in highp uint gl_CoreIDARM;" - "flat in highp uint gl_CoreCountARM;" - "flat in highp uint gl_CoreMaxIDARM;" - "flat in highp uint gl_WarpIDARM;" - "flat in highp uint gl_WarpMaxIDARM;" - "\n"; - const char* computeSubgroupDecls = - "in highp uint gl_NumSubgroups;" - "in highp uint gl_SubgroupID;" - "\n"; - // These builtins are volatile for RT stages - const char* rtSubgroupDecls = - "in mediump volatile uint gl_SubgroupSize;" - "in mediump volatile uint gl_SubgroupInvocationID;" - "in highp volatile uvec4 gl_SubgroupEqMask;" - "in highp volatile uvec4 gl_SubgroupGeMask;" - "in highp volatile uvec4 gl_SubgroupGtMask;" - "in highp volatile uvec4 gl_SubgroupLeMask;" - "in highp volatile uvec4 gl_SubgroupLtMask;" - // GL_NV_shader_sm_builtins - "in highp uint gl_WarpsPerSMNV;" - "in highp uint gl_SMCountNV;" - "in highp volatile uint gl_WarpIDNV;" - "in highp volatile uint gl_SMIDNV;" - // GL_ARM_shader_core_builtins - "in highp uint gl_CoreIDARM;" - "in highp uint gl_CoreCountARM;" - "in highp uint gl_CoreMaxIDARM;" - "in highp uint gl_WarpIDARM;" - "in highp uint gl_WarpMaxIDARM;" - "\n"; - - stageBuiltins[EShLangVertex] .append(subgroupDecls); - stageBuiltins[EShLangTessControl] .append(subgroupDecls); - stageBuiltins[EShLangTessEvaluation].append(subgroupDecls); - stageBuiltins[EShLangGeometry] .append(subgroupDecls); - stageBuiltins[EShLangCompute] .append(subgroupDecls); - stageBuiltins[EShLangCompute] .append(computeSubgroupDecls); - stageBuiltins[EShLangFragment] .append(fragmentSubgroupDecls); - stageBuiltins[EShLangMesh] .append(subgroupDecls); - stageBuiltins[EShLangMesh] .append(computeSubgroupDecls); - stageBuiltins[EShLangTask] .append(subgroupDecls); - stageBuiltins[EShLangTask] .append(computeSubgroupDecls); - stageBuiltins[EShLangRayGen] .append(rtSubgroupDecls); - stageBuiltins[EShLangIntersect] .append(rtSubgroupDecls); - // No volatile qualifier on these builtins in any-hit - stageBuiltins[EShLangAnyHit] .append(subgroupDecls); - stageBuiltins[EShLangClosestHit] .append(rtSubgroupDecls); - stageBuiltins[EShLangMiss] .append(rtSubgroupDecls); - stageBuiltins[EShLangCallable] .append(rtSubgroupDecls); - } - - // GL_NV_ray_tracing/GL_EXT_ray_tracing - if (profile != EEsProfile && version >= 460) { - - const char *constRayFlags = - "const uint gl_RayFlagsNoneNV = 0U;" - "const uint gl_RayFlagsNoneEXT = 0U;" - "const uint gl_RayFlagsOpaqueNV = 1U;" - "const uint gl_RayFlagsOpaqueEXT = 1U;" - "const uint gl_RayFlagsNoOpaqueNV = 2U;" - "const uint gl_RayFlagsNoOpaqueEXT = 2U;" - "const uint gl_RayFlagsTerminateOnFirstHitNV = 4U;" - "const uint gl_RayFlagsTerminateOnFirstHitEXT = 4U;" - "const uint gl_RayFlagsSkipClosestHitShaderNV = 8U;" - "const uint gl_RayFlagsSkipClosestHitShaderEXT = 8U;" - "const uint gl_RayFlagsCullBackFacingTrianglesNV = 16U;" - "const uint gl_RayFlagsCullBackFacingTrianglesEXT = 16U;" - "const uint gl_RayFlagsCullFrontFacingTrianglesNV = 32U;" - "const uint gl_RayFlagsCullFrontFacingTrianglesEXT = 32U;" - "const uint gl_RayFlagsCullOpaqueNV = 64U;" - "const uint gl_RayFlagsCullOpaqueEXT = 64U;" - "const uint gl_RayFlagsCullNoOpaqueNV = 128U;" - "const uint gl_RayFlagsCullNoOpaqueEXT = 128U;" - "const uint gl_RayFlagsSkipTrianglesEXT = 256U;" - "const uint gl_RayFlagsSkipAABBEXT = 512U;" - "const uint gl_RayFlagsForceOpacityMicromap2StateEXT = 1024U;" - "const uint gl_HitKindFrontFacingTriangleEXT = 254U;" - "const uint gl_HitKindBackFacingTriangleEXT = 255U;" - "in uint gl_HitKindFrontFacingMicroTriangleNV;" - "in uint gl_HitKindBackFacingMicroTriangleNV;" - "\n"; - - const char *constRayQueryIntersection = - "const uint gl_RayQueryCandidateIntersectionEXT = 0U;" - "const uint gl_RayQueryCommittedIntersectionEXT = 1U;" - "const uint gl_RayQueryCommittedIntersectionNoneEXT = 0U;" - "const uint gl_RayQueryCommittedIntersectionTriangleEXT = 1U;" - "const uint gl_RayQueryCommittedIntersectionGeneratedEXT = 2U;" - "const uint gl_RayQueryCandidateIntersectionTriangleEXT = 0U;" - "const uint gl_RayQueryCandidateIntersectionAABBEXT = 1U;" - "\n"; - - const char *rayGenDecls = - "in uvec3 gl_LaunchIDNV;" - "in uvec3 gl_LaunchIDEXT;" - "in uvec3 gl_LaunchSizeNV;" - "in uvec3 gl_LaunchSizeEXT;" - "\n"; - const char *intersectDecls = - "in uvec3 gl_LaunchIDNV;" - "in uvec3 gl_LaunchIDEXT;" - "in uvec3 gl_LaunchSizeNV;" - "in uvec3 gl_LaunchSizeEXT;" - "in int gl_PrimitiveID;" - "in int gl_InstanceID;" - "in int gl_InstanceCustomIndexNV;" - "in int gl_InstanceCustomIndexEXT;" - "in int gl_GeometryIndexEXT;" - "in vec3 gl_WorldRayOriginNV;" - "in vec3 gl_WorldRayOriginEXT;" - "in vec3 gl_WorldRayDirectionNV;" - "in vec3 gl_WorldRayDirectionEXT;" - "in vec3 gl_ObjectRayOriginNV;" - "in vec3 gl_ObjectRayOriginEXT;" - "in vec3 gl_ObjectRayDirectionNV;" - "in vec3 gl_ObjectRayDirectionEXT;" - "in float gl_RayTminNV;" - "in float gl_RayTminEXT;" - "in float gl_RayTmaxNV;" - "in volatile float gl_RayTmaxEXT;" - "in mat4x3 gl_ObjectToWorldNV;" - "in mat4x3 gl_ObjectToWorldEXT;" - "in mat3x4 gl_ObjectToWorld3x4EXT;" - "in mat4x3 gl_WorldToObjectNV;" - "in mat4x3 gl_WorldToObjectEXT;" - "in mat3x4 gl_WorldToObject3x4EXT;" - "in uint gl_IncomingRayFlagsNV;" - "in uint gl_IncomingRayFlagsEXT;" - "in float gl_CurrentRayTimeNV;" - "in uint gl_CullMaskEXT;" - "\n"; - const char *hitDecls = - "in uvec3 gl_LaunchIDNV;" - "in uvec3 gl_LaunchIDEXT;" - "in uvec3 gl_LaunchSizeNV;" - "in uvec3 gl_LaunchSizeEXT;" - "in int gl_PrimitiveID;" - "in int gl_InstanceID;" - "in int gl_InstanceCustomIndexNV;" - "in int gl_InstanceCustomIndexEXT;" - "in int gl_GeometryIndexEXT;" - "in vec3 gl_WorldRayOriginNV;" - "in vec3 gl_WorldRayOriginEXT;" - "in vec3 gl_WorldRayDirectionNV;" - "in vec3 gl_WorldRayDirectionEXT;" - "in vec3 gl_ObjectRayOriginNV;" - "in vec3 gl_ObjectRayOriginEXT;" - "in vec3 gl_ObjectRayDirectionNV;" - "in vec3 gl_ObjectRayDirectionEXT;" - "in float gl_RayTminNV;" - "in float gl_RayTminEXT;" - "in float gl_RayTmaxNV;" - "in float gl_RayTmaxEXT;" - "in float gl_HitTNV;" - "in float gl_HitTEXT;" - "in uint gl_HitKindNV;" - "in uint gl_HitKindEXT;" - "in mat4x3 gl_ObjectToWorldNV;" - "in mat4x3 gl_ObjectToWorldEXT;" - "in mat3x4 gl_ObjectToWorld3x4EXT;" - "in mat4x3 gl_WorldToObjectNV;" - "in mat4x3 gl_WorldToObjectEXT;" - "in mat3x4 gl_WorldToObject3x4EXT;" - "in uint gl_IncomingRayFlagsNV;" - "in uint gl_IncomingRayFlagsEXT;" - "in float gl_CurrentRayTimeNV;" - "in uint gl_CullMaskEXT;" - "in vec3 gl_HitTriangleVertexPositionsEXT[3];" - "in vec3 gl_HitMicroTriangleVertexPositionsNV[3];" - "in vec2 gl_HitMicroTriangleVertexBarycentricsNV[3];" - "\n"; - - const char *missDecls = - "in uvec3 gl_LaunchIDNV;" - "in uvec3 gl_LaunchIDEXT;" - "in uvec3 gl_LaunchSizeNV;" - "in uvec3 gl_LaunchSizeEXT;" - "in vec3 gl_WorldRayOriginNV;" - "in vec3 gl_WorldRayOriginEXT;" - "in vec3 gl_WorldRayDirectionNV;" - "in vec3 gl_WorldRayDirectionEXT;" - "in vec3 gl_ObjectRayOriginNV;" - "in vec3 gl_ObjectRayDirectionNV;" - "in float gl_RayTminNV;" - "in float gl_RayTminEXT;" - "in float gl_RayTmaxNV;" - "in float gl_RayTmaxEXT;" - "in uint gl_IncomingRayFlagsNV;" - "in uint gl_IncomingRayFlagsEXT;" - "in float gl_CurrentRayTimeNV;" - "in uint gl_CullMaskEXT;" - "\n"; - - const char *callableDecls = - "in uvec3 gl_LaunchIDNV;" - "in uvec3 gl_LaunchIDEXT;" - "in uvec3 gl_LaunchSizeNV;" - "in uvec3 gl_LaunchSizeEXT;" - "\n"; - - - commonBuiltins.append(constRayQueryIntersection); - commonBuiltins.append(constRayFlags); - - stageBuiltins[EShLangRayGen].append(rayGenDecls); - stageBuiltins[EShLangIntersect].append(intersectDecls); - stageBuiltins[EShLangAnyHit].append(hitDecls); - stageBuiltins[EShLangClosestHit].append(hitDecls); - stageBuiltins[EShLangMiss].append(missDecls); - stageBuiltins[EShLangCallable].append(callableDecls); - - } - - if ((profile != EEsProfile && version >= 140)) { - const char *deviceIndex = - "in highp int gl_DeviceIndex;" // GL_EXT_device_group - "\n"; - - stageBuiltins[EShLangRayGen].append(deviceIndex); - stageBuiltins[EShLangIntersect].append(deviceIndex); - stageBuiltins[EShLangAnyHit].append(deviceIndex); - stageBuiltins[EShLangClosestHit].append(deviceIndex); - stageBuiltins[EShLangMiss].append(deviceIndex); - } - - if ((profile != EEsProfile && version >= 420) || - (profile == EEsProfile && version >= 310)) { - commonBuiltins.append("const int gl_ScopeDevice = 1;\n"); - commonBuiltins.append("const int gl_ScopeWorkgroup = 2;\n"); - commonBuiltins.append("const int gl_ScopeSubgroup = 3;\n"); - commonBuiltins.append("const int gl_ScopeInvocation = 4;\n"); - commonBuiltins.append("const int gl_ScopeQueueFamily = 5;\n"); - commonBuiltins.append("const int gl_ScopeShaderCallEXT = 6;\n"); - - commonBuiltins.append("const int gl_SemanticsRelaxed = 0x0;\n"); - commonBuiltins.append("const int gl_SemanticsAcquire = 0x2;\n"); - commonBuiltins.append("const int gl_SemanticsRelease = 0x4;\n"); - commonBuiltins.append("const int gl_SemanticsAcquireRelease = 0x8;\n"); - commonBuiltins.append("const int gl_SemanticsMakeAvailable = 0x2000;\n"); - commonBuiltins.append("const int gl_SemanticsMakeVisible = 0x4000;\n"); - commonBuiltins.append("const int gl_SemanticsVolatile = 0x8000;\n"); - - commonBuiltins.append("const int gl_StorageSemanticsNone = 0x0;\n"); - commonBuiltins.append("const int gl_StorageSemanticsBuffer = 0x40;\n"); - commonBuiltins.append("const int gl_StorageSemanticsShared = 0x100;\n"); - commonBuiltins.append("const int gl_StorageSemanticsImage = 0x800;\n"); - commonBuiltins.append("const int gl_StorageSemanticsOutput = 0x1000;\n"); - } - - // Adding these to common built-ins triggers an assert due to a memory corruption in related code when testing - // So instead add to each stage individually, avoiding the GLSLang bug - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 310)) { - for (int stage=EShLangVertex; stage(stage)].append("const highp int gl_ShadingRateFlag2VerticalPixelsEXT = 1;\n"); - stageBuiltins[static_cast(stage)].append("const highp int gl_ShadingRateFlag4VerticalPixelsEXT = 2;\n"); - stageBuiltins[static_cast(stage)].append("const highp int gl_ShadingRateFlag2HorizontalPixelsEXT = 4;\n"); - stageBuiltins[static_cast(stage)].append("const highp int gl_ShadingRateFlag4HorizontalPixelsEXT = 8;\n"); - } - } - - // GL_EXT_shader_image_int64 - if ((profile != EEsProfile && version >= 420) || - (profile == EEsProfile && version >= 310)) { - - const TBasicType bTypes[] = { EbtInt64, EbtUint64 }; - for (int ms = 0; ms <= 1; ++ms) { // loop over "bool" multisample or not - for (int arrayed = 0; arrayed <= 1; ++arrayed) { // loop over "bool" arrayed or not - for (int dim = Esd1D; dim < EsdSubpass; ++dim) { // 1D, ..., buffer - if ((dim == Esd1D || dim == EsdRect) && profile == EEsProfile) - continue; - - if ((dim == Esd3D || dim == EsdRect || dim == EsdBuffer) && arrayed) - continue; - - if (dim != Esd2D && ms) - continue; - - // Loop over the bTypes - for (size_t bType = 0; bType < sizeof(bTypes)/sizeof(TBasicType); ++bType) { - // - // Now, make all the function prototypes for the type we just built... - // - TSampler sampler; - - sampler.setImage(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false, - false, - ms ? true : false); - - TString typeName = sampler.getString(); - - addQueryFunctions(sampler, typeName, version, profile); - addImageFunctions(sampler, typeName, version, profile); - } - } - } - } - } - - // printf("%s\n", commonBuiltins.c_str()); - // printf("%s\n", stageBuiltins[EShLangFragment].c_str()); -} - -// -// Helper function for initialize(), to add the second set of names for texturing, -// when adding context-independent built-in functions. -// -void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion) -{ - // - // In this function proper, enumerate the types, then calls the next set of functions - // to enumerate all the uses for that type. - // - - // enumerate all the types - const TBasicType bTypes[] = { EbtFloat, EbtInt, EbtUint, - EbtFloat16 - }; - bool skipBuffer = (profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 140); - bool skipCubeArrayed = (profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 130); - for (int image = 0; image <= 1; ++image) // loop over "bool" image vs sampler - { - for (int shadow = 0; shadow <= 1; ++shadow) { // loop over "bool" shadow or not - for (int ms = 0; ms <= 1; ++ms) // loop over "bool" multisample or not - { - if ((ms || image) && shadow) - continue; - if (ms && profile != EEsProfile && version < 150) - continue; - if (ms && image && profile == EEsProfile) - continue; - if (ms && profile == EEsProfile && version < 310) - continue; - - for (int arrayed = 0; arrayed <= 1; ++arrayed) { // loop over "bool" arrayed or not - for (int dim = Esd1D; dim < EsdNumDims; ++dim) { // 1D, ..., buffer, subpass - if (dim == EsdAttachmentEXT) - continue; - if (dim == EsdSubpass && spvVersion.vulkan == 0) - continue; - if (dim == EsdSubpass && (image || shadow || arrayed)) - continue; - if ((dim == Esd1D || dim == EsdRect) && profile == EEsProfile) - continue; - if (dim == EsdSubpass && spvVersion.vulkan == 0) - continue; - if (dim == EsdSubpass && (image || shadow || arrayed)) - continue; - if ((dim == Esd1D || dim == EsdRect) && profile == EEsProfile) - continue; - if (dim != Esd2D && dim != EsdSubpass && ms) - continue; - if (dim == EsdBuffer && skipBuffer) - continue; - if (dim == EsdBuffer && (shadow || arrayed || ms)) - continue; - if (ms && arrayed && profile == EEsProfile && version < 310) - continue; - if (dim == Esd3D && shadow) - continue; - if (dim == EsdCube && arrayed && skipCubeArrayed) - continue; - if ((dim == Esd3D || dim == EsdRect) && arrayed) - continue; - - // Loop over the bTypes - for (size_t bType = 0; bType < sizeof(bTypes)/sizeof(TBasicType); ++bType) { - if (bTypes[bType] == EbtFloat16 && (profile == EEsProfile || version < 450)) - continue; - if (dim == EsdRect && version < 140 && bType > 0) - continue; - if (shadow && (bTypes[bType] == EbtInt || bTypes[bType] == EbtUint)) - continue; - // - // Now, make all the function prototypes for the type we just built... - // - TSampler sampler; - if (dim == EsdSubpass) { - sampler.setSubpass(bTypes[bType], ms ? true : false); - } else if (dim == EsdAttachmentEXT) { - sampler.setAttachmentEXT(bTypes[bType]); - } else - if (image) { - sampler.setImage(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false, - shadow ? true : false, - ms ? true : false); - } else { - sampler.set(bTypes[bType], (TSamplerDim)dim, arrayed ? true : false, - shadow ? true : false, - ms ? true : false); - } - - TString typeName = sampler.getString(); - - if (dim == EsdSubpass) { - addSubpassSampling(sampler, typeName, version, profile); - continue; - } - - addQueryFunctions(sampler, typeName, version, profile); - - if (image) - addImageFunctions(sampler, typeName, version, profile); - else { - addSamplingFunctions(sampler, typeName, version, profile); - addGatherFunctions(sampler, typeName, version, profile); - if (spvVersion.vulkan > 0 && sampler.isCombined() && !sampler.shadow) { - // Base Vulkan allows texelFetch() for - // textureBuffer (i.e. without sampler). - // - // GL_EXT_samplerless_texture_functions - // allows texelFetch() and query functions - // (other than textureQueryLod()) for all - // texture types. - sampler.setTexture(sampler.type, sampler.dim, sampler.arrayed, sampler.shadow, - sampler.ms); - TString textureTypeName = sampler.getString(); - addSamplingFunctions(sampler, textureTypeName, version, profile); - addQueryFunctions(sampler, textureTypeName, version, profile); - } - } - } - } - } - } - } - } - - // - // sparseTexelsResidentARB() - // - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append("bool sparseTexelsResidentARB(int code);\n"); - } -} - -// -// Helper function for add2ndGenerationSamplingImaging(), -// when adding context-independent built-in functions. -// -// Add all the query functions for the given type. -// -void TBuiltIns::addQueryFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) -{ - // - // textureSize() and imageSize() - // - - int sizeDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0) - (sampler.dim == EsdCube ? 1 : 0); - - if (sampler.isImage() && ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 420))) - return; - - if (profile == EEsProfile) - commonBuiltins.append("highp "); - if (sizeDims == 1) - commonBuiltins.append("int"); - else { - commonBuiltins.append("ivec"); - commonBuiltins.append(postfixes[sizeDims]); - } - if (sampler.isImage()) - commonBuiltins.append(" imageSize(readonly writeonly volatile coherent "); - else - commonBuiltins.append(" textureSize("); - commonBuiltins.append(typeName); - if (! sampler.isImage() && ! sampler.isRect() && ! sampler.isBuffer() && ! sampler.isMultiSample()) - commonBuiltins.append(",int);\n"); - else - commonBuiltins.append(");\n"); - - // - // textureSamples() and imageSamples() - // - - // GL_ARB_shader_texture_image_samples - // TODO: spec issue? there are no memory qualifiers; how to query a writeonly/readonly image, etc? - if (profile != EEsProfile && version >= 430 && sampler.isMultiSample()) { - commonBuiltins.append("int "); - if (sampler.isImage()) - commonBuiltins.append("imageSamples(readonly writeonly volatile coherent "); - else - commonBuiltins.append("textureSamples("); - commonBuiltins.append(typeName); - commonBuiltins.append(");\n"); - } - - // - // textureQueryLod(), fragment stage only - // Also enabled with extension GL_ARB_texture_query_lod - // Extension GL_ARB_texture_query_lod says that textureQueryLOD() also exist at extension. - - if (profile != EEsProfile && version >= 150 && sampler.isCombined() && sampler.dim != EsdRect && - ! sampler.isMultiSample() && ! sampler.isBuffer()) { - - const TString funcName[2] = {"vec2 textureQueryLod(", "vec2 textureQueryLOD("}; - - for (int i = 0; i < 2; ++i){ - for (int f16TexAddr = 0; f16TexAddr < 2; ++f16TexAddr) { - if (f16TexAddr && sampler.type != EbtFloat16) - continue; - stageBuiltins[EShLangFragment].append(funcName[i]); - stageBuiltins[EShLangFragment].append(typeName); - if (dimMap[sampler.dim] == 1) - if (f16TexAddr) - stageBuiltins[EShLangFragment].append(", float16_t"); - else - stageBuiltins[EShLangFragment].append(", float"); - else { - if (f16TexAddr) - stageBuiltins[EShLangFragment].append(", f16vec"); - else - stageBuiltins[EShLangFragment].append(", vec"); - stageBuiltins[EShLangFragment].append(postfixes[dimMap[sampler.dim]]); - } - stageBuiltins[EShLangFragment].append(");\n"); - } - - stageBuiltins[EShLangCompute].append(funcName[i]); - stageBuiltins[EShLangCompute].append(typeName); - if (dimMap[sampler.dim] == 1) - stageBuiltins[EShLangCompute].append(", float"); - else { - stageBuiltins[EShLangCompute].append(", vec"); - stageBuiltins[EShLangCompute].append(postfixes[dimMap[sampler.dim]]); - } - stageBuiltins[EShLangCompute].append(");\n"); - } - } - - // - // textureQueryLevels() - // - - if (profile != EEsProfile && version >= 430 && ! sampler.isImage() && sampler.dim != EsdRect && - ! sampler.isMultiSample() && ! sampler.isBuffer()) { - commonBuiltins.append("int textureQueryLevels("); - commonBuiltins.append(typeName); - commonBuiltins.append(");\n"); - } -} - -// -// Helper function for add2ndGenerationSamplingImaging(), -// when adding context-independent built-in functions. -// -// Add all the image access functions for the given type. -// -void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) -{ - int dims = dimMap[sampler.dim]; - // most things with an array add a dimension, except for cubemaps - if (sampler.arrayed && sampler.dim != EsdCube) - ++dims; - - TString imageParams = typeName; - if (dims == 1) - imageParams.append(", int"); - else { - imageParams.append(", ivec"); - imageParams.append(postfixes[dims]); - } - if (sampler.isMultiSample()) - imageParams.append(", int"); - - if (profile == EEsProfile) - commonBuiltins.append("highp "); - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4 imageLoad(readonly volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(");\n"); - - commonBuiltins.append("void imageStore(writeonly volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", "); - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4);\n"); - - if (! sampler.is1D() && ! sampler.isBuffer() && profile != EEsProfile && version >= 450) { - commonBuiltins.append("int sparseImageLoadARB(readonly volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", out "); - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4"); - commonBuiltins.append(");\n"); - } - - if ( profile != EEsProfile || - (profile == EEsProfile && version >= 310)) { - if (sampler.type == EbtInt || sampler.type == EbtUint || sampler.type == EbtInt64 || sampler.type == EbtUint64 ) { - - const char* dataType; - switch (sampler.type) { - case(EbtInt): dataType = "highp int"; break; - case(EbtUint): dataType = "highp uint"; break; - case(EbtInt64): dataType = "highp int64_t"; break; - case(EbtUint64): dataType = "highp uint64_t"; break; - default: dataType = ""; - } - - const int numBuiltins = 7; - - static const char* atomicFunc[numBuiltins] = { - " imageAtomicAdd(volatile coherent ", - " imageAtomicMin(volatile coherent ", - " imageAtomicMax(volatile coherent ", - " imageAtomicAnd(volatile coherent ", - " imageAtomicOr(volatile coherent ", - " imageAtomicXor(volatile coherent ", - " imageAtomicExchange(volatile coherent " - }; - - // Loop twice to add prototypes with/without scope/semantics - for (int j = 0; j < 2; ++j) { - for (size_t i = 0; i < numBuiltins; ++i) { - commonBuiltins.append(dataType); - commonBuiltins.append(atomicFunc[i]); - commonBuiltins.append(imageParams); - commonBuiltins.append(", "); - commonBuiltins.append(dataType); - if (j == 1) { - commonBuiltins.append(", int, int, int"); - } - commonBuiltins.append(");\n"); - } - - commonBuiltins.append(dataType); - commonBuiltins.append(" imageAtomicCompSwap(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", "); - commonBuiltins.append(dataType); - commonBuiltins.append(", "); - commonBuiltins.append(dataType); - if (j == 1) { - commonBuiltins.append(", int, int, int, int, int"); - } - commonBuiltins.append(");\n"); - } - - commonBuiltins.append(dataType); - commonBuiltins.append(" imageAtomicLoad(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", int, int, int);\n"); - - commonBuiltins.append("void imageAtomicStore(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", "); - commonBuiltins.append(dataType); - commonBuiltins.append(", int, int, int);\n"); - - } else { - // not int or uint - // GL_ARB_ES3_1_compatibility - // TODO: spec issue: are there restrictions on the kind of layout() that can be used? what about dropping memory qualifiers? - if (profile == EEsProfile && version >= 310) { - commonBuiltins.append("float imageAtomicExchange(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", float);\n"); - } - if (profile != EEsProfile && version >= 450) { - commonBuiltins.append("float imageAtomicAdd(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", float);\n"); - - commonBuiltins.append("float imageAtomicAdd(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", float"); - commonBuiltins.append(", int, int, int);\n"); - - commonBuiltins.append("float imageAtomicExchange(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", float);\n"); - - commonBuiltins.append("float imageAtomicExchange(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", float"); - commonBuiltins.append(", int, int, int);\n"); - - commonBuiltins.append("float imageAtomicLoad(readonly volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", int, int, int);\n"); - - commonBuiltins.append("void imageAtomicStore(writeonly volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", float"); - commonBuiltins.append(", int, int, int);\n"); - - commonBuiltins.append("float imageAtomicMin(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", float);\n"); - - commonBuiltins.append("float imageAtomicMin(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", float"); - commonBuiltins.append(", int, int, int);\n"); - - commonBuiltins.append("float imageAtomicMax(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", float);\n"); - - commonBuiltins.append("float imageAtomicMax(volatile coherent "); - commonBuiltins.append(imageParams); - commonBuiltins.append(", float"); - commonBuiltins.append(", int, int, int);\n"); - } - } - } - - if (sampler.dim == EsdRect || sampler.dim == EsdBuffer || sampler.shadow || sampler.isMultiSample()) - return; - - if (profile == EEsProfile || version < 450) - return; - - TString imageLodParams = typeName; - if (dims == 1) - imageLodParams.append(", int"); - else { - imageLodParams.append(", ivec"); - imageLodParams.append(postfixes[dims]); - } - imageLodParams.append(", int"); - - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4 imageLoadLodAMD(readonly volatile coherent "); - commonBuiltins.append(imageLodParams); - commonBuiltins.append(");\n"); - - commonBuiltins.append("void imageStoreLodAMD(writeonly volatile coherent "); - commonBuiltins.append(imageLodParams); - commonBuiltins.append(", "); - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4);\n"); - - if (! sampler.is1D()) { - commonBuiltins.append("int sparseImageLoadLodAMD(readonly volatile coherent "); - commonBuiltins.append(imageLodParams); - commonBuiltins.append(", out "); - commonBuiltins.append(prefixes[sampler.type]); - commonBuiltins.append("vec4"); - commonBuiltins.append(");\n"); - } -} - -// -// Helper function for initialize(), -// when adding context-independent built-in functions. -// -// Add all the subpass access functions for the given type. -// -void TBuiltIns::addSubpassSampling(TSampler sampler, const TString& typeName, int /*version*/, EProfile /*profile*/) -{ - stageBuiltins[EShLangFragment].append(prefixes[sampler.type]); - stageBuiltins[EShLangFragment].append("vec4 subpassLoad"); - stageBuiltins[EShLangFragment].append("("); - stageBuiltins[EShLangFragment].append(typeName.c_str()); - if (sampler.isMultiSample()) - stageBuiltins[EShLangFragment].append(", int"); - stageBuiltins[EShLangFragment].append(");\n"); -} - -// -// Helper function for add2ndGenerationSamplingImaging(), -// when adding context-independent built-in functions. -// -// Add all the texture lookup functions for the given type. -// -void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) -{ - // - // texturing - // - for (int proj = 0; proj <= 1; ++proj) { // loop over "bool" projective or not - - if (proj && (sampler.dim == EsdCube || sampler.isBuffer() || sampler.arrayed || sampler.isMultiSample() - || !sampler.isCombined())) - continue; - - for (int lod = 0; lod <= 1; ++lod) { - - if (lod && (sampler.isBuffer() || sampler.isRect() || sampler.isMultiSample() || !sampler.isCombined())) - continue; - if (lod && sampler.dim == Esd2D && sampler.arrayed && sampler.shadow) - continue; - if (lod && sampler.dim == EsdCube && sampler.shadow) - continue; - - for (int bias = 0; bias <= 1; ++bias) { - - if (bias && (lod || sampler.isMultiSample() || !sampler.isCombined())) - continue; - if (bias && (sampler.dim == Esd2D || sampler.dim == EsdCube) && sampler.shadow && sampler.arrayed) - continue; - if (bias && (sampler.isRect() || sampler.isBuffer())) - continue; - - for (int offset = 0; offset <= 1; ++offset) { // loop over "bool" offset or not - - if (proj + offset + bias + lod > 3) - continue; - if (offset && (sampler.dim == EsdCube || sampler.isBuffer() || sampler.isMultiSample())) - continue; - - for (int fetch = 0; fetch <= 1; ++fetch) { // loop over "bool" fetch or not - - if (proj + offset + fetch + bias + lod > 3) - continue; - if (fetch && (lod || bias)) - continue; - if (fetch && (sampler.shadow || sampler.dim == EsdCube)) - continue; - if (fetch == 0 && (sampler.isMultiSample() || sampler.isBuffer() - || !sampler.isCombined())) - continue; - - for (int grad = 0; grad <= 1; ++grad) { // loop over "bool" grad or not - - if (grad && (lod || bias || sampler.isMultiSample() || !sampler.isCombined())) - continue; - if (grad && sampler.isBuffer()) - continue; - if (proj + offset + fetch + grad + bias + lod > 3) - continue; - - for (int extraProj = 0; extraProj <= 1; ++extraProj) { - bool compare = false; - int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0); - // skip dummy unused second component for 1D non-array shadows - if (sampler.shadow && totalDims < 2) - totalDims = 2; - totalDims += (sampler.shadow ? 1 : 0) + proj; - if (totalDims > 4 && sampler.shadow) { - compare = true; - totalDims = 4; - } - assert(totalDims <= 4); - - if (extraProj && ! proj) - continue; - if (extraProj && (sampler.dim == Esd3D || sampler.shadow || !sampler.isCombined())) - continue; - - // loop over 16-bit floating-point texel addressing - for (int f16TexAddr = 0; f16TexAddr <= 1; ++f16TexAddr) - { - if (f16TexAddr && sampler.type != EbtFloat16) - continue; - if (f16TexAddr && sampler.shadow && ! compare) { - compare = true; // compare argument is always present - totalDims--; - } - // loop over "bool" lod clamp - for (int lodClamp = 0; lodClamp <= 1 ;++lodClamp) - { - if (lodClamp && (profile == EEsProfile || version < 450)) - continue; - if (lodClamp && (proj || lod || fetch)) - continue; - - // loop over "bool" sparse or not - for (int sparse = 0; sparse <= 1; ++sparse) - { - if (sparse && (profile == EEsProfile || version < 450)) - continue; - // Sparse sampling is not for 1D/1D array texture, buffer texture, and - // projective texture - if (sparse && (sampler.is1D() || sampler.isBuffer() || proj)) - continue; - - TString s; - - // return type - if (sparse) - s.append("int "); - else { - if (sampler.shadow) - if (sampler.type == EbtFloat16) - s.append("float16_t "); - else - s.append("float "); - else { - s.append(prefixes[sampler.type]); - s.append("vec4 "); - } - } - - // name - if (sparse) { - if (fetch) - s.append("sparseTexel"); - else - s.append("sparseTexture"); - } - else { - if (fetch) - s.append("texel"); - else - s.append("texture"); - } - if (proj) - s.append("Proj"); - if (lod) - s.append("Lod"); - if (grad) - s.append("Grad"); - if (fetch) - s.append("Fetch"); - if (offset) - s.append("Offset"); - if (lodClamp) - s.append("Clamp"); - if (lodClamp != 0 || sparse) - s.append("ARB"); - s.append("("); - - // sampler type - s.append(typeName); - // P coordinate - if (extraProj) { - if (f16TexAddr) - s.append(",f16vec4"); - else - s.append(",vec4"); - } else { - s.append(","); - TBasicType t = fetch ? EbtInt : (f16TexAddr ? EbtFloat16 : EbtFloat); - if (totalDims == 1) - s.append(TType::getBasicString(t)); - else { - s.append(prefixes[t]); - s.append("vec"); - s.append(postfixes[totalDims]); - } - } - // non-optional compare - if (compare) - s.append(",float"); - - // non-optional lod argument (lod that's not driven by lod loop) or sample - if ((fetch && !sampler.isBuffer() && - !sampler.isRect() && !sampler.isMultiSample()) - || (sampler.isMultiSample() && fetch)) - s.append(",int"); - // non-optional lod - if (lod) { - if (f16TexAddr) - s.append(",float16_t"); - else - s.append(",float"); - } - - // gradient arguments - if (grad) { - if (dimMap[sampler.dim] == 1) { - if (f16TexAddr) - s.append(",float16_t,float16_t"); - else - s.append(",float,float"); - } else { - if (f16TexAddr) - s.append(",f16vec"); - else - s.append(",vec"); - s.append(postfixes[dimMap[sampler.dim]]); - if (f16TexAddr) - s.append(",f16vec"); - else - s.append(",vec"); - s.append(postfixes[dimMap[sampler.dim]]); - } - } - // offset - if (offset) { - if (dimMap[sampler.dim] == 1) - s.append(",int"); - else { - s.append(",ivec"); - s.append(postfixes[dimMap[sampler.dim]]); - } - } - - // lod clamp - if (lodClamp) { - if (f16TexAddr) - s.append(",float16_t"); - else - s.append(",float"); - } - // texel out (for sparse texture) - if (sparse) { - s.append(",out "); - if (sampler.shadow) - if (sampler.type == EbtFloat16) - s.append("float16_t"); - else - s.append("float"); - else { - s.append(prefixes[sampler.type]); - s.append("vec4"); - } - } - // optional bias - if (bias) { - if (f16TexAddr) - s.append(",float16_t"); - else - s.append(",float"); - } - s.append(");\n"); - - // Add to the per-language set of built-ins - if (!grad && (bias || lodClamp != 0)) { - stageBuiltins[EShLangFragment].append(s); - stageBuiltins[EShLangCompute].append(s); - } else - commonBuiltins.append(s); - - } - } - } - } - } - } - } - } - } - } -} - -// -// Helper function for add2ndGenerationSamplingImaging(), -// when adding context-independent built-in functions. -// -// Add all the texture gather functions for the given type. -// -void TBuiltIns::addGatherFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) -{ - switch (sampler.dim) { - case Esd2D: - case EsdRect: - case EsdCube: - break; - default: - return; - } - - if (sampler.isMultiSample()) - return; - - if (version < 140 && sampler.dim == EsdRect && sampler.type != EbtFloat) - return; - - for (int f16TexAddr = 0; f16TexAddr <= 1; ++f16TexAddr) { // loop over 16-bit floating-point texel addressing - - if (f16TexAddr && sampler.type != EbtFloat16) - continue; - for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name: none, Offset, and Offsets - - for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument - - if (comp > 0 && sampler.shadow) - continue; - - if (offset > 0 && sampler.dim == EsdCube) - continue; - - for (int sparse = 0; sparse <= 1; ++sparse) { // loop over "bool" sparse or not - if (sparse && (profile == EEsProfile || version < 450)) - continue; - - TString s; - - // return type - if (sparse) - s.append("int "); - else { - s.append(prefixes[sampler.type]); - s.append("vec4 "); - } - - // name - if (sparse) - s.append("sparseTextureGather"); - else - s.append("textureGather"); - switch (offset) { - case 1: - s.append("Offset"); - break; - case 2: - s.append("Offsets"); - break; - default: - break; - } - if (sparse) - s.append("ARB"); - s.append("("); - - // sampler type argument - s.append(typeName); - - // P coordinate argument - if (f16TexAddr) - s.append(",f16vec"); - else - s.append(",vec"); - int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0); - s.append(postfixes[totalDims]); - - // refZ argument - if (sampler.shadow) - s.append(",float"); - - // offset argument - if (offset > 0) { - s.append(",ivec2"); - if (offset == 2) - s.append("[4]"); - } - - // texel out (for sparse texture) - if (sparse) { - s.append(",out "); - s.append(prefixes[sampler.type]); - s.append("vec4 "); - } - - // comp argument - if (comp) - s.append(",int"); - - s.append(");\n"); - commonBuiltins.append(s); - } - } - } - } - - if (sampler.dim == EsdRect || sampler.shadow) - return; - - if (profile == EEsProfile || version < 450) - return; - - for (int bias = 0; bias < 2; ++bias) { // loop over presence of bias argument - - for (int lod = 0; lod < 2; ++lod) { // loop over presence of lod argument - - if ((lod && bias) || (lod == 0 && bias == 0)) - continue; - - for (int f16TexAddr = 0; f16TexAddr <= 1; ++f16TexAddr) { // loop over 16-bit floating-point texel addressing - - if (f16TexAddr && sampler.type != EbtFloat16) - continue; - - for (int offset = 0; offset < 3; ++offset) { // loop over three forms of offset in the call name: none, Offset, and Offsets - - for (int comp = 0; comp < 2; ++comp) { // loop over presence of comp argument - - if (comp == 0 && bias) - continue; - - if (offset > 0 && sampler.dim == EsdCube) - continue; - - for (int sparse = 0; sparse <= 1; ++sparse) { // loop over "bool" sparse or not - if (sparse && (profile == EEsProfile || version < 450)) - continue; - - TString s; - - // return type - if (sparse) - s.append("int "); - else { - s.append(prefixes[sampler.type]); - s.append("vec4 "); - } - - // name - if (sparse) - s.append("sparseTextureGather"); - else - s.append("textureGather"); - - if (lod) - s.append("Lod"); - - switch (offset) { - case 1: - s.append("Offset"); - break; - case 2: - s.append("Offsets"); - break; - default: - break; - } - - if (lod) - s.append("AMD"); - else if (sparse) - s.append("ARB"); - - s.append("("); - - // sampler type argument - s.append(typeName); - - // P coordinate argument - if (f16TexAddr) - s.append(",f16vec"); - else - s.append(",vec"); - int totalDims = dimMap[sampler.dim] + (sampler.arrayed ? 1 : 0); - s.append(postfixes[totalDims]); - - // lod argument - if (lod) { - if (f16TexAddr) - s.append(",float16_t"); - else - s.append(",float"); - } - - // offset argument - if (offset > 0) { - s.append(",ivec2"); - if (offset == 2) - s.append("[4]"); - } - - // texel out (for sparse texture) - if (sparse) { - s.append(",out "); - s.append(prefixes[sampler.type]); - s.append("vec4 "); - } - - // comp argument - if (comp) - s.append(",int"); - - // bias argument - if (bias) { - if (f16TexAddr) - s.append(",float16_t"); - else - s.append(",float"); - } - - s.append(");\n"); - if (bias) - stageBuiltins[EShLangFragment].append(s); - else - commonBuiltins.append(s); - } - } - } - } - } - } -} - -// -// Add context-dependent built-in functions and variables that are present -// for the given version and profile. All the results are put into just the -// commonBuiltins, because it is called for just a specific stage. So, -// add stage-specific entries to the commonBuiltins, and only if that stage -// was requested. -// -void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language) -{ - // - // Initialize the context-dependent (resource-dependent) built-in strings for parsing. - // - - //============================================================================ - // - // Standard Uniforms - // - //============================================================================ - - TString& s = commonBuiltins; - const int maxSize = 200; - char builtInConstant[maxSize]; - - // - // Build string of implementation dependent constants. - // - - if (profile == EEsProfile) { - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers); - s.append(builtInConstant); - - if (version == 100) { - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors); - s.append(builtInConstant); - } else { - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxVertexOutputVectors = %d;", resources.maxVertexOutputVectors); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxFragmentInputVectors = %d;", resources.maxFragmentInputVectors); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MinProgramTexelOffset = %d;", resources.minProgramTexelOffset); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxProgramTexelOffset = %d;", resources.maxProgramTexelOffset); - s.append(builtInConstant); - } - - if (version >= 310) { - // geometry - - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryInputComponents = %d;", resources.maxGeometryInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputComponents = %d;", resources.maxGeometryOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryImageUniforms = %d;", resources.maxGeometryImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTextureImageUnits = %d;", resources.maxGeometryTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputVertices = %d;", resources.maxGeometryOutputVertices); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTotalOutputComponents = %d;", resources.maxGeometryTotalOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryUniformComponents = %d;", resources.maxGeometryUniformComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources.maxGeometryAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources.maxGeometryAtomicCounterBuffers); - s.append(builtInConstant); - - // tessellation - - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlInputComponents = %d;", resources.maxTessControlInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlOutputComponents = %d;", resources.maxTessControlOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTextureImageUnits = %d;", resources.maxTessControlTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlUniformComponents = %d;", resources.maxTessControlUniformComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTotalOutputComponents = %d;", resources.maxTessControlTotalOutputComponents); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationInputComponents = %d;", resources.maxTessEvaluationInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationOutputComponents = %d;", resources.maxTessEvaluationOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationTextureImageUnits = %d;", resources.maxTessEvaluationTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationUniformComponents = %d;", resources.maxTessEvaluationUniformComponents); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTessPatchComponents = %d;", resources.maxTessPatchComponents); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxPatchVertices = %d;", resources.maxPatchVertices); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessGenLevel = %d;", resources.maxTessGenLevel); - s.append(builtInConstant); - - // this is here instead of with the others in initialize(version, profile) due to the dependence on gl_MaxPatchVertices - if (language == EShLangTessControl || language == EShLangTessEvaluation) { - s.append( - "in gl_PerVertex {" - "highp vec4 gl_Position;" - "highp float gl_PointSize;" - "highp vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "highp vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes - "} gl_in[gl_MaxPatchVertices];" - "\n"); - } - } - - if (version >= 320) { - // tessellation - - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlImageUniforms = %d;", resources.maxTessControlImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationImageUniforms = %d;", resources.maxTessEvaluationImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounters = %d;", resources.maxTessControlAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounters = %d;", resources.maxTessEvaluationAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounterBuffers = %d;", resources.maxTessControlAtomicCounterBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounterBuffers = %d;", resources.maxTessEvaluationAtomicCounterBuffers); - s.append(builtInConstant); - } - - if (version >= 100) { - // GL_EXT_blend_func_extended - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxDualSourceDrawBuffersEXT = %d;", resources.maxDualSourceDrawBuffersEXT); - s.append(builtInConstant); - // this is here instead of with the others in initialize(version, profile) due to the dependence on gl_MaxDualSourceDrawBuffersEXT - if (language == EShLangFragment) { - s.append( - "mediump vec4 gl_SecondaryFragColorEXT;" - "mediump vec4 gl_SecondaryFragDataEXT[gl_MaxDualSourceDrawBuffersEXT];" - "\n"); - } - } - } else { - // non-ES profile - - if (version > 400) { - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors); - s.append(builtInConstant); - } - - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxLights = %d;", resources.maxLights); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxClipPlanes = %d;", resources.maxClipPlanes); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTextureUnits = %d;", resources.maxTextureUnits); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTextureCoords = %d;", resources.maxTextureCoords); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexUniformComponents = %d;", resources.maxVertexUniformComponents); - s.append(builtInConstant); - - // Moved from just being deprecated into compatibility profile only as of 4.20 - if (version < 420 || profile == ECompatibilityProfile) { - snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingFloats = %d;", resources.maxVaryingFloats); - s.append(builtInConstant); - } - - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentUniformComponents = %d;", resources.maxFragmentUniformComponents); - s.append(builtInConstant); - - if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) { - // - // OpenGL'uniform' state. Page numbers are in reference to version - // 1.4 of the OpenGL specification. - // - - // - // Matrix state. p. 31, 32, 37, 39, 40. - // - s.append("uniform mat4 gl_TextureMatrix[gl_MaxTextureCoords];" - - // - // Derived matrix state that provides inverse and transposed versions - // of the matrices above. - // - "uniform mat4 gl_TextureMatrixInverse[gl_MaxTextureCoords];" - - "uniform mat4 gl_TextureMatrixTranspose[gl_MaxTextureCoords];" - - "uniform mat4 gl_TextureMatrixInverseTranspose[gl_MaxTextureCoords];" - - // - // Clip planes p. 42. - // - "uniform vec4 gl_ClipPlane[gl_MaxClipPlanes];" - - // - // Light State p 50, 53, 55. - // - "uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];" - - // - // Derived state from products of light. - // - "uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];" - "uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];" - - // - // Texture Environment and Generation, p. 152, p. 40-42. - // - "uniform vec4 gl_TextureEnvColor[gl_MaxTextureImageUnits];" - "uniform vec4 gl_EyePlaneS[gl_MaxTextureCoords];" - "uniform vec4 gl_EyePlaneT[gl_MaxTextureCoords];" - "uniform vec4 gl_EyePlaneR[gl_MaxTextureCoords];" - "uniform vec4 gl_EyePlaneQ[gl_MaxTextureCoords];" - "uniform vec4 gl_ObjectPlaneS[gl_MaxTextureCoords];" - "uniform vec4 gl_ObjectPlaneT[gl_MaxTextureCoords];" - "uniform vec4 gl_ObjectPlaneR[gl_MaxTextureCoords];" - "uniform vec4 gl_ObjectPlaneQ[gl_MaxTextureCoords];"); - } - - if (version >= 130) { - snprintf(builtInConstant, maxSize, "const int gl_MaxClipDistances = %d;", resources.maxClipDistances); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxVaryingComponents = %d;", resources.maxVaryingComponents); - s.append(builtInConstant); - - // GL_ARB_shading_language_420pack - snprintf(builtInConstant, maxSize, "const mediump int gl_MinProgramTexelOffset = %d;", resources.minProgramTexelOffset); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const mediump int gl_MaxProgramTexelOffset = %d;", resources.maxProgramTexelOffset); - s.append(builtInConstant); - } - - // geometry - if (version >= 150) { - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryInputComponents = %d;", resources.maxGeometryInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputComponents = %d;", resources.maxGeometryOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTextureImageUnits = %d;", resources.maxGeometryTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryOutputVertices = %d;", resources.maxGeometryOutputVertices); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryTotalOutputComponents = %d;", resources.maxGeometryTotalOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryUniformComponents = %d;", resources.maxGeometryUniformComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryVaryingComponents = %d;", resources.maxGeometryVaryingComponents); - s.append(builtInConstant); - - } - - if (version >= 150) { - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexOutputComponents = %d;", resources.maxVertexOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentInputComponents = %d;", resources.maxFragmentInputComponents); - s.append(builtInConstant); - } - - // tessellation - if (version >= 150) { - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlInputComponents = %d;", resources.maxTessControlInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlOutputComponents = %d;", resources.maxTessControlOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTextureImageUnits = %d;", resources.maxTessControlTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlUniformComponents = %d;", resources.maxTessControlUniformComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlTotalOutputComponents = %d;", resources.maxTessControlTotalOutputComponents); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationInputComponents = %d;", resources.maxTessEvaluationInputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationOutputComponents = %d;", resources.maxTessEvaluationOutputComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationTextureImageUnits = %d;", resources.maxTessEvaluationTextureImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationUniformComponents = %d;", resources.maxTessEvaluationUniformComponents); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxTessPatchComponents = %d;", resources.maxTessPatchComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessGenLevel = %d;", resources.maxTessGenLevel); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxPatchVertices = %d;", resources.maxPatchVertices); - s.append(builtInConstant); - - // this is here instead of with the others in initialize(version, profile) due to the dependence on gl_MaxPatchVertices - if (language == EShLangTessControl || language == EShLangTessEvaluation) { - s.append( - "in gl_PerVertex {" - "vec4 gl_Position;" - "float gl_PointSize;" - "float gl_ClipDistance[];" - ); - if (profile == ECompatibilityProfile) - s.append( - "vec4 gl_ClipVertex;" - "vec4 gl_FrontColor;" - "vec4 gl_BackColor;" - "vec4 gl_FrontSecondaryColor;" - "vec4 gl_BackSecondaryColor;" - "vec4 gl_TexCoord[];" - "float gl_FogFragCoord;" - ); - if (profile != EEsProfile && version >= 450) - s.append( - "float gl_CullDistance[];" - "vec4 gl_SecondaryPositionNV;" // GL_NV_stereo_view_rendering - "vec4 gl_PositionPerViewNV[];" // GL_NVX_multiview_per_view_attributes - ); - s.append( - "} gl_in[gl_MaxPatchVertices];" - "\n"); - } - } - - if (version >= 150) { - snprintf(builtInConstant, maxSize, "const int gl_MaxViewports = %d;", resources.maxViewports); - s.append(builtInConstant); - } - - // images - if (version >= 130) { - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedImageUnitsAndFragmentOutputs = %d;", resources.maxCombinedImageUnitsAndFragmentOutputs); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxImageSamples = %d;", resources.maxImageSamples); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlImageUniforms = %d;", resources.maxTessControlImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationImageUniforms = %d;", resources.maxTessEvaluationImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryImageUniforms = %d;", resources.maxGeometryImageUniforms); - s.append(builtInConstant); - } - - // enhanced layouts - if (version >= 430) { - snprintf(builtInConstant, maxSize, "const int gl_MaxTransformFeedbackBuffers = %d;", resources.maxTransformFeedbackBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTransformFeedbackInterleavedComponents = %d;", resources.maxTransformFeedbackInterleavedComponents); - s.append(builtInConstant); - } - } - - // compute - if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 420)) { - snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupCount = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupCountX, - resources.maxComputeWorkGroupCountY, - resources.maxComputeWorkGroupCountZ); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxComputeWorkGroupSize = ivec3(%d,%d,%d);", resources.maxComputeWorkGroupSizeX, - resources.maxComputeWorkGroupSizeY, - resources.maxComputeWorkGroupSizeZ); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxComputeUniformComponents = %d;", resources.maxComputeUniformComponents); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxComputeTextureImageUnits = %d;", resources.maxComputeTextureImageUnits); - s.append(builtInConstant); - - s.append("\n"); - } - - // images (some in compute below) - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 130)) { - snprintf(builtInConstant, maxSize, "const int gl_MaxImageUnits = %d;", resources.maxImageUnits); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedShaderOutputResources = %d;", resources.maxCombinedShaderOutputResources); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexImageUniforms = %d;", resources.maxVertexImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentImageUniforms = %d;", resources.maxFragmentImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedImageUniforms = %d;", resources.maxCombinedImageUniforms); - s.append(builtInConstant); - } - - // compute - if ((profile == EEsProfile && version >= 310) || (profile != EEsProfile && version >= 420)) { - snprintf(builtInConstant, maxSize, "const int gl_MaxComputeImageUniforms = %d;", resources.maxComputeImageUniforms); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounters = %d;", resources.maxComputeAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxComputeAtomicCounterBuffers = %d;", resources.maxComputeAtomicCounterBuffers); - s.append(builtInConstant); - - s.append("\n"); - } - - // atomic counters (some in compute below) - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 420)) { - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounters = %d;", resources. maxVertexAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounters = %d;", resources. maxFragmentAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounters = %d;", resources. maxCombinedAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBindings = %d;", resources. maxAtomicCounterBindings); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxVertexAtomicCounterBuffers = %d;", resources. maxVertexAtomicCounterBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxFragmentAtomicCounterBuffers = %d;", resources. maxFragmentAtomicCounterBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedAtomicCounterBuffers = %d;", resources. maxCombinedAtomicCounterBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxAtomicCounterBufferSize = %d;", resources. maxAtomicCounterBufferSize); - s.append(builtInConstant); - } - if (profile != EEsProfile && version >= 420) { - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounters = %d;", resources. maxTessControlAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounters = %d;", resources. maxTessEvaluationAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounters = %d;", resources. maxGeometryAtomicCounters); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessControlAtomicCounterBuffers = %d;", resources. maxTessControlAtomicCounterBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxTessEvaluationAtomicCounterBuffers = %d;", resources. maxTessEvaluationAtomicCounterBuffers); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxGeometryAtomicCounterBuffers = %d;", resources. maxGeometryAtomicCounterBuffers); - s.append(builtInConstant); - - s.append("\n"); - } - - // GL_ARB_cull_distance - if (profile != EEsProfile && version >= 450) { - snprintf(builtInConstant, maxSize, "const int gl_MaxCullDistances = %d;", resources.maxCullDistances); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const int gl_MaxCombinedClipAndCullDistances = %d;", resources.maxCombinedClipAndCullDistances); - s.append(builtInConstant); - } - - // GL_ARB_ES3_1_compatibility - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 310)) { - snprintf(builtInConstant, maxSize, "const int gl_MaxSamples = %d;", resources.maxSamples); - s.append(builtInConstant); - } - - // SPV_NV_mesh_shader - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { - snprintf(builtInConstant, maxSize, "const int gl_MaxMeshOutputVerticesNV = %d;", resources.maxMeshOutputVerticesNV); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxMeshOutputPrimitivesNV = %d;", resources.maxMeshOutputPrimitivesNV); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxMeshWorkGroupSizeNV = ivec3(%d,%d,%d);", resources.maxMeshWorkGroupSizeX_NV, - resources.maxMeshWorkGroupSizeY_NV, - resources.maxMeshWorkGroupSizeZ_NV); - s.append(builtInConstant); - snprintf(builtInConstant, maxSize, "const ivec3 gl_MaxTaskWorkGroupSizeNV = ivec3(%d,%d,%d);", resources.maxTaskWorkGroupSizeX_NV, - resources.maxTaskWorkGroupSizeY_NV, - resources.maxTaskWorkGroupSizeZ_NV); - s.append(builtInConstant); - - snprintf(builtInConstant, maxSize, "const int gl_MaxMeshViewCountNV = %d;", resources.maxMeshViewCountNV); - s.append(builtInConstant); - - s.append("\n"); - } - - s.append("\n"); -} - -// -// To support special built-ins that have a special qualifier that cannot be declared textually -// in a shader, like gl_Position. -// -// This lets the type of the built-in be declared textually, and then have just its qualifier be -// updated afterward. -// -// Safe to call even if name is not present. -// -// Only use this for built-in variables that have a special qualifier in TStorageQualifier. -// New built-in variables should use a generic (textually declarable) qualifier in -// TStoraregQualifier and only call BuiltInVariable(). -// -static void SpecialQualifier(const char* name, TStorageQualifier qualifier, TBuiltInVariable builtIn, TSymbolTable& symbolTable) -{ - TSymbol* symbol = symbolTable.find(name); - if (symbol == nullptr) - return; - - TQualifier& symQualifier = symbol->getWritableType().getQualifier(); - symQualifier.storage = qualifier; - symQualifier.builtIn = builtIn; -} - -// -// Modify the symbol's flat decoration. -// -// Safe to call even if name is not present. -// -// Originally written to transform gl_SubGroupSizeARB from uniform to fragment input in Vulkan. -// -static void ModifyFlatDecoration(const char* name, bool flat, TSymbolTable& symbolTable) -{ - TSymbol* symbol = symbolTable.find(name); - if (symbol == nullptr) - return; - - TQualifier& symQualifier = symbol->getWritableType().getQualifier(); - symQualifier.flat = flat; -} - -// -// To tag built-in variables with their TBuiltInVariable enum. Use this when the -// normal declaration text already gets the qualifier right, and all that's needed -// is setting the builtIn field. This should be the normal way for all new -// built-in variables. -// -// If SpecialQualifier() was called, this does not need to be called. -// -// Safe to call even if name is not present. -// -static void BuiltInVariable(const char* name, TBuiltInVariable builtIn, TSymbolTable& symbolTable) -{ - TSymbol* symbol = symbolTable.find(name); - if (symbol == nullptr) - return; - - TQualifier& symQualifier = symbol->getWritableType().getQualifier(); - symQualifier.builtIn = builtIn; -} - -static void RetargetVariable(const char* from, const char* to, TSymbolTable& symbolTable) -{ - symbolTable.retargetSymbol(from, to); -} - -// -// For built-in variables inside a named block. -// SpecialQualifier() won't ever go inside a block; their member's qualifier come -// from the qualification of the block. -// -// See comments above for other detail. -// -static void BuiltInVariable(const char* blockName, const char* name, TBuiltInVariable builtIn, TSymbolTable& symbolTable) -{ - TSymbol* symbol = symbolTable.find(blockName); - if (symbol == nullptr) - return; - - TTypeList& structure = *symbol->getWritableType().getWritableStruct(); - for (int i = 0; i < (int)structure.size(); ++i) { - if (structure[i].type->getFieldName().compare(name) == 0) { - structure[i].type->getQualifier().builtIn = builtIn; - return; - } - } -} - -// -// Finish adding/processing context-independent built-in symbols. -// 1) Programmatically add symbols that could not be added by simple text strings above. -// 2) Map built-in functions to operators, for those that will turn into an operation node -// instead of remaining a function call. -// 3) Tag extension-related symbols added to their base version with their extensions, so -// that if an early version has the extension turned off, there is an error reported on use. -// -void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) -{ - // - // Tag built-in variables and functions with additional qualifier and extension information - // that cannot be declared with the text strings. - // - - // N.B.: a symbol should only be tagged once, and this function is called multiple times, once - // per stage that's used for this profile. So - // - generally, stick common ones in the fragment stage to ensure they are tagged exactly once - // - for ES, which has different precisions for different stages, the coarsest-grained tagging - // for a built-in used in many stages needs to be once for the fragment stage and once for - // the vertex stage - - switch(language) { - case EShLangVertex: - if (spvVersion.vulkan > 0) { - BuiltInVariable("gl_VertexIndex", EbvVertexIndex, symbolTable); - BuiltInVariable("gl_InstanceIndex", EbvInstanceIndex, symbolTable); - } - - if (spvVersion.vulkan == 0) { - SpecialQualifier("gl_VertexID", EvqVertexId, EbvVertexId, symbolTable); - SpecialQualifier("gl_InstanceID", EvqInstanceId, EbvInstanceId, symbolTable); - if (version < 140) - symbolTable.setVariableExtensions("gl_InstanceID", 1, &E_GL_EXT_draw_instanced); - } - - if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) { - // treat these built-ins as aliases of VertexIndex and InstanceIndex - RetargetVariable("gl_InstanceID", "gl_InstanceIndex", symbolTable); - RetargetVariable("gl_VertexID", "gl_VertexIndex", symbolTable); - } - - if (profile != EEsProfile) { - if (version >= 440) { - symbolTable.setVariableExtensions("gl_BaseVertexARB", 1, &E_GL_ARB_shader_draw_parameters); - symbolTable.setVariableExtensions("gl_BaseInstanceARB", 1, &E_GL_ARB_shader_draw_parameters); - symbolTable.setVariableExtensions("gl_DrawIDARB", 1, &E_GL_ARB_shader_draw_parameters); - BuiltInVariable("gl_BaseVertexARB", EbvBaseVertex, symbolTable); - BuiltInVariable("gl_BaseInstanceARB", EbvBaseInstance, symbolTable); - BuiltInVariable("gl_DrawIDARB", EbvDrawId, symbolTable); - } - if (version >= 460) { - BuiltInVariable("gl_BaseVertex", EbvBaseVertex, symbolTable); - BuiltInVariable("gl_BaseInstance", EbvBaseInstance, symbolTable); - BuiltInVariable("gl_DrawID", EbvDrawId, symbolTable); - } - symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot); - - symbolTable.setFunctionExtensions("ballotARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setFunctionExtensions("readInvocationARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setFunctionExtensions("readFirstInvocationARB", 1, &E_GL_ARB_shader_ballot); - - if (version >= 430) { - symbolTable.setFunctionExtensions("anyInvocationARB", 1, &E_GL_ARB_shader_group_vote); - symbolTable.setFunctionExtensions("allInvocationsARB", 1, &E_GL_ARB_shader_group_vote); - symbolTable.setFunctionExtensions("allInvocationsEqualARB", 1, &E_GL_ARB_shader_group_vote); - } - } - - - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("minInvocationsAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("minInvocationsNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("swizzleInvocationsAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("swizzleInvocationsWithPatternAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("writeInvocationAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("mbcntAMD", 1, &E_GL_AMD_shader_ballot); - - symbolTable.setFunctionExtensions("minInvocationsInclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsInclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsInclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("minInvocationsInclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsInclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsInclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("minInvocationsExclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsExclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsExclusiveScanAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("minInvocationsExclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("maxInvocationsExclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - symbolTable.setFunctionExtensions("addInvocationsExclusiveScanNonUniformAMD", 1, &E_GL_AMD_shader_ballot); - } - - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("min3", 1, &E_GL_AMD_shader_trinary_minmax); - symbolTable.setFunctionExtensions("max3", 1, &E_GL_AMD_shader_trinary_minmax); - symbolTable.setFunctionExtensions("mid3", 1, &E_GL_AMD_shader_trinary_minmax); - } - - if (profile != EEsProfile) { - symbolTable.setVariableExtensions("gl_SIMDGroupSizeAMD", 1, &E_GL_AMD_gcn_shader); - SpecialQualifier("gl_SIMDGroupSizeAMD", EvqVaryingIn, EbvSubGroupSize, symbolTable); - - symbolTable.setFunctionExtensions("cubeFaceIndexAMD", 1, &E_GL_AMD_gcn_shader); - symbolTable.setFunctionExtensions("cubeFaceCoordAMD", 1, &E_GL_AMD_gcn_shader); - symbolTable.setFunctionExtensions("timeAMD", 1, &E_GL_AMD_gcn_shader); - } - - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("fragmentMaskFetchAMD", 1, &E_GL_AMD_shader_fragment_mask); - symbolTable.setFunctionExtensions("fragmentFetchAMD", 1, &E_GL_AMD_shader_fragment_mask); - } - - symbolTable.setFunctionExtensions("countLeadingZeros", 1, &E_GL_INTEL_shader_integer_functions2); - symbolTable.setFunctionExtensions("countTrailingZeros", 1, &E_GL_INTEL_shader_integer_functions2); - symbolTable.setFunctionExtensions("absoluteDifference", 1, &E_GL_INTEL_shader_integer_functions2); - symbolTable.setFunctionExtensions("addSaturate", 1, &E_GL_INTEL_shader_integer_functions2); - symbolTable.setFunctionExtensions("subtractSaturate", 1, &E_GL_INTEL_shader_integer_functions2); - symbolTable.setFunctionExtensions("average", 1, &E_GL_INTEL_shader_integer_functions2); - symbolTable.setFunctionExtensions("averageRounded", 1, &E_GL_INTEL_shader_integer_functions2); - symbolTable.setFunctionExtensions("multiply32x16", 1, &E_GL_INTEL_shader_integer_functions2); - - symbolTable.setFunctionExtensions("textureFootprintNV", 1, &E_GL_NV_shader_texture_footprint); - symbolTable.setFunctionExtensions("textureFootprintClampNV", 1, &E_GL_NV_shader_texture_footprint); - symbolTable.setFunctionExtensions("textureFootprintLodNV", 1, &E_GL_NV_shader_texture_footprint); - symbolTable.setFunctionExtensions("textureFootprintGradNV", 1, &E_GL_NV_shader_texture_footprint); - symbolTable.setFunctionExtensions("textureFootprintGradClampNV", 1, &E_GL_NV_shader_texture_footprint); - // Compatibility variables, vertex only - if (spvVersion.spv == 0) { - BuiltInVariable("gl_Color", EbvColor, symbolTable); - BuiltInVariable("gl_SecondaryColor", EbvSecondaryColor, symbolTable); - BuiltInVariable("gl_Normal", EbvNormal, symbolTable); - BuiltInVariable("gl_Vertex", EbvVertex, symbolTable); - BuiltInVariable("gl_MultiTexCoord0", EbvMultiTexCoord0, symbolTable); - BuiltInVariable("gl_MultiTexCoord1", EbvMultiTexCoord1, symbolTable); - BuiltInVariable("gl_MultiTexCoord2", EbvMultiTexCoord2, symbolTable); - BuiltInVariable("gl_MultiTexCoord3", EbvMultiTexCoord3, symbolTable); - BuiltInVariable("gl_MultiTexCoord4", EbvMultiTexCoord4, symbolTable); - BuiltInVariable("gl_MultiTexCoord5", EbvMultiTexCoord5, symbolTable); - BuiltInVariable("gl_MultiTexCoord6", EbvMultiTexCoord6, symbolTable); - BuiltInVariable("gl_MultiTexCoord7", EbvMultiTexCoord7, symbolTable); - BuiltInVariable("gl_FogCoord", EbvFogFragCoord, symbolTable); - } - - if (profile == EEsProfile) { - if (spvVersion.spv == 0) { - symbolTable.setFunctionExtensions("texture2DGradEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("textureCubeGradEXT", 1, &E_GL_EXT_shader_texture_lod); - if (version == 310) - symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5); - } - if (version == 310) - symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5); - } - - if (profile == EEsProfile && version < 320) { - symbolTable.setFunctionExtensions("imageAtomicAdd", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicMin", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicMax", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicAnd", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicOr", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicXor", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicExchange", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic); - } - - if (version >= 300 /* both ES and non-ES */) { - symbolTable.setVariableExtensions("gl_ViewID_OVR", Num_OVR_multiview_EXTs, OVR_multiview_EXTs); - BuiltInVariable("gl_ViewID_OVR", EbvViewIndex, symbolTable); - } - - if (profile == EEsProfile) { - symbolTable.setFunctionExtensions("shadow2DEXT", 1, &E_GL_EXT_shadow_samplers); - symbolTable.setFunctionExtensions("shadow2DProjEXT", 1, &E_GL_EXT_shadow_samplers); - } - - // E_GL_EXT_texture_array - if (profile != EEsProfile && spvVersion.spv == 0) { - symbolTable.setFunctionExtensions("texture1DArray", 1, &E_GL_EXT_texture_array); - symbolTable.setFunctionExtensions("texture2DArray", 1, &E_GL_EXT_texture_array); - symbolTable.setFunctionExtensions("shadow1DArray", 1, &E_GL_EXT_texture_array); - symbolTable.setFunctionExtensions("shadow2DArray", 1, &E_GL_EXT_texture_array); - - symbolTable.setFunctionExtensions("texture1DArrayLod", 1, &E_GL_EXT_texture_array); - symbolTable.setFunctionExtensions("texture2DArrayLod", 1, &E_GL_EXT_texture_array); - symbolTable.setFunctionExtensions("shadow1DArrayLod", 1, &E_GL_EXT_texture_array); - } - // Fall through - - case EShLangTessControl: - if (profile == EEsProfile && version >= 310) { - BuiltInVariable("gl_BoundingBoxEXT", EbvBoundingBox, symbolTable); - symbolTable.setVariableExtensions("gl_BoundingBoxEXT", 1, - &E_GL_EXT_primitive_bounding_box); - BuiltInVariable("gl_BoundingBoxOES", EbvBoundingBox, symbolTable); - symbolTable.setVariableExtensions("gl_BoundingBoxOES", 1, - &E_GL_OES_primitive_bounding_box); - - if (version >= 320) { - BuiltInVariable("gl_BoundingBox", EbvBoundingBox, symbolTable); - } - } - // Fall through - - case EShLangTessEvaluation: - case EShLangGeometry: - SpecialQualifier("gl_Position", EvqPosition, EbvPosition, symbolTable); - SpecialQualifier("gl_PointSize", EvqPointSize, EbvPointSize, symbolTable); - - BuiltInVariable("gl_in", "gl_Position", EbvPosition, symbolTable); - BuiltInVariable("gl_in", "gl_PointSize", EbvPointSize, symbolTable); - - BuiltInVariable("gl_out", "gl_Position", EbvPosition, symbolTable); - BuiltInVariable("gl_out", "gl_PointSize", EbvPointSize, symbolTable); - - SpecialQualifier("gl_ClipVertex", EvqClipVertex, EbvClipVertex, symbolTable); - - BuiltInVariable("gl_in", "gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_in", "gl_CullDistance", EbvCullDistance, symbolTable); - - BuiltInVariable("gl_out", "gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_out", "gl_CullDistance", EbvCullDistance, symbolTable); - - BuiltInVariable("gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_CullDistance", EbvCullDistance, symbolTable); - BuiltInVariable("gl_PrimitiveIDIn", EbvPrimitiveId, symbolTable); - BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable); - BuiltInVariable("gl_InvocationID", EbvInvocationId, symbolTable); - BuiltInVariable("gl_Layer", EbvLayer, symbolTable); - BuiltInVariable("gl_ViewportIndex", EbvViewportIndex, symbolTable); - - if (language != EShLangGeometry) { - symbolTable.setVariableExtensions("gl_Layer", Num_viewportEXTs, viewportEXTs); - symbolTable.setVariableExtensions("gl_ViewportIndex", Num_viewportEXTs, viewportEXTs); - } - symbolTable.setVariableExtensions("gl_ViewportMask", 1, &E_GL_NV_viewport_array2); - symbolTable.setVariableExtensions("gl_SecondaryPositionNV", 1, &E_GL_NV_stereo_view_rendering); - symbolTable.setVariableExtensions("gl_SecondaryViewportMaskNV", 1, &E_GL_NV_stereo_view_rendering); - symbolTable.setVariableExtensions("gl_PositionPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes); - symbolTable.setVariableExtensions("gl_ViewportMaskPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes); - - BuiltInVariable("gl_ViewportMask", EbvViewportMaskNV, symbolTable); - BuiltInVariable("gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable); - BuiltInVariable("gl_SecondaryViewportMaskNV", EbvSecondaryViewportMaskNV, symbolTable); - BuiltInVariable("gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable); - BuiltInVariable("gl_ViewportMaskPerViewNV", EbvViewportMaskPerViewNV, symbolTable); - - if (language == EShLangVertex || language == EShLangGeometry) { - symbolTable.setVariableExtensions("gl_in", "gl_SecondaryPositionNV", 1, &E_GL_NV_stereo_view_rendering); - symbolTable.setVariableExtensions("gl_in", "gl_PositionPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes); - - BuiltInVariable("gl_in", "gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable); - BuiltInVariable("gl_in", "gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable); - } - symbolTable.setVariableExtensions("gl_out", "gl_ViewportMask", 1, &E_GL_NV_viewport_array2); - symbolTable.setVariableExtensions("gl_out", "gl_SecondaryPositionNV", 1, &E_GL_NV_stereo_view_rendering); - symbolTable.setVariableExtensions("gl_out", "gl_SecondaryViewportMaskNV", 1, &E_GL_NV_stereo_view_rendering); - symbolTable.setVariableExtensions("gl_out", "gl_PositionPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes); - symbolTable.setVariableExtensions("gl_out", "gl_ViewportMaskPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes); - - BuiltInVariable("gl_out", "gl_ViewportMask", EbvViewportMaskNV, symbolTable); - BuiltInVariable("gl_out", "gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable); - BuiltInVariable("gl_out", "gl_SecondaryViewportMaskNV", EbvSecondaryViewportMaskNV, symbolTable); - BuiltInVariable("gl_out", "gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable); - BuiltInVariable("gl_out", "gl_ViewportMaskPerViewNV", EbvViewportMaskPerViewNV, symbolTable); - - BuiltInVariable("gl_PatchVerticesIn", EbvPatchVertices, symbolTable); - BuiltInVariable("gl_TessLevelOuter", EbvTessLevelOuter, symbolTable); - BuiltInVariable("gl_TessLevelInner", EbvTessLevelInner, symbolTable); - BuiltInVariable("gl_TessCoord", EbvTessCoord, symbolTable); - - if (version < 410) - symbolTable.setVariableExtensions("gl_ViewportIndex", 1, &E_GL_ARB_viewport_array); - - // Compatibility variables - - BuiltInVariable("gl_in", "gl_ClipVertex", EbvClipVertex, symbolTable); - BuiltInVariable("gl_in", "gl_FrontColor", EbvFrontColor, symbolTable); - BuiltInVariable("gl_in", "gl_BackColor", EbvBackColor, symbolTable); - BuiltInVariable("gl_in", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable); - BuiltInVariable("gl_in", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable); - BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable); - - BuiltInVariable("gl_out", "gl_ClipVertex", EbvClipVertex, symbolTable); - BuiltInVariable("gl_out", "gl_FrontColor", EbvFrontColor, symbolTable); - BuiltInVariable("gl_out", "gl_BackColor", EbvBackColor, symbolTable); - BuiltInVariable("gl_out", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable); - BuiltInVariable("gl_out", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable); - BuiltInVariable("gl_out", "gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_out", "gl_FogFragCoord", EbvFogFragCoord, symbolTable); - - BuiltInVariable("gl_ClipVertex", EbvClipVertex, symbolTable); - BuiltInVariable("gl_FrontColor", EbvFrontColor, symbolTable); - BuiltInVariable("gl_BackColor", EbvBackColor, symbolTable); - BuiltInVariable("gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable); - BuiltInVariable("gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable); - BuiltInVariable("gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_FogFragCoord", EbvFogFragCoord, symbolTable); - - // gl_PointSize, when it needs to be tied to an extension, is always a member of a block. - // (Sometimes with an instance name, sometimes anonymous). - if (profile == EEsProfile) { - if (language == EShLangGeometry) { - symbolTable.setVariableExtensions("gl_PointSize", Num_AEP_geometry_point_size, AEP_geometry_point_size); - symbolTable.setVariableExtensions("gl_in", "gl_PointSize", Num_AEP_geometry_point_size, AEP_geometry_point_size); - } else if (language == EShLangTessEvaluation || language == EShLangTessControl) { - // gl_in tessellation settings of gl_PointSize are in the context-dependent paths - symbolTable.setVariableExtensions("gl_PointSize", Num_AEP_tessellation_point_size, AEP_tessellation_point_size); - symbolTable.setVariableExtensions("gl_out", "gl_PointSize", Num_AEP_tessellation_point_size, AEP_tessellation_point_size); - } - } - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); - BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); - symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview); - BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable); - } - - if (profile != EEsProfile) { - BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable); - BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable); - BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable); - BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable); - BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable); - BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable); - - if (spvVersion.vulkan > 0) { - // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan - SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable); - if (language == EShLangFragment) - ModifyFlatDecoration("gl_SubGroupSizeARB", true, symbolTable); - } - else - BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable); - } - - // GL_KHR_shader_subgroup - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - - BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable); - BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable); - BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable); - BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable); - BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable); - BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable); - BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable); - - // GL_NV_shader_sm_builtins - symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins); - BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable); - BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable); - BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable); - BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable); - - // GL_ARM_shader_core_builtins - symbolTable.setVariableExtensions("gl_CoreCountARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - - BuiltInVariable("gl_CoreCountARM", EbvCoreCountARM, symbolTable); - BuiltInVariable("gl_CoreIDARM", EbvCoreIDARM, symbolTable); - BuiltInVariable("gl_CoreMaxIDARM", EbvCoreMaxIDARM, symbolTable); - BuiltInVariable("gl_WarpIDARM", EbvWarpIDARM, symbolTable); - BuiltInVariable("gl_WarpMaxIDARM", EbvWarpMaxIDARM, symbolTable); - } - - if (language == EShLangGeometry || language == EShLangVertex) { - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 450)) { - symbolTable.setVariableExtensions("gl_PrimitiveShadingRateEXT", 1, &E_GL_EXT_fragment_shading_rate); - BuiltInVariable("gl_PrimitiveShadingRateEXT", EbvPrimitiveShadingRateKHR, symbolTable); - - symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - } - } - break; - - case EShLangFragment: - SpecialQualifier("gl_FrontFacing", EvqFace, EbvFace, symbolTable); - SpecialQualifier("gl_FragCoord", EvqFragCoord, EbvFragCoord, symbolTable); - SpecialQualifier("gl_PointCoord", EvqPointCoord, EbvPointCoord, symbolTable); - if (spvVersion.spv == 0) - SpecialQualifier("gl_FragColor", EvqFragColor, EbvFragColor, symbolTable); - else { - TSymbol* symbol = symbolTable.find("gl_FragColor"); - if (symbol) { - symbol->getWritableType().getQualifier().storage = EvqVaryingOut; - symbol->getWritableType().getQualifier().layoutLocation = 0; - } - } - SpecialQualifier("gl_FragDepth", EvqFragDepth, EbvFragDepth, symbolTable); - SpecialQualifier("gl_FragDepthEXT", EvqFragDepth, EbvFragDepth, symbolTable); - SpecialQualifier("gl_FragStencilRefARB", EvqFragStencil, EbvFragStencilRef, symbolTable); - SpecialQualifier("gl_HelperInvocation", EvqVaryingIn, EbvHelperInvocation, symbolTable); - - BuiltInVariable("gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_CullDistance", EbvCullDistance, symbolTable); - BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable); - - if (profile != EEsProfile && version >= 140) { - symbolTable.setVariableExtensions("gl_FragStencilRefARB", 1, &E_GL_ARB_shader_stencil_export); - BuiltInVariable("gl_FragStencilRefARB", EbvFragStencilRef, symbolTable); - } - - if (profile != EEsProfile && version < 400) { - symbolTable.setFunctionExtensions("textureQueryLOD", 1, &E_GL_ARB_texture_query_lod); - } - - if (profile != EEsProfile && version >= 460) { - symbolTable.setFunctionExtensions("rayQueryInitializeEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryTerminateEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGenerateIntersectionEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryConfirmIntersectionEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryProceedEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionTypeEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionTEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetRayFlagsEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetRayTMinEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceCustomIndexEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceIdEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionGeometryIndexEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionPrimitiveIndexEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionBarycentricsEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionFrontFaceEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionCandidateAABBOpaqueEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectRayDirectionEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectRayOriginEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionObjectToWorldEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionWorldToObjectEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetWorldRayOriginEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetWorldRayDirectionEXT", 1, &E_GL_EXT_ray_query); - symbolTable.setFunctionExtensions("rayQueryGetIntersectionTriangleVertexPositionsEXT", 1, &E_GL_EXT_ray_tracing_position_fetch); - symbolTable.setVariableExtensions("gl_RayFlagsSkipAABBEXT", 1, &E_GL_EXT_ray_flags_primitive_culling); - symbolTable.setVariableExtensions("gl_RayFlagsSkipTrianglesEXT", 1, &E_GL_EXT_ray_flags_primitive_culling); - symbolTable.setVariableExtensions("gl_RayFlagsForceOpacityMicromap2StateEXT", 1, &E_GL_EXT_opacity_micromap); - } - - if ((profile != EEsProfile && version >= 130) || - (profile == EEsProfile && version >= 310)) { - BuiltInVariable("gl_SampleID", EbvSampleId, symbolTable); - BuiltInVariable("gl_SamplePosition", EbvSamplePosition, symbolTable); - BuiltInVariable("gl_SampleMask", EbvSampleMask, symbolTable); - - if (profile != EEsProfile && version < 400) { - BuiltInVariable("gl_NumSamples", EbvSampleMask, symbolTable); - - symbolTable.setVariableExtensions("gl_SampleMask", 1, &E_GL_ARB_sample_shading); - symbolTable.setVariableExtensions("gl_SampleID", 1, &E_GL_ARB_sample_shading); - symbolTable.setVariableExtensions("gl_SamplePosition", 1, &E_GL_ARB_sample_shading); - symbolTable.setVariableExtensions("gl_NumSamples", 1, &E_GL_ARB_sample_shading); - } else { - BuiltInVariable("gl_SampleMaskIn", EbvSampleMask, symbolTable); - - if (profile == EEsProfile && version < 320) { - symbolTable.setVariableExtensions("gl_SampleID", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_SamplePosition", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_SampleMaskIn", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_SampleMask", 1, &E_GL_OES_sample_variables); - symbolTable.setVariableExtensions("gl_NumSamples", 1, &E_GL_OES_sample_variables); - } - } - } - - BuiltInVariable("gl_Layer", EbvLayer, symbolTable); - BuiltInVariable("gl_ViewportIndex", EbvViewportIndex, symbolTable); - - // Compatibility variables - - BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable); - BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_in", "gl_Color", EbvColor, symbolTable); - BuiltInVariable("gl_in", "gl_SecondaryColor", EbvSecondaryColor, symbolTable); - - BuiltInVariable("gl_FogFragCoord", EbvFogFragCoord, symbolTable); - BuiltInVariable("gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_Color", EbvColor, symbolTable); - BuiltInVariable("gl_SecondaryColor", EbvSecondaryColor, symbolTable); - - // built-in functions - - if (profile == EEsProfile) { - if (spvVersion.spv == 0) { - symbolTable.setFunctionExtensions("texture2DLodEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DProjLodEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("textureCubeLodEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DGradEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DProjGradEXT", 1, &E_GL_EXT_shader_texture_lod); - symbolTable.setFunctionExtensions("textureCubeGradEXT", 1, &E_GL_EXT_shader_texture_lod); - if (version < 320) - symbolTable.setFunctionExtensions("textureGatherOffsets", Num_AEP_gpu_shader5, AEP_gpu_shader5); - } - if (version == 100) { - symbolTable.setFunctionExtensions("dFdx", 1, &E_GL_OES_standard_derivatives); - symbolTable.setFunctionExtensions("dFdy", 1, &E_GL_OES_standard_derivatives); - symbolTable.setFunctionExtensions("fwidth", 1, &E_GL_OES_standard_derivatives); - } - if (version == 310) { - symbolTable.setFunctionExtensions("fma", Num_AEP_gpu_shader5, AEP_gpu_shader5); - symbolTable.setFunctionExtensions("interpolateAtCentroid", 1, &E_GL_OES_shader_multisample_interpolation); - symbolTable.setFunctionExtensions("interpolateAtSample", 1, &E_GL_OES_shader_multisample_interpolation); - symbolTable.setFunctionExtensions("interpolateAtOffset", 1, &E_GL_OES_shader_multisample_interpolation); - } - } else if (version < 130) { - if (spvVersion.spv == 0) { - symbolTable.setFunctionExtensions("texture1DLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture3DLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("textureCubeLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture1DProjLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DProjLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture3DProjLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow1DLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow1DProjLod", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DProjLod", 1, &E_GL_ARB_shader_texture_lod); - } - } - - // E_GL_ARB_shader_texture_lod functions usable only with the extension enabled - if (profile != EEsProfile && spvVersion.spv == 0) { - symbolTable.setFunctionExtensions("texture1DGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture1DProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture3DGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture3DProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("textureCubeGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow1DGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow1DProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DRectGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("texture2DRectProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DRectGradARB", 1, &E_GL_ARB_shader_texture_lod); - symbolTable.setFunctionExtensions("shadow2DRectProjGradARB", 1, &E_GL_ARB_shader_texture_lod); - } - - // E_GL_ARB_shader_image_load_store - if (profile != EEsProfile && version < 420) - symbolTable.setFunctionExtensions("memoryBarrier", 1, &E_GL_ARB_shader_image_load_store); - // All the image access functions are protected by checks on the type of the first argument. - - // E_GL_ARB_shader_atomic_counters - if (profile != EEsProfile && version < 420) { - symbolTable.setFunctionExtensions("atomicCounterIncrement", 1, &E_GL_ARB_shader_atomic_counters); - symbolTable.setFunctionExtensions("atomicCounterDecrement", 1, &E_GL_ARB_shader_atomic_counters); - symbolTable.setFunctionExtensions("atomicCounter" , 1, &E_GL_ARB_shader_atomic_counters); - } - - // E_GL_ARB_shader_atomic_counter_ops - if (profile != EEsProfile && version == 450) { - symbolTable.setFunctionExtensions("atomicCounterAddARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); - symbolTable.setFunctionExtensions("atomicCounterSubtractARB", 1, &E_GL_ARB_shader_atomic_counter_ops); - symbolTable.setFunctionExtensions("atomicCounterMinARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); - symbolTable.setFunctionExtensions("atomicCounterMaxARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); - symbolTable.setFunctionExtensions("atomicCounterAndARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); - symbolTable.setFunctionExtensions("atomicCounterOrARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); - symbolTable.setFunctionExtensions("atomicCounterXorARB" , 1, &E_GL_ARB_shader_atomic_counter_ops); - symbolTable.setFunctionExtensions("atomicCounterExchangeARB", 1, &E_GL_ARB_shader_atomic_counter_ops); - symbolTable.setFunctionExtensions("atomicCounterCompSwapARB", 1, &E_GL_ARB_shader_atomic_counter_ops); - } - - // E_GL_ARB_derivative_control - if (profile != EEsProfile && version < 450) { - symbolTable.setFunctionExtensions("dFdxFine", 1, &E_GL_ARB_derivative_control); - symbolTable.setFunctionExtensions("dFdyFine", 1, &E_GL_ARB_derivative_control); - symbolTable.setFunctionExtensions("fwidthFine", 1, &E_GL_ARB_derivative_control); - symbolTable.setFunctionExtensions("dFdxCoarse", 1, &E_GL_ARB_derivative_control); - symbolTable.setFunctionExtensions("dFdyCoarse", 1, &E_GL_ARB_derivative_control); - symbolTable.setFunctionExtensions("fwidthCoarse", 1, &E_GL_ARB_derivative_control); - } - - // E_GL_ARB_sparse_texture2 - if (profile != EEsProfile) - { - symbolTable.setFunctionExtensions("sparseTextureARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureLodARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureOffsetARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTexelFetchARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTexelFetchOffsetARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureLodOffsetARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureGradARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureGradOffsetARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureGatherARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureGatherOffsetARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTextureGatherOffsetsARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseImageLoadARB", 1, &E_GL_ARB_sparse_texture2); - symbolTable.setFunctionExtensions("sparseTexelsResident", 1, &E_GL_ARB_sparse_texture2); - } - - // E_GL_ARB_sparse_texture_clamp - if (profile != EEsProfile) - { - symbolTable.setFunctionExtensions("sparseTextureClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("sparseTextureOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("sparseTextureGradClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("sparseTextureGradOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("textureClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("textureOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("textureGradClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - symbolTable.setFunctionExtensions("textureGradOffsetClampARB", 1, &E_GL_ARB_sparse_texture_clamp); - } - - // E_GL_AMD_shader_explicit_vertex_parameter - if (profile != EEsProfile) { - symbolTable.setVariableExtensions("gl_BaryCoordNoPerspAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordNoPerspCentroidAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordNoPerspSampleAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordSmoothAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordSmoothCentroidAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordSmoothSampleAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - symbolTable.setVariableExtensions("gl_BaryCoordPullModelAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - - symbolTable.setFunctionExtensions("interpolateAtVertexAMD", 1, &E_GL_AMD_shader_explicit_vertex_parameter); - - BuiltInVariable("gl_BaryCoordNoPerspAMD", EbvBaryCoordNoPersp, symbolTable); - BuiltInVariable("gl_BaryCoordNoPerspCentroidAMD", EbvBaryCoordNoPerspCentroid, symbolTable); - BuiltInVariable("gl_BaryCoordNoPerspSampleAMD", EbvBaryCoordNoPerspSample, symbolTable); - BuiltInVariable("gl_BaryCoordSmoothAMD", EbvBaryCoordSmooth, symbolTable); - BuiltInVariable("gl_BaryCoordSmoothCentroidAMD", EbvBaryCoordSmoothCentroid, symbolTable); - BuiltInVariable("gl_BaryCoordSmoothSampleAMD", EbvBaryCoordSmoothSample, symbolTable); - BuiltInVariable("gl_BaryCoordPullModelAMD", EbvBaryCoordPullModel, symbolTable); - } - - // E_GL_AMD_texture_gather_bias_lod - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("textureGatherLodAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - symbolTable.setFunctionExtensions("textureGatherLodOffsetAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - symbolTable.setFunctionExtensions("textureGatherLodOffsetsAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - symbolTable.setFunctionExtensions("sparseTextureGatherLodAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - symbolTable.setFunctionExtensions("sparseTextureGatherLodOffsetsAMD", 1, &E_GL_AMD_texture_gather_bias_lod); - } - - // E_GL_AMD_shader_image_load_store_lod - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("imageLoadLodAMD", 1, &E_GL_AMD_shader_image_load_store_lod); - symbolTable.setFunctionExtensions("imageStoreLodAMD", 1, &E_GL_AMD_shader_image_load_store_lod); - symbolTable.setFunctionExtensions("sparseImageLoadLodAMD", 1, &E_GL_AMD_shader_image_load_store_lod); - } - if (profile != EEsProfile && version >= 430) { - symbolTable.setVariableExtensions("gl_FragFullyCoveredNV", 1, &E_GL_NV_conservative_raster_underestimation); - BuiltInVariable("gl_FragFullyCoveredNV", EbvFragFullyCoveredNV, symbolTable); - } - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 320)) { - symbolTable.setVariableExtensions("gl_FragmentSizeNV", 1, &E_GL_NV_shading_rate_image); - symbolTable.setVariableExtensions("gl_InvocationsPerPixelNV", 1, &E_GL_NV_shading_rate_image); - BuiltInVariable("gl_FragmentSizeNV", EbvFragmentSizeNV, symbolTable); - BuiltInVariable("gl_InvocationsPerPixelNV", EbvInvocationsPerPixelNV, symbolTable); - symbolTable.setVariableExtensions("gl_BaryCoordNV", 1, &E_GL_NV_fragment_shader_barycentric); - symbolTable.setVariableExtensions("gl_BaryCoordNoPerspNV", 1, &E_GL_NV_fragment_shader_barycentric); - BuiltInVariable("gl_BaryCoordNV", EbvBaryCoordNV, symbolTable); - BuiltInVariable("gl_BaryCoordNoPerspNV", EbvBaryCoordNoPerspNV, symbolTable); - symbolTable.setVariableExtensions("gl_BaryCoordEXT", 1, &E_GL_EXT_fragment_shader_barycentric); - symbolTable.setVariableExtensions("gl_BaryCoordNoPerspEXT", 1, &E_GL_EXT_fragment_shader_barycentric); - BuiltInVariable("gl_BaryCoordEXT", EbvBaryCoordEXT, symbolTable); - BuiltInVariable("gl_BaryCoordNoPerspEXT", EbvBaryCoordNoPerspEXT, symbolTable); - } - - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 310)) { - symbolTable.setVariableExtensions("gl_FragSizeEXT", 1, &E_GL_EXT_fragment_invocation_density); - symbolTable.setVariableExtensions("gl_FragInvocationCountEXT", 1, &E_GL_EXT_fragment_invocation_density); - BuiltInVariable("gl_FragSizeEXT", EbvFragSizeEXT, symbolTable); - BuiltInVariable("gl_FragInvocationCountEXT", EbvFragInvocationCountEXT, symbolTable); - } - - symbolTable.setVariableExtensions("gl_FragDepthEXT", 1, &E_GL_EXT_frag_depth); - - symbolTable.setFunctionExtensions("clockARB", 1, &E_GL_ARB_shader_clock); - symbolTable.setFunctionExtensions("clock2x32ARB", 1, &E_GL_ARB_shader_clock); - - symbolTable.setFunctionExtensions("clockRealtimeEXT", 1, &E_GL_EXT_shader_realtime_clock); - symbolTable.setFunctionExtensions("clockRealtime2x32EXT", 1, &E_GL_EXT_shader_realtime_clock); - - if (profile == EEsProfile && version < 320) { - symbolTable.setVariableExtensions("gl_PrimitiveID", Num_AEP_geometry_shader, AEP_geometry_shader); - symbolTable.setVariableExtensions("gl_Layer", Num_AEP_geometry_shader, AEP_geometry_shader); - } - - if (profile == EEsProfile && version < 320) { - symbolTable.setFunctionExtensions("imageAtomicAdd", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicMin", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicMax", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicAnd", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicOr", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicXor", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicExchange", 1, &E_GL_OES_shader_image_atomic); - symbolTable.setFunctionExtensions("imageAtomicCompSwap", 1, &E_GL_OES_shader_image_atomic); - } - - if (profile != EEsProfile && version < 330 ) { - const char* bitsConvertExt[2] = {E_GL_ARB_shader_bit_encoding, E_GL_ARB_gpu_shader5}; - symbolTable.setFunctionExtensions("floatBitsToInt", 2, bitsConvertExt); - symbolTable.setFunctionExtensions("floatBitsToUint", 2, bitsConvertExt); - symbolTable.setFunctionExtensions("intBitsToFloat", 2, bitsConvertExt); - symbolTable.setFunctionExtensions("uintBitsToFloat", 2, bitsConvertExt); - } - - if (profile != EEsProfile && version < 430 ) { - symbolTable.setFunctionExtensions("imageSize", 1, &E_GL_ARB_shader_image_size); - } - - // GL_ARB_shader_storage_buffer_object - if (profile != EEsProfile && version < 430 ) { - symbolTable.setFunctionExtensions("atomicAdd", 1, &E_GL_ARB_shader_storage_buffer_object); - symbolTable.setFunctionExtensions("atomicMin", 1, &E_GL_ARB_shader_storage_buffer_object); - symbolTable.setFunctionExtensions("atomicMax", 1, &E_GL_ARB_shader_storage_buffer_object); - symbolTable.setFunctionExtensions("atomicAnd", 1, &E_GL_ARB_shader_storage_buffer_object); - symbolTable.setFunctionExtensions("atomicOr", 1, &E_GL_ARB_shader_storage_buffer_object); - symbolTable.setFunctionExtensions("atomicXor", 1, &E_GL_ARB_shader_storage_buffer_object); - symbolTable.setFunctionExtensions("atomicExchange", 1, &E_GL_ARB_shader_storage_buffer_object); - symbolTable.setFunctionExtensions("atomicCompSwap", 1, &E_GL_ARB_shader_storage_buffer_object); - } - - // GL_ARB_shading_language_packing - if (profile != EEsProfile && version < 400 ) { - symbolTable.setFunctionExtensions("packUnorm2x16", 1, &E_GL_ARB_shading_language_packing); - symbolTable.setFunctionExtensions("unpackUnorm2x16", 1, &E_GL_ARB_shading_language_packing); - symbolTable.setFunctionExtensions("packSnorm4x8", 1, &E_GL_ARB_shading_language_packing); - symbolTable.setFunctionExtensions("packUnorm4x8", 1, &E_GL_ARB_shading_language_packing); - symbolTable.setFunctionExtensions("unpackSnorm4x8", 1, &E_GL_ARB_shading_language_packing); - symbolTable.setFunctionExtensions("unpackUnorm4x8", 1, &E_GL_ARB_shading_language_packing); - } - if (profile != EEsProfile && version < 420 ) { - symbolTable.setFunctionExtensions("packSnorm2x16", 1, &E_GL_ARB_shading_language_packing); - symbolTable.setFunctionExtensions("unpackSnorm2x16", 1, &E_GL_ARB_shading_language_packing); - symbolTable.setFunctionExtensions("unpackHalf2x16", 1, &E_GL_ARB_shading_language_packing); - symbolTable.setFunctionExtensions("packHalf2x16", 1, &E_GL_ARB_shading_language_packing); - } - - symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); - BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); - symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview); - BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable); - if (version >= 300 /* both ES and non-ES */) { - symbolTable.setVariableExtensions("gl_ViewID_OVR", Num_OVR_multiview_EXTs, OVR_multiview_EXTs); - BuiltInVariable("gl_ViewID_OVR", EbvViewIndex, symbolTable); - } - - // GL_ARB_shader_ballot - if (profile != EEsProfile) { - symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot); - - BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable); - BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable); - BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable); - BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable); - BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable); - BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable); - - if (spvVersion.vulkan > 0) { - // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan - SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable); - if (language == EShLangFragment) - ModifyFlatDecoration("gl_SubGroupSizeARB", true, symbolTable); - } - else - BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable); - } - - // GL_KHR_shader_subgroup - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - - BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable); - BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable); - BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable); - BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable); - BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable); - BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable); - BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable); - - symbolTable.setFunctionExtensions("subgroupBarrier", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setFunctionExtensions("subgroupMemoryBarrier", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setFunctionExtensions("subgroupMemoryBarrierBuffer", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setFunctionExtensions("subgroupMemoryBarrierImage", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setFunctionExtensions("subgroupElect", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setFunctionExtensions("subgroupAll", 1, &E_GL_KHR_shader_subgroup_vote); - symbolTable.setFunctionExtensions("subgroupAny", 1, &E_GL_KHR_shader_subgroup_vote); - symbolTable.setFunctionExtensions("subgroupAllEqual", 1, &E_GL_KHR_shader_subgroup_vote); - symbolTable.setFunctionExtensions("subgroupBroadcast", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBroadcastFirst", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallot", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupInverseBallot", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotBitExtract", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotBitCount", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotInclusiveBitCount", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotExclusiveBitCount", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotFindLSB", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupBallotFindMSB", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setFunctionExtensions("subgroupShuffle", 1, &E_GL_KHR_shader_subgroup_shuffle); - symbolTable.setFunctionExtensions("subgroupShuffleXor", 1, &E_GL_KHR_shader_subgroup_shuffle); - symbolTable.setFunctionExtensions("subgroupShuffleUp", 1, &E_GL_KHR_shader_subgroup_shuffle_relative); - symbolTable.setFunctionExtensions("subgroupShuffleDown", 1, &E_GL_KHR_shader_subgroup_shuffle_relative); - symbolTable.setFunctionExtensions("subgroupAdd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupMul", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupMin", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupMax", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupAnd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupOr", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupXor", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveAdd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveMul", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveMin", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveMax", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveAnd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveOr", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupInclusiveXor", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveAdd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveMul", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveMin", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveMax", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveAnd", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveOr", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupExclusiveXor", 1, &E_GL_KHR_shader_subgroup_arithmetic); - symbolTable.setFunctionExtensions("subgroupClusteredAdd", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredMul", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredMin", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredMax", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredAnd", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredOr", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupClusteredXor", 1, &E_GL_KHR_shader_subgroup_clustered); - symbolTable.setFunctionExtensions("subgroupQuadBroadcast", 1, &E_GL_KHR_shader_subgroup_quad); - symbolTable.setFunctionExtensions("subgroupQuadSwapHorizontal", 1, &E_GL_KHR_shader_subgroup_quad); - symbolTable.setFunctionExtensions("subgroupQuadSwapVertical", 1, &E_GL_KHR_shader_subgroup_quad); - symbolTable.setFunctionExtensions("subgroupQuadSwapDiagonal", 1, &E_GL_KHR_shader_subgroup_quad); - symbolTable.setFunctionExtensions("subgroupPartitionNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedAddNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedMulNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedMinNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedMaxNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedAndNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedOrNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedXorNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveAddNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveMulNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveMinNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveMaxNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveAndNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveOrNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedInclusiveXorNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveAddNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveMulNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveMinNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveMaxNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveAndNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveOrNV", 1, &E_GL_NV_shader_subgroup_partitioned); - symbolTable.setFunctionExtensions("subgroupPartitionedExclusiveXorNV", 1, &E_GL_NV_shader_subgroup_partitioned); - - // GL_NV_shader_sm_builtins - symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins); - BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable); - BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable); - BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable); - BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable); - - // GL_ARM_shader_core_builtins - symbolTable.setVariableExtensions("gl_CoreCountARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - - BuiltInVariable("gl_CoreCountARM", EbvCoreCountARM, symbolTable); - BuiltInVariable("gl_CoreIDARM", EbvCoreIDARM, symbolTable); - BuiltInVariable("gl_CoreMaxIDARM", EbvCoreMaxIDARM, symbolTable); - BuiltInVariable("gl_WarpIDARM", EbvWarpIDARM, symbolTable); - BuiltInVariable("gl_WarpMaxIDARM", EbvWarpMaxIDARM, symbolTable); - } - - if (profile == EEsProfile) { - symbolTable.setFunctionExtensions("shadow2DEXT", 1, &E_GL_EXT_shadow_samplers); - symbolTable.setFunctionExtensions("shadow2DProjEXT", 1, &E_GL_EXT_shadow_samplers); - } - - if (spvVersion.vulkan > 0) { - symbolTable.setVariableExtensions("gl_ScopeDevice", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_ScopeWorkgroup", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_ScopeSubgroup", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_ScopeInvocation", 1, &E_GL_KHR_memory_scope_semantics); - - symbolTable.setVariableExtensions("gl_SemanticsRelaxed", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_SemanticsAcquire", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_SemanticsRelease", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_SemanticsAcquireRelease", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_SemanticsMakeAvailable", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_SemanticsMakeVisible", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_SemanticsVolatile", 1, &E_GL_KHR_memory_scope_semantics); - - symbolTable.setVariableExtensions("gl_StorageSemanticsNone", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_StorageSemanticsBuffer", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_StorageSemanticsShared", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_StorageSemanticsImage", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setVariableExtensions("gl_StorageSemanticsOutput", 1, &E_GL_KHR_memory_scope_semantics); - } - - symbolTable.setFunctionExtensions("helperInvocationEXT", 1, &E_GL_EXT_demote_to_helper_invocation); - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 450)) { - symbolTable.setVariableExtensions("gl_ShadingRateEXT", 1, &E_GL_EXT_fragment_shading_rate); - BuiltInVariable("gl_ShadingRateEXT", EbvShadingRateKHR, symbolTable); - - symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - } - - // GL_EXT_shader_tile_image - symbolTable.setFunctionExtensions("stencilAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image); - symbolTable.setFunctionExtensions("depthAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image); - symbolTable.setFunctionExtensions("colorAttachmentReadEXT", 1, &E_GL_EXT_shader_tile_image); - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - symbolTable.setFunctionExtensions("textureWeightedQCOM", 1, &E_GL_QCOM_image_processing); - symbolTable.setFunctionExtensions("textureBoxFilterQCOM", 1, &E_GL_QCOM_image_processing); - symbolTable.setFunctionExtensions("textureBlockMatchSADQCOM", 1, &E_GL_QCOM_image_processing); - symbolTable.setFunctionExtensions("textureBlockMatchSSDQCOM", 1, &E_GL_QCOM_image_processing); - } - break; - - case EShLangCompute: - BuiltInVariable("gl_NumWorkGroups", EbvNumWorkGroups, symbolTable); - BuiltInVariable("gl_WorkGroupSize", EbvWorkGroupSize, symbolTable); - BuiltInVariable("gl_WorkGroupID", EbvWorkGroupId, symbolTable); - BuiltInVariable("gl_LocalInvocationID", EbvLocalInvocationId, symbolTable); - BuiltInVariable("gl_GlobalInvocationID", EbvGlobalInvocationId, symbolTable); - BuiltInVariable("gl_LocalInvocationIndex", EbvLocalInvocationIndex, symbolTable); - BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); - BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable); - - if ((profile != EEsProfile && version >= 140) || - (profile == EEsProfile && version >= 310)) { - symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); - symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview); - } - - if (profile != EEsProfile && version < 430) { - symbolTable.setVariableExtensions("gl_NumWorkGroups", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_WorkGroupSize", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_WorkGroupID", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationID", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_GlobalInvocationID", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationIndex", 1, &E_GL_ARB_compute_shader); - - symbolTable.setVariableExtensions("gl_MaxComputeWorkGroupCount", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeWorkGroupSize", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeUniformComponents", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeTextureImageUnits", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeImageUniforms", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeAtomicCounters", 1, &E_GL_ARB_compute_shader); - symbolTable.setVariableExtensions("gl_MaxComputeAtomicCounterBuffers", 1, &E_GL_ARB_compute_shader); - - symbolTable.setFunctionExtensions("barrier", 1, &E_GL_ARB_compute_shader); - symbolTable.setFunctionExtensions("memoryBarrierAtomicCounter", 1, &E_GL_ARB_compute_shader); - symbolTable.setFunctionExtensions("memoryBarrierBuffer", 1, &E_GL_ARB_compute_shader); - symbolTable.setFunctionExtensions("memoryBarrierImage", 1, &E_GL_ARB_compute_shader); - symbolTable.setFunctionExtensions("memoryBarrierShared", 1, &E_GL_ARB_compute_shader); - symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_ARB_compute_shader); - } - - - symbolTable.setFunctionExtensions("controlBarrier", 1, &E_GL_KHR_memory_scope_semantics); - symbolTable.setFunctionExtensions("debugPrintfEXT", 1, &E_GL_EXT_debug_printf); - - // GL_ARB_shader_ballot - if (profile != EEsProfile) { - symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot); - - BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable); - BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable); - BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable); - BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable); - BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable); - BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable); - - if (spvVersion.vulkan > 0) { - // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan - SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable); - if (language == EShLangFragment) - ModifyFlatDecoration("gl_SubGroupSizeARB", true, symbolTable); - } - else - BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable); - } - - // GL_KHR_shader_subgroup - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - - BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable); - BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable); - BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable); - BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable); - BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable); - BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable); - BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable); - - // GL_NV_shader_sm_builtins - symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins); - BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable); - BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable); - BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable); - BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable); - - // GL_ARM_shader_core_builtins - symbolTable.setVariableExtensions("gl_CoreCountARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - - BuiltInVariable("gl_CoreCountARM", EbvCoreCountARM, symbolTable); - BuiltInVariable("gl_CoreIDARM", EbvCoreIDARM, symbolTable); - BuiltInVariable("gl_CoreMaxIDARM", EbvCoreMaxIDARM, symbolTable); - BuiltInVariable("gl_WarpIDARM", EbvWarpIDARM, symbolTable); - BuiltInVariable("gl_WarpMaxIDARM", EbvWarpMaxIDARM, symbolTable); - } - - // GL_KHR_shader_subgroup - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - symbolTable.setVariableExtensions("gl_NumSubgroups", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupID", 1, &E_GL_KHR_shader_subgroup_basic); - - BuiltInVariable("gl_NumSubgroups", EbvNumSubgroups, symbolTable); - BuiltInVariable("gl_SubgroupID", EbvSubgroupID, symbolTable); - - symbolTable.setFunctionExtensions("subgroupMemoryBarrierShared", 1, &E_GL_KHR_shader_subgroup_basic); - } - - { - const char *coopExt[2] = { E_GL_NV_cooperative_matrix, E_GL_NV_integer_cooperative_matrix }; - symbolTable.setFunctionExtensions("coopMatLoadNV", 2, coopExt); - symbolTable.setFunctionExtensions("coopMatStoreNV", 2, coopExt); - symbolTable.setFunctionExtensions("coopMatMulAddNV", 2, coopExt); - } - - { - symbolTable.setFunctionExtensions("coopMatLoad", 1, &E_GL_KHR_cooperative_matrix); - symbolTable.setFunctionExtensions("coopMatStore", 1, &E_GL_KHR_cooperative_matrix); - symbolTable.setFunctionExtensions("coopMatMulAdd", 1, &E_GL_KHR_cooperative_matrix); - } - - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { - symbolTable.setFunctionExtensions("dFdx", 1, &E_GL_NV_compute_shader_derivatives); - symbolTable.setFunctionExtensions("dFdy", 1, &E_GL_NV_compute_shader_derivatives); - symbolTable.setFunctionExtensions("fwidth", 1, &E_GL_NV_compute_shader_derivatives); - symbolTable.setFunctionExtensions("dFdxFine", 1, &E_GL_NV_compute_shader_derivatives); - symbolTable.setFunctionExtensions("dFdyFine", 1, &E_GL_NV_compute_shader_derivatives); - symbolTable.setFunctionExtensions("fwidthFine", 1, &E_GL_NV_compute_shader_derivatives); - symbolTable.setFunctionExtensions("dFdxCoarse", 1, &E_GL_NV_compute_shader_derivatives); - symbolTable.setFunctionExtensions("dFdyCoarse", 1, &E_GL_NV_compute_shader_derivatives); - symbolTable.setFunctionExtensions("fwidthCoarse", 1, &E_GL_NV_compute_shader_derivatives); - } - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 450)) { - symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - } - - if ((profile != EEsProfile && version >= 460)) { - symbolTable.setFunctionExtensions("fetchMicroTriangleVertexPositionNV", 1, &E_GL_NV_displacement_micromap); - symbolTable.setFunctionExtensions("fetchMicroTriangleVertexBarycentricNV", 1, &E_GL_NV_displacement_micromap); - } - break; - - case EShLangRayGen: - case EShLangIntersect: - case EShLangAnyHit: - case EShLangClosestHit: - case EShLangMiss: - case EShLangCallable: - if (profile != EEsProfile && version >= 460) { - const char *rtexts[] = { E_GL_NV_ray_tracing, E_GL_EXT_ray_tracing }; - symbolTable.setVariableExtensions("gl_LaunchIDNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_LaunchIDEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_LaunchSizeNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_LaunchSizeEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_PrimitiveID", 2, rtexts); - symbolTable.setVariableExtensions("gl_InstanceID", 2, rtexts); - symbolTable.setVariableExtensions("gl_InstanceCustomIndexNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_InstanceCustomIndexEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_GeometryIndexEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_WorldRayOriginNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_WorldRayOriginEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_WorldRayDirectionNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_WorldRayDirectionEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_ObjectRayOriginNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_ObjectRayOriginEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_ObjectRayDirectionNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_ObjectRayDirectionEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_RayTminNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_RayTminEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_RayTmaxNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_RayTmaxEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_CullMaskEXT", 1, &E_GL_EXT_ray_cull_mask); - symbolTable.setVariableExtensions("gl_HitTNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_HitTEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_HitKindNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_HitKindEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_ObjectToWorldNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_ObjectToWorldEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_ObjectToWorld3x4EXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_WorldToObjectNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_WorldToObjectEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_WorldToObject3x4EXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_IncomingRayFlagsNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setVariableExtensions("gl_IncomingRayFlagsEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setVariableExtensions("gl_CurrentRayTimeNV", 1, &E_GL_NV_ray_tracing_motion_blur); - symbolTable.setVariableExtensions("gl_HitTriangleVertexPositionsEXT", 1, &E_GL_EXT_ray_tracing_position_fetch); - symbolTable.setVariableExtensions("gl_HitMicroTriangleVertexPositionsNV", 1, &E_GL_NV_displacement_micromap); - symbolTable.setVariableExtensions("gl_HitMicroTriangleVertexBarycentricsNV", 1, &E_GL_NV_displacement_micromap); - - symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); - - - symbolTable.setFunctionExtensions("traceNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setFunctionExtensions("traceRayMotionNV", 1, &E_GL_NV_ray_tracing_motion_blur); - symbolTable.setFunctionExtensions("traceRayEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setFunctionExtensions("reportIntersectionNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setFunctionExtensions("reportIntersectionEXT", 1, &E_GL_EXT_ray_tracing); - symbolTable.setFunctionExtensions("ignoreIntersectionNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setFunctionExtensions("terminateRayNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setFunctionExtensions("executeCallableNV", 1, &E_GL_NV_ray_tracing); - symbolTable.setFunctionExtensions("executeCallableEXT", 1, &E_GL_EXT_ray_tracing); - - symbolTable.setFunctionExtensions("hitObjectTraceRayNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectTraceRayMotionNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectRecordHitNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectRecordHitMotionNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectRecordHitWithIndexNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectRecordHitWithIndexMotionNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectRecordMissNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectRecordMissMotionNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectRecordEmptyNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectExecuteShaderNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectIsEmptyNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectIsMissNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectIsHitNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetRayTMinNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetRayTMaxNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetObjectRayOriginNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetObjectRayDirectionNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetWorldRayOriginNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetWorldRayDirectionNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetWorldToObjectNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetbjectToWorldNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetInstanceCustomIndexNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetInstanceIdNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetGeometryIndexNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetPrimitiveIndexNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetHitKindNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetAttributesNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetCurrentTimeNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetShaderBindingTableRecordIndexNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("hitObjectGetShaderRecordBufferHandleNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("reorderThreadNV", 1, &E_GL_NV_shader_invocation_reorder); - symbolTable.setFunctionExtensions("fetchMicroTriangleVertexPositionNV", 1, &E_GL_NV_displacement_micromap); - symbolTable.setFunctionExtensions("fetchMicroTriangleVertexBarycentricNV", 1, &E_GL_NV_displacement_micromap); - - - BuiltInVariable("gl_LaunchIDNV", EbvLaunchId, symbolTable); - BuiltInVariable("gl_LaunchIDEXT", EbvLaunchId, symbolTable); - BuiltInVariable("gl_LaunchSizeNV", EbvLaunchSize, symbolTable); - BuiltInVariable("gl_LaunchSizeEXT", EbvLaunchSize, symbolTable); - BuiltInVariable("gl_PrimitiveID", EbvPrimitiveId, symbolTable); - BuiltInVariable("gl_InstanceID", EbvInstanceId, symbolTable); - BuiltInVariable("gl_InstanceCustomIndexNV", EbvInstanceCustomIndex,symbolTable); - BuiltInVariable("gl_InstanceCustomIndexEXT", EbvInstanceCustomIndex,symbolTable); - BuiltInVariable("gl_GeometryIndexEXT", EbvGeometryIndex, symbolTable); - BuiltInVariable("gl_WorldRayOriginNV", EbvWorldRayOrigin, symbolTable); - BuiltInVariable("gl_WorldRayOriginEXT", EbvWorldRayOrigin, symbolTable); - BuiltInVariable("gl_WorldRayDirectionNV", EbvWorldRayDirection, symbolTable); - BuiltInVariable("gl_WorldRayDirectionEXT", EbvWorldRayDirection, symbolTable); - BuiltInVariable("gl_ObjectRayOriginNV", EbvObjectRayOrigin, symbolTable); - BuiltInVariable("gl_ObjectRayOriginEXT", EbvObjectRayOrigin, symbolTable); - BuiltInVariable("gl_ObjectRayDirectionNV", EbvObjectRayDirection, symbolTable); - BuiltInVariable("gl_ObjectRayDirectionEXT", EbvObjectRayDirection, symbolTable); - BuiltInVariable("gl_RayTminNV", EbvRayTmin, symbolTable); - BuiltInVariable("gl_RayTminEXT", EbvRayTmin, symbolTable); - BuiltInVariable("gl_RayTmaxNV", EbvRayTmax, symbolTable); - BuiltInVariable("gl_RayTmaxEXT", EbvRayTmax, symbolTable); - BuiltInVariable("gl_CullMaskEXT", EbvCullMask, symbolTable); - BuiltInVariable("gl_HitTNV", EbvHitT, symbolTable); - BuiltInVariable("gl_HitTEXT", EbvHitT, symbolTable); - BuiltInVariable("gl_HitKindNV", EbvHitKind, symbolTable); - BuiltInVariable("gl_HitKindEXT", EbvHitKind, symbolTable); - BuiltInVariable("gl_ObjectToWorldNV", EbvObjectToWorld, symbolTable); - BuiltInVariable("gl_ObjectToWorldEXT", EbvObjectToWorld, symbolTable); - BuiltInVariable("gl_ObjectToWorld3x4EXT", EbvObjectToWorld3x4, symbolTable); - BuiltInVariable("gl_WorldToObjectNV", EbvWorldToObject, symbolTable); - BuiltInVariable("gl_WorldToObjectEXT", EbvWorldToObject, symbolTable); - BuiltInVariable("gl_WorldToObject3x4EXT", EbvWorldToObject3x4, symbolTable); - BuiltInVariable("gl_IncomingRayFlagsNV", EbvIncomingRayFlags, symbolTable); - BuiltInVariable("gl_IncomingRayFlagsEXT", EbvIncomingRayFlags, symbolTable); - BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); - BuiltInVariable("gl_CurrentRayTimeNV", EbvCurrentRayTimeNV, symbolTable); - BuiltInVariable("gl_HitTriangleVertexPositionsEXT", EbvPositionFetch, symbolTable); - BuiltInVariable("gl_HitMicroTriangleVertexPositionsNV", EbvMicroTrianglePositionNV, symbolTable); - BuiltInVariable("gl_HitMicroTriangleVertexBarycentricsNV", EbvMicroTriangleBaryNV, symbolTable); - BuiltInVariable("gl_HitKindFrontFacingMicroTriangleNV", EbvHitKindFrontFacingMicroTriangleNV, symbolTable); - BuiltInVariable("gl_HitKindBackFacingMicroTriangleNV", EbvHitKindBackFacingMicroTriangleNV, symbolTable); - - // GL_ARB_shader_ballot - symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot); - - BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable); - BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable); - BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable); - BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable); - BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable); - BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable); - - if (spvVersion.vulkan > 0) { - // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan - SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable); - if (language == EShLangFragment) - ModifyFlatDecoration("gl_SubGroupSizeARB", true, symbolTable); - } - else - BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable); - - // GL_KHR_shader_subgroup - symbolTable.setVariableExtensions("gl_NumSubgroups", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - - BuiltInVariable("gl_NumSubgroups", EbvNumSubgroups, symbolTable); - BuiltInVariable("gl_SubgroupID", EbvSubgroupID, symbolTable); - BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable); - BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable); - BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable); - BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable); - BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable); - BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable); - BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable); - - // GL_NV_shader_sm_builtins - symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins); - BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable); - BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable); - BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable); - BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable); - - // GL_ARM_shader_core_builtins - symbolTable.setVariableExtensions("gl_CoreCountARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - - BuiltInVariable("gl_CoreCountARM", EbvCoreCountARM, symbolTable); - BuiltInVariable("gl_CoreIDARM", EbvCoreIDARM, symbolTable); - BuiltInVariable("gl_CoreMaxIDARM", EbvCoreMaxIDARM, symbolTable); - BuiltInVariable("gl_WarpIDARM", EbvWarpIDARM, symbolTable); - BuiltInVariable("gl_WarpMaxIDARM", EbvWarpMaxIDARM, symbolTable); - } - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 450)) { - symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - } - break; - - case EShLangMesh: - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { - // per-vertex builtins - symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_Position", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_PointSize", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_ClipDistance", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_CullDistance", 1, &E_GL_NV_mesh_shader); - - BuiltInVariable("gl_MeshVerticesNV", "gl_Position", EbvPosition, symbolTable); - BuiltInVariable("gl_MeshVerticesNV", "gl_PointSize", EbvPointSize, symbolTable); - BuiltInVariable("gl_MeshVerticesNV", "gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_MeshVerticesNV", "gl_CullDistance", EbvCullDistance, symbolTable); - - symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_PositionPerViewNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_ClipDistancePerViewNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshVerticesNV", "gl_CullDistancePerViewNV", 1, &E_GL_NV_mesh_shader); - - BuiltInVariable("gl_MeshVerticesNV", "gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable); - BuiltInVariable("gl_MeshVerticesNV", "gl_ClipDistancePerViewNV", EbvClipDistancePerViewNV, symbolTable); - BuiltInVariable("gl_MeshVerticesNV", "gl_CullDistancePerViewNV", EbvCullDistancePerViewNV, symbolTable); - - // per-primitive builtins - symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_PrimitiveID", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_Layer", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_ViewportIndex", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_ViewportMask", 1, &E_GL_NV_mesh_shader); - - BuiltInVariable("gl_MeshPrimitivesNV", "gl_PrimitiveID", EbvPrimitiveId, symbolTable); - BuiltInVariable("gl_MeshPrimitivesNV", "gl_Layer", EbvLayer, symbolTable); - BuiltInVariable("gl_MeshPrimitivesNV", "gl_ViewportIndex", EbvViewportIndex, symbolTable); - BuiltInVariable("gl_MeshPrimitivesNV", "gl_ViewportMask", EbvViewportMaskNV, symbolTable); - - // per-view per-primitive builtins - symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_LayerPerViewNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshPrimitivesNV", "gl_ViewportMaskPerViewNV", 1, &E_GL_NV_mesh_shader); - - BuiltInVariable("gl_MeshPrimitivesNV", "gl_LayerPerViewNV", EbvLayerPerViewNV, symbolTable); - BuiltInVariable("gl_MeshPrimitivesNV", "gl_ViewportMaskPerViewNV", EbvViewportMaskPerViewNV, symbolTable); - - // other builtins - symbolTable.setVariableExtensions("gl_PrimitiveCountNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_PrimitiveIndicesNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshViewCountNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshViewIndicesNV", 1, &E_GL_NV_mesh_shader); - if (profile != EEsProfile) { - symbolTable.setVariableExtensions("gl_WorkGroupSize", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setVariableExtensions("gl_WorkGroupID", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationID", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setVariableExtensions("gl_GlobalInvocationID", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationIndex", Num_AEP_mesh_shader, AEP_mesh_shader); - } else { - symbolTable.setVariableExtensions("gl_WorkGroupSize", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_WorkGroupID", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationID", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_GlobalInvocationID", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationIndex", 1, &E_GL_NV_mesh_shader); - } - BuiltInVariable("gl_PrimitiveCountNV", EbvPrimitiveCountNV, symbolTable); - BuiltInVariable("gl_PrimitiveIndicesNV", EbvPrimitiveIndicesNV, symbolTable); - BuiltInVariable("gl_MeshViewCountNV", EbvMeshViewCountNV, symbolTable); - BuiltInVariable("gl_MeshViewIndicesNV", EbvMeshViewIndicesNV, symbolTable); - BuiltInVariable("gl_WorkGroupSize", EbvWorkGroupSize, symbolTable); - BuiltInVariable("gl_WorkGroupID", EbvWorkGroupId, symbolTable); - BuiltInVariable("gl_LocalInvocationID", EbvLocalInvocationId, symbolTable); - BuiltInVariable("gl_GlobalInvocationID", EbvGlobalInvocationId, symbolTable); - BuiltInVariable("gl_LocalInvocationIndex", EbvLocalInvocationIndex, symbolTable); - - // builtin constants - symbolTable.setVariableExtensions("gl_MaxMeshOutputVerticesNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MaxMeshOutputPrimitivesNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MaxMeshWorkGroupSizeNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MaxMeshViewCountNV", 1, &E_GL_NV_mesh_shader); - - // builtin functions - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("barrier", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setFunctionExtensions("memoryBarrierShared", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setFunctionExtensions("groupMemoryBarrier", Num_AEP_mesh_shader, AEP_mesh_shader); - } else { - symbolTable.setFunctionExtensions("barrier", 1, &E_GL_NV_mesh_shader); - symbolTable.setFunctionExtensions("memoryBarrierShared", 1, &E_GL_NV_mesh_shader); - symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_NV_mesh_shader); - } - symbolTable.setFunctionExtensions("writePackedPrimitiveIndices4x8NV", 1, &E_GL_NV_mesh_shader); - } - - if (profile != EEsProfile && version >= 450) { - // GL_EXT_Mesh_shader - symbolTable.setVariableExtensions("gl_PrimitivePointIndicesEXT", 1, &E_GL_EXT_mesh_shader); - symbolTable.setVariableExtensions("gl_PrimitiveLineIndicesEXT", 1, &E_GL_EXT_mesh_shader); - symbolTable.setVariableExtensions("gl_PrimitiveTriangleIndicesEXT", 1, &E_GL_EXT_mesh_shader); - symbolTable.setVariableExtensions("gl_NumWorkGroups", 1, &E_GL_EXT_mesh_shader); - - BuiltInVariable("gl_PrimitivePointIndicesEXT", EbvPrimitivePointIndicesEXT, symbolTable); - BuiltInVariable("gl_PrimitiveLineIndicesEXT", EbvPrimitiveLineIndicesEXT, symbolTable); - BuiltInVariable("gl_PrimitiveTriangleIndicesEXT", EbvPrimitiveTriangleIndicesEXT, symbolTable); - BuiltInVariable("gl_NumWorkGroups", EbvNumWorkGroups, symbolTable); - - symbolTable.setVariableExtensions("gl_MeshVerticesEXT", "gl_Position", 1, &E_GL_EXT_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshVerticesEXT", "gl_PointSize", 1, &E_GL_EXT_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshVerticesEXT", "gl_ClipDistance", 1, &E_GL_EXT_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshVerticesEXT", "gl_CullDistance", 1, &E_GL_EXT_mesh_shader); - - BuiltInVariable("gl_MeshVerticesEXT", "gl_Position", EbvPosition, symbolTable); - BuiltInVariable("gl_MeshVerticesEXT", "gl_PointSize", EbvPointSize, symbolTable); - BuiltInVariable("gl_MeshVerticesEXT", "gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_MeshVerticesEXT", "gl_CullDistance", EbvCullDistance, symbolTable); - - symbolTable.setVariableExtensions("gl_MeshPrimitivesEXT", "gl_PrimitiveID", 1, &E_GL_EXT_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshPrimitivesEXT", "gl_Layer", 1, &E_GL_EXT_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshPrimitivesEXT", "gl_ViewportIndex", 1, &E_GL_EXT_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshPrimitivesEXT", "gl_CullPrimitiveEXT", 1, &E_GL_EXT_mesh_shader); - - // note: technically this member requires both GL_EXT_mesh_shader and GL_EXT_fragment_shading_rate - // since setVariableExtensions only needs *one of* the extensions to validate, it's more useful to specify EXT_fragment_shading_rate - // GL_EXT_mesh_shader will be required in practice by use of other fields of gl_MeshPrimitivesEXT - symbolTable.setVariableExtensions("gl_MeshPrimitivesEXT", "gl_PrimitiveShadingRateEXT", 1, &E_GL_EXT_fragment_shading_rate); - - BuiltInVariable("gl_MeshPrimitivesEXT", "gl_PrimitiveID", EbvPrimitiveId, symbolTable); - BuiltInVariable("gl_MeshPrimitivesEXT", "gl_Layer", EbvLayer, symbolTable); - BuiltInVariable("gl_MeshPrimitivesEXT", "gl_ViewportIndex", EbvViewportIndex, symbolTable); - BuiltInVariable("gl_MeshPrimitivesEXT", "gl_CullPrimitiveEXT", EbvCullPrimitiveEXT, symbolTable); - BuiltInVariable("gl_MeshPrimitivesEXT", "gl_PrimitiveShadingRateEXT", EbvPrimitiveShadingRateKHR, symbolTable); - - symbolTable.setFunctionExtensions("SetMeshOutputsEXT", 1, &E_GL_EXT_mesh_shader); - - // GL_EXT_device_group - symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); - BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); - - // GL_ARB_shader_draw_parameters - symbolTable.setVariableExtensions("gl_DrawIDARB", 1, &E_GL_ARB_shader_draw_parameters); - BuiltInVariable("gl_DrawIDARB", EbvDrawId, symbolTable); - if (version >= 460) { - BuiltInVariable("gl_DrawID", EbvDrawId, symbolTable); - } - // GL_EXT_multiview - BuiltInVariable("gl_ViewIndex", EbvViewIndex, symbolTable); - symbolTable.setVariableExtensions("gl_ViewIndex", 1, &E_GL_EXT_multiview); - - // GL_ARB_shader_ballot - symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot); - - BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable); - BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable); - BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable); - BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable); - BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable); - BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable); - - if (spvVersion.vulkan > 0) { - // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan - SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable); - if (language == EShLangFragment) - ModifyFlatDecoration("gl_SubGroupSizeARB", true, symbolTable); - } - else - BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable); - } - - // GL_KHR_shader_subgroup - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - symbolTable.setVariableExtensions("gl_NumSubgroups", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - - BuiltInVariable("gl_NumSubgroups", EbvNumSubgroups, symbolTable); - BuiltInVariable("gl_SubgroupID", EbvSubgroupID, symbolTable); - BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable); - BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable); - BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable); - BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable); - BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable); - BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable); - BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable); - - symbolTable.setFunctionExtensions("subgroupMemoryBarrierShared", 1, &E_GL_KHR_shader_subgroup_basic); - - // GL_NV_shader_sm_builtins - symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins); - BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable); - BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable); - BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable); - BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable); - - // GL_ARM_shader_core_builtins - symbolTable.setVariableExtensions("gl_CoreCountARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - - BuiltInVariable("gl_CoreCountARM", EbvCoreCountARM, symbolTable); - BuiltInVariable("gl_CoreIDARM", EbvCoreIDARM, symbolTable); - BuiltInVariable("gl_CoreMaxIDARM", EbvCoreMaxIDARM, symbolTable); - BuiltInVariable("gl_WarpIDARM", EbvWarpIDARM, symbolTable); - BuiltInVariable("gl_WarpMaxIDARM", EbvWarpMaxIDARM, symbolTable); - } - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 450)) { - symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - } - - // Builtins for GL_NV_displacment_micromap - if ((profile != EEsProfile && version >= 460)) { - symbolTable.setFunctionExtensions("fetchMicroTriangleVertexPositionNV", 1, &E_GL_NV_displacement_micromap); - symbolTable.setFunctionExtensions("fetchMicroTriangleVertexBarycentricNV", 1, &E_GL_NV_displacement_micromap); - } - - break; - - case EShLangTask: - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { - symbolTable.setVariableExtensions("gl_TaskCountNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshViewCountNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MeshViewIndicesNV", 1, &E_GL_NV_mesh_shader); - if (profile != EEsProfile) { - symbolTable.setVariableExtensions("gl_WorkGroupSize", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setVariableExtensions("gl_WorkGroupID", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationID", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setVariableExtensions("gl_GlobalInvocationID", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationIndex", Num_AEP_mesh_shader, AEP_mesh_shader); - } else { - symbolTable.setVariableExtensions("gl_WorkGroupSize", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_WorkGroupID", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationID", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_GlobalInvocationID", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_LocalInvocationIndex", 1, &E_GL_NV_mesh_shader); - } - - BuiltInVariable("gl_TaskCountNV", EbvTaskCountNV, symbolTable); - BuiltInVariable("gl_WorkGroupSize", EbvWorkGroupSize, symbolTable); - BuiltInVariable("gl_WorkGroupID", EbvWorkGroupId, symbolTable); - BuiltInVariable("gl_LocalInvocationID", EbvLocalInvocationId, symbolTable); - BuiltInVariable("gl_GlobalInvocationID", EbvGlobalInvocationId, symbolTable); - BuiltInVariable("gl_LocalInvocationIndex", EbvLocalInvocationIndex, symbolTable); - BuiltInVariable("gl_MeshViewCountNV", EbvMeshViewCountNV, symbolTable); - BuiltInVariable("gl_MeshViewIndicesNV", EbvMeshViewIndicesNV, symbolTable); - - symbolTable.setVariableExtensions("gl_MaxTaskWorkGroupSizeNV", 1, &E_GL_NV_mesh_shader); - symbolTable.setVariableExtensions("gl_MaxMeshViewCountNV", 1, &E_GL_NV_mesh_shader); - - if (profile != EEsProfile) { - symbolTable.setFunctionExtensions("barrier", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setFunctionExtensions("memoryBarrierShared", Num_AEP_mesh_shader, AEP_mesh_shader); - symbolTable.setFunctionExtensions("groupMemoryBarrier", Num_AEP_mesh_shader, AEP_mesh_shader); - } else { - symbolTable.setFunctionExtensions("barrier", 1, &E_GL_NV_mesh_shader); - symbolTable.setFunctionExtensions("memoryBarrierShared", 1, &E_GL_NV_mesh_shader); - symbolTable.setFunctionExtensions("groupMemoryBarrier", 1, &E_GL_NV_mesh_shader); - } - } - - if (profile != EEsProfile && version >= 450) { - // GL_EXT_mesh_shader - symbolTable.setFunctionExtensions("EmitMeshTasksEXT", 1, &E_GL_EXT_mesh_shader); - symbolTable.setVariableExtensions("gl_NumWorkGroups", 1, &E_GL_EXT_mesh_shader); - BuiltInVariable("gl_NumWorkGroups", EbvNumWorkGroups, symbolTable); - - // GL_EXT_device_group - symbolTable.setVariableExtensions("gl_DeviceIndex", 1, &E_GL_EXT_device_group); - BuiltInVariable("gl_DeviceIndex", EbvDeviceIndex, symbolTable); - - // GL_ARB_shader_draw_parameters - symbolTable.setVariableExtensions("gl_DrawIDARB", 1, &E_GL_ARB_shader_draw_parameters); - BuiltInVariable("gl_DrawIDARB", EbvDrawId, symbolTable); - if (version >= 460) { - BuiltInVariable("gl_DrawID", EbvDrawId, symbolTable); - } - - // GL_ARB_shader_ballot - symbolTable.setVariableExtensions("gl_SubGroupSizeARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupInvocationARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupEqMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupGtMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLeMaskARB", 1, &E_GL_ARB_shader_ballot); - symbolTable.setVariableExtensions("gl_SubGroupLtMaskARB", 1, &E_GL_ARB_shader_ballot); - - BuiltInVariable("gl_SubGroupInvocationARB", EbvSubGroupInvocation, symbolTable); - BuiltInVariable("gl_SubGroupEqMaskARB", EbvSubGroupEqMask, symbolTable); - BuiltInVariable("gl_SubGroupGeMaskARB", EbvSubGroupGeMask, symbolTable); - BuiltInVariable("gl_SubGroupGtMaskARB", EbvSubGroupGtMask, symbolTable); - BuiltInVariable("gl_SubGroupLeMaskARB", EbvSubGroupLeMask, symbolTable); - BuiltInVariable("gl_SubGroupLtMaskARB", EbvSubGroupLtMask, symbolTable); - - if (spvVersion.vulkan > 0) { - // Treat "gl_SubGroupSizeARB" as shader input instead of uniform for Vulkan - SpecialQualifier("gl_SubGroupSizeARB", EvqVaryingIn, EbvSubGroupSize, symbolTable); - if (language == EShLangFragment) - ModifyFlatDecoration("gl_SubGroupSizeARB", true, symbolTable); - } - else - BuiltInVariable("gl_SubGroupSizeARB", EbvSubGroupSize, symbolTable); - } - - // GL_KHR_shader_subgroup - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - symbolTable.setVariableExtensions("gl_NumSubgroups", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupSize", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupInvocationID", 1, &E_GL_KHR_shader_subgroup_basic); - symbolTable.setVariableExtensions("gl_SubgroupEqMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupGtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLeMask", 1, &E_GL_KHR_shader_subgroup_ballot); - symbolTable.setVariableExtensions("gl_SubgroupLtMask", 1, &E_GL_KHR_shader_subgroup_ballot); - - BuiltInVariable("gl_NumSubgroups", EbvNumSubgroups, symbolTable); - BuiltInVariable("gl_SubgroupID", EbvSubgroupID, symbolTable); - BuiltInVariable("gl_SubgroupSize", EbvSubgroupSize2, symbolTable); - BuiltInVariable("gl_SubgroupInvocationID", EbvSubgroupInvocation2, symbolTable); - BuiltInVariable("gl_SubgroupEqMask", EbvSubgroupEqMask2, symbolTable); - BuiltInVariable("gl_SubgroupGeMask", EbvSubgroupGeMask2, symbolTable); - BuiltInVariable("gl_SubgroupGtMask", EbvSubgroupGtMask2, symbolTable); - BuiltInVariable("gl_SubgroupLeMask", EbvSubgroupLeMask2, symbolTable); - BuiltInVariable("gl_SubgroupLtMask", EbvSubgroupLtMask2, symbolTable); - - symbolTable.setFunctionExtensions("subgroupMemoryBarrierShared", 1, &E_GL_KHR_shader_subgroup_basic); - - // GL_NV_shader_sm_builtins - symbolTable.setVariableExtensions("gl_WarpsPerSMNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMCountNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_WarpIDNV", 1, &E_GL_NV_shader_sm_builtins); - symbolTable.setVariableExtensions("gl_SMIDNV", 1, &E_GL_NV_shader_sm_builtins); - BuiltInVariable("gl_WarpsPerSMNV", EbvWarpsPerSM, symbolTable); - BuiltInVariable("gl_SMCountNV", EbvSMCount, symbolTable); - BuiltInVariable("gl_WarpIDNV", EbvWarpID, symbolTable); - BuiltInVariable("gl_SMIDNV", EbvSMID, symbolTable); - - // GL_ARM_shader_core_builtins - symbolTable.setVariableExtensions("gl_CoreCountARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_CoreMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpIDARM", 1, &E_GL_ARM_shader_core_builtins); - symbolTable.setVariableExtensions("gl_WarpMaxIDARM", 1, &E_GL_ARM_shader_core_builtins); - - BuiltInVariable("gl_CoreCountARM", EbvCoreCountARM, symbolTable); - BuiltInVariable("gl_CoreIDARM", EbvCoreIDARM, symbolTable); - BuiltInVariable("gl_CoreMaxIDARM", EbvCoreMaxIDARM, symbolTable); - BuiltInVariable("gl_WarpIDARM", EbvWarpIDARM, symbolTable); - BuiltInVariable("gl_WarpMaxIDARM", EbvWarpMaxIDARM, symbolTable); - } - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 450)) { - symbolTable.setVariableExtensions("gl_ShadingRateFlag2VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4VerticalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag2HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - symbolTable.setVariableExtensions("gl_ShadingRateFlag4HorizontalPixelsEXT", 1, &E_GL_EXT_fragment_shading_rate); - } - break; - - default: - assert(false && "Language not supported"); - break; - } - - // - // Next, identify which built-ins have a mapping to an operator. - // If PureOperatorBuiltins is false, those that are not identified as such are - // expected to be resolved through a library of functions, versus as - // operations. - // - - relateTabledBuiltins(version, profile, spvVersion, language, symbolTable); - - symbolTable.relateToOperator("doubleBitsToInt64", EOpDoubleBitsToInt64); - symbolTable.relateToOperator("doubleBitsToUint64", EOpDoubleBitsToUint64); - symbolTable.relateToOperator("int64BitsToDouble", EOpInt64BitsToDouble); - symbolTable.relateToOperator("uint64BitsToDouble", EOpUint64BitsToDouble); - symbolTable.relateToOperator("halfBitsToInt16", EOpFloat16BitsToInt16); - symbolTable.relateToOperator("halfBitsToUint16", EOpFloat16BitsToUint16); - symbolTable.relateToOperator("float16BitsToInt16", EOpFloat16BitsToInt16); - symbolTable.relateToOperator("float16BitsToUint16", EOpFloat16BitsToUint16); - symbolTable.relateToOperator("int16BitsToFloat16", EOpInt16BitsToFloat16); - symbolTable.relateToOperator("uint16BitsToFloat16", EOpUint16BitsToFloat16); - - symbolTable.relateToOperator("int16BitsToHalf", EOpInt16BitsToFloat16); - symbolTable.relateToOperator("uint16BitsToHalf", EOpUint16BitsToFloat16); - - symbolTable.relateToOperator("packSnorm4x8", EOpPackSnorm4x8); - symbolTable.relateToOperator("unpackSnorm4x8", EOpUnpackSnorm4x8); - symbolTable.relateToOperator("packUnorm4x8", EOpPackUnorm4x8); - symbolTable.relateToOperator("unpackUnorm4x8", EOpUnpackUnorm4x8); - - symbolTable.relateToOperator("packDouble2x32", EOpPackDouble2x32); - symbolTable.relateToOperator("unpackDouble2x32", EOpUnpackDouble2x32); - - symbolTable.relateToOperator("packInt2x32", EOpPackInt2x32); - symbolTable.relateToOperator("unpackInt2x32", EOpUnpackInt2x32); - symbolTable.relateToOperator("packUint2x32", EOpPackUint2x32); - symbolTable.relateToOperator("unpackUint2x32", EOpUnpackUint2x32); - - symbolTable.relateToOperator("packInt2x16", EOpPackInt2x16); - symbolTable.relateToOperator("unpackInt2x16", EOpUnpackInt2x16); - symbolTable.relateToOperator("packUint2x16", EOpPackUint2x16); - symbolTable.relateToOperator("unpackUint2x16", EOpUnpackUint2x16); - - symbolTable.relateToOperator("packInt4x16", EOpPackInt4x16); - symbolTable.relateToOperator("unpackInt4x16", EOpUnpackInt4x16); - symbolTable.relateToOperator("packUint4x16", EOpPackUint4x16); - symbolTable.relateToOperator("unpackUint4x16", EOpUnpackUint4x16); - symbolTable.relateToOperator("packFloat2x16", EOpPackFloat2x16); - symbolTable.relateToOperator("unpackFloat2x16", EOpUnpackFloat2x16); - - symbolTable.relateToOperator("pack16", EOpPack16); - symbolTable.relateToOperator("pack32", EOpPack32); - symbolTable.relateToOperator("pack64", EOpPack64); - - symbolTable.relateToOperator("unpack32", EOpUnpack32); - symbolTable.relateToOperator("unpack16", EOpUnpack16); - symbolTable.relateToOperator("unpack8", EOpUnpack8); - - symbolTable.relateToOperator("controlBarrier", EOpBarrier); - symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierAtomicCounter); - symbolTable.relateToOperator("memoryBarrierImage", EOpMemoryBarrierImage); - - if (spvVersion.vulkanRelaxed) { - // - // functions signature have been replaced to take uint operations on buffer variables - // remap atomic counter functions to atomic operations - // - symbolTable.relateToOperator("memoryBarrierAtomicCounter", EOpMemoryBarrierBuffer); - } - - symbolTable.relateToOperator("atomicLoad", EOpAtomicLoad); - symbolTable.relateToOperator("atomicStore", EOpAtomicStore); - - symbolTable.relateToOperator("atomicCounterIncrement", EOpAtomicCounterIncrement); - symbolTable.relateToOperator("atomicCounterDecrement", EOpAtomicCounterDecrement); - symbolTable.relateToOperator("atomicCounter", EOpAtomicCounter); - - if (spvVersion.vulkanRelaxed) { - // - // functions signature have been replaced to take uint operations - // remap atomic counter functions to atomic operations - // - // these atomic counter functions do not match signatures of glsl - // atomic functions, so they will be remapped to semantically - // equivalent functions in the parser - // - symbolTable.relateToOperator("atomicCounterIncrement", EOpNull); - symbolTable.relateToOperator("atomicCounterDecrement", EOpNull); - symbolTable.relateToOperator("atomicCounter", EOpNull); - } - - symbolTable.relateToOperator("clockARB", EOpReadClockSubgroupKHR); - symbolTable.relateToOperator("clock2x32ARB", EOpReadClockSubgroupKHR); - - symbolTable.relateToOperator("clockRealtimeEXT", EOpReadClockDeviceKHR); - symbolTable.relateToOperator("clockRealtime2x32EXT", EOpReadClockDeviceKHR); - - if (profile != EEsProfile && version == 450) { - symbolTable.relateToOperator("atomicCounterAddARB", EOpAtomicCounterAdd); - symbolTable.relateToOperator("atomicCounterSubtractARB", EOpAtomicCounterSubtract); - symbolTable.relateToOperator("atomicCounterMinARB", EOpAtomicCounterMin); - symbolTable.relateToOperator("atomicCounterMaxARB", EOpAtomicCounterMax); - symbolTable.relateToOperator("atomicCounterAndARB", EOpAtomicCounterAnd); - symbolTable.relateToOperator("atomicCounterOrARB", EOpAtomicCounterOr); - symbolTable.relateToOperator("atomicCounterXorARB", EOpAtomicCounterXor); - symbolTable.relateToOperator("atomicCounterExchangeARB", EOpAtomicCounterExchange); - symbolTable.relateToOperator("atomicCounterCompSwapARB", EOpAtomicCounterCompSwap); - } - - if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("atomicCounterAdd", EOpAtomicCounterAdd); - symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicCounterSubtract); - symbolTable.relateToOperator("atomicCounterMin", EOpAtomicCounterMin); - symbolTable.relateToOperator("atomicCounterMax", EOpAtomicCounterMax); - symbolTable.relateToOperator("atomicCounterAnd", EOpAtomicCounterAnd); - symbolTable.relateToOperator("atomicCounterOr", EOpAtomicCounterOr); - symbolTable.relateToOperator("atomicCounterXor", EOpAtomicCounterXor); - symbolTable.relateToOperator("atomicCounterExchange", EOpAtomicCounterExchange); - symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCounterCompSwap); - } - - if (spvVersion.vulkanRelaxed) { - // - // functions signature have been replaced to take 'uint' instead of 'atomic_uint' - // remap atomic counter functions to non-counter atomic ops so - // functions act as aliases to non-counter atomic ops - // - symbolTable.relateToOperator("atomicCounterAdd", EOpAtomicAdd); - symbolTable.relateToOperator("atomicCounterSubtract", EOpAtomicSubtract); - symbolTable.relateToOperator("atomicCounterMin", EOpAtomicMin); - symbolTable.relateToOperator("atomicCounterMax", EOpAtomicMax); - symbolTable.relateToOperator("atomicCounterAnd", EOpAtomicAnd); - symbolTable.relateToOperator("atomicCounterOr", EOpAtomicOr); - symbolTable.relateToOperator("atomicCounterXor", EOpAtomicXor); - symbolTable.relateToOperator("atomicCounterExchange", EOpAtomicExchange); - symbolTable.relateToOperator("atomicCounterCompSwap", EOpAtomicCompSwap); - } - - symbolTable.relateToOperator("fma", EOpFma); - symbolTable.relateToOperator("frexp", EOpFrexp); - symbolTable.relateToOperator("ldexp", EOpLdexp); - symbolTable.relateToOperator("uaddCarry", EOpAddCarry); - symbolTable.relateToOperator("usubBorrow", EOpSubBorrow); - symbolTable.relateToOperator("umulExtended", EOpUMulExtended); - symbolTable.relateToOperator("imulExtended", EOpIMulExtended); - symbolTable.relateToOperator("bitfieldExtract", EOpBitfieldExtract); - symbolTable.relateToOperator("bitfieldInsert", EOpBitfieldInsert); - symbolTable.relateToOperator("bitfieldReverse", EOpBitFieldReverse); - symbolTable.relateToOperator("bitCount", EOpBitCount); - symbolTable.relateToOperator("findLSB", EOpFindLSB); - symbolTable.relateToOperator("findMSB", EOpFindMSB); - - symbolTable.relateToOperator("helperInvocationEXT", EOpIsHelperInvocation); - - symbolTable.relateToOperator("countLeadingZeros", EOpCountLeadingZeros); - symbolTable.relateToOperator("countTrailingZeros", EOpCountTrailingZeros); - symbolTable.relateToOperator("absoluteDifference", EOpAbsDifference); - symbolTable.relateToOperator("addSaturate", EOpAddSaturate); - symbolTable.relateToOperator("subtractSaturate", EOpSubSaturate); - symbolTable.relateToOperator("average", EOpAverage); - symbolTable.relateToOperator("averageRounded", EOpAverageRounded); - symbolTable.relateToOperator("multiply32x16", EOpMul32x16); - symbolTable.relateToOperator("debugPrintfEXT", EOpDebugPrintf); - - - if (PureOperatorBuiltins) { - symbolTable.relateToOperator("imageSize", EOpImageQuerySize); - symbolTable.relateToOperator("imageSamples", EOpImageQuerySamples); - symbolTable.relateToOperator("imageLoad", EOpImageLoad); - symbolTable.relateToOperator("imageStore", EOpImageStore); - symbolTable.relateToOperator("imageAtomicAdd", EOpImageAtomicAdd); - symbolTable.relateToOperator("imageAtomicMin", EOpImageAtomicMin); - symbolTable.relateToOperator("imageAtomicMax", EOpImageAtomicMax); - symbolTable.relateToOperator("imageAtomicAnd", EOpImageAtomicAnd); - symbolTable.relateToOperator("imageAtomicOr", EOpImageAtomicOr); - symbolTable.relateToOperator("imageAtomicXor", EOpImageAtomicXor); - symbolTable.relateToOperator("imageAtomicExchange", EOpImageAtomicExchange); - symbolTable.relateToOperator("imageAtomicCompSwap", EOpImageAtomicCompSwap); - symbolTable.relateToOperator("imageAtomicLoad", EOpImageAtomicLoad); - symbolTable.relateToOperator("imageAtomicStore", EOpImageAtomicStore); - - symbolTable.relateToOperator("subpassLoad", EOpSubpassLoad); - symbolTable.relateToOperator("subpassLoadMS", EOpSubpassLoadMS); - - symbolTable.relateToOperator("textureGather", EOpTextureGather); - symbolTable.relateToOperator("textureGatherOffset", EOpTextureGatherOffset); - symbolTable.relateToOperator("textureGatherOffsets", EOpTextureGatherOffsets); - - symbolTable.relateToOperator("noise1", EOpNoise); - symbolTable.relateToOperator("noise2", EOpNoise); - symbolTable.relateToOperator("noise3", EOpNoise); - symbolTable.relateToOperator("noise4", EOpNoise); - - symbolTable.relateToOperator("textureFootprintNV", EOpImageSampleFootprintNV); - symbolTable.relateToOperator("textureFootprintClampNV", EOpImageSampleFootprintClampNV); - symbolTable.relateToOperator("textureFootprintLodNV", EOpImageSampleFootprintLodNV); - symbolTable.relateToOperator("textureFootprintGradNV", EOpImageSampleFootprintGradNV); - symbolTable.relateToOperator("textureFootprintGradClampNV", EOpImageSampleFootprintGradClampNV); - - if (spvVersion.spv == 0 && IncludeLegacy(version, profile, spvVersion)) - symbolTable.relateToOperator("ftransform", EOpFtransform); - - if (spvVersion.spv == 0 && (IncludeLegacy(version, profile, spvVersion) || - (profile == EEsProfile && version == 100))) { - - symbolTable.relateToOperator("texture1D", EOpTexture); - symbolTable.relateToOperator("texture1DGradARB", EOpTextureGrad); - symbolTable.relateToOperator("texture1DProj", EOpTextureProj); - symbolTable.relateToOperator("texture1DProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("texture1DLod", EOpTextureLod); - symbolTable.relateToOperator("texture1DProjLod", EOpTextureProjLod); - - symbolTable.relateToOperator("texture2DRect", EOpTexture); - symbolTable.relateToOperator("texture2DRectProj", EOpTextureProj); - symbolTable.relateToOperator("texture2DRectGradARB", EOpTextureGrad); - symbolTable.relateToOperator("texture2DRectProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("shadow2DRect", EOpTexture); - symbolTable.relateToOperator("shadow2DRectProj", EOpTextureProj); - symbolTable.relateToOperator("shadow2DRectGradARB", EOpTextureGrad); - symbolTable.relateToOperator("shadow2DRectProjGradARB", EOpTextureProjGrad); - - symbolTable.relateToOperator("texture2D", EOpTexture); - symbolTable.relateToOperator("texture2DProj", EOpTextureProj); - symbolTable.relateToOperator("texture2DGradEXT", EOpTextureGrad); - symbolTable.relateToOperator("texture2DGradARB", EOpTextureGrad); - symbolTable.relateToOperator("texture2DProjGradEXT", EOpTextureProjGrad); - symbolTable.relateToOperator("texture2DProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("texture2DLod", EOpTextureLod); - symbolTable.relateToOperator("texture2DLodEXT", EOpTextureLod); - symbolTable.relateToOperator("texture2DProjLod", EOpTextureProjLod); - symbolTable.relateToOperator("texture2DProjLodEXT", EOpTextureProjLod); - - symbolTable.relateToOperator("texture3D", EOpTexture); - symbolTable.relateToOperator("texture3DGradARB", EOpTextureGrad); - symbolTable.relateToOperator("texture3DProj", EOpTextureProj); - symbolTable.relateToOperator("texture3DProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("texture3DLod", EOpTextureLod); - symbolTable.relateToOperator("texture3DProjLod", EOpTextureProjLod); - symbolTable.relateToOperator("textureCube", EOpTexture); - symbolTable.relateToOperator("textureCubeGradEXT", EOpTextureGrad); - symbolTable.relateToOperator("textureCubeGradARB", EOpTextureGrad); - symbolTable.relateToOperator("textureCubeLod", EOpTextureLod); - symbolTable.relateToOperator("textureCubeLodEXT", EOpTextureLod); - symbolTable.relateToOperator("shadow1D", EOpTexture); - symbolTable.relateToOperator("shadow1DGradARB", EOpTextureGrad); - symbolTable.relateToOperator("shadow2D", EOpTexture); - symbolTable.relateToOperator("shadow2DGradARB", EOpTextureGrad); - symbolTable.relateToOperator("shadow1DProj", EOpTextureProj); - symbolTable.relateToOperator("shadow2DProj", EOpTextureProj); - symbolTable.relateToOperator("shadow1DProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("shadow2DProjGradARB", EOpTextureProjGrad); - symbolTable.relateToOperator("shadow1DLod", EOpTextureLod); - symbolTable.relateToOperator("shadow2DLod", EOpTextureLod); - symbolTable.relateToOperator("shadow1DProjLod", EOpTextureProjLod); - symbolTable.relateToOperator("shadow2DProjLod", EOpTextureProjLod); - } - - if (profile != EEsProfile) { - symbolTable.relateToOperator("sparseTextureARB", EOpSparseTexture); - symbolTable.relateToOperator("sparseTextureLodARB", EOpSparseTextureLod); - symbolTable.relateToOperator("sparseTextureOffsetARB", EOpSparseTextureOffset); - symbolTable.relateToOperator("sparseTexelFetchARB", EOpSparseTextureFetch); - symbolTable.relateToOperator("sparseTexelFetchOffsetARB", EOpSparseTextureFetchOffset); - symbolTable.relateToOperator("sparseTextureLodOffsetARB", EOpSparseTextureLodOffset); - symbolTable.relateToOperator("sparseTextureGradARB", EOpSparseTextureGrad); - symbolTable.relateToOperator("sparseTextureGradOffsetARB", EOpSparseTextureGradOffset); - symbolTable.relateToOperator("sparseTextureGatherARB", EOpSparseTextureGather); - symbolTable.relateToOperator("sparseTextureGatherOffsetARB", EOpSparseTextureGatherOffset); - symbolTable.relateToOperator("sparseTextureGatherOffsetsARB", EOpSparseTextureGatherOffsets); - symbolTable.relateToOperator("sparseImageLoadARB", EOpSparseImageLoad); - symbolTable.relateToOperator("sparseTexelsResidentARB", EOpSparseTexelsResident); - - symbolTable.relateToOperator("sparseTextureClampARB", EOpSparseTextureClamp); - symbolTable.relateToOperator("sparseTextureOffsetClampARB", EOpSparseTextureOffsetClamp); - symbolTable.relateToOperator("sparseTextureGradClampARB", EOpSparseTextureGradClamp); - symbolTable.relateToOperator("sparseTextureGradOffsetClampARB", EOpSparseTextureGradOffsetClamp); - symbolTable.relateToOperator("textureClampARB", EOpTextureClamp); - symbolTable.relateToOperator("textureOffsetClampARB", EOpTextureOffsetClamp); - symbolTable.relateToOperator("textureGradClampARB", EOpTextureGradClamp); - symbolTable.relateToOperator("textureGradOffsetClampARB", EOpTextureGradOffsetClamp); - - symbolTable.relateToOperator("ballotARB", EOpBallot); - symbolTable.relateToOperator("readInvocationARB", EOpReadInvocation); - symbolTable.relateToOperator("readFirstInvocationARB", EOpReadFirstInvocation); - - if (version >= 430) { - symbolTable.relateToOperator("anyInvocationARB", EOpAnyInvocation); - symbolTable.relateToOperator("allInvocationsARB", EOpAllInvocations); - symbolTable.relateToOperator("allInvocationsEqualARB", EOpAllInvocationsEqual); - } - if (version >= 460) { - symbolTable.relateToOperator("anyInvocation", EOpAnyInvocation); - symbolTable.relateToOperator("allInvocations", EOpAllInvocations); - symbolTable.relateToOperator("allInvocationsEqual", EOpAllInvocationsEqual); - } - symbolTable.relateToOperator("minInvocationsAMD", EOpMinInvocations); - symbolTable.relateToOperator("maxInvocationsAMD", EOpMaxInvocations); - symbolTable.relateToOperator("addInvocationsAMD", EOpAddInvocations); - symbolTable.relateToOperator("minInvocationsNonUniformAMD", EOpMinInvocationsNonUniform); - symbolTable.relateToOperator("maxInvocationsNonUniformAMD", EOpMaxInvocationsNonUniform); - symbolTable.relateToOperator("addInvocationsNonUniformAMD", EOpAddInvocationsNonUniform); - symbolTable.relateToOperator("minInvocationsInclusiveScanAMD", EOpMinInvocationsInclusiveScan); - symbolTable.relateToOperator("maxInvocationsInclusiveScanAMD", EOpMaxInvocationsInclusiveScan); - symbolTable.relateToOperator("addInvocationsInclusiveScanAMD", EOpAddInvocationsInclusiveScan); - symbolTable.relateToOperator("minInvocationsInclusiveScanNonUniformAMD", EOpMinInvocationsInclusiveScanNonUniform); - symbolTable.relateToOperator("maxInvocationsInclusiveScanNonUniformAMD", EOpMaxInvocationsInclusiveScanNonUniform); - symbolTable.relateToOperator("addInvocationsInclusiveScanNonUniformAMD", EOpAddInvocationsInclusiveScanNonUniform); - symbolTable.relateToOperator("minInvocationsExclusiveScanAMD", EOpMinInvocationsExclusiveScan); - symbolTable.relateToOperator("maxInvocationsExclusiveScanAMD", EOpMaxInvocationsExclusiveScan); - symbolTable.relateToOperator("addInvocationsExclusiveScanAMD", EOpAddInvocationsExclusiveScan); - symbolTable.relateToOperator("minInvocationsExclusiveScanNonUniformAMD", EOpMinInvocationsExclusiveScanNonUniform); - symbolTable.relateToOperator("maxInvocationsExclusiveScanNonUniformAMD", EOpMaxInvocationsExclusiveScanNonUniform); - symbolTable.relateToOperator("addInvocationsExclusiveScanNonUniformAMD", EOpAddInvocationsExclusiveScanNonUniform); - symbolTable.relateToOperator("swizzleInvocationsAMD", EOpSwizzleInvocations); - symbolTable.relateToOperator("swizzleInvocationsMaskedAMD", EOpSwizzleInvocationsMasked); - symbolTable.relateToOperator("writeInvocationAMD", EOpWriteInvocation); - symbolTable.relateToOperator("mbcntAMD", EOpMbcnt); - - symbolTable.relateToOperator("min3", EOpMin3); - symbolTable.relateToOperator("max3", EOpMax3); - symbolTable.relateToOperator("mid3", EOpMid3); - - symbolTable.relateToOperator("cubeFaceIndexAMD", EOpCubeFaceIndex); - symbolTable.relateToOperator("cubeFaceCoordAMD", EOpCubeFaceCoord); - symbolTable.relateToOperator("timeAMD", EOpTime); - - symbolTable.relateToOperator("textureGatherLodAMD", EOpTextureGatherLod); - symbolTable.relateToOperator("textureGatherLodOffsetAMD", EOpTextureGatherLodOffset); - symbolTable.relateToOperator("textureGatherLodOffsetsAMD", EOpTextureGatherLodOffsets); - symbolTable.relateToOperator("sparseTextureGatherLodAMD", EOpSparseTextureGatherLod); - symbolTable.relateToOperator("sparseTextureGatherLodOffsetAMD", EOpSparseTextureGatherLodOffset); - symbolTable.relateToOperator("sparseTextureGatherLodOffsetsAMD", EOpSparseTextureGatherLodOffsets); - - symbolTable.relateToOperator("imageLoadLodAMD", EOpImageLoadLod); - symbolTable.relateToOperator("imageStoreLodAMD", EOpImageStoreLod); - symbolTable.relateToOperator("sparseImageLoadLodAMD", EOpSparseImageLoadLod); - - symbolTable.relateToOperator("fragmentMaskFetchAMD", EOpFragmentMaskFetch); - symbolTable.relateToOperator("fragmentFetchAMD", EOpFragmentFetch); - } - - // GL_KHR_shader_subgroup - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - symbolTable.relateToOperator("subgroupBarrier", EOpSubgroupBarrier); - symbolTable.relateToOperator("subgroupMemoryBarrier", EOpSubgroupMemoryBarrier); - symbolTable.relateToOperator("subgroupMemoryBarrierBuffer", EOpSubgroupMemoryBarrierBuffer); - symbolTable.relateToOperator("subgroupMemoryBarrierImage", EOpSubgroupMemoryBarrierImage); - symbolTable.relateToOperator("subgroupElect", EOpSubgroupElect); - symbolTable.relateToOperator("subgroupAll", EOpSubgroupAll); - symbolTable.relateToOperator("subgroupAny", EOpSubgroupAny); - symbolTable.relateToOperator("subgroupAllEqual", EOpSubgroupAllEqual); - symbolTable.relateToOperator("subgroupBroadcast", EOpSubgroupBroadcast); - symbolTable.relateToOperator("subgroupBroadcastFirst", EOpSubgroupBroadcastFirst); - symbolTable.relateToOperator("subgroupBallot", EOpSubgroupBallot); - symbolTable.relateToOperator("subgroupInverseBallot", EOpSubgroupInverseBallot); - symbolTable.relateToOperator("subgroupBallotBitExtract", EOpSubgroupBallotBitExtract); - symbolTable.relateToOperator("subgroupBallotBitCount", EOpSubgroupBallotBitCount); - symbolTable.relateToOperator("subgroupBallotInclusiveBitCount", EOpSubgroupBallotInclusiveBitCount); - symbolTable.relateToOperator("subgroupBallotExclusiveBitCount", EOpSubgroupBallotExclusiveBitCount); - symbolTable.relateToOperator("subgroupBallotFindLSB", EOpSubgroupBallotFindLSB); - symbolTable.relateToOperator("subgroupBallotFindMSB", EOpSubgroupBallotFindMSB); - symbolTable.relateToOperator("subgroupShuffle", EOpSubgroupShuffle); - symbolTable.relateToOperator("subgroupShuffleXor", EOpSubgroupShuffleXor); - symbolTable.relateToOperator("subgroupShuffleUp", EOpSubgroupShuffleUp); - symbolTable.relateToOperator("subgroupShuffleDown", EOpSubgroupShuffleDown); - symbolTable.relateToOperator("subgroupAdd", EOpSubgroupAdd); - symbolTable.relateToOperator("subgroupMul", EOpSubgroupMul); - symbolTable.relateToOperator("subgroupMin", EOpSubgroupMin); - symbolTable.relateToOperator("subgroupMax", EOpSubgroupMax); - symbolTable.relateToOperator("subgroupAnd", EOpSubgroupAnd); - symbolTable.relateToOperator("subgroupOr", EOpSubgroupOr); - symbolTable.relateToOperator("subgroupXor", EOpSubgroupXor); - symbolTable.relateToOperator("subgroupInclusiveAdd", EOpSubgroupInclusiveAdd); - symbolTable.relateToOperator("subgroupInclusiveMul", EOpSubgroupInclusiveMul); - symbolTable.relateToOperator("subgroupInclusiveMin", EOpSubgroupInclusiveMin); - symbolTable.relateToOperator("subgroupInclusiveMax", EOpSubgroupInclusiveMax); - symbolTable.relateToOperator("subgroupInclusiveAnd", EOpSubgroupInclusiveAnd); - symbolTable.relateToOperator("subgroupInclusiveOr", EOpSubgroupInclusiveOr); - symbolTable.relateToOperator("subgroupInclusiveXor", EOpSubgroupInclusiveXor); - symbolTable.relateToOperator("subgroupExclusiveAdd", EOpSubgroupExclusiveAdd); - symbolTable.relateToOperator("subgroupExclusiveMul", EOpSubgroupExclusiveMul); - symbolTable.relateToOperator("subgroupExclusiveMin", EOpSubgroupExclusiveMin); - symbolTable.relateToOperator("subgroupExclusiveMax", EOpSubgroupExclusiveMax); - symbolTable.relateToOperator("subgroupExclusiveAnd", EOpSubgroupExclusiveAnd); - symbolTable.relateToOperator("subgroupExclusiveOr", EOpSubgroupExclusiveOr); - symbolTable.relateToOperator("subgroupExclusiveXor", EOpSubgroupExclusiveXor); - symbolTable.relateToOperator("subgroupClusteredAdd", EOpSubgroupClusteredAdd); - symbolTable.relateToOperator("subgroupClusteredMul", EOpSubgroupClusteredMul); - symbolTable.relateToOperator("subgroupClusteredMin", EOpSubgroupClusteredMin); - symbolTable.relateToOperator("subgroupClusteredMax", EOpSubgroupClusteredMax); - symbolTable.relateToOperator("subgroupClusteredAnd", EOpSubgroupClusteredAnd); - symbolTable.relateToOperator("subgroupClusteredOr", EOpSubgroupClusteredOr); - symbolTable.relateToOperator("subgroupClusteredXor", EOpSubgroupClusteredXor); - symbolTable.relateToOperator("subgroupQuadBroadcast", EOpSubgroupQuadBroadcast); - symbolTable.relateToOperator("subgroupQuadSwapHorizontal", EOpSubgroupQuadSwapHorizontal); - symbolTable.relateToOperator("subgroupQuadSwapVertical", EOpSubgroupQuadSwapVertical); - symbolTable.relateToOperator("subgroupQuadSwapDiagonal", EOpSubgroupQuadSwapDiagonal); - - symbolTable.relateToOperator("subgroupPartitionNV", EOpSubgroupPartition); - symbolTable.relateToOperator("subgroupPartitionedAddNV", EOpSubgroupPartitionedAdd); - symbolTable.relateToOperator("subgroupPartitionedMulNV", EOpSubgroupPartitionedMul); - symbolTable.relateToOperator("subgroupPartitionedMinNV", EOpSubgroupPartitionedMin); - symbolTable.relateToOperator("subgroupPartitionedMaxNV", EOpSubgroupPartitionedMax); - symbolTable.relateToOperator("subgroupPartitionedAndNV", EOpSubgroupPartitionedAnd); - symbolTable.relateToOperator("subgroupPartitionedOrNV", EOpSubgroupPartitionedOr); - symbolTable.relateToOperator("subgroupPartitionedXorNV", EOpSubgroupPartitionedXor); - symbolTable.relateToOperator("subgroupPartitionedInclusiveAddNV", EOpSubgroupPartitionedInclusiveAdd); - symbolTable.relateToOperator("subgroupPartitionedInclusiveMulNV", EOpSubgroupPartitionedInclusiveMul); - symbolTable.relateToOperator("subgroupPartitionedInclusiveMinNV", EOpSubgroupPartitionedInclusiveMin); - symbolTable.relateToOperator("subgroupPartitionedInclusiveMaxNV", EOpSubgroupPartitionedInclusiveMax); - symbolTable.relateToOperator("subgroupPartitionedInclusiveAndNV", EOpSubgroupPartitionedInclusiveAnd); - symbolTable.relateToOperator("subgroupPartitionedInclusiveOrNV", EOpSubgroupPartitionedInclusiveOr); - symbolTable.relateToOperator("subgroupPartitionedInclusiveXorNV", EOpSubgroupPartitionedInclusiveXor); - symbolTable.relateToOperator("subgroupPartitionedExclusiveAddNV", EOpSubgroupPartitionedExclusiveAdd); - symbolTable.relateToOperator("subgroupPartitionedExclusiveMulNV", EOpSubgroupPartitionedExclusiveMul); - symbolTable.relateToOperator("subgroupPartitionedExclusiveMinNV", EOpSubgroupPartitionedExclusiveMin); - symbolTable.relateToOperator("subgroupPartitionedExclusiveMaxNV", EOpSubgroupPartitionedExclusiveMax); - symbolTable.relateToOperator("subgroupPartitionedExclusiveAndNV", EOpSubgroupPartitionedExclusiveAnd); - symbolTable.relateToOperator("subgroupPartitionedExclusiveOrNV", EOpSubgroupPartitionedExclusiveOr); - symbolTable.relateToOperator("subgroupPartitionedExclusiveXorNV", EOpSubgroupPartitionedExclusiveXor); - } - - if (profile == EEsProfile) { - symbolTable.relateToOperator("shadow2DEXT", EOpTexture); - symbolTable.relateToOperator("shadow2DProjEXT", EOpTextureProj); - } - - if ((profile == EEsProfile && version >= 310) || - (profile != EEsProfile && version >= 140)) { - symbolTable.relateToOperator("textureWeightedQCOM", EOpImageSampleWeightedQCOM); - symbolTable.relateToOperator("textureBoxFilterQCOM", EOpImageBoxFilterQCOM); - symbolTable.relateToOperator("textureBlockMatchSADQCOM", EOpImageBlockMatchSADQCOM); - symbolTable.relateToOperator("textureBlockMatchSSDQCOM", EOpImageBlockMatchSSDQCOM); - } - - if (profile != EEsProfile && spvVersion.spv == 0) { - symbolTable.relateToOperator("texture1DArray", EOpTexture); - symbolTable.relateToOperator("texture2DArray", EOpTexture); - symbolTable.relateToOperator("shadow1DArray", EOpTexture); - symbolTable.relateToOperator("shadow2DArray", EOpTexture); - - symbolTable.relateToOperator("texture1DArrayLod", EOpTextureLod); - symbolTable.relateToOperator("texture2DArrayLod", EOpTextureLod); - symbolTable.relateToOperator("shadow1DArrayLod", EOpTextureLod); - } - } - - switch(language) { - case EShLangVertex: - break; - - case EShLangTessControl: - case EShLangTessEvaluation: - break; - - case EShLangGeometry: - symbolTable.relateToOperator("EmitStreamVertex", EOpEmitStreamVertex); - symbolTable.relateToOperator("EndStreamPrimitive", EOpEndStreamPrimitive); - symbolTable.relateToOperator("EmitVertex", EOpEmitVertex); - symbolTable.relateToOperator("EndPrimitive", EOpEndPrimitive); - break; - - case EShLangFragment: - if (profile != EEsProfile && version >= 400) { - symbolTable.relateToOperator("dFdxFine", EOpDPdxFine); - symbolTable.relateToOperator("dFdyFine", EOpDPdyFine); - symbolTable.relateToOperator("fwidthFine", EOpFwidthFine); - symbolTable.relateToOperator("dFdxCoarse", EOpDPdxCoarse); - symbolTable.relateToOperator("dFdyCoarse", EOpDPdyCoarse); - symbolTable.relateToOperator("fwidthCoarse", EOpFwidthCoarse); - } - - if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("rayQueryInitializeEXT", EOpRayQueryInitialize); - symbolTable.relateToOperator("rayQueryTerminateEXT", EOpRayQueryTerminate); - symbolTable.relateToOperator("rayQueryGenerateIntersectionEXT", EOpRayQueryGenerateIntersection); - symbolTable.relateToOperator("rayQueryConfirmIntersectionEXT", EOpRayQueryConfirmIntersection); - symbolTable.relateToOperator("rayQueryProceedEXT", EOpRayQueryProceed); - symbolTable.relateToOperator("rayQueryGetIntersectionTypeEXT", EOpRayQueryGetIntersectionType); - symbolTable.relateToOperator("rayQueryGetRayTMinEXT", EOpRayQueryGetRayTMin); - symbolTable.relateToOperator("rayQueryGetRayFlagsEXT", EOpRayQueryGetRayFlags); - symbolTable.relateToOperator("rayQueryGetIntersectionTEXT", EOpRayQueryGetIntersectionT); - symbolTable.relateToOperator("rayQueryGetIntersectionInstanceCustomIndexEXT", EOpRayQueryGetIntersectionInstanceCustomIndex); - symbolTable.relateToOperator("rayQueryGetIntersectionInstanceIdEXT", EOpRayQueryGetIntersectionInstanceId); - symbolTable.relateToOperator("rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT", EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset); - symbolTable.relateToOperator("rayQueryGetIntersectionGeometryIndexEXT", EOpRayQueryGetIntersectionGeometryIndex); - symbolTable.relateToOperator("rayQueryGetIntersectionPrimitiveIndexEXT", EOpRayQueryGetIntersectionPrimitiveIndex); - symbolTable.relateToOperator("rayQueryGetIntersectionBarycentricsEXT", EOpRayQueryGetIntersectionBarycentrics); - symbolTable.relateToOperator("rayQueryGetIntersectionFrontFaceEXT", EOpRayQueryGetIntersectionFrontFace); - symbolTable.relateToOperator("rayQueryGetIntersectionCandidateAABBOpaqueEXT", EOpRayQueryGetIntersectionCandidateAABBOpaque); - symbolTable.relateToOperator("rayQueryGetIntersectionObjectRayDirectionEXT", EOpRayQueryGetIntersectionObjectRayDirection); - symbolTable.relateToOperator("rayQueryGetIntersectionObjectRayOriginEXT", EOpRayQueryGetIntersectionObjectRayOrigin); - symbolTable.relateToOperator("rayQueryGetWorldRayDirectionEXT", EOpRayQueryGetWorldRayDirection); - symbolTable.relateToOperator("rayQueryGetWorldRayOriginEXT", EOpRayQueryGetWorldRayOrigin); - symbolTable.relateToOperator("rayQueryGetIntersectionObjectToWorldEXT", EOpRayQueryGetIntersectionObjectToWorld); - symbolTable.relateToOperator("rayQueryGetIntersectionWorldToObjectEXT", EOpRayQueryGetIntersectionWorldToObject); - symbolTable.relateToOperator("rayQueryGetIntersectionTriangleVertexPositionsEXT", EOpRayQueryGetIntersectionTriangleVertexPositionsEXT); - } - - symbolTable.relateToOperator("interpolateAtCentroid", EOpInterpolateAtCentroid); - symbolTable.relateToOperator("interpolateAtSample", EOpInterpolateAtSample); - symbolTable.relateToOperator("interpolateAtOffset", EOpInterpolateAtOffset); - - if (profile != EEsProfile) - symbolTable.relateToOperator("interpolateAtVertexAMD", EOpInterpolateAtVertex); - - symbolTable.relateToOperator("beginInvocationInterlockARB", EOpBeginInvocationInterlock); - symbolTable.relateToOperator("endInvocationInterlockARB", EOpEndInvocationInterlock); - - symbolTable.relateToOperator("stencilAttachmentReadEXT", EOpStencilAttachmentReadEXT); - symbolTable.relateToOperator("depthAttachmentReadEXT", EOpDepthAttachmentReadEXT); - symbolTable.relateToOperator("colorAttachmentReadEXT", EOpColorAttachmentReadEXT); - - break; - - case EShLangCompute: - symbolTable.relateToOperator("subgroupMemoryBarrierShared", EOpSubgroupMemoryBarrierShared); - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 320)) { - symbolTable.relateToOperator("dFdx", EOpDPdx); - symbolTable.relateToOperator("dFdy", EOpDPdy); - symbolTable.relateToOperator("fwidth", EOpFwidth); - symbolTable.relateToOperator("dFdxFine", EOpDPdxFine); - symbolTable.relateToOperator("dFdyFine", EOpDPdyFine); - symbolTable.relateToOperator("fwidthFine", EOpFwidthFine); - symbolTable.relateToOperator("dFdxCoarse", EOpDPdxCoarse); - symbolTable.relateToOperator("dFdyCoarse", EOpDPdyCoarse); - symbolTable.relateToOperator("fwidthCoarse",EOpFwidthCoarse); - } - symbolTable.relateToOperator("coopMatLoadNV", EOpCooperativeMatrixLoadNV); - symbolTable.relateToOperator("coopMatStoreNV", EOpCooperativeMatrixStoreNV); - symbolTable.relateToOperator("coopMatMulAddNV", EOpCooperativeMatrixMulAddNV); - - symbolTable.relateToOperator("coopMatLoad", EOpCooperativeMatrixLoad); - symbolTable.relateToOperator("coopMatStore", EOpCooperativeMatrixStore); - symbolTable.relateToOperator("coopMatMulAdd", EOpCooperativeMatrixMulAdd); - - if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("fetchMicroTriangleVertexPositionNV", EOpFetchMicroTriangleVertexPositionNV); - symbolTable.relateToOperator("fetchMicroTriangleVertexBarycentricNV", EOpFetchMicroTriangleVertexBarycentricNV); - } - break; - - case EShLangRayGen: - if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("fetchMicroTriangleVertexPositionNV", EOpFetchMicroTriangleVertexPositionNV); - symbolTable.relateToOperator("fetchMicroTriangleVertexBarycentricNV", EOpFetchMicroTriangleVertexBarycentricNV); - } // fallthrough - case EShLangClosestHit: - case EShLangMiss: - if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("traceNV", EOpTraceNV); - symbolTable.relateToOperator("traceRayMotionNV", EOpTraceRayMotionNV); - symbolTable.relateToOperator("traceRayEXT", EOpTraceKHR); - symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV); - symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallableKHR); - - symbolTable.relateToOperator("hitObjectTraceRayNV", EOpHitObjectTraceRayNV); - symbolTable.relateToOperator("hitObjectTraceRayMotionNV", EOpHitObjectTraceRayMotionNV); - symbolTable.relateToOperator("hitObjectRecordHitNV", EOpHitObjectRecordHitNV); - symbolTable.relateToOperator("hitObjectRecordHitMotionNV", EOpHitObjectRecordHitMotionNV); - symbolTable.relateToOperator("hitObjectRecordHitWithIndexNV", EOpHitObjectRecordHitWithIndexNV); - symbolTable.relateToOperator("hitObjectRecordHitWithIndexMotionNV", EOpHitObjectRecordHitWithIndexMotionNV); - symbolTable.relateToOperator("hitObjectRecordMissNV", EOpHitObjectRecordMissNV); - symbolTable.relateToOperator("hitObjectRecordMissMotionNV", EOpHitObjectRecordMissMotionNV); - symbolTable.relateToOperator("hitObjectRecordEmptyNV", EOpHitObjectRecordEmptyNV); - symbolTable.relateToOperator("hitObjectExecuteShaderNV", EOpHitObjectExecuteShaderNV); - symbolTable.relateToOperator("hitObjectIsEmptyNV", EOpHitObjectIsEmptyNV); - symbolTable.relateToOperator("hitObjectIsMissNV", EOpHitObjectIsMissNV); - symbolTable.relateToOperator("hitObjectIsHitNV", EOpHitObjectIsHitNV); - symbolTable.relateToOperator("hitObjectGetRayTMinNV", EOpHitObjectGetRayTMinNV); - symbolTable.relateToOperator("hitObjectGetRayTMaxNV", EOpHitObjectGetRayTMaxNV); - symbolTable.relateToOperator("hitObjectGetObjectRayOriginNV", EOpHitObjectGetObjectRayOriginNV); - symbolTable.relateToOperator("hitObjectGetObjectRayDirectionNV", EOpHitObjectGetObjectRayDirectionNV); - symbolTable.relateToOperator("hitObjectGetWorldRayOriginNV", EOpHitObjectGetWorldRayOriginNV); - symbolTable.relateToOperator("hitObjectGetWorldRayDirectionNV", EOpHitObjectGetWorldRayDirectionNV); - symbolTable.relateToOperator("hitObjectGetWorldToObjectNV", EOpHitObjectGetWorldToObjectNV); - symbolTable.relateToOperator("hitObjectGetObjectToWorldNV", EOpHitObjectGetObjectToWorldNV); - symbolTable.relateToOperator("hitObjectGetInstanceCustomIndexNV", EOpHitObjectGetInstanceCustomIndexNV); - symbolTable.relateToOperator("hitObjectGetInstanceIdNV", EOpHitObjectGetInstanceIdNV); - symbolTable.relateToOperator("hitObjectGetGeometryIndexNV", EOpHitObjectGetGeometryIndexNV); - symbolTable.relateToOperator("hitObjectGetPrimitiveIndexNV", EOpHitObjectGetPrimitiveIndexNV); - symbolTable.relateToOperator("hitObjectGetHitKindNV", EOpHitObjectGetHitKindNV); - symbolTable.relateToOperator("hitObjectGetAttributesNV", EOpHitObjectGetAttributesNV); - symbolTable.relateToOperator("hitObjectGetCurrentTimeNV", EOpHitObjectGetCurrentTimeNV); - symbolTable.relateToOperator("hitObjectGetShaderBindingTableRecordIndexNV", EOpHitObjectGetShaderBindingTableRecordIndexNV); - symbolTable.relateToOperator("hitObjectGetShaderRecordBufferHandleNV", EOpHitObjectGetShaderRecordBufferHandleNV); - symbolTable.relateToOperator("reorderThreadNV", EOpReorderThreadNV); - } - break; - case EShLangIntersect: - if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("reportIntersectionNV", EOpReportIntersection); - symbolTable.relateToOperator("reportIntersectionEXT", EOpReportIntersection); - } - break; - case EShLangAnyHit: - if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("ignoreIntersectionNV", EOpIgnoreIntersectionNV); - symbolTable.relateToOperator("terminateRayNV", EOpTerminateRayNV); - } - break; - case EShLangCallable: - if (profile != EEsProfile && version >= 460) { - symbolTable.relateToOperator("executeCallableNV", EOpExecuteCallableNV); - symbolTable.relateToOperator("executeCallableEXT", EOpExecuteCallableKHR); - } - break; - case EShLangMesh: - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { - symbolTable.relateToOperator("writePackedPrimitiveIndices4x8NV", EOpWritePackedPrimitiveIndices4x8NV); - symbolTable.relateToOperator("memoryBarrierShared", EOpMemoryBarrierShared); - symbolTable.relateToOperator("groupMemoryBarrier", EOpGroupMemoryBarrier); - symbolTable.relateToOperator("subgroupMemoryBarrierShared", EOpSubgroupMemoryBarrierShared); - } - - if (profile != EEsProfile && version >= 450) { - symbolTable.relateToOperator("SetMeshOutputsEXT", EOpSetMeshOutputsEXT); - } - - if (profile != EEsProfile && version >= 460) { - // Builtins for GL_NV_displacement_micromap. - symbolTable.relateToOperator("fetchMicroTriangleVertexPositionNV", EOpFetchMicroTriangleVertexPositionNV); - symbolTable.relateToOperator("fetchMicroTriangleVertexBarycentricNV", EOpFetchMicroTriangleVertexBarycentricNV); - } - break; - case EShLangTask: - if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) { - symbolTable.relateToOperator("memoryBarrierShared", EOpMemoryBarrierShared); - symbolTable.relateToOperator("groupMemoryBarrier", EOpGroupMemoryBarrier); - symbolTable.relateToOperator("subgroupMemoryBarrierShared", EOpSubgroupMemoryBarrierShared); - } - if (profile != EEsProfile && version >= 450) { - symbolTable.relateToOperator("EmitMeshTasksEXT", EOpEmitMeshTasksEXT); - } - break; - - default: - assert(false && "Language not supported"); - } -} - -// -// Add context-dependent (resource-specific) built-ins not handled by the above. These -// would be ones that need to be programmatically added because they cannot -// be added by simple text strings. For these, also -// 1) Map built-in functions to operators, for those that will turn into an operation node -// instead of remaining a function call. -// 2) Tag extension-related symbols added to their base version with their extensions, so -// that if an early version has the extension turned off, there is an error reported on use. -// -void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) -{ - if (profile != EEsProfile && version >= 430 && version < 440) { - symbolTable.setVariableExtensions("gl_MaxTransformFeedbackBuffers", 1, &E_GL_ARB_enhanced_layouts); - symbolTable.setVariableExtensions("gl_MaxTransformFeedbackInterleavedComponents", 1, &E_GL_ARB_enhanced_layouts); - } - if (profile != EEsProfile && version >= 130 && version < 420) { - symbolTable.setVariableExtensions("gl_MinProgramTexelOffset", 1, &E_GL_ARB_shading_language_420pack); - symbolTable.setVariableExtensions("gl_MaxProgramTexelOffset", 1, &E_GL_ARB_shading_language_420pack); - } - if (profile != EEsProfile && version >= 150 && version < 410) - symbolTable.setVariableExtensions("gl_MaxViewports", 1, &E_GL_ARB_viewport_array); - - switch(language) { - case EShLangFragment: - // Set up gl_FragData based on current array size. - if (version == 100 || IncludeLegacy(version, profile, spvVersion) || (! ForwardCompatibility && profile != EEsProfile && version < 420)) { - TPrecisionQualifier pq = profile == EEsProfile ? EpqMedium : EpqNone; - TType fragData(EbtFloat, EvqFragColor, pq, 4); - TArraySizes* arraySizes = new TArraySizes; - arraySizes->addInnerSize(resources.maxDrawBuffers); - fragData.transferArraySizes(arraySizes); - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData)); - SpecialQualifier("gl_FragData", EvqFragColor, EbvFragData, symbolTable); - } - - // GL_EXT_blend_func_extended - if (profile == EEsProfile && version >= 100) { - symbolTable.setVariableExtensions("gl_MaxDualSourceDrawBuffersEXT", 1, &E_GL_EXT_blend_func_extended); - symbolTable.setVariableExtensions("gl_SecondaryFragColorEXT", 1, &E_GL_EXT_blend_func_extended); - symbolTable.setVariableExtensions("gl_SecondaryFragDataEXT", 1, &E_GL_EXT_blend_func_extended); - SpecialQualifier("gl_SecondaryFragColorEXT", EvqVaryingOut, EbvSecondaryFragColorEXT, symbolTable); - SpecialQualifier("gl_SecondaryFragDataEXT", EvqVaryingOut, EbvSecondaryFragDataEXT, symbolTable); - } - - break; - - case EShLangTessControl: - case EShLangTessEvaluation: - // Because of the context-dependent array size (gl_MaxPatchVertices), - // these variables were added later than the others and need to be mapped now. - - // standard members - BuiltInVariable("gl_in", "gl_Position", EbvPosition, symbolTable); - BuiltInVariable("gl_in", "gl_PointSize", EbvPointSize, symbolTable); - BuiltInVariable("gl_in", "gl_ClipDistance", EbvClipDistance, symbolTable); - BuiltInVariable("gl_in", "gl_CullDistance", EbvCullDistance, symbolTable); - - // compatibility members - BuiltInVariable("gl_in", "gl_ClipVertex", EbvClipVertex, symbolTable); - BuiltInVariable("gl_in", "gl_FrontColor", EbvFrontColor, symbolTable); - BuiltInVariable("gl_in", "gl_BackColor", EbvBackColor, symbolTable); - BuiltInVariable("gl_in", "gl_FrontSecondaryColor", EbvFrontSecondaryColor, symbolTable); - BuiltInVariable("gl_in", "gl_BackSecondaryColor", EbvBackSecondaryColor, symbolTable); - BuiltInVariable("gl_in", "gl_TexCoord", EbvTexCoord, symbolTable); - BuiltInVariable("gl_in", "gl_FogFragCoord", EbvFogFragCoord, symbolTable); - - symbolTable.setVariableExtensions("gl_in", "gl_SecondaryPositionNV", 1, &E_GL_NV_stereo_view_rendering); - symbolTable.setVariableExtensions("gl_in", "gl_PositionPerViewNV", 1, &E_GL_NVX_multiview_per_view_attributes); - - BuiltInVariable("gl_in", "gl_SecondaryPositionNV", EbvSecondaryPositionNV, symbolTable); - BuiltInVariable("gl_in", "gl_PositionPerViewNV", EbvPositionPerViewNV, symbolTable); - - // extension requirements - if (profile == EEsProfile) { - symbolTable.setVariableExtensions("gl_in", "gl_PointSize", Num_AEP_tessellation_point_size, AEP_tessellation_point_size); - } - - break; - - default: - break; - } -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/Initialize.h b/3rdparty/glslang/glslang/MachineIndependent/Initialize.h deleted file mode 100644 index 42c32ddb..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/Initialize.h +++ /dev/null @@ -1,115 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013-2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _INITIALIZE_INCLUDED_ -#define _INITIALIZE_INCLUDED_ - -#include "../Include/ResourceLimits.h" -#include "../Include/Common.h" -#include "../Include/ShHandle.h" -#include "SymbolTable.h" -#include "Versions.h" - -namespace glslang { - -// -// This is made to hold parseable strings for almost all the built-in -// functions and variables for one specific combination of version -// and profile. (Some still need to be added programmatically.) -// This is a base class for language-specific derivations, which -// can be used for language independent builtins. -// -// The strings are organized by -// commonBuiltins: intersection of all stages' built-ins, processed just once -// stageBuiltins[]: anything a stage needs that's not in commonBuiltins -// -class TBuiltInParseables { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - TBuiltInParseables(); - virtual ~TBuiltInParseables(); - virtual void initialize(int version, EProfile, const SpvVersion& spvVersion) = 0; - virtual void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage) = 0; - virtual const TString& getCommonString() const { return commonBuiltins; } - virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; } - - virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) = 0; - virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0; - -protected: - TString commonBuiltins; - TString stageBuiltins[EShLangCount]; -}; - -// -// This is a GLSL specific derivation of TBuiltInParseables. To present a stable -// interface and match other similar code, it is called TBuiltIns, rather -// than TBuiltInParseablesGlsl. -// -class TBuiltIns : public TBuiltInParseables { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - TBuiltIns(); - virtual ~TBuiltIns(); - void initialize(int version, EProfile, const SpvVersion& spvVersion); - void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage); - - void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable); - void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources); - -protected: - void addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion); - void relateTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage, TSymbolTable&); - void add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion); - void addSubpassSampling(TSampler, const TString& typeName, int version, EProfile profile); - void addQueryFunctions(TSampler, const TString& typeName, int version, EProfile profile); - void addImageFunctions(TSampler, const TString& typeName, int version, EProfile profile); - void addSamplingFunctions(TSampler, const TString& typeName, int version, EProfile profile); - void addGatherFunctions(TSampler, const TString& typeName, int version, EProfile profile); - - // Helpers for making textual representations of the permutations - // of texturing/imaging functions. - const char* postfixes[5]; - const char* prefixes[EbtNumTypes]; - int dimMap[EsdNumDims]; -}; - -// change this back to false if depending on textual spellings of texturing calls when consuming the AST -// Using PureOperatorBuiltins=false is deprecated. -constexpr bool PureOperatorBuiltins = true; -} // end namespace glslang - -#endif // _INITIALIZE_INCLUDED_ diff --git a/3rdparty/glslang/glslang/MachineIndependent/IntermTraverse.cpp b/3rdparty/glslang/glslang/MachineIndependent/IntermTraverse.cpp deleted file mode 100644 index 553b1b5f..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/IntermTraverse.cpp +++ /dev/null @@ -1,309 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// Copyright (c) 2002-2010 The ANGLE Project Authors. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/intermediate.h" - -namespace glslang { - -// -// Traverse the intermediate representation tree, and -// call a node type specific function for each node. -// Done recursively through the member function Traverse(). -// Node types can be skipped if their function to call is 0, -// but their subtree will still be traversed. -// Nodes with children can have their whole subtree skipped -// if preVisit is turned on and the type specific function -// returns false. -// -// preVisit, postVisit, and rightToLeft control what order -// nodes are visited in. -// - -// -// Traversal functions for terminals are straightforward.... -// -void TIntermMethod::traverse(TIntermTraverser*) -{ - // Tree should always resolve all methods as a non-method. -} - -void TIntermSymbol::traverse(TIntermTraverser *it) -{ - it->visitSymbol(this); -} - -void TIntermConstantUnion::traverse(TIntermTraverser *it) -{ - it->visitConstantUnion(this); -} - -const TString& TIntermSymbol::getAccessName() const { - if (getBasicType() == EbtBlock) - return getType().getTypeName(); - else - return getName(); -} - -// -// Traverse a binary node. -// -void TIntermBinary::traverse(TIntermTraverser *it) -{ - bool visit = true; - - // - // visit the node before children if pre-visiting. - // - if (it->preVisit) - visit = it->visitBinary(EvPreVisit, this); - - // - // Visit the children, in the right order. - // - if (visit) { - it->incrementDepth(this); - - if (it->rightToLeft) { - if (right) - right->traverse(it); - - if (it->inVisit) - visit = it->visitBinary(EvInVisit, this); - - if (visit && left) - left->traverse(it); - } else { - if (left) - left->traverse(it); - - if (it->inVisit) - visit = it->visitBinary(EvInVisit, this); - - if (visit && right) - right->traverse(it); - } - - it->decrementDepth(); - } - - // - // Visit the node after the children, if requested and the traversal - // hasn't been canceled yet. - // - if (visit && it->postVisit) - it->visitBinary(EvPostVisit, this); -} - -// -// Traverse a unary node. Same comments in binary node apply here. -// -void TIntermUnary::traverse(TIntermTraverser *it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitUnary(EvPreVisit, this); - - if (visit) { - it->incrementDepth(this); - operand->traverse(it); - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitUnary(EvPostVisit, this); -} - -// -// Traverse an aggregate node. Same comments in binary node apply here. -// -void TIntermAggregate::traverse(TIntermTraverser *it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitAggregate(EvPreVisit, this); - - if (visit) { - it->incrementDepth(this); - - if (it->rightToLeft) { - for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) { - (*sit)->traverse(it); - - if (visit && it->inVisit) { - if (*sit != sequence.front()) - visit = it->visitAggregate(EvInVisit, this); - } - } - } else { - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) { - (*sit)->traverse(it); - - if (visit && it->inVisit) { - if (*sit != sequence.back()) - visit = it->visitAggregate(EvInVisit, this); - } - } - } - - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitAggregate(EvPostVisit, this); -} - -// -// Traverse a selection node. Same comments in binary node apply here. -// -void TIntermSelection::traverse(TIntermTraverser *it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitSelection(EvPreVisit, this); - - if (visit) { - it->incrementDepth(this); - if (it->rightToLeft) { - if (falseBlock) - falseBlock->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - condition->traverse(it); - } else { - condition->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - if (falseBlock) - falseBlock->traverse(it); - } - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitSelection(EvPostVisit, this); -} - -// -// Traverse a loop node. Same comments in binary node apply here. -// -void TIntermLoop::traverse(TIntermTraverser *it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitLoop(EvPreVisit, this); - - if (visit) { - it->incrementDepth(this); - - if (it->rightToLeft) { - if (terminal) - terminal->traverse(it); - - if (body) - body->traverse(it); - - if (test) - test->traverse(it); - } else { - if (test) - test->traverse(it); - - if (body) - body->traverse(it); - - if (terminal) - terminal->traverse(it); - } - - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitLoop(EvPostVisit, this); -} - -// -// Traverse a branch node. Same comments in binary node apply here. -// -void TIntermBranch::traverse(TIntermTraverser *it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitBranch(EvPreVisit, this); - - if (visit && expression) { - it->incrementDepth(this); - expression->traverse(it); - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitBranch(EvPostVisit, this); -} - -// -// Traverse a switch node. -// -void TIntermSwitch::traverse(TIntermTraverser* it) -{ - bool visit = true; - - if (it->preVisit) - visit = it->visitSwitch(EvPreVisit, this); - - if (visit) { - it->incrementDepth(this); - if (it->rightToLeft) { - body->traverse(it); - condition->traverse(it); - } else { - condition->traverse(it); - body->traverse(it); - } - it->decrementDepth(); - } - - if (visit && it->postVisit) - it->visitSwitch(EvPostVisit, this); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp b/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp deleted file mode 100644 index ae62f196..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/Intermediate.cpp +++ /dev/null @@ -1,4046 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2015 LunarG, Inc. -// Copyright (C) 2015-2020 Google, Inc. -// Copyright (C) 2017 ARM Limited. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Build the intermediate representation. -// - -#include "localintermediate.h" -#include "RemoveTree.h" -#include "SymbolTable.h" -#include "propagateNoContraction.h" - -#include -#include -#include - -namespace glslang { - -//////////////////////////////////////////////////////////////////////////// -// -// First set of functions are to help build the intermediate representation. -// These functions are not member functions of the nodes. -// They are called from parser productions. -// -///////////////////////////////////////////////////////////////////////////// - -// -// Add a terminal node for an identifier in an expression. -// -// Returns the added node. -// - -TIntermSymbol* TIntermediate::addSymbol(long long id, const TString& name, const TType& type, const TConstUnionArray& constArray, - TIntermTyped* constSubtree, const TSourceLoc& loc) -{ - TIntermSymbol* node = new TIntermSymbol(id, name, type); - node->setLoc(loc); - node->setConstArray(constArray); - node->setConstSubtree(constSubtree); - - return node; -} - -TIntermSymbol* TIntermediate::addSymbol(const TIntermSymbol& intermSymbol) -{ - return addSymbol(intermSymbol.getId(), - intermSymbol.getName(), - intermSymbol.getType(), - intermSymbol.getConstArray(), - intermSymbol.getConstSubtree(), - intermSymbol.getLoc()); -} - -TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable) -{ - glslang::TSourceLoc loc; // just a null location - loc.init(); - - return addSymbol(variable, loc); -} - -TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable, const TSourceLoc& loc) -{ - return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), variable.getConstArray(), variable.getConstSubtree(), loc); -} - -TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc) -{ - TConstUnionArray unionArray; // just a null constant - - return addSymbol(0, "", type, unionArray, nullptr, loc); -} - -// -// Connect two nodes with a new parent that does a binary operation on the nodes. -// -// Returns the added node. -// -// Returns nullptr if the working conversions and promotions could not be found. -// -TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc) -{ - // No operations work on blocks - if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock) - return nullptr; - - // Convert "reference +/- int" and "reference - reference" to integer math - if (op == EOpAdd || op == EOpSub) { - - // No addressing math on struct with unsized array. - if ((left->isReference() && left->getType().getReferentType()->containsUnsizedArray()) || - (right->isReference() && right->getType().getReferentType()->containsUnsizedArray())) { - return nullptr; - } - - if (left->isReference() && isTypeInt(right->getBasicType())) { - const TType& referenceType = left->getType(); - TIntermConstantUnion* size = addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(left->getType()), loc, true); - left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64)); - - right = createConversion(EbtInt64, right); - right = addBinaryMath(EOpMul, right, size, loc); - - TIntermTyped *node = addBinaryMath(op, left, right, loc); - node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType); - return node; - } - } - - if (op == EOpAdd && right->isReference() && isTypeInt(left->getBasicType())) { - const TType& referenceType = right->getType(); - TIntermConstantUnion* size = - addConstantUnion((unsigned long long)computeBufferReferenceTypeSize(right->getType()), loc, true); - right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64)); - - left = createConversion(EbtInt64, left); - left = addBinaryMath(EOpMul, left, size, loc); - - TIntermTyped *node = addBinaryMath(op, left, right, loc); - node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType); - return node; - } - - if (op == EOpSub && left->isReference() && right->isReference()) { - TIntermConstantUnion* size = - addConstantUnion((long long)computeBufferReferenceTypeSize(left->getType()), loc, true); - - left = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, left, TType(EbtUint64)); - right = addBuiltInFunctionCall(loc, EOpConvPtrToUint64, true, right, TType(EbtUint64)); - - left = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, left, TType(EbtInt64)); - right = addBuiltInFunctionCall(loc, EOpConvUint64ToInt64, true, right, TType(EbtInt64)); - - left = addBinaryMath(EOpSub, left, right, loc); - - TIntermTyped *node = addBinaryMath(EOpDiv, left, size, loc); - return node; - } - - // No other math operators supported on references - if (left->isReference() || right->isReference()) - return nullptr; - - // Try converting the children's base types to compatible types. - auto children = addPairConversion(op, left, right); - left = std::get<0>(children); - right = std::get<1>(children); - - if (left == nullptr || right == nullptr) - return nullptr; - - // Convert the children's type shape to be compatible. - addBiShapeConversion(op, left, right); - if (left == nullptr || right == nullptr) - return nullptr; - - // - // Need a new node holding things together. Make - // one and promote it to the right type. - // - TIntermBinary* node = addBinaryNode(op, left, right, loc); - if (! promote(node)) - return nullptr; - - node->updatePrecision(); - - // - // If they are both (non-specialization) constants, they must be folded. - // (Unless it's the sequence (comma) operator, but that's handled in addComma().) - // - TIntermConstantUnion *leftTempConstant = node->getLeft()->getAsConstantUnion(); - TIntermConstantUnion *rightTempConstant = node->getRight()->getAsConstantUnion(); - if (leftTempConstant && rightTempConstant) { - TIntermTyped* folded = leftTempConstant->fold(node->getOp(), rightTempConstant); - if (folded) - return folded; - } - - // If can propagate spec-constantness and if the operation is an allowed - // specialization-constant operation, make a spec-constant. - if (specConstantPropagates(*node->getLeft(), *node->getRight()) && isSpecializationOperation(*node)) - node->getWritableType().getQualifier().makeSpecConstant(); - - // If must propagate nonuniform, make a nonuniform. - if ((node->getLeft()->getQualifier().isNonUniform() || node->getRight()->getQualifier().isNonUniform()) && - isNonuniformPropagating(node->getOp())) - node->getWritableType().getQualifier().nonUniform = true; - - return node; -} - -// -// Low level: add binary node (no promotions or other argument modifications) -// -TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, - const TSourceLoc& loc) const -{ - // build the node - TIntermBinary* node = new TIntermBinary(op); - node->setLoc(loc.line != 0 ? loc : left->getLoc()); - node->setLeft(left); - node->setRight(right); - - return node; -} - -// -// like non-type form, but sets node's type. -// -TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, - const TSourceLoc& loc, const TType& type) const -{ - TIntermBinary* node = addBinaryNode(op, left, right, loc); - node->setType(type); - return node; -} - -// -// Low level: add unary node (no promotions or other argument modifications) -// -TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc) const -{ - TIntermUnary* node = new TIntermUnary(op); - node->setLoc(loc.line != 0 ? loc : child->getLoc()); - node->setOperand(child); - - return node; -} - -// -// like non-type form, but sets node's type. -// -TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc, const TType& type) - const -{ - TIntermUnary* node = addUnaryNode(op, child, loc); - node->setType(type); - return node; -} - -// -// Connect two nodes through an assignment. -// -// Returns the added node. -// -// Returns nullptr if the 'right' type could not be converted to match the 'left' type, -// or the resulting operation cannot be properly promoted. -// -TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, - const TSourceLoc& loc) -{ - // No block assignment - if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock) - return nullptr; - - // Convert "reference += int" to "reference = reference + int". We need this because the - // "reference + int" calculation involves a cast back to the original type, which makes it - // not an lvalue. - if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference()) { - if (!(right->getType().isScalar() && right->getType().isIntegerDomain())) - return nullptr; - - TIntermTyped* node = addBinaryMath(op == EOpAddAssign ? EOpAdd : EOpSub, left, right, loc); - if (!node) - return nullptr; - - TIntermSymbol* symbol = left->getAsSymbolNode(); - left = addSymbol(*symbol); - - node = addAssign(EOpAssign, left, node, loc); - return node; - } - - // - // Like adding binary math, except the conversion can only go - // from right to left. - // - - // convert base types, nullptr return means not possible - right = addConversion(op, left->getType(), right); - if (right == nullptr) - return nullptr; - - // convert shape - right = addUniShapeConversion(op, left->getType(), right); - - // build the node - TIntermBinary* node = addBinaryNode(op, left, right, loc); - - if (! promote(node)) - return nullptr; - - node->updatePrecision(); - - return node; -} - -// -// Connect two nodes through an index operator, where the left node is the base -// of an array or struct, and the right node is a direct or indirect offset. -// -// Returns the added node. -// The caller should set the type of the returned node. -// -TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, - const TSourceLoc& loc) -{ - // caller should set the type - return addBinaryNode(op, base, index, loc); -} - -// -// Add one node as the parent of another that it operates on. -// -// Returns the added node. -// -TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, - const TSourceLoc& loc) -{ - if (child == nullptr) - return nullptr; - - if (child->getType().getBasicType() == EbtBlock) - return nullptr; - - switch (op) { - case EOpLogicalNot: - if (getSource() == EShSourceHlsl) { - break; // HLSL can promote logical not - } - - if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { - return nullptr; - } - break; - - case EOpPostIncrement: - case EOpPreIncrement: - case EOpPostDecrement: - case EOpPreDecrement: - case EOpNegative: - if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) - return nullptr; - default: break; // some compilers want this - } - - // - // Do we need to promote the operand? - // - TBasicType newType = EbtVoid; - switch (op) { - case EOpConstructBool: newType = EbtBool; break; - case EOpConstructFloat: newType = EbtFloat; break; - case EOpConstructInt: newType = EbtInt; break; - case EOpConstructUint: newType = EbtUint; break; - case EOpConstructInt8: newType = EbtInt8; break; - case EOpConstructUint8: newType = EbtUint8; break; - case EOpConstructInt16: newType = EbtInt16; break; - case EOpConstructUint16: newType = EbtUint16; break; - case EOpConstructInt64: newType = EbtInt64; break; - case EOpConstructUint64: newType = EbtUint64; break; - case EOpConstructDouble: newType = EbtDouble; break; - case EOpConstructFloat16: newType = EbtFloat16; break; - default: break; // some compilers want this - } - - if (newType != EbtVoid) { - child = addConversion(op, TType(newType, EvqTemporary, child->getVectorSize(), - child->getMatrixCols(), - child->getMatrixRows(), - child->isVector()), - child); - if (child == nullptr) - return nullptr; - } - - // - // For constructors, we are now done, it was all in the conversion. - // TODO: but, did this bypass constant folding? - // - switch (op) { - case EOpConstructInt8: - case EOpConstructUint8: - case EOpConstructInt16: - case EOpConstructUint16: - case EOpConstructInt: - case EOpConstructUint: - case EOpConstructInt64: - case EOpConstructUint64: - case EOpConstructBool: - case EOpConstructFloat: - case EOpConstructDouble: - case EOpConstructFloat16: { - TIntermUnary* unary_node = child->getAsUnaryNode(); - if (unary_node != nullptr) - unary_node->updatePrecision(); - return child; - } - default: break; // some compilers want this - } - - // - // Make a new node for the operator. - // - TIntermUnary* node = addUnaryNode(op, child, loc); - - if (! promote(node)) - return nullptr; - - node->updatePrecision(); - - // If it's a (non-specialization) constant, it must be folded. - if (node->getOperand()->getAsConstantUnion()) - return node->getOperand()->getAsConstantUnion()->fold(op, node->getType()); - - // If it's a specialization constant, the result is too, - // if the operation is allowed for specialization constants. - if (node->getOperand()->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*node)) - node->getWritableType().getQualifier().makeSpecConstant(); - - // If must propagate nonuniform, make a nonuniform. - if (node->getOperand()->getQualifier().isNonUniform() && isNonuniformPropagating(node->getOp())) - node->getWritableType().getQualifier().nonUniform = true; - - return node; -} - -TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOperator op, bool unary, - TIntermNode* childNode, const TType& returnType) -{ - if (unary) { - // - // Treat it like a unary operator. - // addUnaryMath() should get the type correct on its own; - // including constness (which would differ from the prototype). - // - TIntermTyped* child = childNode->getAsTyped(); - if (child == nullptr) - return nullptr; - - if (child->getAsConstantUnion()) { - TIntermTyped* folded = child->getAsConstantUnion()->fold(op, returnType); - if (folded) - return folded; - } - - return addUnaryNode(op, child, child->getLoc(), returnType); - } else { - // setAggregateOperater() calls fold() for constant folding - TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc); - - return node; - } -} - -// -// This is the safe way to change the operator on an aggregate, as it -// does lots of error checking and fixing. Especially for establishing -// a function call's operation on its set of parameters. Sequences -// of instructions are also aggregates, but they just directly set -// their operator to EOpSequence. -// -// Returns an aggregate node, which could be the one passed in if -// it was already an aggregate. -// -TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, - const TSourceLoc& loc) -{ - TIntermAggregate* aggNode; - - // - // Make sure we have an aggregate. If not turn it into one. - // - if (node != nullptr) { - aggNode = node->getAsAggregate(); - if (aggNode == nullptr || aggNode->getOp() != EOpNull) { - // - // Make an aggregate containing this node. - // - aggNode = new TIntermAggregate(); - aggNode->getSequence().push_back(node); - } - } else - aggNode = new TIntermAggregate(); - - // - // Set the operator. - // - aggNode->setOperator(op); - if (loc.line != 0 || node != nullptr) - aggNode->setLoc(loc.line != 0 ? loc : node->getLoc()); - - aggNode->setType(type); - - return fold(aggNode); -} - -bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const -{ - // - // Does the base type even allow the operation? - // - switch (node->getBasicType()) { - case EbtVoid: - return false; - case EbtAtomicUint: - case EbtSampler: - case EbtAccStruct: - // opaque types can be passed to functions - if (op == EOpFunction) - break; - - // HLSL can assign samplers directly (no constructor) - if (getSource() == EShSourceHlsl && node->getBasicType() == EbtSampler) - break; - - // samplers can get assigned via a sampler constructor - // (well, not yet, but code in the rest of this function is ready for it) - if (node->getBasicType() == EbtSampler && op == EOpAssign && - node->getAsOperator() != nullptr && node->getAsOperator()->getOp() == EOpConstructTextureSampler) - break; - - // otherwise, opaque types can't even be operated on, let alone converted - return false; - default: - break; - } - - return true; -} - -bool TIntermediate::buildConvertOp(TBasicType dst, TBasicType src, TOperator& newOp) const -{ - switch (dst) { - case EbtDouble: - switch (src) { - case EbtUint: newOp = EOpConvUintToDouble; break; - case EbtBool: newOp = EOpConvBoolToDouble; break; - case EbtFloat: newOp = EOpConvFloatToDouble; break; - case EbtInt: newOp = EOpConvIntToDouble; break; - case EbtInt8: newOp = EOpConvInt8ToDouble; break; - case EbtUint8: newOp = EOpConvUint8ToDouble; break; - case EbtInt16: newOp = EOpConvInt16ToDouble; break; - case EbtUint16: newOp = EOpConvUint16ToDouble; break; - case EbtFloat16: newOp = EOpConvFloat16ToDouble; break; - case EbtInt64: newOp = EOpConvInt64ToDouble; break; - case EbtUint64: newOp = EOpConvUint64ToDouble; break; - default: - return false; - } - break; - case EbtFloat: - switch (src) { - case EbtInt: newOp = EOpConvIntToFloat; break; - case EbtUint: newOp = EOpConvUintToFloat; break; - case EbtBool: newOp = EOpConvBoolToFloat; break; - case EbtDouble: newOp = EOpConvDoubleToFloat; break; - case EbtInt8: newOp = EOpConvInt8ToFloat; break; - case EbtUint8: newOp = EOpConvUint8ToFloat; break; - case EbtInt16: newOp = EOpConvInt16ToFloat; break; - case EbtUint16: newOp = EOpConvUint16ToFloat; break; - case EbtFloat16: newOp = EOpConvFloat16ToFloat; break; - case EbtInt64: newOp = EOpConvInt64ToFloat; break; - case EbtUint64: newOp = EOpConvUint64ToFloat; break; - default: - return false; - } - break; - case EbtFloat16: - switch (src) { - case EbtInt8: newOp = EOpConvInt8ToFloat16; break; - case EbtUint8: newOp = EOpConvUint8ToFloat16; break; - case EbtInt16: newOp = EOpConvInt16ToFloat16; break; - case EbtUint16: newOp = EOpConvUint16ToFloat16; break; - case EbtInt: newOp = EOpConvIntToFloat16; break; - case EbtUint: newOp = EOpConvUintToFloat16; break; - case EbtBool: newOp = EOpConvBoolToFloat16; break; - case EbtFloat: newOp = EOpConvFloatToFloat16; break; - case EbtDouble: newOp = EOpConvDoubleToFloat16; break; - case EbtInt64: newOp = EOpConvInt64ToFloat16; break; - case EbtUint64: newOp = EOpConvUint64ToFloat16; break; - default: - return false; - } - break; - case EbtBool: - switch (src) { - case EbtInt: newOp = EOpConvIntToBool; break; - case EbtUint: newOp = EOpConvUintToBool; break; - case EbtFloat: newOp = EOpConvFloatToBool; break; - case EbtDouble: newOp = EOpConvDoubleToBool; break; - case EbtInt8: newOp = EOpConvInt8ToBool; break; - case EbtUint8: newOp = EOpConvUint8ToBool; break; - case EbtInt16: newOp = EOpConvInt16ToBool; break; - case EbtUint16: newOp = EOpConvUint16ToBool; break; - case EbtFloat16: newOp = EOpConvFloat16ToBool; break; - case EbtInt64: newOp = EOpConvInt64ToBool; break; - case EbtUint64: newOp = EOpConvUint64ToBool; break; - default: - return false; - } - break; - case EbtInt8: - switch (src) { - case EbtUint8: newOp = EOpConvUint8ToInt8; break; - case EbtInt16: newOp = EOpConvInt16ToInt8; break; - case EbtUint16: newOp = EOpConvUint16ToInt8; break; - case EbtInt: newOp = EOpConvIntToInt8; break; - case EbtUint: newOp = EOpConvUintToInt8; break; - case EbtInt64: newOp = EOpConvInt64ToInt8; break; - case EbtUint64: newOp = EOpConvUint64ToInt8; break; - case EbtBool: newOp = EOpConvBoolToInt8; break; - case EbtFloat: newOp = EOpConvFloatToInt8; break; - case EbtDouble: newOp = EOpConvDoubleToInt8; break; - case EbtFloat16: newOp = EOpConvFloat16ToInt8; break; - default: - return false; - } - break; - case EbtUint8: - switch (src) { - case EbtInt8: newOp = EOpConvInt8ToUint8; break; - case EbtInt16: newOp = EOpConvInt16ToUint8; break; - case EbtUint16: newOp = EOpConvUint16ToUint8; break; - case EbtInt: newOp = EOpConvIntToUint8; break; - case EbtUint: newOp = EOpConvUintToUint8; break; - case EbtInt64: newOp = EOpConvInt64ToUint8; break; - case EbtUint64: newOp = EOpConvUint64ToUint8; break; - case EbtBool: newOp = EOpConvBoolToUint8; break; - case EbtFloat: newOp = EOpConvFloatToUint8; break; - case EbtDouble: newOp = EOpConvDoubleToUint8; break; - case EbtFloat16: newOp = EOpConvFloat16ToUint8; break; - default: - return false; - } - break; - - case EbtInt16: - switch (src) { - case EbtUint8: newOp = EOpConvUint8ToInt16; break; - case EbtInt8: newOp = EOpConvInt8ToInt16; break; - case EbtUint16: newOp = EOpConvUint16ToInt16; break; - case EbtInt: newOp = EOpConvIntToInt16; break; - case EbtUint: newOp = EOpConvUintToInt16; break; - case EbtInt64: newOp = EOpConvInt64ToInt16; break; - case EbtUint64: newOp = EOpConvUint64ToInt16; break; - case EbtBool: newOp = EOpConvBoolToInt16; break; - case EbtFloat: newOp = EOpConvFloatToInt16; break; - case EbtDouble: newOp = EOpConvDoubleToInt16; break; - case EbtFloat16: newOp = EOpConvFloat16ToInt16; break; - default: - return false; - } - break; - case EbtUint16: - switch (src) { - case EbtInt8: newOp = EOpConvInt8ToUint16; break; - case EbtUint8: newOp = EOpConvUint8ToUint16; break; - case EbtInt16: newOp = EOpConvInt16ToUint16; break; - case EbtInt: newOp = EOpConvIntToUint16; break; - case EbtUint: newOp = EOpConvUintToUint16; break; - case EbtInt64: newOp = EOpConvInt64ToUint16; break; - case EbtUint64: newOp = EOpConvUint64ToUint16; break; - case EbtBool: newOp = EOpConvBoolToUint16; break; - case EbtFloat: newOp = EOpConvFloatToUint16; break; - case EbtDouble: newOp = EOpConvDoubleToUint16; break; - case EbtFloat16: newOp = EOpConvFloat16ToUint16; break; - default: - return false; - } - break; - - case EbtInt: - switch (src) { - case EbtUint: newOp = EOpConvUintToInt; break; - case EbtBool: newOp = EOpConvBoolToInt; break; - case EbtFloat: newOp = EOpConvFloatToInt; break; - case EbtInt8: newOp = EOpConvInt8ToInt; break; - case EbtUint8: newOp = EOpConvUint8ToInt; break; - case EbtInt16: newOp = EOpConvInt16ToInt; break; - case EbtUint16: newOp = EOpConvUint16ToInt; break; - case EbtDouble: newOp = EOpConvDoubleToInt; break; - case EbtFloat16: newOp = EOpConvFloat16ToInt; break; - case EbtInt64: newOp = EOpConvInt64ToInt; break; - case EbtUint64: newOp = EOpConvUint64ToInt; break; - default: - return false; - } - break; - case EbtUint: - switch (src) { - case EbtInt: newOp = EOpConvIntToUint; break; - case EbtBool: newOp = EOpConvBoolToUint; break; - case EbtFloat: newOp = EOpConvFloatToUint; break; - case EbtInt8: newOp = EOpConvInt8ToUint; break; - case EbtUint8: newOp = EOpConvUint8ToUint; break; - case EbtInt16: newOp = EOpConvInt16ToUint; break; - case EbtUint16: newOp = EOpConvUint16ToUint; break; - case EbtDouble: newOp = EOpConvDoubleToUint; break; - case EbtFloat16: newOp = EOpConvFloat16ToUint; break; - case EbtInt64: newOp = EOpConvInt64ToUint; break; - case EbtUint64: newOp = EOpConvUint64ToUint; break; - // For bindless texture type conversion, add a dummy convert op, just - // to generate a new TIntermTyped - // uvec2(any sampler type) - // uvec2(any image type) - case EbtSampler: newOp = EOpConvIntToUint; break; - default: - return false; - } - break; - case EbtInt64: - switch (src) { - case EbtInt8: newOp = EOpConvInt8ToInt64; break; - case EbtUint8: newOp = EOpConvUint8ToInt64; break; - case EbtInt16: newOp = EOpConvInt16ToInt64; break; - case EbtUint16: newOp = EOpConvUint16ToInt64; break; - case EbtInt: newOp = EOpConvIntToInt64; break; - case EbtUint: newOp = EOpConvUintToInt64; break; - case EbtBool: newOp = EOpConvBoolToInt64; break; - case EbtFloat: newOp = EOpConvFloatToInt64; break; - case EbtDouble: newOp = EOpConvDoubleToInt64; break; - case EbtFloat16: newOp = EOpConvFloat16ToInt64; break; - case EbtUint64: newOp = EOpConvUint64ToInt64; break; - default: - return false; - } - break; - case EbtUint64: - switch (src) { - case EbtInt8: newOp = EOpConvInt8ToUint64; break; - case EbtUint8: newOp = EOpConvUint8ToUint64; break; - case EbtInt16: newOp = EOpConvInt16ToUint64; break; - case EbtUint16: newOp = EOpConvUint16ToUint64; break; - case EbtInt: newOp = EOpConvIntToUint64; break; - case EbtUint: newOp = EOpConvUintToUint64; break; - case EbtBool: newOp = EOpConvBoolToUint64; break; - case EbtFloat: newOp = EOpConvFloatToUint64; break; - case EbtDouble: newOp = EOpConvDoubleToUint64; break; - case EbtFloat16: newOp = EOpConvFloat16ToUint64; break; - case EbtInt64: newOp = EOpConvInt64ToUint64; break; - default: - return false; - } - break; - default: - return false; - } - return true; -} - -// This is 'mechanism' here, it does any conversion told. -// It is about basic type, not about shape. -// The policy comes from the shader or the calling code. -TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped* node) const -{ - // - // Add a new newNode for the conversion. - // - - bool convertToIntTypes = (convertTo == EbtInt8 || convertTo == EbtUint8 || - convertTo == EbtInt16 || convertTo == EbtUint16 || - convertTo == EbtInt || convertTo == EbtUint || - convertTo == EbtInt64 || convertTo == EbtUint64); - - bool convertFromIntTypes = (node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8 || - node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16 || - node->getBasicType() == EbtInt || node->getBasicType() == EbtUint || - node->getBasicType() == EbtInt64 || node->getBasicType() == EbtUint64); - - bool convertToFloatTypes = (convertTo == EbtFloat16 || convertTo == EbtFloat || convertTo == EbtDouble); - - bool convertFromFloatTypes = (node->getBasicType() == EbtFloat16 || - node->getBasicType() == EbtFloat || - node->getBasicType() == EbtDouble); - - if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) || - ((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes)) { - if (! getArithemeticInt8Enabled()) { - return nullptr; - } - } - - if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) || - ((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes)) { - if (! getArithemeticInt16Enabled()) { - return nullptr; - } - } - - if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) || - (node->getBasicType() == EbtFloat16 && ! convertToFloatTypes)) { - if (! getArithemeticFloat16Enabled()) { - return nullptr; - } - } - - TIntermUnary* newNode = nullptr; - TOperator newOp = EOpNull; - if (!buildConvertOp(convertTo, node->getBasicType(), newOp)) { - return nullptr; - } - - TType newType(convertTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows()); - newNode = addUnaryNode(newOp, node, node->getLoc(), newType); - - if (node->getAsConstantUnion()) { - // 8/16-bit storage extensions don't support 8/16-bit constants, so don't fold conversions - // to those types - if ((getArithemeticInt8Enabled() || !(convertTo == EbtInt8 || convertTo == EbtUint8)) && - (getArithemeticInt16Enabled() || !(convertTo == EbtInt16 || convertTo == EbtUint16)) && - (getArithemeticFloat16Enabled() || !(convertTo == EbtFloat16))) - { - TIntermTyped* folded = node->getAsConstantUnion()->fold(newOp, newType); - if (folded) - return folded; - } - } - - // Propagate specialization-constant-ness, if allowed - if (node->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*newNode)) - newNode->getWritableType().getQualifier().makeSpecConstant(); - - return newNode; -} - -TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* node) const -{ - return createConversion(convertTo, node); -} - -// For converting a pair of operands to a binary operation to compatible -// types with each other, relative to the operation in 'op'. -// This does not cover assignment operations, which is asymmetric in that the -// left type is not changeable. -// See addConversion(op, type, node) for assignments and unary operation -// conversions. -// -// Generally, this is focused on basic type conversion, not shape conversion. -// See addShapeConversion() for shape conversions. -// -// Returns the converted pair of nodes. -// Returns when there is no conversion. -std::tuple -TIntermediate::addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) -{ - if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1)) - return std::make_tuple(nullptr, nullptr); - - if (node0->getType() != node1->getType()) { - // If differing structure, then no conversions. - if (node0->isStruct() || node1->isStruct()) - return std::make_tuple(nullptr, nullptr); - - // If differing arrays, then no conversions. - if (node0->getType().isArray() || node1->getType().isArray()) - return std::make_tuple(nullptr, nullptr); - - // No implicit conversions for operations involving cooperative matrices - if (node0->getType().isCoopMat() || node1->getType().isCoopMat()) - return std::make_tuple(node0, node1); - } - - auto promoteTo = std::make_tuple(EbtNumTypes, EbtNumTypes); - - switch (op) { - // - // List all the binary ops that can implicitly convert one operand to the other's type; - // This implements the 'policy' for implicit type conversion. - // - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - case EOpEqual: - case EOpNotEqual: - - case EOpAdd: - case EOpSub: - case EOpMul: - case EOpDiv: - case EOpMod: - - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - - case EOpSequence: // used by ?: - - if (node0->getBasicType() == node1->getBasicType()) - return std::make_tuple(node0, node1); - - promoteTo = getConversionDestinationType(node0->getBasicType(), node1->getBasicType(), op); - if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes) - return std::make_tuple(nullptr, nullptr); - - break; - - case EOpLogicalAnd: - case EOpLogicalOr: - case EOpLogicalXor: - if (getSource() == EShSourceHlsl) - promoteTo = std::make_tuple(EbtBool, EbtBool); - else - return std::make_tuple(node0, node1); - break; - - // There are no conversions needed for GLSL; the shift amount just needs to be an - // integer type, as does the base. - // HLSL can promote bools to ints to make this work. - case EOpLeftShift: - case EOpRightShift: - if (getSource() == EShSourceHlsl) { - TBasicType node0BasicType = node0->getBasicType(); - if (node0BasicType == EbtBool) - node0BasicType = EbtInt; - if (node1->getBasicType() == EbtBool) - promoteTo = std::make_tuple(node0BasicType, EbtInt); - else - promoteTo = std::make_tuple(node0BasicType, node1->getBasicType()); - } else { - if (isTypeInt(node0->getBasicType()) && isTypeInt(node1->getBasicType())) - return std::make_tuple(node0, node1); - else - return std::make_tuple(nullptr, nullptr); - } - break; - - default: - if (node0->getType() == node1->getType()) - return std::make_tuple(node0, node1); - - return std::make_tuple(nullptr, nullptr); - } - - TIntermTyped* newNode0; - TIntermTyped* newNode1; - - if (std::get<0>(promoteTo) != node0->getType().getBasicType()) { - if (node0->getAsConstantUnion()) - newNode0 = promoteConstantUnion(std::get<0>(promoteTo), node0->getAsConstantUnion()); - else - newNode0 = createConversion(std::get<0>(promoteTo), node0); - } else - newNode0 = node0; - - if (std::get<1>(promoteTo) != node1->getType().getBasicType()) { - if (node1->getAsConstantUnion()) - newNode1 = promoteConstantUnion(std::get<1>(promoteTo), node1->getAsConstantUnion()); - else - newNode1 = createConversion(std::get<1>(promoteTo), node1); - } else - newNode1 = node1; - - return std::make_tuple(newNode0, newNode1); -} - -// -// Convert the node's type to the given type, as allowed by the operation involved: 'op'. -// For implicit conversions, 'op' is not the requested conversion, it is the explicit -// operation requiring the implicit conversion. -// -// Binary operation conversions should be handled by addConversion(op, node, node), not here. -// -// Returns a node representing the conversion, which could be the same -// node passed in if no conversion was needed. -// -// Generally, this is focused on basic type conversion, not shape conversion. -// See addShapeConversion() for shape conversions. -// -// Return nullptr if a conversion can't be done. -// -TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) -{ - if (!isConversionAllowed(op, node)) - return nullptr; - - // Otherwise, if types are identical, no problem - if (type == node->getType()) - return node; - - // If one's a structure, then no conversions. - if (type.isStruct() || node->isStruct()) - return nullptr; - - // If one's an array, then no conversions. - if (type.isArray() || node->getType().isArray()) - return nullptr; - - // Reject implicit conversions to cooperative matrix types - if (node->getType().isCoopMat() && - op != EOpConstructCooperativeMatrixNV && - op != EOpConstructCooperativeMatrixKHR) - return nullptr; - - // Note: callers are responsible for other aspects of shape, - // like vector and matrix sizes. - - switch (op) { - // - // Explicit conversions (unary operations) - // - case EOpConstructBool: - case EOpConstructFloat: - case EOpConstructInt: - case EOpConstructUint: - case EOpConstructDouble: - case EOpConstructFloat16: - case EOpConstructInt8: - case EOpConstructUint8: - case EOpConstructInt16: - case EOpConstructUint16: - case EOpConstructInt64: - case EOpConstructUint64: - break; - - // - // Implicit conversions - // - case EOpLogicalNot: - - case EOpFunctionCall: - - case EOpReturn: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpDivAssign: - case EOpModAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - - case EOpAtan: - case EOpClamp: - case EOpCross: - case EOpDistance: - case EOpDot: - case EOpDst: - case EOpFaceForward: - case EOpFma: - case EOpFrexp: - case EOpLdexp: - case EOpMix: - case EOpLit: - case EOpMax: - case EOpMin: - case EOpMod: - case EOpModf: - case EOpPow: - case EOpReflect: - case EOpRefract: - case EOpSmoothStep: - case EOpStep: - - case EOpSequence: - case EOpConstructStruct: - case EOpConstructCooperativeMatrixNV: - case EOpConstructCooperativeMatrixKHR: - - if (type.isReference() || node->getType().isReference()) { - // types must match to assign a reference - if (type == node->getType()) - return node; - else - return nullptr; - } - - if (type.getBasicType() == node->getType().getBasicType()) - return node; - - if (! canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op)) - return nullptr; - break; - - // For GLSL, there are no conversions needed; the shift amount just needs to be an - // integer type, as do the base/result. - // HLSL can convert the shift from a bool to an int. - case EOpLeftShiftAssign: - case EOpRightShiftAssign: - { - if (!(getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool)) { - if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType())) - return node; - else - return nullptr; - } - break; - } - - default: - // default is to require a match; all exceptions should have case statements above - - if (type.getBasicType() == node->getType().getBasicType()) - return node; - else - return nullptr; - } - - bool canPromoteConstant = true; - // GL_EXT_shader_16bit_storage can't do OpConstantComposite with - // 16-bit types, so disable promotion for those types. - // Many issues with this, from JohnK: - // - this isn't really right to discuss SPIR-V here - // - this could easily be entirely about scalars, so is overstepping - // - we should be looking at what the shader asked for, and saying whether or - // not it can be done, in the parser, by calling requireExtensions(), not - // changing language sementics on the fly by asking what extensions are in use - // - at the time of this writing (14-Aug-2020), no test results are changed by this. - switch (op) { - case EOpConstructFloat16: - canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16); - break; - case EOpConstructInt8: - case EOpConstructUint8: - canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8); - break; - case EOpConstructInt16: - case EOpConstructUint16: - canPromoteConstant = numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16); - break; - default: - break; - } - - if (canPromoteConstant && node->getAsConstantUnion()) - return promoteConstantUnion(type.getBasicType(), node->getAsConstantUnion()); - - // - // Add a new newNode for the conversion. - // - TIntermTyped* newNode = createConversion(type.getBasicType(), node); - - return newNode; -} - -// Convert the node's shape of type for the given type, as allowed by the -// operation involved: 'op'. This is for situations where there is only one -// direction to consider doing the shape conversion. -// -// This implements policy, it call addShapeConversion() for the mechanism. -// -// Generally, the AST represents allowed GLSL shapes, so this isn't needed -// for GLSL. Bad shapes are caught in conversion or promotion. -// -// Return 'node' if no conversion was done. Promotion handles final shape -// checking. -// -TIntermTyped* TIntermediate::addUniShapeConversion(TOperator op, const TType& type, TIntermTyped* node) -{ - // some source languages don't do this - switch (getSource()) { - case EShSourceHlsl: - break; - case EShSourceGlsl: - default: - return node; - } - - // some operations don't do this - switch (op) { - case EOpFunctionCall: - case EOpReturn: - break; - - case EOpMulAssign: - // want to support vector *= scalar native ops in AST and lower, not smear, similarly for - // matrix *= scalar, etc. - - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - case EOpRightShiftAssign: - case EOpLeftShiftAssign: - if (node->getVectorSize() == 1) - return node; - break; - - case EOpAssign: - break; - - case EOpMix: - break; - - default: - return node; - } - - return addShapeConversion(type, node); -} - -// Convert the nodes' shapes to be compatible for the operation 'op'. -// -// This implements policy, it call addShapeConversion() for the mechanism. -// -// Generally, the AST represents allowed GLSL shapes, so this isn't needed -// for GLSL. Bad shapes are caught in conversion or promotion. -// -void TIntermediate::addBiShapeConversion(TOperator op, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode) -{ - // some source languages don't do this - switch (getSource()) { - case EShSourceHlsl: - break; - case EShSourceGlsl: - default: - return; - } - - // some operations don't do this - // 'break' will mean attempt bidirectional conversion - switch (op) { - case EOpMulAssign: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - case EOpRightShiftAssign: - case EOpLeftShiftAssign: - // switch to unidirectional conversion (the lhs can't change) - rhsNode = addUniShapeConversion(op, lhsNode->getType(), rhsNode); - return; - - case EOpMul: - // matrix multiply does not change shapes - if (lhsNode->isMatrix() && rhsNode->isMatrix()) - return; - case EOpAdd: - case EOpSub: - case EOpDiv: - // want to support vector * scalar native ops in AST and lower, not smear, similarly for - // matrix * vector, etc. - if (lhsNode->getVectorSize() == 1 || rhsNode->getVectorSize() == 1) - return; - break; - - case EOpRightShift: - case EOpLeftShift: - // can natively support the right operand being a scalar and the left a vector, - // but not the reverse - if (rhsNode->getVectorSize() == 1) - return; - break; - - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - - case EOpEqual: - case EOpNotEqual: - - case EOpLogicalAnd: - case EOpLogicalOr: - case EOpLogicalXor: - - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - - case EOpMix: - break; - - default: - return; - } - - // Do bidirectional conversions - if (lhsNode->getType().isScalarOrVec1() || rhsNode->getType().isScalarOrVec1()) { - if (lhsNode->getType().isScalarOrVec1()) - lhsNode = addShapeConversion(rhsNode->getType(), lhsNode); - else - rhsNode = addShapeConversion(lhsNode->getType(), rhsNode); - } - lhsNode = addShapeConversion(rhsNode->getType(), lhsNode); - rhsNode = addShapeConversion(lhsNode->getType(), rhsNode); -} - -// Convert the node's shape of type for the given type, as allowed by the -// operation involved: 'op'. -// -// Generally, the AST represents allowed GLSL shapes, so this isn't needed -// for GLSL. Bad shapes are caught in conversion or promotion. -// -// Return 'node' if no conversion was done. Promotion handles final shape -// checking. -// -TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped* node) -{ - // no conversion needed - if (node->getType() == type) - return node; - - // structures and arrays don't change shape, either to or from - if (node->getType().isStruct() || node->getType().isArray() || - type.isStruct() || type.isArray()) - return node; - - // The new node that handles the conversion - TOperator constructorOp = mapTypeToConstructorOp(type); - - if (getSource() == EShSourceHlsl) { - // HLSL rules for scalar, vector and matrix conversions: - // 1) scalar can become anything, initializing every component with its value - // 2) vector and matrix can become scalar, first element is used (warning: truncation) - // 3) matrix can become matrix with less rows and/or columns (warning: truncation) - // 4) vector can become vector with less rows size (warning: truncation) - // 5a) vector 4 can become 2x2 matrix (special case) (same packing layout, its a reinterpret) - // 5b) 2x2 matrix can become vector 4 (special case) (same packing layout, its a reinterpret) - - const TType &sourceType = node->getType(); - - // rule 1 for scalar to matrix is special - if (sourceType.isScalarOrVec1() && type.isMatrix()) { - - // HLSL semantics: the scalar (or vec1) is replicated to every component of the matrix. Left to its - // own devices, the constructor from a scalar would populate the diagonal. This forces replication - // to every matrix element. - - // Note that if the node is complex (e.g, a function call), we don't want to duplicate it here - // repeatedly, so we copy it to a temp, then use the temp. - const int matSize = type.computeNumComponents(); - TIntermAggregate* rhsAggregate = new TIntermAggregate(); - - const bool isSimple = (node->getAsSymbolNode() != nullptr) || (node->getAsConstantUnion() != nullptr); - - if (!isSimple) { - assert(0); // TODO: use node replicator service when available. - } - - for (int x = 0; x < matSize; ++x) - rhsAggregate->getSequence().push_back(node); - - return setAggregateOperator(rhsAggregate, constructorOp, type, node->getLoc()); - } - - // rule 1 and 2 - if ((sourceType.isScalar() && !type.isScalar()) || (!sourceType.isScalar() && type.isScalar())) - return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); - - // rule 3 and 5b - if (sourceType.isMatrix()) { - // rule 3 - if (type.isMatrix()) { - if ((sourceType.getMatrixCols() != type.getMatrixCols() || sourceType.getMatrixRows() != type.getMatrixRows()) && - sourceType.getMatrixCols() >= type.getMatrixCols() && sourceType.getMatrixRows() >= type.getMatrixRows()) - return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); - // rule 5b - } else if (type.isVector()) { - if (type.getVectorSize() == 4 && sourceType.getMatrixCols() == 2 && sourceType.getMatrixRows() == 2) - return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); - } - } - - // rule 4 and 5a - if (sourceType.isVector()) { - // rule 4 - if (type.isVector()) - { - if (sourceType.getVectorSize() > type.getVectorSize()) - return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); - // rule 5a - } else if (type.isMatrix()) { - if (sourceType.getVectorSize() == 4 && type.getMatrixCols() == 2 && type.getMatrixRows() == 2) - return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); - } - } - } - - // scalar -> vector or vec1 -> vector or - // vector -> scalar or - // bigger vector -> smaller vector - if ((node->getType().isScalarOrVec1() && type.isVector()) || - (node->getType().isVector() && type.isScalar()) || - (node->isVector() && type.isVector() && node->getVectorSize() > type.getVectorSize())) - return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc()); - - return node; -} - -bool TIntermediate::isIntegralPromotion(TBasicType from, TBasicType to) const -{ - // integral promotions - if (to == EbtInt) { - switch(from) { - case EbtInt8: - case EbtInt16: - case EbtUint8: - case EbtUint16: - return true; - default: - break; - } - } - return false; -} - -bool TIntermediate::isFPPromotion(TBasicType from, TBasicType to) const -{ - // floating-point promotions - if (to == EbtDouble) { - switch(from) { - case EbtFloat16: - case EbtFloat: - return true; - default: - break; - } - } - return false; -} - -bool TIntermediate::isIntegralConversion(TBasicType from, TBasicType to) const -{ - switch (from) { - case EbtInt: - switch(to) { - case EbtUint: - return version >= 400 || getSource() == EShSourceHlsl; - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtUint: - switch(to) { - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtInt8: - switch (to) { - case EbtUint8: - case EbtInt16: - case EbtUint16: - case EbtUint: - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtUint8: - switch (to) { - case EbtInt16: - case EbtUint16: - case EbtUint: - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtInt16: - switch(to) { - case EbtUint16: - case EbtUint: - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtUint16: - switch(to) { - case EbtUint: - case EbtInt64: - case EbtUint64: - return true; - default: - break; - } - break; - case EbtInt64: - if (to == EbtUint64) { - return true; - } - break; - default: - break; - } - return false; -} - -bool TIntermediate::isFPConversion(TBasicType from, TBasicType to) const -{ - if (to == EbtFloat && from == EbtFloat16) { - return true; - } else { - return false; - } -} - -bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const -{ - switch (from) { - case EbtInt: - case EbtUint: - switch(to) { - case EbtFloat: - case EbtDouble: - return true; - default: - break; - } - break; - case EbtInt8: - case EbtUint8: - case EbtInt16: - case EbtUint16: - switch (to) { - case EbtFloat16: - case EbtFloat: - case EbtDouble: - return true; - default: - break; - } - break; - case EbtInt64: - case EbtUint64: - if (to == EbtDouble) { - return true; - } - break; - default: - break; - } - return false; -} - -// -// See if the 'from' type is allowed to be implicitly converted to the -// 'to' type. This is not about vector/array/struct, only about basic type. -// -bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const -{ - if ((isEsProfile() && version < 310 ) || version == 110) - return false; - - if (from == to) - return true; - - // TODO: Move more policies into language-specific handlers. - // Some languages allow more general (or potentially, more specific) conversions under some conditions. - if (getSource() == EShSourceHlsl) { - const bool fromConvertable = (from == EbtFloat || from == EbtDouble || from == EbtInt || from == EbtUint || from == EbtBool); - const bool toConvertable = (to == EbtFloat || to == EbtDouble || to == EbtInt || to == EbtUint || to == EbtBool); - - if (fromConvertable && toConvertable) { - switch (op) { - case EOpAndAssign: // assignments can perform arbitrary conversions - case EOpInclusiveOrAssign: // ... - case EOpExclusiveOrAssign: // ... - case EOpAssign: // ... - case EOpAddAssign: // ... - case EOpSubAssign: // ... - case EOpMulAssign: // ... - case EOpVectorTimesScalarAssign: // ... - case EOpMatrixTimesScalarAssign: // ... - case EOpDivAssign: // ... - case EOpModAssign: // ... - case EOpReturn: // function returns can also perform arbitrary conversions - case EOpFunctionCall: // conversion of a calling parameter - case EOpLogicalNot: - case EOpLogicalAnd: - case EOpLogicalOr: - case EOpLogicalXor: - case EOpConstructStruct: - return true; - default: - break; - } - } - } - - if (getSource() == EShSourceHlsl) { - // HLSL - if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat)) - return true; - } else { - // GLSL - if (isIntegralPromotion(from, to) || - isFPPromotion(from, to) || - isIntegralConversion(from, to) || - isFPConversion(from, to) || - isFPIntegralConversion(from, to)) { - - if (numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int32) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int64) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float32) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float64)) { - return true; - } - } - } - - if (isEsProfile()) { - switch (to) { - case EbtFloat: - switch (from) { - case EbtInt: - case EbtUint: - return numericFeatures.contains(TNumericFeatures::shader_implicit_conversions); - default: - return false; - } - case EbtUint: - switch (from) { - case EbtInt: - return numericFeatures.contains(TNumericFeatures::shader_implicit_conversions); - default: - return false; - } - default: - return false; - } - } else { - switch (to) { - case EbtDouble: - switch (from) { - case EbtInt: - case EbtUint: - case EbtInt64: - case EbtUint64: - case EbtFloat: - return version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64); - case EbtInt16: - case EbtUint16: - return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) && - numericFeatures.contains(TNumericFeatures::gpu_shader_int16); - case EbtFloat16: - return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) && - numericFeatures.contains(TNumericFeatures::gpu_shader_half_float); - default: - return false; - } - case EbtFloat: - switch (from) { - case EbtInt: - case EbtUint: - return true; - case EbtBool: - return getSource() == EShSourceHlsl; - case EbtInt16: - case EbtUint16: - return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); - case EbtFloat16: - return numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) || - getSource() == EShSourceHlsl; - default: - return false; - } - case EbtUint: - switch (from) { - case EbtInt: - return version >= 400 || getSource() == EShSourceHlsl || IsRequestedExtension(E_GL_ARB_gpu_shader5); - case EbtBool: - return getSource() == EShSourceHlsl; - case EbtInt16: - case EbtUint16: - return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); - default: - return false; - } - case EbtInt: - switch (from) { - case EbtBool: - return getSource() == EShSourceHlsl; - case EbtInt16: - return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); - default: - return false; - } - case EbtUint64: - switch (from) { - case EbtInt: - case EbtUint: - case EbtInt64: - return true; - case EbtInt16: - case EbtUint16: - return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); - default: - return false; - } - case EbtInt64: - switch (from) { - case EbtInt: - return true; - case EbtInt16: - return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); - default: - return false; - } - case EbtFloat16: - switch (from) { - case EbtInt16: - case EbtUint16: - return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); - default: - break; - } - return false; - case EbtUint16: - switch (from) { - case EbtInt16: - return numericFeatures.contains(TNumericFeatures::gpu_shader_int16); - default: - break; - } - return false; - default: - return false; - } - } - - return false; -} - -static bool canSignedIntTypeRepresentAllUnsignedValues(TBasicType sintType, TBasicType uintType) -{ - switch(sintType) { - case EbtInt8: - switch(uintType) { - case EbtUint8: - case EbtUint16: - case EbtUint: - case EbtUint64: - return false; - default: - assert(false); - return false; - } - break; - case EbtInt16: - switch(uintType) { - case EbtUint8: - return true; - case EbtUint16: - case EbtUint: - case EbtUint64: - return false; - default: - assert(false); - return false; - } - break; - case EbtInt: - switch(uintType) { - case EbtUint8: - case EbtUint16: - return true; - case EbtUint: - return false; - default: - assert(false); - return false; - } - break; - case EbtInt64: - switch(uintType) { - case EbtUint8: - case EbtUint16: - case EbtUint: - return true; - case EbtUint64: - return false; - default: - assert(false); - return false; - } - break; - default: - assert(false); - return false; - } -} - - -static TBasicType getCorrespondingUnsignedType(TBasicType type) -{ - switch(type) { - case EbtInt8: - return EbtUint8; - case EbtInt16: - return EbtUint16; - case EbtInt: - return EbtUint; - case EbtInt64: - return EbtUint64; - default: - assert(false); - return EbtNumTypes; - } -} - -// Implements the following rules -// - If either operand has type float64_t or derived from float64_t, -// the other shall be converted to float64_t or derived type. -// - Otherwise, if either operand has type float32_t or derived from -// float32_t, the other shall be converted to float32_t or derived type. -// - Otherwise, if either operand has type float16_t or derived from -// float16_t, the other shall be converted to float16_t or derived type. -// - Otherwise, if both operands have integer types the following rules -// shall be applied to the operands: -// - If both operands have the same type, no further conversion -// is needed. -// - Otherwise, if both operands have signed integer types or both -// have unsigned integer types, the operand with the type of lesser -// integer conversion rank shall be converted to the type of the -// operand with greater rank. -// - Otherwise, if the operand that has unsigned integer type has rank -// greater than or equal to the rank of the type of the other -// operand, the operand with signed integer type shall be converted -// to the type of the operand with unsigned integer type. -// - Otherwise, if the type of the operand with signed integer type can -// represent all of the values of the type of the operand with -// unsigned integer type, the operand with unsigned integer type -// shall be converted to the type of the operand with signed -// integer type. -// - Otherwise, both operands shall be converted to the unsigned -// integer type corresponding to the type of the operand with signed -// integer type. - -std::tuple TIntermediate::getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const -{ - TBasicType res0 = EbtNumTypes; - TBasicType res1 = EbtNumTypes; - - if ((isEsProfile() && - (version < 310 || !numericFeatures.contains(TNumericFeatures::shader_implicit_conversions))) || - version == 110) - return std::make_tuple(res0, res1); - - if (getSource() == EShSourceHlsl) { - if (canImplicitlyPromote(type1, type0, op)) { - res0 = type0; - res1 = type0; - } else if (canImplicitlyPromote(type0, type1, op)) { - res0 = type1; - res1 = type1; - } - return std::make_tuple(res0, res1); - } - - if ((type0 == EbtDouble && canImplicitlyPromote(type1, EbtDouble, op)) || - (type1 == EbtDouble && canImplicitlyPromote(type0, EbtDouble, op)) ) { - res0 = EbtDouble; - res1 = EbtDouble; - } else if ((type0 == EbtFloat && canImplicitlyPromote(type1, EbtFloat, op)) || - (type1 == EbtFloat && canImplicitlyPromote(type0, EbtFloat, op)) ) { - res0 = EbtFloat; - res1 = EbtFloat; - } else if ((type0 == EbtFloat16 && canImplicitlyPromote(type1, EbtFloat16, op)) || - (type1 == EbtFloat16 && canImplicitlyPromote(type0, EbtFloat16, op)) ) { - res0 = EbtFloat16; - res1 = EbtFloat16; - } else if (isTypeInt(type0) && isTypeInt(type1) && - (canImplicitlyPromote(type0, type1, op) || canImplicitlyPromote(type1, type0, op))) { - if ((isTypeSignedInt(type0) && isTypeSignedInt(type1)) || - (isTypeUnsignedInt(type0) && isTypeUnsignedInt(type1))) { - if (getTypeRank(type0) < getTypeRank(type1)) { - res0 = type1; - res1 = type1; - } else { - res0 = type0; - res1 = type0; - } - } else if (isTypeUnsignedInt(type0) && (getTypeRank(type0) > getTypeRank(type1))) { - res0 = type0; - res1 = type0; - } else if (isTypeUnsignedInt(type1) && (getTypeRank(type1) > getTypeRank(type0))) { - res0 = type1; - res1 = type1; - } else if (isTypeSignedInt(type0)) { - if (canSignedIntTypeRepresentAllUnsignedValues(type0, type1)) { - res0 = type0; - res1 = type0; - } else { - res0 = getCorrespondingUnsignedType(type0); - res1 = getCorrespondingUnsignedType(type0); - } - } else if (isTypeSignedInt(type1)) { - if (canSignedIntTypeRepresentAllUnsignedValues(type1, type0)) { - res0 = type1; - res1 = type1; - } else { - res0 = getCorrespondingUnsignedType(type1); - res1 = getCorrespondingUnsignedType(type1); - } - } - } - - return std::make_tuple(res0, res1); -} - -// -// Given a type, find what operation would fully construct it. -// -TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const -{ - TOperator op = EOpNull; - - if (type.getQualifier().isNonUniform()) - return EOpConstructNonuniform; - - if (type.isCoopMatNV()) - return EOpConstructCooperativeMatrixNV; - - if (type.isCoopMatKHR()) - return EOpConstructCooperativeMatrixKHR; - - switch (type.getBasicType()) { - case EbtStruct: - op = EOpConstructStruct; - break; - case EbtSampler: - if (type.getSampler().isCombined()) - op = EOpConstructTextureSampler; - break; - case EbtFloat: - if (type.isMatrix()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructMat2x2; break; - case 3: op = EOpConstructMat2x3; break; - case 4: op = EOpConstructMat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructMat3x2; break; - case 3: op = EOpConstructMat3x3; break; - case 4: op = EOpConstructMat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructMat4x2; break; - case 3: op = EOpConstructMat4x3; break; - case 4: op = EOpConstructMat4x4; break; - default: break; // some compilers want this - } - break; - default: break; // some compilers want this - } - } else { - switch(type.getVectorSize()) { - case 1: op = EOpConstructFloat; break; - case 2: op = EOpConstructVec2; break; - case 3: op = EOpConstructVec3; break; - case 4: op = EOpConstructVec4; break; - default: break; // some compilers want this - } - } - break; - case EbtInt: - if (type.getMatrixCols()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructIMat2x2; break; - case 3: op = EOpConstructIMat2x3; break; - case 4: op = EOpConstructIMat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructIMat3x2; break; - case 3: op = EOpConstructIMat3x3; break; - case 4: op = EOpConstructIMat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructIMat4x2; break; - case 3: op = EOpConstructIMat4x3; break; - case 4: op = EOpConstructIMat4x4; break; - default: break; // some compilers want this - } - break; - } - } else { - switch(type.getVectorSize()) { - case 1: op = EOpConstructInt; break; - case 2: op = EOpConstructIVec2; break; - case 3: op = EOpConstructIVec3; break; - case 4: op = EOpConstructIVec4; break; - default: break; // some compilers want this - } - } - break; - case EbtUint: - if (type.getMatrixCols()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructUMat2x2; break; - case 3: op = EOpConstructUMat2x3; break; - case 4: op = EOpConstructUMat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructUMat3x2; break; - case 3: op = EOpConstructUMat3x3; break; - case 4: op = EOpConstructUMat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructUMat4x2; break; - case 3: op = EOpConstructUMat4x3; break; - case 4: op = EOpConstructUMat4x4; break; - default: break; // some compilers want this - } - break; - } - } else { - switch(type.getVectorSize()) { - case 1: op = EOpConstructUint; break; - case 2: op = EOpConstructUVec2; break; - case 3: op = EOpConstructUVec3; break; - case 4: op = EOpConstructUVec4; break; - default: break; // some compilers want this - } - } - break; - case EbtBool: - if (type.getMatrixCols()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructBMat2x2; break; - case 3: op = EOpConstructBMat2x3; break; - case 4: op = EOpConstructBMat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructBMat3x2; break; - case 3: op = EOpConstructBMat3x3; break; - case 4: op = EOpConstructBMat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructBMat4x2; break; - case 3: op = EOpConstructBMat4x3; break; - case 4: op = EOpConstructBMat4x4; break; - default: break; // some compilers want this - } - break; - } - } else { - switch(type.getVectorSize()) { - case 1: op = EOpConstructBool; break; - case 2: op = EOpConstructBVec2; break; - case 3: op = EOpConstructBVec3; break; - case 4: op = EOpConstructBVec4; break; - default: break; // some compilers want this - } - } - break; - case EbtDouble: - if (type.getMatrixCols()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructDMat2x2; break; - case 3: op = EOpConstructDMat2x3; break; - case 4: op = EOpConstructDMat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructDMat3x2; break; - case 3: op = EOpConstructDMat3x3; break; - case 4: op = EOpConstructDMat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructDMat4x2; break; - case 3: op = EOpConstructDMat4x3; break; - case 4: op = EOpConstructDMat4x4; break; - default: break; // some compilers want this - } - break; - } - } else { - switch(type.getVectorSize()) { - case 1: op = EOpConstructDouble; break; - case 2: op = EOpConstructDVec2; break; - case 3: op = EOpConstructDVec3; break; - case 4: op = EOpConstructDVec4; break; - default: break; // some compilers want this - } - } - break; - case EbtFloat16: - if (type.getMatrixCols()) { - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructF16Mat2x2; break; - case 3: op = EOpConstructF16Mat2x3; break; - case 4: op = EOpConstructF16Mat2x4; break; - default: break; // some compilers want this - } - break; - case 3: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructF16Mat3x2; break; - case 3: op = EOpConstructF16Mat3x3; break; - case 4: op = EOpConstructF16Mat3x4; break; - default: break; // some compilers want this - } - break; - case 4: - switch (type.getMatrixRows()) { - case 2: op = EOpConstructF16Mat4x2; break; - case 3: op = EOpConstructF16Mat4x3; break; - case 4: op = EOpConstructF16Mat4x4; break; - default: break; // some compilers want this - } - break; - } - } - else { - switch (type.getVectorSize()) { - case 1: op = EOpConstructFloat16; break; - case 2: op = EOpConstructF16Vec2; break; - case 3: op = EOpConstructF16Vec3; break; - case 4: op = EOpConstructF16Vec4; break; - default: break; // some compilers want this - } - } - break; - case EbtInt8: - switch(type.getVectorSize()) { - case 1: op = EOpConstructInt8; break; - case 2: op = EOpConstructI8Vec2; break; - case 3: op = EOpConstructI8Vec3; break; - case 4: op = EOpConstructI8Vec4; break; - default: break; // some compilers want this - } - break; - case EbtUint8: - switch(type.getVectorSize()) { - case 1: op = EOpConstructUint8; break; - case 2: op = EOpConstructU8Vec2; break; - case 3: op = EOpConstructU8Vec3; break; - case 4: op = EOpConstructU8Vec4; break; - default: break; // some compilers want this - } - break; - case EbtInt16: - switch(type.getVectorSize()) { - case 1: op = EOpConstructInt16; break; - case 2: op = EOpConstructI16Vec2; break; - case 3: op = EOpConstructI16Vec3; break; - case 4: op = EOpConstructI16Vec4; break; - default: break; // some compilers want this - } - break; - case EbtUint16: - switch(type.getVectorSize()) { - case 1: op = EOpConstructUint16; break; - case 2: op = EOpConstructU16Vec2; break; - case 3: op = EOpConstructU16Vec3; break; - case 4: op = EOpConstructU16Vec4; break; - default: break; // some compilers want this - } - break; - case EbtInt64: - switch(type.getVectorSize()) { - case 1: op = EOpConstructInt64; break; - case 2: op = EOpConstructI64Vec2; break; - case 3: op = EOpConstructI64Vec3; break; - case 4: op = EOpConstructI64Vec4; break; - default: break; // some compilers want this - } - break; - case EbtUint64: - switch(type.getVectorSize()) { - case 1: op = EOpConstructUint64; break; - case 2: op = EOpConstructU64Vec2; break; - case 3: op = EOpConstructU64Vec3; break; - case 4: op = EOpConstructU64Vec4; break; - default: break; // some compilers want this - } - break; - case EbtReference: - op = EOpConstructReference; - break; - - case EbtAccStruct: - op = EOpConstructAccStruct; - break; - default: - break; - } - - return op; -} - -// -// Safe way to combine two nodes into an aggregate. Works with null pointers, -// a node that's not a aggregate yet, etc. -// -// Returns the resulting aggregate, unless nullptr was passed in for -// both existing nodes. -// -TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right) -{ - if (left == nullptr && right == nullptr) - return nullptr; - - TIntermAggregate* aggNode = nullptr; - if (left != nullptr) - aggNode = left->getAsAggregate(); - if (aggNode == nullptr || aggNode->getOp() != EOpNull) { - aggNode = new TIntermAggregate; - if (left != nullptr) - aggNode->getSequence().push_back(left); - } - - if (right != nullptr) - aggNode->getSequence().push_back(right); - - return aggNode; -} - -TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& loc) -{ - TIntermAggregate* aggNode = growAggregate(left, right); - if (aggNode) - aggNode->setLoc(loc); - - return aggNode; -} - -TIntermAggregate* TIntermediate::mergeAggregate(TIntermNode* left, TIntermNode* right) -{ - if (left == nullptr && right == nullptr) - return nullptr; - - TIntermAggregate* aggNode = nullptr; - if (left != nullptr) - aggNode = left->getAsAggregate(); - if (aggNode == nullptr || aggNode->getOp() != EOpNull) { - aggNode = new TIntermAggregate; - if (left != nullptr) - aggNode->getSequence().push_back(left); - } - - TIntermAggregate* rhsagg = right->getAsAggregate(); - if (rhsagg == nullptr || rhsagg->getOp() != EOpNull) - aggNode->getSequence().push_back(right); - else - aggNode->getSequence().insert(aggNode->getSequence().end(), - rhsagg->getSequence().begin(), - rhsagg->getSequence().end()); - - return aggNode; -} - -TIntermAggregate* TIntermediate::mergeAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& loc) -{ - TIntermAggregate* aggNode = mergeAggregate(left, right); - if (aggNode) - aggNode->setLoc(loc); - - return aggNode; -} - -// -// Turn an existing node into an aggregate. -// -// Returns an aggregate, unless nullptr was passed in for the existing node. -// -TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node) -{ - if (node == nullptr) - return nullptr; - - TIntermAggregate* aggNode = new TIntermAggregate; - aggNode->getSequence().push_back(node); - aggNode->setLoc(node->getLoc()); - - return aggNode; -} - -TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& loc) -{ - if (node == nullptr) - return nullptr; - - TIntermAggregate* aggNode = new TIntermAggregate; - aggNode->getSequence().push_back(node); - aggNode->setLoc(loc); - - return aggNode; -} - -// -// Make an aggregate with an empty sequence. -// -TIntermAggregate* TIntermediate::makeAggregate(const TSourceLoc& loc) -{ - TIntermAggregate* aggNode = new TIntermAggregate; - aggNode->setLoc(loc); - - return aggNode; -} - -// -// For "if" test nodes. There are three children; a condition, -// a true path, and a false path. The two paths are in the -// nodePair. -// -// Returns the selection node created. -// -TIntermSelection* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc) -{ - // - // Don't prune the false path for compile-time constants; it's needed - // for static access analysis. - // - - TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); - node->setLoc(loc); - - return node; -} - -TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc) -{ - // However, the lowest precedence operators of the sequence operator ( , ) and the assignment operators - // ... are not included in the operators that can create a constant expression. - // - // if (left->getType().getQualifier().storage == EvqConst && - // right->getType().getQualifier().storage == EvqConst) { - - // return right; - //} - - TIntermTyped *commaAggregate = growAggregate(left, right, loc); - commaAggregate->getAsAggregate()->setOperator(EOpComma); - commaAggregate->setType(right->getType()); - commaAggregate->getWritableType().getQualifier().makeTemporary(); - - return commaAggregate; -} - -TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type, const TString* name, const TSourceLoc& loc) -{ - TIntermMethod* method = new TIntermMethod(object, type, *name); - method->setLoc(loc); - - return method; -} - -// -// For "?:" test nodes. There are three children; a condition, -// a true path, and a false path. The two paths are specified -// as separate parameters. For vector 'cond', the true and false -// are not paths, but vectors to mix. -// -// Specialization constant operations include -// - The ternary operator ( ? : ) -// -// Returns the selection node created, or nullptr if one could not be. -// -TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, - const TSourceLoc& loc) -{ - // If it's void, go to the if-then-else selection() - if (trueBlock->getBasicType() == EbtVoid && falseBlock->getBasicType() == EbtVoid) { - TIntermNodePair pair = { trueBlock, falseBlock }; - TIntermSelection* selection = addSelection(cond, pair, loc); - if (getSource() == EShSourceHlsl) - selection->setNoShortCircuit(); - - return selection; - } - - // - // Get compatible types. - // - auto children = addPairConversion(EOpSequence, trueBlock, falseBlock); - trueBlock = std::get<0>(children); - falseBlock = std::get<1>(children); - - if (trueBlock == nullptr || falseBlock == nullptr) - return nullptr; - - // Handle a vector condition as a mix - if (!cond->getType().isScalarOrVec1()) { - TType targetVectorType(trueBlock->getType().getBasicType(), EvqTemporary, - cond->getType().getVectorSize()); - // smear true/false operands as needed - trueBlock = addUniShapeConversion(EOpMix, targetVectorType, trueBlock); - falseBlock = addUniShapeConversion(EOpMix, targetVectorType, falseBlock); - - // After conversion, types have to match. - if (falseBlock->getType() != trueBlock->getType()) - return nullptr; - - // make the mix operation - TIntermAggregate* mix = makeAggregate(loc); - mix = growAggregate(mix, falseBlock); - mix = growAggregate(mix, trueBlock); - mix = growAggregate(mix, cond); - mix->setType(targetVectorType); - mix->setOp(EOpMix); - - return mix; - } - - // Now have a scalar condition... - - // Convert true and false expressions to matching types - addBiShapeConversion(EOpMix, trueBlock, falseBlock); - - // After conversion, types have to match. - if (falseBlock->getType() != trueBlock->getType()) - return nullptr; - - // Eliminate the selection when the condition is a scalar and all operands are constant. - if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { - if (cond->getAsConstantUnion()->getConstArray()[0].getBConst()) - return trueBlock; - else - return falseBlock; - } - - // - // Make a selection node. - // - TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); - node->setLoc(loc); - node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision); - - if ((cond->getQualifier().isConstant() && specConstantPropagates(*trueBlock, *falseBlock)) || - (cond->getQualifier().isSpecConstant() && trueBlock->getQualifier().isConstant() && - falseBlock->getQualifier().isConstant())) - node->getQualifier().makeSpecConstant(); - else - node->getQualifier().makeTemporary(); - - if (getSource() == EShSourceHlsl) - node->setNoShortCircuit(); - - return node; -} - -// -// Constant terminal nodes. Has a union that contains bool, float or int constants -// -// Returns the constant union node created. -// - -TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, const TSourceLoc& loc, bool literal) const -{ - TIntermConstantUnion* node = new TIntermConstantUnion(unionArray, t); - node->getQualifier().storage = EvqConst; - node->setLoc(loc); - if (literal) - node->setLiteral(); - - return node; -} -TIntermConstantUnion* TIntermediate::addConstantUnion(signed char i8, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setI8Const(i8); - - return addConstantUnion(unionArray, TType(EbtInt8, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned char u8, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setUConst(u8); - - return addConstantUnion(unionArray, TType(EbtUint8, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(signed short i16, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setI16Const(i16); - - return addConstantUnion(unionArray, TType(EbtInt16, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned short u16, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setU16Const(u16); - - return addConstantUnion(unionArray, TType(EbtUint16, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(int i, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setIConst(i); - - return addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned int u, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setUConst(u); - - return addConstantUnion(unionArray, TType(EbtUint, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(long long i64, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setI64Const(i64); - - return addConstantUnion(unionArray, TType(EbtInt64, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned long long u64, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setU64Const(u64); - - return addConstantUnion(unionArray, TType(EbtUint64, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(bool b, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setBConst(b); - - return addConstantUnion(unionArray, TType(EbtBool, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(double d, TBasicType baseType, const TSourceLoc& loc, bool literal) const -{ - assert(baseType == EbtFloat || baseType == EbtDouble || baseType == EbtFloat16); - - if (isEsProfile() && (baseType == EbtFloat || baseType == EbtFloat16)) { - int exponent = 0; - frexp(d, &exponent); - int minExp = baseType == EbtFloat ? -126 : -14; - int maxExp = baseType == EbtFloat ? 127 : 15; - if (exponent > maxExp) { //overflow, d = inf - d = std::numeric_limits::infinity(); - } else if (exponent < minExp) { //underflow, d = 0.0; - d = 0.0; - } - } - - TConstUnionArray unionArray(1); - unionArray[0].setDConst(d); - - return addConstantUnion(unionArray, TType(baseType, EvqConst), loc, literal); -} - -TIntermConstantUnion* TIntermediate::addConstantUnion(const TString* s, const TSourceLoc& loc, bool literal) const -{ - TConstUnionArray unionArray(1); - unionArray[0].setSConst(s); - - return addConstantUnion(unionArray, TType(EbtString, EvqConst), loc, literal); -} - -// Put vector swizzle selectors onto the given sequence -void TIntermediate::pushSelector(TIntermSequence& sequence, const TVectorSelector& selector, const TSourceLoc& loc) -{ - TIntermConstantUnion* constIntNode = addConstantUnion(selector, loc); - sequence.push_back(constIntNode); -} - -// Put matrix swizzle selectors onto the given sequence -void TIntermediate::pushSelector(TIntermSequence& sequence, const TMatrixSelector& selector, const TSourceLoc& loc) -{ - TIntermConstantUnion* constIntNode = addConstantUnion(selector.coord1, loc); - sequence.push_back(constIntNode); - constIntNode = addConstantUnion(selector.coord2, loc); - sequence.push_back(constIntNode); -} - -// Make an aggregate node that has a sequence of all selectors. -template TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors& selector, const TSourceLoc& loc); -template TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors& selector, const TSourceLoc& loc); -template -TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors& selector, const TSourceLoc& loc) -{ - TIntermAggregate* node = new TIntermAggregate(EOpSequence); - - node->setLoc(loc); - TIntermSequence &sequenceVector = node->getSequence(); - - for (int i = 0; i < selector.size(); i++) - pushSelector(sequenceVector, selector[i], loc); - - return node; -} - -// -// Follow the left branches down to the root of an l-value -// expression (just "." and []). -// -// Return the base of the l-value (where following indexing quits working). -// Return nullptr if a chain following dereferences cannot be followed. -// -// 'swizzleOkay' says whether or not it is okay to consider a swizzle -// a valid part of the dereference chain. -// -// 'bufferReferenceOk' says if type is buffer_reference, the routine will stop to find the most left node. -// -// 'proc' is an optional function to run on each node that is processed during the traversal. 'proc' must -// return true to continue the traversal, or false to end the traversal early. -// - -const TIntermTyped* TIntermediate::traverseLValueBase(const TIntermTyped* node, bool swizzleOkay, - bool bufferReferenceOk, - std::function proc) -{ - do { - const TIntermBinary* binary = node->getAsBinaryNode(); - if (binary == nullptr) { - if (proc) { - proc(*node); - } - return node; - } - TOperator op = binary->getOp(); - if (op != EOpIndexDirect && op != EOpIndexIndirect && op != EOpIndexDirectStruct && op != EOpVectorSwizzle && - op != EOpMatrixSwizzle) - return nullptr; - if (!swizzleOkay) { - if (op == EOpVectorSwizzle || op == EOpMatrixSwizzle) - return nullptr; - if ((op == EOpIndexDirect || op == EOpIndexIndirect) && - (binary->getLeft()->getType().isVector() || binary->getLeft()->getType().isScalar()) && - !binary->getLeft()->getType().isArray()) - return nullptr; - } - if (proc) { - if (!proc(*node)) { - return node; - } - } - node = binary->getLeft(); - if (bufferReferenceOk && node->isReference()) - return node; - } while (true); -} - -// -// Create while and do-while loop nodes. -// -TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, - const TSourceLoc& loc) -{ - TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst); - node->setLoc(loc); - - return node; -} - -// -// Create a for-loop sequence. -// -TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, - TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TIntermLoop*& node) -{ - node = new TIntermLoop(body, test, terminal, testFirst); - node->setLoc(loc); - - // make a sequence of the initializer and statement, but try to reuse the - // aggregate already created for whatever is in the initializer, if there is one - TIntermAggregate* loopSequence = (initializer == nullptr || - initializer->getAsAggregate() == nullptr) ? makeAggregate(initializer, loc) - : initializer->getAsAggregate(); - if (loopSequence != nullptr && (loopSequence->getOp() == EOpSequence || loopSequence->getOp() == EOpScope)) - loopSequence->setOp(EOpNull); - loopSequence = growAggregate(loopSequence, node); - loopSequence->setOperator(getDebugInfo() ? EOpScope : EOpSequence); - - return loopSequence; -} - -// -// Add branches. -// -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& loc) -{ - return addBranch(branchOp, nullptr, loc); -} - -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& loc) -{ - TIntermBranch* node = new TIntermBranch(branchOp, expression); - node->setLoc(loc); - - return node; -} - -// Propagate precision from formal function return type to actual return type, -// and on to its subtree. -void TIntermBranch::updatePrecision(TPrecisionQualifier parentPrecision) -{ - TIntermTyped* exp = getExpression(); - if (exp == nullptr) - return; - - if (exp->getBasicType() == EbtInt || exp->getBasicType() == EbtUint || - exp->getBasicType() == EbtFloat) { - if (parentPrecision != EpqNone && exp->getQualifier().precision == EpqNone) { - exp->propagatePrecision(parentPrecision); - } - } -} - -// -// This is to be executed after the final root is put on top by the parsing -// process. -// -bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/) -{ - if (root == nullptr) - return true; - - // Finish off the top-level sequence - TIntermAggregate* aggRoot = root->getAsAggregate(); - if (aggRoot && aggRoot->getOp() == EOpNull) - aggRoot->setOperator(EOpSequence); - - // Propagate 'noContraction' label in backward from 'precise' variables. - glslang::PropagateNoContraction(*this); - - switch (textureSamplerTransformMode) { - case EShTexSampTransKeep: - break; - case EShTexSampTransUpgradeTextureRemoveSampler: - performTextureUpgradeAndSamplerRemovalTransformation(root); - break; - case EShTexSampTransCount: - assert(0); - break; - } - - return true; -} - -void TIntermediate::addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage language, TSymbolTable& symbolTable) -{ - // Add top-level nodes for declarations that must be checked cross - // compilation unit by a linker, yet might not have been referenced - // by the AST. - // - // Almost entirely, translation of symbols is driven by what's present - // in the AST traversal, not by translating the symbol table. - // - // However, there are some special cases: - // - From the specification: "Special built-in inputs gl_VertexID and - // gl_InstanceID are also considered active vertex attributes." - // - Linker-based type mismatch error reporting needs to see all - // uniforms/ins/outs variables and blocks. - // - ftransform() can make gl_Vertex and gl_ModelViewProjectionMatrix active. - // - - // if (ftransformUsed) { - // TODO: 1.1 lowering functionality: track ftransform() usage - // addSymbolLinkageNode(root, symbolTable, "gl_Vertex"); - // addSymbolLinkageNode(root, symbolTable, "gl_ModelViewProjectionMatrix"); - //} - - if (language == EShLangVertex) { - addSymbolLinkageNode(linkage, symbolTable, "gl_VertexID"); - if ((version < 140 && requestedExtensions.find(E_GL_EXT_draw_instanced) != requestedExtensions.end()) || version >= 140) - addSymbolLinkageNode(linkage, symbolTable, "gl_InstanceID"); - } - - // Add a child to the root node for the linker objects - linkage->setOperator(EOpLinkerObjects); - treeRoot = growAggregate(treeRoot, linkage); -} - -// -// Add the given name or symbol to the list of nodes at the end of the tree used -// for link-time checking and external linkage. -// - -void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable& symbolTable, const TString& name) -{ - TSymbol* symbol = symbolTable.find(name); - if (symbol) - addSymbolLinkageNode(linkage, *symbol->getAsVariable()); -} - -void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol& symbol) -{ - const TVariable* variable = symbol.getAsVariable(); - if (! variable) { - // This must be a member of an anonymous block, and we need to add the whole block - const TAnonMember* anon = symbol.getAsAnonMember(); - variable = &anon->getAnonContainer(); - } - TIntermSymbol* node = addSymbol(*variable); - linkage = growAggregate(linkage, node); -} - -// -// Add a caller->callee relationship to the call graph. -// Assumes the strings are unique per signature. -// -void TIntermediate::addToCallGraph(TInfoSink& /*infoSink*/, const TString& caller, const TString& callee) -{ - // Duplicates are okay, but faster to not keep them, and they come grouped by caller, - // as long as new ones are push on the same end we check on for duplicates - for (TGraph::const_iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - if (call->caller != caller) - break; - if (call->callee == callee) - return; - } - - callGraph.emplace_front(caller, callee); -} - -// -// This deletes the tree. -// -void TIntermediate::removeTree() -{ - if (treeRoot) - RemoveAllTreeNodes(treeRoot); -} - -// -// Implement the part of KHR_vulkan_glsl that lists the set of operations -// that can result in a specialization constant operation. -// -// "5.x Specialization Constant Operations" -// -// Only some operations discussed in this section may be applied to a -// specialization constant and still yield a result that is as -// specialization constant. The operations allowed are listed below. -// When a specialization constant is operated on with one of these -// operators and with another constant or specialization constant, the -// result is implicitly a specialization constant. -// -// - int(), uint(), and bool() constructors for type conversions -// from any of the following types to any of the following types: -// * int -// * uint -// * bool -// - vector versions of the above conversion constructors -// - allowed implicit conversions of the above -// - swizzles (e.g., foo.yx) -// - The following when applied to integer or unsigned integer types: -// * unary negative ( - ) -// * binary operations ( + , - , * , / , % ) -// * shift ( <<, >> ) -// * bitwise operations ( & , | , ^ ) -// - The following when applied to integer or unsigned integer scalar types: -// * comparison ( == , != , > , >= , < , <= ) -// - The following when applied to the Boolean scalar type: -// * not ( ! ) -// * logical operations ( && , || , ^^ ) -// * comparison ( == , != )" -// -// This function just handles binary and unary nodes. Construction -// rules are handled in construction paths that are not covered by the unary -// and binary paths, while required conversions will still show up here -// as unary converters in the from a construction operator. -// -bool TIntermediate::isSpecializationOperation(const TIntermOperator& node) const -{ - // The operations resulting in floating point are quite limited - // (However, some floating-point operations result in bool, like ">", - // so are handled later.) - if (node.getType().isFloatingDomain()) { - switch (node.getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpVectorSwizzle: - case EOpConvFloatToDouble: - case EOpConvDoubleToFloat: - case EOpConvFloat16ToFloat: - case EOpConvFloatToFloat16: - case EOpConvFloat16ToDouble: - case EOpConvDoubleToFloat16: - return true; - default: - return false; - } - } - - // Check for floating-point arguments - if (const TIntermBinary* bin = node.getAsBinaryNode()) - if (bin->getLeft() ->getType().isFloatingDomain() || - bin->getRight()->getType().isFloatingDomain()) - return false; - - // So, for now, we can assume everything left is non-floating-point... - - // Now check for integer/bool-based operations - switch (node.getOp()) { - - // dereference/swizzle - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpVectorSwizzle: - - // (u)int* -> bool - case EOpConvInt8ToBool: - case EOpConvInt16ToBool: - case EOpConvIntToBool: - case EOpConvInt64ToBool: - case EOpConvUint8ToBool: - case EOpConvUint16ToBool: - case EOpConvUintToBool: - case EOpConvUint64ToBool: - - // bool -> (u)int* - case EOpConvBoolToInt8: - case EOpConvBoolToInt16: - case EOpConvBoolToInt: - case EOpConvBoolToInt64: - case EOpConvBoolToUint8: - case EOpConvBoolToUint16: - case EOpConvBoolToUint: - case EOpConvBoolToUint64: - - // int8_t -> (u)int* - case EOpConvInt8ToInt16: - case EOpConvInt8ToInt: - case EOpConvInt8ToInt64: - case EOpConvInt8ToUint8: - case EOpConvInt8ToUint16: - case EOpConvInt8ToUint: - case EOpConvInt8ToUint64: - - // int16_t -> (u)int* - case EOpConvInt16ToInt8: - case EOpConvInt16ToInt: - case EOpConvInt16ToInt64: - case EOpConvInt16ToUint8: - case EOpConvInt16ToUint16: - case EOpConvInt16ToUint: - case EOpConvInt16ToUint64: - - // int32_t -> (u)int* - case EOpConvIntToInt8: - case EOpConvIntToInt16: - case EOpConvIntToInt64: - case EOpConvIntToUint8: - case EOpConvIntToUint16: - case EOpConvIntToUint: - case EOpConvIntToUint64: - - // int64_t -> (u)int* - case EOpConvInt64ToInt8: - case EOpConvInt64ToInt16: - case EOpConvInt64ToInt: - case EOpConvInt64ToUint8: - case EOpConvInt64ToUint16: - case EOpConvInt64ToUint: - case EOpConvInt64ToUint64: - - // uint8_t -> (u)int* - case EOpConvUint8ToInt8: - case EOpConvUint8ToInt16: - case EOpConvUint8ToInt: - case EOpConvUint8ToInt64: - case EOpConvUint8ToUint16: - case EOpConvUint8ToUint: - case EOpConvUint8ToUint64: - - // uint16_t -> (u)int* - case EOpConvUint16ToInt8: - case EOpConvUint16ToInt16: - case EOpConvUint16ToInt: - case EOpConvUint16ToInt64: - case EOpConvUint16ToUint8: - case EOpConvUint16ToUint: - case EOpConvUint16ToUint64: - - // uint32_t -> (u)int* - case EOpConvUintToInt8: - case EOpConvUintToInt16: - case EOpConvUintToInt: - case EOpConvUintToInt64: - case EOpConvUintToUint8: - case EOpConvUintToUint16: - case EOpConvUintToUint64: - - // uint64_t -> (u)int* - case EOpConvUint64ToInt8: - case EOpConvUint64ToInt16: - case EOpConvUint64ToInt: - case EOpConvUint64ToInt64: - case EOpConvUint64ToUint8: - case EOpConvUint64ToUint16: - case EOpConvUint64ToUint: - - // unary operations - case EOpNegative: - case EOpLogicalNot: - case EOpBitwiseNot: - - // binary operations - case EOpAdd: - case EOpSub: - case EOpMul: - case EOpVectorTimesScalar: - case EOpDiv: - case EOpMod: - case EOpRightShift: - case EOpLeftShift: - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - return true; - default: - return false; - } -} - -// Is the operation one that must propagate nonuniform? -bool TIntermediate::isNonuniformPropagating(TOperator op) const -{ - // "* All Operators in Section 5.1 (Operators), except for assignment, - // arithmetic assignment, and sequence - // * Component selection in Section 5.5 - // * Matrix components in Section 5.6 - // * Structure and Array Operations in Section 5.7, except for the length - // method." - switch (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - - case EOpNegative: - case EOpLogicalNot: - case EOpVectorLogicalNot: - case EOpBitwiseNot: - - case EOpAdd: - case EOpSub: - case EOpMul: - case EOpDiv: - case EOpMod: - case EOpRightShift: - case EOpLeftShift: - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpVectorSwizzle: - return true; - - default: - break; - } - - return false; -} - -//////////////////////////////////////////////////////////////// -// -// Member functions of the nodes used for building the tree. -// -//////////////////////////////////////////////////////////////// - -// -// Say whether or not an operation node changes the value of a variable. -// -// Returns true if state is modified. -// -bool TIntermOperator::modifiesState() const -{ - switch (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - case EOpModAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - case EOpLeftShiftAssign: - case EOpRightShiftAssign: - return true; - default: - return false; - } -} - -// -// returns true if the operator is for one of the constructors -// -bool TIntermOperator::isConstructor() const -{ - return op > EOpConstructGuardStart && op < EOpConstructGuardEnd; -} - -// -// Make sure the type of an operator is appropriate for its -// combination of operation and operand type. This will invoke -// promoteUnary, promoteBinary, etc as needed. -// -// Returns false if nothing makes sense. -// -bool TIntermediate::promote(TIntermOperator* node) -{ - if (node == nullptr) - return false; - - if (node->getAsUnaryNode()) - return promoteUnary(*node->getAsUnaryNode()); - - if (node->getAsBinaryNode()) - return promoteBinary(*node->getAsBinaryNode()); - - if (node->getAsAggregate()) - return promoteAggregate(*node->getAsAggregate()); - - return false; -} - -// -// See TIntermediate::promote -// -bool TIntermediate::promoteUnary(TIntermUnary& node) -{ - const TOperator op = node.getOp(); - TIntermTyped* operand = node.getOperand(); - - switch (op) { - case EOpLogicalNot: - // Convert operand to a boolean type - if (operand->getBasicType() != EbtBool) { - // Add constructor to boolean type. If that fails, we can't do it, so return false. - TIntermTyped* converted = addConversion(op, TType(EbtBool), operand); - if (converted == nullptr) - return false; - - // Use the result of converting the node to a bool. - node.setOperand(operand = converted); // also updates stack variable - } - break; - case EOpBitwiseNot: - if (!isTypeInt(operand->getBasicType())) - return false; - break; - case EOpNegative: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (!isTypeInt(operand->getBasicType()) && - operand->getBasicType() != EbtFloat && - operand->getBasicType() != EbtFloat16 && - operand->getBasicType() != EbtDouble) - - return false; - break; - default: - // HLSL uses this path for initial function signature finding for built-ins - // taking a single argument, which generally don't participate in - // operator-based type promotion (type conversion will occur later). - // For now, scalar argument cases are relying on the setType() call below. - if (getSource() == EShSourceHlsl) - break; - - // GLSL only allows integer arguments for the cases identified above in the - // case statements. - if (operand->getBasicType() != EbtFloat) - return false; - } - - node.setType(operand->getType()); - node.getWritableType().getQualifier().makeTemporary(); - - return true; -} - -// Propagate precision qualifiers *up* from children to parent. -void TIntermUnary::updatePrecision() -{ - if (getBasicType() == EbtInt || getBasicType() == EbtUint || - getBasicType() == EbtFloat) { - if (operand->getQualifier().precision > getQualifier().precision) - getQualifier().precision = operand->getQualifier().precision; - } -} - -// -// See TIntermediate::promote -// -bool TIntermediate::promoteBinary(TIntermBinary& node) -{ - TOperator op = node.getOp(); - TIntermTyped* left = node.getLeft(); - TIntermTyped* right = node.getRight(); - - // Arrays and structures have to be exact matches. - if ((left->isArray() || right->isArray() || left->getBasicType() == EbtStruct || right->getBasicType() == EbtStruct) - && left->getType() != right->getType()) - return false; - - // Base assumption: just make the type the same as the left - // operand. Only deviations from this will be coded. - node.setType(left->getType()); - node.getWritableType().getQualifier().clear(); - - // Composite and opaque types don't having pending operator changes, e.g., - // array, structure, and samplers. Just establish final type and correctness. - if (left->isArray() || left->getBasicType() == EbtStruct || left->getBasicType() == EbtSampler) { - switch (op) { - case EOpEqual: - case EOpNotEqual: - if (left->getBasicType() == EbtSampler) { - // can't compare samplers - return false; - } else { - // Promote to conditional - node.setType(TType(EbtBool)); - } - - return true; - - case EOpAssign: - // Keep type from above - - return true; - - default: - return false; - } - } - - // - // We now have only scalars, vectors, and matrices to worry about. - // - - // HLSL implicitly promotes bool -> int for numeric operations. - // (Implicit conversions to make the operands match each other's types were already done.) - if (getSource() == EShSourceHlsl && - (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool)) { - switch (op) { - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - - case EOpRightShift: - case EOpLeftShift: - - case EOpMod: - - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - if (left->getBasicType() == EbtBool) - left = createConversion(EbtInt, left); - if (right->getBasicType() == EbtBool) - right = createConversion(EbtInt, right); - if (left == nullptr || right == nullptr) - return false; - node.setLeft(left); - node.setRight(right); - - // Update the original base assumption on result type.. - node.setType(left->getType()); - node.getWritableType().getQualifier().clear(); - - break; - - default: - break; - } - } - - // Do general type checks against individual operands (comparing left and right is coming up, checking mixed shapes after that) - switch (op) { - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - // Relational comparisons need numeric types and will promote to scalar Boolean. - if (left->getBasicType() == EbtBool) - return false; - - node.setType(TType(EbtBool, EvqTemporary, left->getVectorSize())); - break; - - case EOpEqual: - case EOpNotEqual: - if (getSource() == EShSourceHlsl) { - const int resultWidth = std::max(left->getVectorSize(), right->getVectorSize()); - - // In HLSL, == or != on vectors means component-wise comparison. - if (resultWidth > 1) { - op = (op == EOpEqual) ? EOpVectorEqual : EOpVectorNotEqual; - node.setOp(op); - } - - node.setType(TType(EbtBool, EvqTemporary, resultWidth)); - } else { - // All the above comparisons result in a bool (but not the vector compares) - node.setType(TType(EbtBool)); - } - break; - - case EOpLogicalAnd: - case EOpLogicalOr: - case EOpLogicalXor: - // logical ops operate only on Booleans or vectors of Booleans. - if (left->getBasicType() != EbtBool || left->isMatrix()) - return false; - - if (getSource() == EShSourceGlsl) { - // logical ops operate only on scalar Booleans and will promote to scalar Boolean. - if (left->isVector()) - return false; - } - - node.setType(TType(EbtBool, EvqTemporary, left->getVectorSize())); - break; - - case EOpRightShift: - case EOpLeftShift: - case EOpRightShiftAssign: - case EOpLeftShiftAssign: - - case EOpMod: - case EOpModAssign: - - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - if (getSource() == EShSourceHlsl) - break; - - // Check for integer-only operands. - if (!isTypeInt(left->getBasicType()) && !isTypeInt(right->getBasicType())) - return false; - if (left->isMatrix() || right->isMatrix()) - return false; - - break; - - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpDivAssign: - // check for non-Boolean operands - if (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool) - return false; - - default: - break; - } - - // Compare left and right, and finish with the cases where the operand types must match - switch (op) { - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - - case EOpEqual: - case EOpNotEqual: - case EOpVectorEqual: - case EOpVectorNotEqual: - - case EOpLogicalAnd: - case EOpLogicalOr: - case EOpLogicalXor: - return left->getType() == right->getType(); - - case EOpMod: - case EOpModAssign: - - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - - case EOpAdd: - case EOpSub: - case EOpDiv: - - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - // Quick out in case the types do match - if (left->getType() == right->getType()) - return true; - - // Fall through - - case EOpMul: - case EOpMulAssign: - // At least the basic type has to match - if (left->getBasicType() != right->getBasicType()) - return false; - - default: - break; - } - - if (left->getType().isCoopMat() || right->getType().isCoopMat()) { - // Operations on two cooperative matrices must have identical types - if (left->getType().isCoopMat() && right->getType().isCoopMat() && - left->getType() != right->getType()) { - return false; - } - switch (op) { - case EOpMul: - case EOpMulAssign: - // Mul not supported in NV_cooperative_matrix - if (left->getType().isCoopMatNV() && right->getType().isCoopMatNV()) { - return false; - } - // NV_cooperative_matrix supports MulAssign is for mat*=scalar only. - // KHR_cooperative_matrix supports it for mat*=mat as well. - if (op == EOpMulAssign && right->getType().isCoopMatNV()) { - return false; - } - // Use MatrixTimesScalar if either operand is not a matrix. Otherwise use Mul. - if (!left->getType().isCoopMat() || !right->getType().isCoopMat()) { - node.setOp(op == EOpMulAssign ? EOpMatrixTimesScalarAssign : EOpMatrixTimesScalar); - } - // In case of scalar*matrix, take the result type from the matrix. - if (right->getType().isCoopMat()) { - node.setType(right->getType()); - } - return true; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpAssign: - // These require both to be cooperative matrices - if (!left->getType().isCoopMat() || !right->getType().isCoopMat()) { - return false; - } - return true; - default: - break; - } - return false; - } - - // Finish handling the case, for all ops, where both operands are scalars. - if (left->isScalar() && right->isScalar()) - return true; - - // Finish handling the case, for all ops, where there are two vectors of different sizes - if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize() && right->getVectorSize() > 1) - return false; - - // - // We now have a mix of scalars, vectors, or matrices, for non-relational operations. - // - - // Can these two operands be combined, what is the resulting type? - TBasicType basicType = left->getBasicType(); - switch (op) { - case EOpMul: - if (!left->isMatrix() && right->isMatrix()) { - if (left->isVector()) { - if (left->getVectorSize() != right->getMatrixRows()) - return false; - node.setOp(op = EOpVectorTimesMatrix); - node.setType(TType(basicType, EvqTemporary, right->getMatrixCols())); - } else { - node.setOp(op = EOpMatrixTimesScalar); - node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), right->getMatrixRows())); - } - } else if (left->isMatrix() && !right->isMatrix()) { - if (right->isVector()) { - if (left->getMatrixCols() != right->getVectorSize()) - return false; - node.setOp(op = EOpMatrixTimesVector); - node.setType(TType(basicType, EvqTemporary, left->getMatrixRows())); - } else { - node.setOp(op = EOpMatrixTimesScalar); - } - } else if (left->isMatrix() && right->isMatrix()) { - if (left->getMatrixCols() != right->getMatrixRows()) - return false; - node.setOp(op = EOpMatrixTimesMatrix); - node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), left->getMatrixRows())); - } else if (! left->isMatrix() && ! right->isMatrix()) { - if (left->isVector() && right->isVector()) { - ; // leave as component product - } else if (left->isVector() || right->isVector()) { - node.setOp(op = EOpVectorTimesScalar); - if (right->isVector()) - node.setType(TType(basicType, EvqTemporary, right->getVectorSize())); - } - } else { - return false; - } - break; - case EOpMulAssign: - if (! left->isMatrix() && right->isMatrix()) { - if (left->isVector()) { - if (left->getVectorSize() != right->getMatrixRows() || left->getVectorSize() != right->getMatrixCols()) - return false; - node.setOp(op = EOpVectorTimesMatrixAssign); - } else { - return false; - } - } else if (left->isMatrix() && !right->isMatrix()) { - if (right->isVector()) { - return false; - } else { - node.setOp(op = EOpMatrixTimesScalarAssign); - } - } else if (left->isMatrix() && right->isMatrix()) { - if (left->getMatrixCols() != right->getMatrixCols() || left->getMatrixCols() != right->getMatrixRows()) - return false; - node.setOp(op = EOpMatrixTimesMatrixAssign); - } else if (!left->isMatrix() && !right->isMatrix()) { - if (left->isVector() && right->isVector()) { - // leave as component product - } else if (left->isVector() || right->isVector()) { - if (! left->isVector()) - return false; - node.setOp(op = EOpVectorTimesScalarAssign); - } - } else { - return false; - } - break; - - case EOpRightShift: - case EOpLeftShift: - case EOpRightShiftAssign: - case EOpLeftShiftAssign: - if (right->isVector() && (! left->isVector() || right->getVectorSize() != left->getVectorSize())) - return false; - break; - - case EOpAssign: - if (left->getVectorSize() != right->getVectorSize() || left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows()) - return false; - // fall through - - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMod: - case EOpAnd: - case EOpInclusiveOr: - case EOpExclusiveOr: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - case EOpModAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - - if ((left->isMatrix() && right->isVector()) || - (left->isVector() && right->isMatrix()) || - left->getBasicType() != right->getBasicType()) - return false; - if (left->isMatrix() && right->isMatrix() && (left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows())) - return false; - if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize()) - return false; - if (right->isVector() || right->isMatrix()) { - node.getWritableType().shallowCopy(right->getType()); - node.getWritableType().getQualifier().makeTemporary(); - } - break; - - default: - return false; - } - - // - // One more check for assignment. - // - switch (op) { - // The resulting type has to match the left operand. - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpDivAssign: - case EOpModAssign: - case EOpAndAssign: - case EOpInclusiveOrAssign: - case EOpExclusiveOrAssign: - case EOpLeftShiftAssign: - case EOpRightShiftAssign: - if (node.getType() != left->getType()) - return false; - break; - default: - break; - } - - return true; -} - -// -// See TIntermediate::promote -// -bool TIntermediate::promoteAggregate(TIntermAggregate& node) -{ - TOperator op = node.getOp(); - TIntermSequence& args = node.getSequence(); - const int numArgs = static_cast(args.size()); - - // Presently, only hlsl does intrinsic promotions. - if (getSource() != EShSourceHlsl) - return true; - - // set of opcodes that can be promoted in this manner. - switch (op) { - case EOpAtan: - case EOpClamp: - case EOpCross: - case EOpDistance: - case EOpDot: - case EOpDst: - case EOpFaceForward: - // case EOpFindMSB: TODO: - // case EOpFindLSB: TODO: - case EOpFma: - case EOpMod: - case EOpFrexp: - case EOpLdexp: - case EOpMix: - case EOpLit: - case EOpMax: - case EOpMin: - case EOpModf: - // case EOpGenMul: TODO: - case EOpPow: - case EOpReflect: - case EOpRefract: - // case EOpSinCos: TODO: - case EOpSmoothStep: - case EOpStep: - break; - default: - return true; - } - - // TODO: array and struct behavior - - // Try converting all nodes to the given node's type - TIntermSequence convertedArgs(numArgs, nullptr); - - // Try to convert all types to the nonConvArg type. - for (int nonConvArg = 0; nonConvArg < numArgs; ++nonConvArg) { - // Try converting all args to this arg's type - for (int convArg = 0; convArg < numArgs; ++convArg) { - convertedArgs[convArg] = addConversion(op, args[nonConvArg]->getAsTyped()->getType(), - args[convArg]->getAsTyped()); - } - - // If we successfully converted all the args, use the result. - if (std::all_of(convertedArgs.begin(), convertedArgs.end(), - [](const TIntermNode* node) { return node != nullptr; })) { - - std::swap(args, convertedArgs); - return true; - } - } - - return false; -} - -// Propagate precision qualifiers *up* from children to parent, and then -// back *down* again to the children's subtrees. -void TIntermAggregate::updatePrecision() -{ - if (getBasicType() == EbtInt || getBasicType() == EbtUint || - getBasicType() == EbtFloat) { - TPrecisionQualifier maxPrecision = EpqNone; - TIntermSequence operands = getSequence(); - for (unsigned int i = 0; i < operands.size(); ++i) { - TIntermTyped* typedNode = operands[i]->getAsTyped(); - assert(typedNode); - maxPrecision = std::max(maxPrecision, typedNode->getQualifier().precision); - } - getQualifier().precision = maxPrecision; - for (unsigned int i = 0; i < operands.size(); ++i) { - TIntermTyped* typedNode = operands[i]->getAsTyped(); - assert(typedNode); - typedNode->propagatePrecision(maxPrecision); - } - } -} - -// Propagate precision qualifiers *up* from children to parent, and then -// back *down* again to the children's subtrees. -void TIntermBinary::updatePrecision() -{ - if (getBasicType() == EbtInt || getBasicType() == EbtUint || - getBasicType() == EbtFloat) { - if (op == EOpRightShift || op == EOpLeftShift) { - // For shifts get precision from left side only and thus no need to propagate - getQualifier().precision = left->getQualifier().precision; - } else { - getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision); - if (getQualifier().precision != EpqNone) { - left->propagatePrecision(getQualifier().precision); - right->propagatePrecision(getQualifier().precision); - } - } - } -} - -// Recursively propagate precision qualifiers *down* the subtree of the current node, -// until reaching a node that already has a precision qualifier or otherwise does -// not participate in precision propagation. -void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision) -{ - if (getQualifier().precision != EpqNone || - (getBasicType() != EbtInt && getBasicType() != EbtUint && - getBasicType() != EbtFloat && getBasicType() != EbtFloat16)) - return; - - getQualifier().precision = newPrecision; - - TIntermBinary* binaryNode = getAsBinaryNode(); - if (binaryNode) { - binaryNode->getLeft()->propagatePrecision(newPrecision); - binaryNode->getRight()->propagatePrecision(newPrecision); - - return; - } - - TIntermUnary* unaryNode = getAsUnaryNode(); - if (unaryNode) { - unaryNode->getOperand()->propagatePrecision(newPrecision); - - return; - } - - TIntermAggregate* aggregateNode = getAsAggregate(); - if (aggregateNode) { - TIntermSequence operands = aggregateNode->getSequence(); - for (unsigned int i = 0; i < operands.size(); ++i) { - TIntermTyped* typedNode = operands[i]->getAsTyped(); - if (! typedNode) - break; - typedNode->propagatePrecision(newPrecision); - } - - return; - } - - TIntermSelection* selectionNode = getAsSelectionNode(); - if (selectionNode) { - TIntermTyped* typedNode = selectionNode->getTrueBlock()->getAsTyped(); - if (typedNode) { - typedNode->propagatePrecision(newPrecision); - typedNode = selectionNode->getFalseBlock()->getAsTyped(); - if (typedNode) - typedNode->propagatePrecision(newPrecision); - } - - return; - } -} - -TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) const -{ - const TConstUnionArray& rightUnionArray = node->getConstArray(); - int size = node->getType().computeNumComponents(); - - TConstUnionArray leftUnionArray(size); - - for (int i=0; i < size; i++) { - -#define PROMOTE(Set, CType, Get) leftUnionArray[i].Set(static_cast(rightUnionArray[i].Get())) -#define PROMOTE_TO_BOOL(Get) leftUnionArray[i].setBConst(rightUnionArray[i].Get() != 0) - -#define TO_ALL(Get) \ - switch (promoteTo) { \ - case EbtFloat16: PROMOTE(setDConst, double, Get); break; \ - case EbtFloat: PROMOTE(setDConst, double, Get); break; \ - case EbtDouble: PROMOTE(setDConst, double, Get); break; \ - case EbtInt8: PROMOTE(setI8Const, signed char, Get); break; \ - case EbtInt16: PROMOTE(setI16Const, short, Get); break; \ - case EbtInt: PROMOTE(setIConst, int, Get); break; \ - case EbtInt64: PROMOTE(setI64Const, long long, Get); break; \ - case EbtUint8: PROMOTE(setU8Const, unsigned char, Get); break; \ - case EbtUint16: PROMOTE(setU16Const, unsigned short, Get); break; \ - case EbtUint: PROMOTE(setUConst, unsigned int, Get); break; \ - case EbtUint64: PROMOTE(setU64Const, unsigned long long, Get); break; \ - case EbtBool: PROMOTE_TO_BOOL(Get); break; \ - default: return node; \ - } - - switch (node->getType().getBasicType()) { - case EbtFloat: TO_ALL(getDConst); break; - case EbtInt: TO_ALL(getIConst); break; - case EbtUint: TO_ALL(getUConst); break; - case EbtBool: TO_ALL(getBConst); break; - case EbtFloat16: TO_ALL(getDConst); break; - case EbtDouble: TO_ALL(getDConst); break; - case EbtInt8: TO_ALL(getI8Const); break; - case EbtInt16: TO_ALL(getI16Const); break; - case EbtInt64: TO_ALL(getI64Const); break; - case EbtUint8: TO_ALL(getU8Const); break; - case EbtUint16: TO_ALL(getU16Const); break; - case EbtUint64: TO_ALL(getU64Const); break; - default: return node; - } - } - - const TType& t = node->getType(); - - return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier().storage, t.getVectorSize(), t.getMatrixCols(), t.getMatrixRows()), - node->getLoc()); -} - -void TIntermAggregate::setPragmaTable(const TPragmaTable& pTable) -{ - assert(pragmaTable == nullptr); - pragmaTable = new TPragmaTable; - *pragmaTable = pTable; -} - -// If either node is a specialization constant, while the other is -// a constant (or specialization constant), the result is still -// a specialization constant. -bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TIntermTyped& node2) -{ - return (node1.getType().getQualifier().isSpecConstant() && node2.getType().getQualifier().isConstant()) || - (node2.getType().getQualifier().isSpecConstant() && node1.getType().getQualifier().isConstant()); -} - -struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser { - void visitSymbol(TIntermSymbol* symbol) override { - if (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isTexture()) { - symbol->getWritableType().getSampler().setCombined(true); - } - } - bool visitAggregate(TVisit, TIntermAggregate* ag) override { - using namespace std; - TIntermSequence& seq = ag->getSequence(); - TQualifierList& qual = ag->getQualifierList(); - - // qual and seq are indexed using the same indices, so we have to modify both in lock-step - assert(seq.size() == qual.size() || qual.empty()); - - size_t write = 0; - for (size_t i = 0; i < seq.size(); ++i) { - TIntermSymbol* symbol = seq[i]->getAsSymbolNode(); - if (symbol && symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isPureSampler()) { - // remove pure sampler variables - continue; - } - - TIntermNode* result = seq[i]; - - // replace constructors with sampler/textures - TIntermAggregate *constructor = seq[i]->getAsAggregate(); - if (constructor && constructor->getOp() == EOpConstructTextureSampler) { - if (!constructor->getSequence().empty()) - result = constructor->getSequence()[0]; - } - - // write new node & qualifier - seq[write] = result; - if (!qual.empty()) - qual[write] = qual[i]; - write++; - } - - seq.resize(write); - if (!qual.empty()) - qual.resize(write); - - return true; - } -}; - -void TIntermediate::performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root) -{ - TextureUpgradeAndSamplerRemovalTransform transform; - root->traverse(&transform); -} - -const char* TIntermediate::getResourceName(TResourceType res) -{ - switch (res) { - case EResSampler: return "shift-sampler-binding"; - case EResTexture: return "shift-texture-binding"; - case EResImage: return "shift-image-binding"; - case EResUbo: return "shift-UBO-binding"; - case EResSsbo: return "shift-ssbo-binding"; - case EResUav: return "shift-uav-binding"; - default: - assert(0); // internal error: should only be called with valid resource types. - return nullptr; - } -} - - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/LiveTraverser.h b/3rdparty/glslang/glslang/MachineIndependent/LiveTraverser.h deleted file mode 100644 index 9b39b598..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/LiveTraverser.h +++ /dev/null @@ -1,168 +0,0 @@ -// -// Copyright (C) 2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -#include "../Include/Common.h" -#include "reflection.h" -#include "localintermediate.h" - -#include "gl_types.h" - -#include -#include - -namespace glslang { - -// -// The traverser: mostly pass through, except -// - processing function-call nodes to push live functions onto the stack of functions to process -// - processing selection nodes to trim semantically dead code -// -// This is in the glslang namespace directly so it can be a friend of TReflection. -// This can be derived from to implement reflection database traversers or -// binding mappers: anything that wants to traverse the live subset of the tree. -// - -class TLiveTraverser : public TIntermTraverser { -public: - TLiveTraverser(const TIntermediate& i, bool traverseAll = false, - bool preVisit = true, bool inVisit = false, bool postVisit = false) : - TIntermTraverser(preVisit, inVisit, postVisit), - intermediate(i), traverseAll(traverseAll) - { } - - // - // Given a function name, find its subroot in the tree, and push it onto the stack of - // functions left to process. - // - void pushFunction(const TString& name) - { - TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence(); - for (unsigned int f = 0; f < globals.size(); ++f) { - TIntermAggregate* candidate = globals[f]->getAsAggregate(); - if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) { - destinations.push_back(candidate); - break; - } - } - } - - void pushGlobalReference(const TString& name) - { - TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence(); - for (unsigned int f = 0; f < globals.size(); ++f) { - TIntermAggregate* candidate = globals[f]->getAsAggregate(); - if (candidate && candidate->getOp() == EOpSequence && - candidate->getSequence().size() == 1 && - candidate->getSequence()[0]->getAsBinaryNode()) { - TIntermBinary* binary = candidate->getSequence()[0]->getAsBinaryNode(); - TIntermSymbol* symbol = binary->getLeft()->getAsSymbolNode(); - if (symbol && symbol->getQualifier().storage == EvqGlobal && - symbol->getName() == name) { - destinations.push_back(candidate); - break; - } - } - } - } - - typedef std::list TDestinationStack; - TDestinationStack destinations; - -protected: - // To catch which function calls are not dead, and hence which functions must be visited. - virtual bool visitAggregate(TVisit, TIntermAggregate* node) - { - if (!traverseAll) - if (node->getOp() == EOpFunctionCall) - addFunctionCall(node); - - return true; // traverse this subtree - } - - // To prune semantically dead paths. - virtual bool visitSelection(TVisit /* visit */, TIntermSelection* node) - { - if (traverseAll) - return true; // traverse all code - - TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion(); - if (constant) { - // cull the path that is dead - if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock()) - node->getTrueBlock()->traverse(this); - if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock()) - node->getFalseBlock()->traverse(this); - - return false; // don't traverse any more, we did it all above - } else - return true; // traverse the whole subtree - } - - // Track live functions as well as uniforms, so that we don't visit dead functions - // and only visit each function once. - void addFunctionCall(TIntermAggregate* call) - { - // just use the map to ensure we process each function at most once - if (liveFunctions.find(call->getName()) == liveFunctions.end()) { - liveFunctions.insert(call->getName()); - pushFunction(call->getName()); - } - } - - void addGlobalReference(const TString& name) - { - // just use the map to ensure we process each global at most once - if (liveGlobals.find(name) == liveGlobals.end()) { - liveGlobals.insert(name); - pushGlobalReference(name); - } - } - - const TIntermediate& intermediate; - typedef std::unordered_set TLiveFunctions; - TLiveFunctions liveFunctions; - typedef std::unordered_set TLiveGlobals; - TLiveGlobals liveGlobals; - bool traverseAll; - -private: - // prevent copy & copy construct - TLiveTraverser(TLiveTraverser&); - TLiveTraverser& operator=(TLiveTraverser&); -}; - -} // namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp b/3rdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp deleted file mode 100644 index 8e8bcd88..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/ParseContextBase.cpp +++ /dev/null @@ -1,750 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// Implement the TParseContextBase class. - -#include - -#include "ParseHelper.h" - -extern int yyparse(glslang::TParseContext*); - -namespace glslang { - -// -// Used to output syntax, parsing, and semantic errors. -// - -void TParseContextBase::outputMessage(const TSourceLoc& loc, const char* szReason, - const char* szToken, - const char* szExtraInfoFormat, - TPrefixType prefix, va_list args) -{ - const int maxSize = MaxTokenLength + 200; - char szExtraInfo[maxSize]; - - safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args); - - infoSink.info.prefix(prefix); - infoSink.info.location(loc); - infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n"; - - if (prefix == EPrefixError) { - ++numErrors; - } -} - -void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) -{ - if (messages & EShMsgOnlyPreprocessor) - return; - // If enhanced msg readability, only print one error - if (messages & EShMsgEnhanced && numErrors > 0) - return; - va_list args; - va_start(args, szExtraInfoFormat); - outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args); - va_end(args); - - if ((messages & EShMsgCascadingErrors) == 0) - currentScanner->setEndOfInput(); -} - -void C_DECL TParseContextBase::warn(const TSourceLoc& loc, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) -{ - if (suppressWarnings()) - return; - va_list args; - va_start(args, szExtraInfoFormat); - outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args); - va_end(args); -} - -void C_DECL TParseContextBase::ppError(const TSourceLoc& loc, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) -{ - va_list args; - va_start(args, szExtraInfoFormat); - outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args); - va_end(args); - - if ((messages & EShMsgCascadingErrors) == 0) - currentScanner->setEndOfInput(); -} - -void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) -{ - va_list args; - va_start(args, szExtraInfoFormat); - outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args); - va_end(args); -} - -// -// Both test and if necessary, spit out an error, to see if the node is really -// an l-value that can be operated on this way. -// -// Returns true if there was an error. -// -bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) -{ - TIntermBinary* binaryNode = node->getAsBinaryNode(); - - const char* symbol = nullptr; - TIntermSymbol* symNode = node->getAsSymbolNode(); - if (symNode != nullptr) - symbol = symNode->getName().c_str(); - - const char* message = nullptr; - switch (node->getQualifier().storage) { - case EvqConst: message = "can't modify a const"; break; - case EvqConstReadOnly: message = "can't modify a const"; break; - case EvqUniform: message = "can't modify a uniform"; break; - case EvqBuffer: - if (node->getQualifier().isReadOnly()) - message = "can't modify a readonly buffer"; - if (node->getQualifier().isShaderRecord()) - message = "can't modify a shaderrecordnv qualified buffer"; - break; - case EvqHitAttr: - if (language != EShLangIntersect) - message = "cannot modify hitAttributeNV in this stage"; - break; - - default: - // - // Type that can't be written to? - // - switch (node->getBasicType()) { - case EbtSampler: - if (extensionTurnedOn(E_GL_ARB_bindless_texture) == false) - message = "can't modify a sampler"; - break; - case EbtVoid: - message = "can't modify void"; - break; - case EbtAtomicUint: - message = "can't modify an atomic_uint"; - break; - case EbtAccStruct: - message = "can't modify accelerationStructureNV"; - break; - case EbtRayQuery: - message = "can't modify rayQueryEXT"; - break; - case EbtHitObjectNV: - message = "can't modify hitObjectNV"; - break; - default: - break; - } - } - - if (message == nullptr && binaryNode == nullptr && symNode == nullptr) { - error(loc, " l-value required", op, "", ""); - - return true; - } - - // - // Everything else is okay, no error. - // - if (message == nullptr) - { - if (binaryNode) { - switch (binaryNode->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: // fall through - case EOpIndexDirectStruct: // fall through - case EOpVectorSwizzle: - case EOpMatrixSwizzle: - return lValueErrorCheck(loc, op, binaryNode->getLeft()); - default: - break; - } - error(loc, " l-value required", op, "", ""); - - return true; - } - return false; - } - - // - // If we get here, we have an error and a message. - // - const TIntermTyped* leftMostTypeNode = TIntermediate::traverseLValueBase(node, true); - - if (symNode) - error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message); - else - if (binaryNode && binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct) - if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName())) - error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str(), message); - else - error(loc, " l-value required", op, "\"%s\" (%s)", leftMostTypeNode->getAsSymbolNode()->getName().c_str(), message); - else - error(loc, " l-value required", op, "(%s)", message); - - return true; -} - -// Test for and give an error if the node can't be read from. -void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) -{ - if (! node) - return; - - TIntermBinary* binaryNode = node->getAsBinaryNode(); - const TIntermSymbol* symNode = node->getAsSymbolNode(); - - if (node->getQualifier().isWriteOnly()) { - const TIntermTyped* leftMostTypeNode = TIntermediate::traverseLValueBase(node, true); - - if (symNode != nullptr) - error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str()); - else if (binaryNode && - (binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct || - binaryNode->getAsOperator()->getOp() == EOpIndexDirect)) - if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName())) - error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str()); - else - error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getName().c_str()); - else - error(loc, "can't read from writeonly object: ", op, ""); - - } else { - if (binaryNode) { - switch (binaryNode->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - case EOpVectorSwizzle: - case EOpMatrixSwizzle: - rValueErrorCheck(loc, op, binaryNode->getLeft()); - default: - break; - } - } - } -} - -// Add 'symbol' to the list of deferred linkage symbols, which -// are later processed in finish(), at which point the symbol -// must still be valid. -// It is okay if the symbol's type will be subsequently edited; -// the modifications will be tracked. -// Order is preserved, to avoid creating novel forward references. -void TParseContextBase::trackLinkage(TSymbol& symbol) -{ - if (!parsingBuiltins) - linkageSymbols.push_back(&symbol); -} - -// Ensure index is in bounds, correct if necessary. -// Give an error if not. -void TParseContextBase::checkIndex(const TSourceLoc& loc, const TType& type, int& index) -{ - const auto sizeIsSpecializationExpression = [&type]() { - return type.containsSpecializationSize() && - type.getArraySizes()->getOuterNode() != nullptr && - type.getArraySizes()->getOuterNode()->getAsSymbolNode() == nullptr; }; - - if (index < 0) { - error(loc, "", "[", "index out of range '%d'", index); - index = 0; - } else if (type.isArray()) { - if (type.isSizedArray() && !sizeIsSpecializationExpression() && - index >= type.getOuterArraySize()) { - error(loc, "", "[", "array index out of range '%d'", index); - index = type.getOuterArraySize() - 1; - } - } else if (type.isVector()) { - if (index >= type.getVectorSize()) { - error(loc, "", "[", "vector index out of range '%d'", index); - index = type.getVectorSize() - 1; - } - } else if (type.isMatrix()) { - if (index >= type.getMatrixCols()) { - error(loc, "", "[", "matrix index out of range '%d'", index); - index = type.getMatrixCols() - 1; - } - } -} - -// Make a shared symbol have a non-shared version that can be edited by the current -// compile, such that editing its type will not change the shared version and will -// effect all nodes already sharing it (non-shallow type), -// or adopting its full type after being edited (shallow type). -void TParseContextBase::makeEditable(TSymbol*& symbol) -{ - // copyUp() does a deep copy of the type. - symbol = symbolTable.copyUp(symbol); - - // Save it (deferred, so it can be edited first) in the AST for linker use. - if (symbol) - trackLinkage(*symbol); -} - -// Return a writable version of the variable 'name'. -// -// Return nullptr if 'name' is not found. This should mean -// something is seriously wrong (e.g., compiler asking self for -// built-in that doesn't exist). -TVariable* TParseContextBase::getEditableVariable(const char* name) -{ - bool builtIn; - TSymbol* symbol = symbolTable.find(name, &builtIn); - - assert(symbol != nullptr); - if (symbol == nullptr) - return nullptr; - - if (builtIn) - makeEditable(symbol); - - return symbol->getAsVariable(); -} - -// Select the best matching function for 'call' from 'candidateList'. -// -// Assumptions -// -// There is no exact match, so a selection algorithm needs to run. That is, the -// language-specific handler should check for exact match first, to -// decide what to do, before calling this selector. -// -// Input -// -// * list of candidate signatures to select from -// * the call -// * a predicate function convertible(from, to) that says whether or not type -// 'from' can implicitly convert to type 'to' (it includes the case of what -// the calling language would consider a matching type with no conversion -// needed) -// * a predicate function better(from1, from2, to1, to2) that says whether or -// not a conversion from <-> to2 is considered better than a conversion -// from <-> to1 (both in and out directions need testing, as declared by the -// formal parameter) -// -// Output -// -// * best matching candidate (or none, if no viable candidates found) -// * whether there was a tie for the best match (ambiguous overload selection, -// caller's choice for how to report) -// -const TFunction* TParseContextBase::selectFunction( - const TVector candidateList, - const TFunction& call, - std::function convertible, - std::function better, - /* output */ bool& tie) -{ -// -// Operation -// -// 1. Prune the input list of candidates down to a list of viable candidates, -// where each viable candidate has -// -// * at least as many parameters as there are calling arguments, with any -// remaining parameters being optional or having default values -// * each parameter is true under convertible(A, B), where A is the calling -// type for in and B is the formal type, and in addition, for out B is the -// calling type and A is the formal type -// -// 2. If there are no viable candidates, return with no match. -// -// 3. If there is only one viable candidate, it is the best match. -// -// 4. If there are multiple viable candidates, select the first viable candidate -// as the incumbent. Compare the incumbent to the next viable candidate, and if -// that candidate is better (bullets below), make it the incumbent. Repeat, with -// a linear walk through the viable candidate list. The final incumbent will be -// returned as the best match. A viable candidate is better than the incumbent if -// -// * it has a function argument with a better(...) conversion than the incumbent, -// for all directions needed by in and out -// * the incumbent has no argument with a better(...) conversion then the -// candidate, for either in or out (as needed) -// -// 5. Check for ambiguity by comparing the best match against all other viable -// candidates. If any other viable candidate has a function argument with a -// better(...) conversion than the best candidate (for either in or out -// directions), return that there was a tie for best. -// - - tie = false; - - // 1. prune to viable... - TVector viableCandidates; - for (auto it = candidateList.begin(); it != candidateList.end(); ++it) { - const TFunction& candidate = *(*it); - - // to even be a potential match, number of arguments must be >= the number of - // fixed (non-default) parameters, and <= the total (including parameter with defaults). - if (call.getParamCount() < candidate.getFixedParamCount() || - call.getParamCount() > candidate.getParamCount()) - continue; - - // see if arguments are convertible - bool viable = true; - - // The call can have fewer parameters than the candidate, if some have defaults. - const int paramCount = std::min(call.getParamCount(), candidate.getParamCount()); - for (int param = 0; param < paramCount; ++param) { - if (candidate[param].type->getQualifier().isParamInput()) { - if (! convertible(*call[param].type, *candidate[param].type, candidate.getBuiltInOp(), param)) { - viable = false; - break; - } - } - if (candidate[param].type->getQualifier().isParamOutput()) { - if (! convertible(*candidate[param].type, *call[param].type, candidate.getBuiltInOp(), param)) { - viable = false; - break; - } - } - } - - if (viable) - viableCandidates.push_back(&candidate); - } - - // 2. none viable... - if (viableCandidates.size() == 0) - return nullptr; - - // 3. only one viable... - if (viableCandidates.size() == 1) - return viableCandidates.front(); - - // 4. find best... - const auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool { - // is call -> can2 better than call -> can1 for any parameter - bool hasBetterParam = false; - for (int param = 0; param < call.getParamCount(); ++param) { - if (better(*call[param].type, *can1[param].type, *can2[param].type)) { - hasBetterParam = true; - break; - } - } - return hasBetterParam; - }; - - const auto equivalentParams = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool { - // is call -> can2 equivalent to call -> can1 for all the call parameters? - for (int param = 0; param < call.getParamCount(); ++param) { - if (better(*call[param].type, *can1[param].type, *can2[param].type) || - better(*call[param].type, *can2[param].type, *can1[param].type)) - return false; - } - return true; - }; - - const TFunction* incumbent = viableCandidates.front(); - for (auto it = viableCandidates.begin() + 1; it != viableCandidates.end(); ++it) { - const TFunction& candidate = *(*it); - if (betterParam(*incumbent, candidate) && ! betterParam(candidate, *incumbent)) - incumbent = &candidate; - } - - // 5. ambiguity... - for (auto it = viableCandidates.begin(); it != viableCandidates.end(); ++it) { - if (incumbent == *it) - continue; - const TFunction& candidate = *(*it); - - // In the case of default parameters, it may have an identical initial set, which is - // also ambiguous - if (betterParam(*incumbent, candidate) || equivalentParams(*incumbent, candidate)) - tie = true; - } - - return incumbent; -} - -// -// Look at a '.' field selector string and change it into numerical selectors -// for a vector or scalar. -// -// Always return some form of swizzle, so the result is always usable. -// -void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TString& compString, int vecSize, - TSwizzleSelectors& selector) -{ - // Too long? - if (compString.size() > MaxSwizzleSelectors) - error(loc, "vector swizzle too long", compString.c_str(), ""); - - // Use this to test that all swizzle characters are from the same swizzle-namespace-set - enum { - exyzw, - ergba, - estpq, - } fieldSet[MaxSwizzleSelectors]; - - // Decode the swizzle string. - int size = std::min(MaxSwizzleSelectors, (int)compString.size()); - for (int i = 0; i < size; ++i) { - switch (compString[i]) { - case 'x': - selector.push_back(0); - fieldSet[i] = exyzw; - break; - case 'r': - selector.push_back(0); - fieldSet[i] = ergba; - break; - case 's': - selector.push_back(0); - fieldSet[i] = estpq; - break; - - case 'y': - selector.push_back(1); - fieldSet[i] = exyzw; - break; - case 'g': - selector.push_back(1); - fieldSet[i] = ergba; - break; - case 't': - selector.push_back(1); - fieldSet[i] = estpq; - break; - - case 'z': - selector.push_back(2); - fieldSet[i] = exyzw; - break; - case 'b': - selector.push_back(2); - fieldSet[i] = ergba; - break; - case 'p': - selector.push_back(2); - fieldSet[i] = estpq; - break; - - case 'w': - selector.push_back(3); - fieldSet[i] = exyzw; - break; - case 'a': - selector.push_back(3); - fieldSet[i] = ergba; - break; - case 'q': - selector.push_back(3); - fieldSet[i] = estpq; - break; - - default: - error(loc, "unknown swizzle selection", compString.c_str(), ""); - break; - } - } - - // Additional error checking. - for (int i = 0; i < selector.size(); ++i) { - if (selector[i] >= vecSize) { - error(loc, "vector swizzle selection out of range", compString.c_str(), ""); - selector.resize(i); - break; - } - - if (i > 0 && fieldSet[i] != fieldSet[i-1]) { - error(loc, "vector swizzle selectors not from the same set", compString.c_str(), ""); - selector.resize(i); - break; - } - } - - // Ensure it is valid. - if (selector.size() == 0) - selector.push_back(0); -} - -// -// Make the passed-in variable information become a member of the -// global uniform block. If this doesn't exist yet, make it. -// -void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) -{ - // Make the global block, if not yet made. - if (globalUniformBlock == nullptr) { - TQualifier blockQualifier; - blockQualifier.clear(); - blockQualifier.storage = EvqUniform; - TType blockType(new TTypeList, *NewPoolTString(getGlobalUniformBlockName()), blockQualifier); - setUniformBlockDefaults(blockType); - globalUniformBlock = new TVariable(NewPoolTString(""), blockType, true); - firstNewMember = 0; - } - - // Update with binding and set - globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding; - globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet; - - // Check for declarations of this default uniform that already exist due to other compilation units. - TSymbol* symbol = symbolTable.find(memberName); - if (symbol) { - if (memberType != symbol->getType()) { - TString err; - err += "Redeclaration: already declared as \"" + symbol->getType().getCompleteString() + "\""; - error(loc, "", memberName.c_str(), err.c_str()); - } - return; - } - - // Add the requested member as a member to the global block. - TType* type = new TType; - type->shallowCopy(memberType); - type->setFieldName(memberName); - if (typeList) - type->setStruct(typeList); - TTypeLoc typeLoc = {type, loc}; - globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc); - - // Insert into the symbol table. - if (firstNewMember == 0) { - // This is the first request; we need a normal symbol table insert - if (symbolTable.insert(*globalUniformBlock)) - trackLinkage(*globalUniformBlock); - else - error(loc, "failed to insert the global constant buffer", "uniform", ""); - } else { - // This is a follow-on request; we need to amend the first insert - symbolTable.amend(*globalUniformBlock, firstNewMember); - } - - ++firstNewMember; -} - -void TParseContextBase::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) { - // Make the atomic counter block, if not yet made. - const auto &at = atomicCounterBuffers.find(binding); - if (at == atomicCounterBuffers.end()) { - atomicCounterBuffers.insert({binding, (TVariable*)nullptr }); - atomicCounterBlockFirstNewMember.insert({binding, 0}); - } - - TVariable*& atomicCounterBuffer = atomicCounterBuffers[binding]; - int& bufferNewMember = atomicCounterBlockFirstNewMember[binding]; - - if (atomicCounterBuffer == nullptr) { - TQualifier blockQualifier; - blockQualifier.clear(); - blockQualifier.storage = EvqBuffer; - - char charBuffer[512]; - if (binding != TQualifier::layoutBindingEnd) { - snprintf(charBuffer, 512, "%s_%d", getAtomicCounterBlockName(), binding); - } else { - snprintf(charBuffer, 512, "%s_0", getAtomicCounterBlockName()); - } - - TType blockType(new TTypeList, *NewPoolTString(charBuffer), blockQualifier); - setUniformBlockDefaults(blockType); - blockType.getQualifier().layoutPacking = ElpStd430; - atomicCounterBuffer = new TVariable(NewPoolTString(""), blockType, true); - // If we arn't auto mapping bindings then set the block to use the same - // binding as what the atomic was set to use - if (!intermediate.getAutoMapBindings()) { - atomicCounterBuffer->getWritableType().getQualifier().layoutBinding = binding; - } - bufferNewMember = 0; - - atomicCounterBuffer->getWritableType().getQualifier().layoutSet = atomicCounterBlockSet; - } - - // Add the requested member as a member to the global block. - TType* type = new TType; - type->shallowCopy(memberType); - type->setFieldName(memberName); - if (typeList) - type->setStruct(typeList); - TTypeLoc typeLoc = {type, loc}; - atomicCounterBuffer->getType().getWritableStruct()->push_back(typeLoc); - - // Insert into the symbol table. - if (bufferNewMember == 0) { - // This is the first request; we need a normal symbol table insert - if (symbolTable.insert(*atomicCounterBuffer)) - trackLinkage(*atomicCounterBuffer); - else - error(loc, "failed to insert the global constant buffer", "buffer", ""); - } else { - // This is a follow-on request; we need to amend the first insert - symbolTable.amend(*atomicCounterBuffer, bufferNewMember); - } - - ++bufferNewMember; -} - -void TParseContextBase::finish() -{ - if (parsingBuiltins) - return; - - for (const TString& relaxedSymbol : relaxedSymbols) - { - TSymbol* symbol = symbolTable.find(relaxedSymbol); - TType& type = symbol->getWritableType(); - for (const TTypeLoc& typeLoc : *type.getStruct()) - { - if (typeLoc.type->isOpaque()) - { - typeLoc.type->getSampler() = TSampler{}; - typeLoc.type->setBasicType(EbtInt); - TString fieldName("/*"); - fieldName.append(typeLoc.type->getFieldName()); - fieldName.append("*/"); - typeLoc.type->setFieldName(fieldName); - } - } - } - - // Transfer the linkage symbols to AST nodes, preserving order. - TIntermAggregate* linkage = new TIntermAggregate; - for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i) - intermediate.addSymbolLinkageNode(linkage, **i); - intermediate.addSymbolLinkageNodes(linkage, getLanguage(), symbolTable); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp deleted file mode 100644 index d9cb640b..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.cpp +++ /dev/null @@ -1,10061 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2015 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// Copyright (C) 2017, 2019 ARM Limited. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "ParseHelper.h" -#include "Initialize.h" -#include "Scan.h" - -#include "../OSDependent/osinclude.h" -#include - -#include "preprocessor/PpContext.h" - -extern int yyparse(glslang::TParseContext*); - -namespace glslang { - -TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, - int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, - TInfoSink& infoSink, bool forwardCompatible, EShMessages messages, - const TString* entryPoint) : - TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, - infoSink, forwardCompatible, messages, entryPoint), - inMain(false), - blockName(nullptr), - limits(resources.limits), - atomicUintOffsets(nullptr), anyIndexLimits(false) -{ - // decide whether precision qualifiers should be ignored or respected - if (isEsProfile() || spvVersion.vulkan > 0) { - precisionManager.respectPrecisionQualifiers(); - if (! parsingBuiltins && language == EShLangFragment && !isEsProfile() && spvVersion.vulkan > 0) - precisionManager.warnAboutDefaults(); - } - - setPrecisionDefaults(); - - globalUniformDefaults.clear(); - globalUniformDefaults.layoutMatrix = ElmColumnMajor; - globalUniformDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd140 : ElpShared; - - globalBufferDefaults.clear(); - globalBufferDefaults.layoutMatrix = ElmColumnMajor; - globalBufferDefaults.layoutPacking = spvVersion.spv != 0 ? ElpStd430 : ElpShared; - - globalInputDefaults.clear(); - globalOutputDefaults.clear(); - - globalSharedDefaults.clear(); - globalSharedDefaults.layoutMatrix = ElmColumnMajor; - globalSharedDefaults.layoutPacking = ElpStd430; - - // "Shaders in the transform - // feedback capturing mode have an initial global default of - // layout(xfb_buffer = 0) out;" - if (language == EShLangVertex || - language == EShLangTessControl || - language == EShLangTessEvaluation || - language == EShLangGeometry) - globalOutputDefaults.layoutXfbBuffer = 0; - - if (language == EShLangGeometry) - globalOutputDefaults.layoutStream = 0; - - if (entryPoint != nullptr && entryPoint->size() > 0 && *entryPoint != "main") - infoSink.info.message(EPrefixError, "Source entry point must be \"main\""); -} - -TParseContext::~TParseContext() -{ - delete [] atomicUintOffsets; -} - -// Set up all default precisions as needed by the current environment. -// Intended just as a TParseContext constructor helper. -void TParseContext::setPrecisionDefaults() -{ - // Set all precision defaults to EpqNone, which is correct for all types - // when not obeying precision qualifiers, and correct for types that don't - // have defaults (thus getting an error on use) when obeying precision - // qualifiers. - - for (int type = 0; type < EbtNumTypes; ++type) - defaultPrecision[type] = EpqNone; - - for (int type = 0; type < maxSamplerIndex; ++type) - defaultSamplerPrecision[type] = EpqNone; - - // replace with real precision defaults for those that have them - if (obeyPrecisionQualifiers()) { - if (isEsProfile()) { - // Most don't have defaults, a few default to lowp. - TSampler sampler; - sampler.set(EbtFloat, Esd2D); - defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; - sampler.set(EbtFloat, EsdCube); - defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; - sampler.set(EbtFloat, Esd2D); - sampler.setExternal(true); - defaultSamplerPrecision[computeSamplerTypeIndex(sampler)] = EpqLow; - } - - // If we are parsing built-in computational variables/functions, it is meaningful to record - // whether the built-in has no precision qualifier, as that ambiguity - // is used to resolve the precision from the supplied arguments/operands instead. - // So, we don't actually want to replace EpqNone with a default precision for built-ins. - if (! parsingBuiltins) { - if (isEsProfile() && language == EShLangFragment) { - defaultPrecision[EbtInt] = EpqMedium; - defaultPrecision[EbtUint] = EpqMedium; - } else { - defaultPrecision[EbtInt] = EpqHigh; - defaultPrecision[EbtUint] = EpqHigh; - defaultPrecision[EbtFloat] = EpqHigh; - } - - if (!isEsProfile()) { - // Non-ES profile - // All sampler precisions default to highp. - for (int type = 0; type < maxSamplerIndex; ++type) - defaultSamplerPrecision[type] = EpqHigh; - } - } - - defaultPrecision[EbtSampler] = EpqLow; - defaultPrecision[EbtAtomicUint] = EpqHigh; - } -} - -void TParseContext::setLimits(const TBuiltInResource& r) -{ - resources = r; - intermediate.setLimits(r); - - anyIndexLimits = ! limits.generalAttributeMatrixVectorIndexing || - ! limits.generalConstantMatrixVectorIndexing || - ! limits.generalSamplerIndexing || - ! limits.generalUniformIndexing || - ! limits.generalVariableIndexing || - ! limits.generalVaryingIndexing; - - - // "Each binding point tracks its own current default offset for - // inheritance of subsequent variables using the same binding. The initial state of compilation is that all - // binding points have an offset of 0." - atomicUintOffsets = new int[resources.maxAtomicCounterBindings]; - for (int b = 0; b < resources.maxAtomicCounterBindings; ++b) - atomicUintOffsets[b] = 0; -} - -// -// Parse an array of strings using yyparse, going through the -// preprocessor to tokenize the shader strings, then through -// the GLSL scanner. -// -// Returns true for successful acceptance of the shader, false if any errors. -// -bool TParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner& input, bool versionWillBeError) -{ - currentScanner = &input; - ppContext.setInput(input, versionWillBeError); - yyparse(this); - - finish(); - - return numErrors == 0; -} - -// This is called from bison when it has a parse (syntax) error -// Note though that to stop cascading errors, we set EOF, which -// will usually cause a syntax error, so be more accurate that -// compilation is terminating. -void TParseContext::parserError(const char* s) -{ - if (! getScanner()->atEndOfInput() || numErrors == 0) - error(getCurrentLoc(), "", "", s, ""); - else - error(getCurrentLoc(), "compilation terminated", "", ""); -} - -void TParseContext::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) -{ - bool createBlock = globalUniformBlock == nullptr; - - if (createBlock) { - globalUniformBinding = intermediate.getGlobalUniformBinding(); - globalUniformSet = intermediate.getGlobalUniformSet(); - } - - // use base class function to create/expand block - TParseContextBase::growGlobalUniformBlock(loc, memberType, memberName, typeList); - - if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) { - // check for a block storage override - TBlockStorageClass storageOverride = intermediate.getBlockStorageOverride(getGlobalUniformBlockName()); - TQualifier& qualifier = globalUniformBlock->getWritableType().getQualifier(); - qualifier.defaultBlock = true; - - if (storageOverride != EbsNone) { - if (createBlock) { - // Remap block storage - qualifier.setBlockStorage(storageOverride); - - // check that the change didn't create errors - blockQualifierCheck(loc, qualifier, false); - } - - // remap meber storage as well - memberType.getQualifier().setBlockStorage(storageOverride); - } - } -} - -void TParseContext::growAtomicCounterBlock(int binding, const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) -{ - bool createBlock = atomicCounterBuffers.find(binding) == atomicCounterBuffers.end(); - - if (createBlock) { - atomicCounterBlockSet = intermediate.getAtomicCounterBlockSet(); - } - - // use base class function to create/expand block - TParseContextBase::growAtomicCounterBlock(binding, loc, memberType, memberName, typeList); - TQualifier& qualifier = atomicCounterBuffers[binding]->getWritableType().getQualifier(); - qualifier.defaultBlock = true; - - if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) { - // check for a Block storage override - TBlockStorageClass storageOverride = intermediate.getBlockStorageOverride(getAtomicCounterBlockName()); - - if (storageOverride != EbsNone) { - if (createBlock) { - // Remap block storage - - qualifier.setBlockStorage(storageOverride); - - // check that the change didn't create errors - blockQualifierCheck(loc, qualifier, false); - } - - // remap meber storage as well - memberType.getQualifier().setBlockStorage(storageOverride); - } - } -} - -const char* TParseContext::getGlobalUniformBlockName() const -{ - const char* name = intermediate.getGlobalUniformBlockName(); - if (std::string(name) == "") - return "gl_DefaultUniformBlock"; - else - return name; -} -void TParseContext::finalizeGlobalUniformBlockLayout(TVariable&) -{ -} -void TParseContext::setUniformBlockDefaults(TType& block) const -{ - block.getQualifier().layoutPacking = ElpStd140; - block.getQualifier().layoutMatrix = ElmColumnMajor; -} - - -const char* TParseContext::getAtomicCounterBlockName() const -{ - const char* name = intermediate.getAtomicCounterBlockName(); - if (std::string(name) == "") - return "gl_AtomicCounterBlock"; - else - return name; -} -void TParseContext::finalizeAtomicCounterBlockLayout(TVariable&) -{ -} - -void TParseContext::setAtomicCounterBlockDefaults(TType& block) const -{ - block.getQualifier().layoutPacking = ElpStd430; - block.getQualifier().layoutMatrix = ElmRowMajor; -} - -void TParseContext::setInvariant(const TSourceLoc& loc, const char* builtin) { - TSymbol* symbol = symbolTable.find(builtin); - if (symbol && symbol->getType().getQualifier().isPipeOutput()) { - if (intermediate.inIoAccessed(builtin)) - warn(loc, "changing qualification after use", "invariant", builtin); - TSymbol* csymbol = symbolTable.copyUp(symbol); - csymbol->getWritableType().getQualifier().invariant = true; - } -} - -void TParseContext::handlePragma(const TSourceLoc& loc, const TVector& tokens) -{ - if (pragmaCallback) - pragmaCallback(loc.line, tokens); - - if (tokens.size() == 0) - return; - - if (tokens[0].compare("optimize") == 0) { - if (tokens.size() != 4) { - error(loc, "optimize pragma syntax is incorrect", "#pragma", ""); - return; - } - - if (tokens[1].compare("(") != 0) { - error(loc, "\"(\" expected after 'optimize' keyword", "#pragma", ""); - return; - } - - if (tokens[2].compare("on") == 0) - contextPragma.optimize = true; - else if (tokens[2].compare("off") == 0) - contextPragma.optimize = false; - else { - if(relaxedErrors()) - // If an implementation does not recognize the tokens following #pragma, then it will ignore that pragma. - warn(loc, "\"on\" or \"off\" expected after '(' for 'optimize' pragma", "#pragma", ""); - return; - } - - if (tokens[3].compare(")") != 0) { - error(loc, "\")\" expected to end 'optimize' pragma", "#pragma", ""); - return; - } - } else if (tokens[0].compare("debug") == 0) { - if (tokens.size() != 4) { - error(loc, "debug pragma syntax is incorrect", "#pragma", ""); - return; - } - - if (tokens[1].compare("(") != 0) { - error(loc, "\"(\" expected after 'debug' keyword", "#pragma", ""); - return; - } - - if (tokens[2].compare("on") == 0) - contextPragma.debug = true; - else if (tokens[2].compare("off") == 0) - contextPragma.debug = false; - else { - if(relaxedErrors()) - // If an implementation does not recognize the tokens following #pragma, then it will ignore that pragma. - warn(loc, "\"on\" or \"off\" expected after '(' for 'debug' pragma", "#pragma", ""); - return; - } - - if (tokens[3].compare(")") != 0) { - error(loc, "\")\" expected to end 'debug' pragma", "#pragma", ""); - return; - } - } else if (spvVersion.spv > 0 && tokens[0].compare("use_storage_buffer") == 0) { - if (tokens.size() != 1) - error(loc, "extra tokens", "#pragma", ""); - intermediate.setUseStorageBuffer(); - } else if (spvVersion.spv > 0 && tokens[0].compare("use_vulkan_memory_model") == 0) { - if (tokens.size() != 1) - error(loc, "extra tokens", "#pragma", ""); - intermediate.setUseVulkanMemoryModel(); - } else if (spvVersion.spv > 0 && tokens[0].compare("use_variable_pointers") == 0) { - if (tokens.size() != 1) - error(loc, "extra tokens", "#pragma", ""); - if (spvVersion.spv < glslang::EShTargetSpv_1_3) - error(loc, "requires SPIR-V 1.3", "#pragma use_variable_pointers", ""); - intermediate.setUseVariablePointers(); - } else if (tokens[0].compare("once") == 0) { - warn(loc, "not implemented", "#pragma once", ""); - } else if (tokens[0].compare("glslang_binary_double_output") == 0) { - intermediate.setBinaryDoubleOutput(); - } else if (spvVersion.spv > 0 && tokens[0].compare("STDGL") == 0 && - tokens[1].compare("invariant") == 0 && tokens[3].compare("all") == 0) { - intermediate.setInvariantAll(); - // Set all builtin out variables invariant if declared - setInvariant(loc, "gl_Position"); - setInvariant(loc, "gl_PointSize"); - setInvariant(loc, "gl_ClipDistance"); - setInvariant(loc, "gl_CullDistance"); - setInvariant(loc, "gl_TessLevelOuter"); - setInvariant(loc, "gl_TessLevelInner"); - setInvariant(loc, "gl_PrimitiveID"); - setInvariant(loc, "gl_Layer"); - setInvariant(loc, "gl_ViewportIndex"); - setInvariant(loc, "gl_FragDepth"); - setInvariant(loc, "gl_SampleMask"); - setInvariant(loc, "gl_ClipVertex"); - setInvariant(loc, "gl_FrontColor"); - setInvariant(loc, "gl_BackColor"); - setInvariant(loc, "gl_FrontSecondaryColor"); - setInvariant(loc, "gl_BackSecondaryColor"); - setInvariant(loc, "gl_TexCoord"); - setInvariant(loc, "gl_FogFragCoord"); - setInvariant(loc, "gl_FragColor"); - setInvariant(loc, "gl_FragData"); - } -} - -// -// Handle seeing a variable identifier in the grammar. -// -TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symbol, const TString* string) -{ - TIntermTyped* node = nullptr; - - // Error check for requiring specific extensions present. - if (symbol && symbol->getNumExtensions()) - requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str()); - - if (symbol && symbol->isReadOnly()) { - // All shared things containing an unsized array must be copied up - // on first use, so that all future references will share its array structure, - // so that editing the implicit size will effect all nodes consuming it, - // and so that editing the implicit size won't change the shared one. - // - // If this is a variable or a block, check it and all it contains, but if this - // is a member of an anonymous block, check the whole block, as the whole block - // will need to be copied up if it contains an unsized array. - // - // This check is being done before the block-name check further down, so guard - // for that too. - if (!symbol->getType().isUnusableName()) { - if (symbol->getType().containsUnsizedArray() || - (symbol->getAsAnonMember() && - symbol->getAsAnonMember()->getAnonContainer().getType().containsUnsizedArray())) - makeEditable(symbol); - } - } - - const TVariable* variable; - const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : nullptr; - if (anon) { - // It was a member of an anonymous container. - - // Create a subtree for its dereference. - variable = anon->getAnonContainer().getAsVariable(); - TIntermTyped* container = intermediate.addSymbol(*variable, loc); - TIntermTyped* constNode = intermediate.addConstantUnion(anon->getMemberNumber(), loc); - node = intermediate.addIndex(EOpIndexDirectStruct, container, constNode, loc); - - node->setType(*(*variable->getType().getStruct())[anon->getMemberNumber()].type); - if (node->getType().hiddenMember()) - error(loc, "member of nameless block was not redeclared", string->c_str(), ""); - } else { - // Not a member of an anonymous container. - - // The symbol table search was done in the lexical phase. - // See if it was a variable. - variable = symbol ? symbol->getAsVariable() : nullptr; - if (variable) { - if (variable->getType().isUnusableName()) { - error(loc, "cannot be used (maybe an instance name is needed)", string->c_str(), ""); - variable = nullptr; - } - - if (language == EShLangMesh && variable) { - TLayoutGeometry primitiveType = intermediate.getOutputPrimitive(); - if ((variable->getMangledName() == "gl_PrimitiveTriangleIndicesEXT" && primitiveType != ElgTriangles) || - (variable->getMangledName() == "gl_PrimitiveLineIndicesEXT" && primitiveType != ElgLines) || - (variable->getMangledName() == "gl_PrimitivePointIndicesEXT" && primitiveType != ElgPoints)) { - error(loc, "cannot be used (ouput primitive type mismatch)", string->c_str(), ""); - variable = nullptr; - } - } - } else { - if (symbol) - error(loc, "variable name expected", string->c_str(), ""); - } - - // Recovery, if it wasn't found or was not a variable. - if (! variable) - variable = new TVariable(string, TType(EbtVoid)); - - if (variable->getType().getQualifier().isFrontEndConstant()) - node = intermediate.addConstantUnion(variable->getConstArray(), variable->getType(), loc); - else - node = intermediate.addSymbol(*variable, loc); - } - - if (variable->getType().getQualifier().isIo()) - intermediate.addIoAccessed(*string); - - if (variable->getType().isReference() && - variable->getType().getQualifier().bufferReferenceNeedsVulkanMemoryModel()) { - intermediate.setUseVulkanMemoryModel(); - } - - return node; -} - -// -// Handle seeing a base[index] dereference in the grammar. -// -TIntermTyped* TParseContext::handleBracketDereference(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index) -{ - int indexValue = 0; - if (index->getQualifier().isFrontEndConstant()) - indexValue = index->getAsConstantUnion()->getConstArray()[0].getIConst(); - - // basic type checks... - variableCheck(base); - - if (! base->isArray() && ! base->isMatrix() && ! base->isVector() && ! base->getType().isCoopMat() && - ! base->isReference()) { - if (base->getAsSymbolNode()) - error(loc, " left of '[' is not of type array, matrix, or vector ", base->getAsSymbolNode()->getName().c_str(), ""); - else - error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", ""); - - // Insert dummy error-recovery result - return intermediate.addConstantUnion(0.0, EbtFloat, loc); - } - - if (!base->isArray() && base->isVector()) { - if (base->getType().contains16BitFloat()) - requireFloat16Arithmetic(loc, "[", "does not operate on types containing float16"); - if (base->getType().contains16BitInt()) - requireInt16Arithmetic(loc, "[", "does not operate on types containing (u)int16"); - if (base->getType().contains8BitInt()) - requireInt8Arithmetic(loc, "[", "does not operate on types containing (u)int8"); - } - - // check for constant folding - if (base->getType().getQualifier().isFrontEndConstant() && index->getQualifier().isFrontEndConstant()) { - // both base and index are front-end constants - checkIndex(loc, base->getType(), indexValue); - return intermediate.foldDereference(base, indexValue, loc); - } - - // at least one of base and index is not a front-end constant variable... - TIntermTyped* result = nullptr; - - if (base->isReference() && ! base->isArray()) { - requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference indexing"); - if (base->getType().getReferentType()->containsUnsizedArray()) { - error(loc, "cannot index reference to buffer containing an unsized array", "", ""); - result = nullptr; - } else { - result = intermediate.addBinaryMath(EOpAdd, base, index, loc); - if (result != nullptr) - result->setType(base->getType()); - } - if (result == nullptr) { - error(loc, "cannot index buffer reference", "", ""); - result = intermediate.addConstantUnion(0.0, EbtFloat, loc); - } - return result; - } - if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) - handleIoResizeArrayAccess(loc, base); - - if (index->getQualifier().isFrontEndConstant()) - checkIndex(loc, base->getType(), indexValue); - - if (index->getQualifier().isFrontEndConstant()) { - if (base->getType().isUnsizedArray()) { - base->getWritableType().updateImplicitArraySize(indexValue + 1); - base->getWritableType().setImplicitlySized(true); - if (base->getQualifier().builtIn == EbvClipDistance && - indexValue >= resources.maxClipDistances) { - error(loc, "gl_ClipDistance", "[", "array index out of range '%d'", indexValue); - } - else if (base->getQualifier().builtIn == EbvCullDistance && - indexValue >= resources.maxCullDistances) { - error(loc, "gl_CullDistance", "[", "array index out of range '%d'", indexValue); - } - // For 2D per-view builtin arrays, update the inner dimension size in parent type - if (base->getQualifier().isPerView() && base->getQualifier().builtIn != EbvNone) { - TIntermBinary* binaryNode = base->getAsBinaryNode(); - if (binaryNode) { - TType& leftType = binaryNode->getLeft()->getWritableType(); - TArraySizes& arraySizes = *leftType.getArraySizes(); - assert(arraySizes.getNumDims() == 2); - arraySizes.setDimSize(1, std::max(arraySizes.getDimSize(1), indexValue + 1)); - } - } - } else - checkIndex(loc, base->getType(), indexValue); - result = intermediate.addIndex(EOpIndexDirect, base, index, loc); - } else { - if (base->getType().isUnsizedArray()) { - // we have a variable index into an unsized array, which is okay, - // depending on the situation - if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) - error(loc, "", "[", "array must be sized by a redeclaration or layout qualifier before being indexed with a variable"); - else { - // it is okay for a run-time sized array - checkRuntimeSizable(loc, *base); - } - base->getWritableType().setArrayVariablyIndexed(); - } - if (base->getBasicType() == EbtBlock) { - if (base->getQualifier().storage == EvqBuffer) - requireProfile(base->getLoc(), ~EEsProfile, "variable indexing buffer block array"); - else if (base->getQualifier().storage == EvqUniform) - profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, - "variable indexing uniform block array"); - else { - // input/output blocks either don't exist or can't be variably indexed - } - } else if (language == EShLangFragment && base->getQualifier().isPipeOutput()) - requireProfile(base->getLoc(), ~EEsProfile, "variable indexing fragment shader output array"); - else if (base->getBasicType() == EbtSampler && version >= 130) { - const char* explanation = "variable indexing sampler array"; - requireProfile(base->getLoc(), EEsProfile | ECoreProfile | ECompatibilityProfile, explanation); - profileRequires(base->getLoc(), EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, explanation); - profileRequires(base->getLoc(), ECoreProfile | ECompatibilityProfile, 400, nullptr, explanation); - } - - result = intermediate.addIndex(EOpIndexIndirect, base, index, loc); - } - - // Insert valid dereferenced result type - TType newType(base->getType(), 0); - if (base->getType().getQualifier().isConstant() && index->getQualifier().isConstant()) { - newType.getQualifier().storage = EvqConst; - // If base or index is a specialization constant, the result should also be a specialization constant. - if (base->getType().getQualifier().isSpecConstant() || index->getQualifier().isSpecConstant()) { - newType.getQualifier().makeSpecConstant(); - } - } else { - newType.getQualifier().storage = EvqTemporary; - newType.getQualifier().specConstant = false; - } - result->setType(newType); - - inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier()); - - // Propagate nonuniform - if (base->getQualifier().isNonUniform() || index->getQualifier().isNonUniform()) - result->getWritableType().getQualifier().nonUniform = true; - - if (anyIndexLimits) - handleIndexLimits(loc, base, index); - - return result; -} - -// for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms -void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* base, TIntermTyped* index) -{ - if ((! limits.generalSamplerIndexing && base->getBasicType() == EbtSampler) || - (! limits.generalUniformIndexing && base->getQualifier().isUniformOrBuffer() && language != EShLangVertex) || - (! limits.generalAttributeMatrixVectorIndexing && base->getQualifier().isPipeInput() && language == EShLangVertex && (base->getType().isMatrix() || base->getType().isVector())) || - (! limits.generalConstantMatrixVectorIndexing && base->getAsConstantUnion()) || - (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniformOrBuffer() && - ! base->getType().getQualifier().isPipeInput() && - ! base->getType().getQualifier().isPipeOutput() && - ! base->getType().getQualifier().isConstant()) || - (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() || - base->getType().getQualifier().isPipeOutput()))) { - // it's too early to know what the inductive variables are, save it for post processing - needsIndexLimitationChecking.push_back(index); - } -} - -// Make a shared symbol have a non-shared version that can be edited by the current -// compile, such that editing its type will not change the shared version and will -// effect all nodes sharing it. -void TParseContext::makeEditable(TSymbol*& symbol) -{ - TParseContextBase::makeEditable(symbol); - - // See if it's tied to IO resizing - if (isIoResizeArray(symbol->getType())) - ioArraySymbolResizeList.push_back(symbol); -} - -// Return true if this is a geometry shader input array or tessellation control output array -// or mesh shader output array. -bool TParseContext::isIoResizeArray(const TType& type) const -{ - return type.isArray() && - ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || - (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && - ! type.getQualifier().patch) || - (language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn && - (type.getQualifier().pervertexNV || type.getQualifier().pervertexEXT)) || - (language == EShLangMesh && type.getQualifier().storage == EvqVaryingOut && - !type.getQualifier().perTaskNV)); -} - -// If an array is not isIoResizeArray() but is an io array, make sure it has the right size -void TParseContext::fixIoArraySize(const TSourceLoc& loc, TType& type) -{ - if (! type.isArray() || type.getQualifier().patch || symbolTable.atBuiltInLevel()) - return; - - assert(! isIoResizeArray(type)); - - if (type.getQualifier().storage != EvqVaryingIn || type.getQualifier().patch) - return; - - if (language == EShLangTessControl || language == EShLangTessEvaluation) { - if (type.getOuterArraySize() != resources.maxPatchVertices) { - if (type.isSizedArray()) - error(loc, "tessellation input array size must be gl_MaxPatchVertices or implicitly sized", "[]", ""); - type.changeOuterArraySize(resources.maxPatchVertices); - } - } -} - -// Issue any errors if the non-array object is missing arrayness WRT -// shader I/O that has array requirements. -// All arrayness checking is handled in array paths, this is for -void TParseContext::ioArrayCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) -{ - if (! type.isArray() && ! symbolTable.atBuiltInLevel()) { - if (type.getQualifier().isArrayedIo(language) && !type.getQualifier().layoutPassthrough) - error(loc, "type must be an array:", type.getStorageQualifierString(), identifier.c_str()); - } -} - -// Handle a dereference of a geometry shader input array or tessellation control output array. -// See ioArraySymbolResizeList comment in ParseHelper.h. -// -void TParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TIntermTyped* base) -{ - TIntermSymbol* symbolNode = base->getAsSymbolNode(); - assert(symbolNode); - if (! symbolNode) - return; - - // fix array size, if it can be fixed and needs to be fixed (will allow variable indexing) - if (symbolNode->getType().isUnsizedArray()) { - int newSize = getIoArrayImplicitSize(symbolNode->getType().getQualifier()); - if (newSize > 0) - symbolNode->getWritableType().changeOuterArraySize(newSize); - } -} - -// If there has been an input primitive declaration (geometry shader) or an output -// number of vertices declaration(tessellation shader), make sure all input array types -// match it in size. Types come either from nodes in the AST or symbols in the -// symbol table. -// -// Types without an array size will be given one. -// Types already having a size that is wrong will get an error. -// -void TParseContext::checkIoArraysConsistency(const TSourceLoc &loc, bool tailOnly) -{ - int requiredSize = 0; - TString featureString; - size_t listSize = ioArraySymbolResizeList.size(); - size_t i = 0; - - // If tailOnly = true, only check the last array symbol in the list. - if (tailOnly) { - i = listSize - 1; - } - for (bool firstIteration = true; i < listSize; ++i) { - TType &type = ioArraySymbolResizeList[i]->getWritableType(); - - // As I/O array sizes don't change, fetch requiredSize only once, - // except for mesh shaders which could have different I/O array sizes based on type qualifiers. - if (firstIteration || (language == EShLangMesh)) { - requiredSize = getIoArrayImplicitSize(type.getQualifier(), &featureString); - if (requiredSize == 0) - break; - firstIteration = false; - } - - checkIoArrayConsistency(loc, requiredSize, featureString.c_str(), type, - ioArraySymbolResizeList[i]->getName()); - } -} - -int TParseContext::getIoArrayImplicitSize(const TQualifier &qualifier, TString *featureString) const -{ - int expectedSize = 0; - TString str = "unknown"; - unsigned int maxVertices = intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0; - - if (language == EShLangGeometry) { - expectedSize = TQualifier::mapGeometryToSize(intermediate.getInputPrimitive()); - str = TQualifier::getGeometryString(intermediate.getInputPrimitive()); - } - else if (language == EShLangTessControl) { - expectedSize = maxVertices; - str = "vertices"; - } else if (language == EShLangFragment) { - // Number of vertices for Fragment shader is always three. - expectedSize = 3; - str = "vertices"; - } else if (language == EShLangMesh) { - unsigned int maxPrimitives = - intermediate.getPrimitives() != TQualifier::layoutNotSet ? intermediate.getPrimitives() : 0; - if (qualifier.builtIn == EbvPrimitiveIndicesNV) { - expectedSize = maxPrimitives * TQualifier::mapGeometryToSize(intermediate.getOutputPrimitive()); - str = "max_primitives*"; - str += TQualifier::getGeometryString(intermediate.getOutputPrimitive()); - } - else if (qualifier.builtIn == EbvPrimitiveTriangleIndicesEXT || qualifier.builtIn == EbvPrimitiveLineIndicesEXT || - qualifier.builtIn == EbvPrimitivePointIndicesEXT) { - expectedSize = maxPrimitives; - str = "max_primitives"; - } - else if (qualifier.isPerPrimitive()) { - expectedSize = maxPrimitives; - str = "max_primitives"; - } - else { - expectedSize = maxVertices; - str = "max_vertices"; - } - } - if (featureString) - *featureString = str; - return expectedSize; -} - -void TParseContext::checkIoArrayConsistency(const TSourceLoc& loc, int requiredSize, const char* feature, TType& type, const TString& name) -{ - if (type.isUnsizedArray()) - type.changeOuterArraySize(requiredSize); - else if (type.getOuterArraySize() != requiredSize) { - if (language == EShLangGeometry) - error(loc, "inconsistent input primitive for array size of", feature, name.c_str()); - else if (language == EShLangTessControl) - error(loc, "inconsistent output number of vertices for array size of", feature, name.c_str()); - else if (language == EShLangFragment) { - if (type.getOuterArraySize() > requiredSize) - error(loc, " cannot be greater than 3 for pervertexEXT", feature, name.c_str()); - } - else if (language == EShLangMesh) - error(loc, "inconsistent output array size of", feature, name.c_str()); - else - assert(0); - } -} - -// Handle seeing a binary node with a math operation. -// Returns nullptr if not semantically allowed. -TIntermTyped* TParseContext::handleBinaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right) -{ - rValueErrorCheck(loc, str, left->getAsTyped()); - rValueErrorCheck(loc, str, right->getAsTyped()); - - bool allowed = true; - switch (op) { - // TODO: Bring more source language-specific checks up from intermediate.cpp - // to the specific parse helpers for that source language. - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if (! left->isScalar() || ! right->isScalar()) - allowed = false; - break; - default: - break; - } - - if (((left->getType().contains16BitFloat() || right->getType().contains16BitFloat()) && !float16Arithmetic()) || - ((left->getType().contains16BitInt() || right->getType().contains16BitInt()) && !int16Arithmetic()) || - ((left->getType().contains8BitInt() || right->getType().contains8BitInt()) && !int8Arithmetic())) { - allowed = false; - } - - TIntermTyped* result = nullptr; - if (allowed) { - if ((left->isReference() || right->isReference())) - requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "buffer reference math"); - result = intermediate.addBinaryMath(op, left, right, loc); - } - - if (result == nullptr) { - bool enhanced = intermediate.getEnhancedMsgs(); - binaryOpError(loc, str, left->getCompleteString(enhanced), right->getCompleteString(enhanced)); - } - - return result; -} - -// Handle seeing a unary node with a math operation. -TIntermTyped* TParseContext::handleUnaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* childNode) -{ - rValueErrorCheck(loc, str, childNode); - - bool allowed = true; - if ((childNode->getType().contains16BitFloat() && !float16Arithmetic()) || - (childNode->getType().contains16BitInt() && !int16Arithmetic()) || - (childNode->getType().contains8BitInt() && !int8Arithmetic())) { - allowed = false; - } - - TIntermTyped* result = nullptr; - if (allowed) - result = intermediate.addUnaryMath(op, childNode, loc); - - if (result) - return result; - else { - bool enhanced = intermediate.getEnhancedMsgs(); - unaryOpError(loc, str, childNode->getCompleteString(enhanced)); - } - - return childNode; -} - -// -// Handle seeing a base.field dereference in the grammar. -// -TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TIntermTyped* base, const TString& field) -{ - variableCheck(base); - - // - // .length() can't be resolved until we later see the function-calling syntax. - // Save away the name in the AST for now. Processing is completed in - // handleLengthMethod(). - // - if (field == "length") { - if (base->isArray()) { - profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, ".length"); - profileRequires(loc, EEsProfile, 300, nullptr, ".length"); - } else if (base->isVector() || base->isMatrix()) { - const char* feature = ".length() on vectors and matrices"; - requireProfile(loc, ~EEsProfile, feature); - profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, feature); - } else if (!base->getType().isCoopMat()) { - bool enhanced = intermediate.getEnhancedMsgs(); - error(loc, "does not operate on this type:", field.c_str(), base->getType().getCompleteString(enhanced).c_str()); - return base; - } - - return intermediate.addMethod(base, TType(EbtInt), &field, loc); - } - - // It's not .length() if we get to here. - - if (base->isArray()) { - error(loc, "cannot apply to an array:", ".", field.c_str()); - - return base; - } - - if (base->getType().isCoopMat()) { - error(loc, "cannot apply to a cooperative matrix type:", ".", field.c_str()); - return base; - } - - // It's neither an array nor .length() if we get here, - // leaving swizzles and struct/block dereferences. - - TIntermTyped* result = base; - if ((base->isVector() || base->isScalar()) && - (base->isFloatingDomain() || base->isIntegerDomain() || base->getBasicType() == EbtBool)) { - result = handleDotSwizzle(loc, base, field); - } else if (base->isStruct() || base->isReference()) { - const TTypeList* fields = base->isReference() ? - base->getType().getReferentType()->getStruct() : - base->getType().getStruct(); - bool fieldFound = false; - int member; - for (member = 0; member < (int)fields->size(); ++member) { - if ((*fields)[member].type->getFieldName() == field) { - fieldFound = true; - break; - } - } - - if (fieldFound) { - if (spvVersion.vulkan != 0 && spvVersion.vulkanRelaxed) - result = vkRelaxedRemapDotDereference(loc, *base, *(*fields)[member].type, field); - - if (result == base) - { - if (base->getType().getQualifier().isFrontEndConstant()) - result = intermediate.foldDereference(base, member, loc); - else { - blockMemberExtensionCheck(loc, base, member, field); - TIntermTyped* index = intermediate.addConstantUnion(member, loc); - result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc); - result->setType(*(*fields)[member].type); - if ((*fields)[member].type->getQualifier().isIo()) - intermediate.addIoAccessed(field); - } - } - - inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier()); - } else { - auto baseSymbol = base; - while (baseSymbol->getAsSymbolNode() == nullptr) { - auto binaryNode = baseSymbol->getAsBinaryNode(); - if (binaryNode == nullptr) break; - baseSymbol = binaryNode->getLeft(); - } - if (baseSymbol->getAsSymbolNode() != nullptr) { - TString structName; - structName.append("\'").append(baseSymbol->getAsSymbolNode()->getName().c_str()).append("\'"); - error(loc, "no such field in structure", field.c_str(), structName.c_str()); - } else { - error(loc, "no such field in structure", field.c_str(), ""); - } - } - } else - error(loc, "does not apply to this type:", field.c_str(), - base->getType().getCompleteString(intermediate.getEnhancedMsgs()).c_str()); - - // Propagate noContraction up the dereference chain - if (base->getQualifier().isNoContraction()) - result->getWritableType().getQualifier().setNoContraction(); - - // Propagate nonuniform - if (base->getQualifier().isNonUniform()) - result->getWritableType().getQualifier().nonUniform = true; - - return result; -} - -// -// Handle seeing a base.swizzle, a subset of base.identifier in the grammar. -// -TIntermTyped* TParseContext::handleDotSwizzle(const TSourceLoc& loc, TIntermTyped* base, const TString& field) -{ - TIntermTyped* result = base; - if (base->isScalar()) { - const char* dotFeature = "scalar swizzle"; - requireProfile(loc, ~EEsProfile, dotFeature); - profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, dotFeature); - } - - TSwizzleSelectors selectors; - parseSwizzleSelector(loc, field, base->getVectorSize(), selectors); - - if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitFloat()) - requireFloat16Arithmetic(loc, ".", "can't swizzle types containing float16"); - if (base->isVector() && selectors.size() != 1 && base->getType().contains16BitInt()) - requireInt16Arithmetic(loc, ".", "can't swizzle types containing (u)int16"); - if (base->isVector() && selectors.size() != 1 && base->getType().contains8BitInt()) - requireInt8Arithmetic(loc, ".", "can't swizzle types containing (u)int8"); - - if (base->isScalar()) { - if (selectors.size() == 1) - return result; - else { - TType type(base->getBasicType(), EvqTemporary, selectors.size()); - // Swizzle operations propagate specialization-constantness - if (base->getQualifier().isSpecConstant()) - type.getQualifier().makeSpecConstant(); - return addConstructor(loc, base, type); - } - } - - if (base->getType().getQualifier().isFrontEndConstant()) - result = intermediate.foldSwizzle(base, selectors, loc); - else { - if (selectors.size() == 1) { - TIntermTyped* index = intermediate.addConstantUnion(selectors[0], loc); - result = intermediate.addIndex(EOpIndexDirect, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision)); - } else { - TIntermTyped* index = intermediate.addSwizzle(selectors, loc); - result = intermediate.addIndex(EOpVectorSwizzle, base, index, loc); - result->setType(TType(base->getBasicType(), EvqTemporary, base->getType().getQualifier().precision, selectors.size())); - } - // Swizzle operations propagate specialization-constantness - if (base->getType().getQualifier().isSpecConstant()) - result->getWritableType().getQualifier().makeSpecConstant(); - } - - return result; -} - -void TParseContext::blockMemberExtensionCheck(const TSourceLoc& loc, const TIntermTyped* base, int member, const TString& memberName) -{ - // a block that needs extension checking is either 'base', or if arrayed, - // one level removed to the left - const TIntermSymbol* baseSymbol = nullptr; - if (base->getAsBinaryNode() == nullptr) - baseSymbol = base->getAsSymbolNode(); - else - baseSymbol = base->getAsBinaryNode()->getLeft()->getAsSymbolNode(); - if (baseSymbol == nullptr) - return; - const TSymbol* symbol = symbolTable.find(baseSymbol->getName()); - if (symbol == nullptr) - return; - const TVariable* variable = symbol->getAsVariable(); - if (variable == nullptr) - return; - if (!variable->hasMemberExtensions()) - return; - - // We now have a variable that is the base of a dot reference - // with members that need extension checking. - if (variable->getNumMemberExtensions(member) > 0) - requireExtensions(loc, variable->getNumMemberExtensions(member), variable->getMemberExtensions(member), memberName.c_str()); -} - -// -// Handle seeing a function declarator in the grammar. This is the precursor -// to recognizing a function prototype or function definition. -// -TFunction* TParseContext::handleFunctionDeclarator(const TSourceLoc& loc, TFunction& function, bool prototype) -{ - // ES can't declare prototypes inside functions - if (! symbolTable.atGlobalLevel()) - requireProfile(loc, ~EEsProfile, "local function declaration"); - - // - // Multiple declarations of the same function name are allowed. - // - // If this is a definition, the definition production code will check for redefinitions - // (we don't know at this point if it's a definition or not). - // - // Redeclarations (full signature match) are allowed. But, return types and parameter qualifiers must also match. - // - except ES 100, which only allows a single prototype - // - // ES 100 does not allow redefining, but does allow overloading of built-in functions. - // ES 300 does not allow redefining or overloading of built-in functions. - // - bool builtIn; - TSymbol* symbol = symbolTable.find(function.getMangledName(), &builtIn); - if (symbol && symbol->getAsFunction() && builtIn) - requireProfile(loc, ~EEsProfile, "redefinition of built-in function"); - // Check the validity of using spirv_literal qualifier - for (int i = 0; i < function.getParamCount(); ++i) { - if (function[i].type->getQualifier().isSpirvLiteral() && function.getBuiltInOp() != EOpSpirvInst) - error(loc, "'spirv_literal' can only be used on functions defined with 'spirv_instruction' for argument", - function.getName().c_str(), "%d", i + 1); - } - - // For function declaration with SPIR-V instruction qualifier, always ignore the built-in function and - // respect this redeclared one. - if (symbol && builtIn && function.getBuiltInOp() == EOpSpirvInst) - symbol = nullptr; - const TFunction* prevDec = symbol ? symbol->getAsFunction() : nullptr; - if (prevDec) { - if (prevDec->isPrototyped() && prototype) - profileRequires(loc, EEsProfile, 300, nullptr, "multiple prototypes for same function"); - if (prevDec->getType() != function.getType()) - error(loc, "overloaded functions must have the same return type", function.getName().c_str(), ""); - if (prevDec->getSpirvInstruction() != function.getSpirvInstruction()) { - error(loc, "overloaded functions must have the same qualifiers", function.getName().c_str(), - "spirv_instruction"); - } - for (int i = 0; i < prevDec->getParamCount(); ++i) { - if ((*prevDec)[i].type->getQualifier().storage != function[i].type->getQualifier().storage) - error(loc, "overloaded functions must have the same parameter storage qualifiers for argument", function[i].type->getStorageQualifierString(), "%d", i+1); - - if ((*prevDec)[i].type->getQualifier().precision != function[i].type->getQualifier().precision) - error(loc, "overloaded functions must have the same parameter precision qualifiers for argument", function[i].type->getPrecisionQualifierString(), "%d", i+1); - } - } - - arrayObjectCheck(loc, function.getType(), "array in function return type"); - - if (prototype) { - // All built-in functions are defined, even though they don't have a body. - // Count their prototype as a definition instead. - if (symbolTable.atBuiltInLevel()) - function.setDefined(); - else { - if (prevDec && ! builtIn) - symbol->getAsFunction()->setPrototyped(); // need a writable one, but like having prevDec as a const - function.setPrototyped(); - } - } - - // This insert won't actually insert it if it's a duplicate signature, but it will still check for - // other forms of name collisions. - if (! symbolTable.insert(function)) - error(loc, "function name is redeclaration of existing name", function.getName().c_str(), ""); - - // - // If this is a redeclaration, it could also be a definition, - // in which case, we need to use the parameter names from this one, and not the one that's - // being redeclared. So, pass back this declaration, not the one in the symbol table. - // - return &function; -} - -// -// Handle seeing the function prototype in front of a function definition in the grammar. -// The body is handled after this function returns. -// -TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, TFunction& function) -{ - currentCaller = function.getMangledName(); - TSymbol* symbol = symbolTable.find(function.getMangledName()); - TFunction* prevDec = symbol ? symbol->getAsFunction() : nullptr; - - if (! prevDec) - error(loc, "can't find function", function.getName().c_str(), ""); - // Note: 'prevDec' could be 'function' if this is the first time we've seen function - // as it would have just been put in the symbol table. Otherwise, we're looking up - // an earlier occurrence. - - if (prevDec && prevDec->isDefined()) { - // Then this function already has a body. - error(loc, "function already has a body", function.getName().c_str(), ""); - } - if (prevDec && ! prevDec->isDefined()) { - prevDec->setDefined(); - - // Remember the return type for later checking for RETURN statements. - currentFunctionType = &(prevDec->getType()); - } else - currentFunctionType = new TType(EbtVoid); - functionReturnsValue = false; - - // Check for entry point - if (function.getName().compare(intermediate.getEntryPointName().c_str()) == 0) { - intermediate.setEntryPointMangledName(function.getMangledName().c_str()); - intermediate.incrementEntryPointCount(); - inMain = true; - } else - inMain = false; - - // - // Raise error message if main function takes any parameters or returns anything other than void - // - if (inMain) { - if (function.getParamCount() > 0) - error(loc, "function cannot take any parameter(s)", function.getName().c_str(), ""); - if (function.getType().getBasicType() != EbtVoid) - error(loc, "", function.getType().getBasicTypeString().c_str(), "entry point cannot return a value"); - if (function.getLinkType() != ELinkNone) - error(loc, "main function cannot be exported", "", ""); - } - - // - // New symbol table scope for body of function plus its arguments - // - symbolTable.push(); - - // - // Insert parameters into the symbol table. - // If the parameter has no name, it's not an error, just don't insert it - // (could be used for unused args). - // - // Also, accumulate the list of parameters into the HIL, so lower level code - // knows where to find parameters. - // - TIntermAggregate* paramNodes = new TIntermAggregate; - for (int i = 0; i < function.getParamCount(); i++) { - TParameter& param = function[i]; - if (param.name != nullptr) { - TVariable *variable = new TVariable(param.name, *param.type); - - // Insert the parameters with name in the symbol table. - if (! symbolTable.insert(*variable)) - error(loc, "redefinition", variable->getName().c_str(), ""); - else { - // Transfer ownership of name pointer to symbol table. - param.name = nullptr; - - // Add the parameter to the HIL - paramNodes = intermediate.growAggregate(paramNodes, - intermediate.addSymbol(*variable, loc), - loc); - } - } else - paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc); - } - paramNodes->setLinkType(function.getLinkType()); - intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc); - loopNestingLevel = 0; - statementNestingLevel = 0; - controlFlowNestingLevel = 0; - postEntryPointReturn = false; - - return paramNodes; -} - -// -// Handle seeing function call syntax in the grammar, which could be any of -// - .length() method -// - constructor -// - a call to a built-in function mapped to an operator -// - a call to a built-in function that will remain a function call (e.g., texturing) -// - user function -// - subroutine call (not implemented yet) -// -TIntermTyped* TParseContext::handleFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments) -{ - TIntermTyped* result = nullptr; - - if (spvVersion.vulkan != 0 && spvVersion.vulkanRelaxed) { - // allow calls that are invalid in Vulkan Semantics to be invisibily - // remapped to equivalent valid functions - result = vkRelaxedRemapFunctionCall(loc, function, arguments); - if (result) - return result; - } - - if (function->getBuiltInOp() == EOpArrayLength) - result = handleLengthMethod(loc, function, arguments); - else if (function->getBuiltInOp() != EOpNull) { - // - // Then this should be a constructor. - // Don't go through the symbol table for constructors. - // Their parameters will be verified algorithmically. - // - TType type(EbtVoid); // use this to get the type back - if (! constructorError(loc, arguments, *function, function->getBuiltInOp(), type)) { - // - // It's a constructor, of type 'type'. - // - result = addConstructor(loc, arguments, type); - if (result == nullptr) - error(loc, "cannot construct with these arguments", type.getCompleteString(intermediate.getEnhancedMsgs()).c_str(), ""); - } - } else { - // - // Find it in the symbol table. - // - const TFunction* fnCandidate; - bool builtIn {false}; - fnCandidate = findFunction(loc, *function, builtIn); - if (fnCandidate) { - // This is a declared function that might map to - // - a built-in operator, - // - a built-in function not mapped to an operator, or - // - a user function. - - // Error check for a function requiring specific extensions present. - if (builtIn && fnCandidate->getNumExtensions()) - requireExtensions(loc, fnCandidate->getNumExtensions(), fnCandidate->getExtensions(), fnCandidate->getName().c_str()); - - if (builtIn && fnCandidate->getType().contains16BitFloat()) - requireFloat16Arithmetic(loc, "built-in function", "float16 types can only be in uniform block or buffer storage"); - if (builtIn && fnCandidate->getType().contains16BitInt()) - requireInt16Arithmetic(loc, "built-in function", "(u)int16 types can only be in uniform block or buffer storage"); - if (builtIn && fnCandidate->getType().contains8BitInt()) - requireInt8Arithmetic(loc, "built-in function", "(u)int8 types can only be in uniform block or buffer storage"); - - if (arguments != nullptr) { - // Make sure qualifications work for these arguments. - TIntermAggregate* aggregate = arguments->getAsAggregate(); - for (int i = 0; i < fnCandidate->getParamCount(); ++i) { - // At this early point there is a slight ambiguity between whether an aggregate 'arguments' - // is the single argument itself or its children are the arguments. Only one argument - // means take 'arguments' itself as the one argument. - TIntermNode* arg = fnCandidate->getParamCount() == 1 ? arguments : (aggregate ? aggregate->getSequence()[i] : arguments); - TQualifier& formalQualifier = (*fnCandidate)[i].type->getQualifier(); - if (formalQualifier.isParamOutput()) { - if (lValueErrorCheck(arguments->getLoc(), "assign", arg->getAsTyped())) - error(arguments->getLoc(), "Non-L-value cannot be passed for 'out' or 'inout' parameters.", "out", ""); - } - if (formalQualifier.isSpirvLiteral()) { - if (!arg->getAsTyped()->getQualifier().isFrontEndConstant()) { - error(arguments->getLoc(), - "Non front-end constant expressions cannot be passed for 'spirv_literal' parameters.", - "spirv_literal", ""); - } - } - const TType& argType = arg->getAsTyped()->getType(); - const TQualifier& argQualifier = argType.getQualifier(); - bool containsBindlessSampler = intermediate.getBindlessMode() && argType.containsSampler(); - if (argQualifier.isMemory() && !containsBindlessSampler && (argType.containsOpaque() || argType.isReference())) { - const char* message = "argument cannot drop memory qualifier when passed to formal parameter"; - if (argQualifier.volatil && ! formalQualifier.volatil) - error(arguments->getLoc(), message, "volatile", ""); - if (argQualifier.coherent && ! (formalQualifier.devicecoherent || formalQualifier.coherent)) - error(arguments->getLoc(), message, "coherent", ""); - if (argQualifier.devicecoherent && ! (formalQualifier.devicecoherent || formalQualifier.coherent)) - error(arguments->getLoc(), message, "devicecoherent", ""); - if (argQualifier.queuefamilycoherent && ! (formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent)) - error(arguments->getLoc(), message, "queuefamilycoherent", ""); - if (argQualifier.workgroupcoherent && ! (formalQualifier.workgroupcoherent || formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent)) - error(arguments->getLoc(), message, "workgroupcoherent", ""); - if (argQualifier.subgroupcoherent && ! (formalQualifier.subgroupcoherent || formalQualifier.workgroupcoherent || formalQualifier.queuefamilycoherent || formalQualifier.devicecoherent || formalQualifier.coherent)) - error(arguments->getLoc(), message, "subgroupcoherent", ""); - if (argQualifier.readonly && ! formalQualifier.readonly) - error(arguments->getLoc(), message, "readonly", ""); - if (argQualifier.writeonly && ! formalQualifier.writeonly) - error(arguments->getLoc(), message, "writeonly", ""); - // Don't check 'restrict', it is different than the rest: - // "...but only restrict can be taken away from a calling argument, by a formal parameter that - // lacks the restrict qualifier..." - } - if (!builtIn && argQualifier.getFormat() != formalQualifier.getFormat()) { - // we have mismatched formats, which should only be allowed if writeonly - // and at least one format is unknown - if (!formalQualifier.isWriteOnly() || (formalQualifier.getFormat() != ElfNone && - argQualifier.getFormat() != ElfNone)) - error(arguments->getLoc(), "image formats must match", "format", ""); - } - if (builtIn && arg->getAsTyped()->getType().contains16BitFloat()) - requireFloat16Arithmetic(arguments->getLoc(), "built-in function", "float16 types can only be in uniform block or buffer storage"); - if (builtIn && arg->getAsTyped()->getType().contains16BitInt()) - requireInt16Arithmetic(arguments->getLoc(), "built-in function", "(u)int16 types can only be in uniform block or buffer storage"); - if (builtIn && arg->getAsTyped()->getType().contains8BitInt()) - requireInt8Arithmetic(arguments->getLoc(), "built-in function", "(u)int8 types can only be in uniform block or buffer storage"); - - // TODO 4.5 functionality: A shader will fail to compile - // if the value passed to the memargument of an atomic memory function does not correspond to a buffer or - // shared variable. It is acceptable to pass an element of an array or a single component of a vector to the - // memargument of an atomic memory function, as long as the underlying array or vector is a buffer or - // shared variable. - } - - // Convert 'in' arguments - addInputArgumentConversions(*fnCandidate, arguments); // arguments may be modified if it's just a single argument node - } - - if (builtIn && fnCandidate->getBuiltInOp() != EOpNull) { - // A function call mapped to a built-in operation. - result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate); - } else if (fnCandidate->getBuiltInOp() == EOpSpirvInst) { - // When SPIR-V instruction qualifier is specified, the function call is still mapped to a built-in operation. - result = handleBuiltInFunctionCall(loc, arguments, *fnCandidate); - } else { - // This is a function call not mapped to built-in operator. - // It could still be a built-in function, but only if PureOperatorBuiltins == false. - result = intermediate.setAggregateOperator(arguments, EOpFunctionCall, fnCandidate->getType(), loc); - TIntermAggregate* call = result->getAsAggregate(); - call->setName(fnCandidate->getMangledName()); - - // this is how we know whether the given function is a built-in function or a user-defined function - // if builtIn == false, it's a userDefined -> could be an overloaded built-in function also - // if builtIn == true, it's definitely a built-in function with EOpNull - if (! builtIn) { - call->setUserDefined(); - if (symbolTable.atGlobalLevel()) { - requireProfile(loc, ~EEsProfile, "calling user function from global scope"); - intermediate.addToCallGraph(infoSink, "main(", fnCandidate->getMangledName()); - } else - intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName()); - } - - if (builtIn) - nonOpBuiltInCheck(loc, *fnCandidate, *call); - else - userFunctionCallCheck(loc, *call); - } - - // Convert 'out' arguments. If it was a constant folded built-in, it won't be an aggregate anymore. - // Built-ins with a single argument aren't called with an aggregate, but they also don't have an output. - // Also, build the qualifier list for user function calls, which are always called with an aggregate. - if (result->getAsAggregate()) { - TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList(); - for (int i = 0; i < fnCandidate->getParamCount(); ++i) { - TStorageQualifier qual = (*fnCandidate)[i].type->getQualifier().storage; - qualifierList.push_back(qual); - } - result = addOutputArgumentConversions(*fnCandidate, *result->getAsAggregate()); - } - - if (result->getAsTyped()->getType().isCoopMat() && - !result->getAsTyped()->getType().isParameterized()) { - assert(fnCandidate->getBuiltInOp() == EOpCooperativeMatrixMulAdd || - fnCandidate->getBuiltInOp() == EOpCooperativeMatrixMulAddNV); - - result->setType(result->getAsAggregate()->getSequence()[2]->getAsTyped()->getType()); - } - } - } - - // generic error recovery - // TODO: simplification: localize all the error recoveries that look like this, and taking type into account to reduce cascades - if (result == nullptr) - result = intermediate.addConstantUnion(0.0, EbtFloat, loc); - - return result; -} - -TIntermTyped* TParseContext::handleBuiltInFunctionCall(TSourceLoc loc, TIntermNode* arguments, - const TFunction& function) -{ - checkLocation(loc, function.getBuiltInOp()); - TIntermTyped *result = intermediate.addBuiltInFunctionCall(loc, function.getBuiltInOp(), - function.getParamCount() == 1, - arguments, function.getType()); - if (result != nullptr && obeyPrecisionQualifiers()) - computeBuiltinPrecisions(*result, function); - - if (result == nullptr) { - if (arguments == nullptr) - error(loc, " wrong operand type", "Internal Error", - "built in unary operator function. Type: %s", ""); - else - error(arguments->getLoc(), " wrong operand type", "Internal Error", - "built in unary operator function. Type: %s", - static_cast(arguments)->getCompleteString(intermediate.getEnhancedMsgs()).c_str()); - } else if (result->getAsOperator()) - builtInOpCheck(loc, function, *result->getAsOperator()); - - // Special handling for function call with SPIR-V instruction qualifier specified - if (function.getBuiltInOp() == EOpSpirvInst) { - if (auto agg = result->getAsAggregate()) { - // Propogate spirv_by_reference/spirv_literal from parameters to arguments - auto& sequence = agg->getSequence(); - for (unsigned i = 0; i < sequence.size(); ++i) { - if (function[i].type->getQualifier().isSpirvByReference()) - sequence[i]->getAsTyped()->getQualifier().setSpirvByReference(); - if (function[i].type->getQualifier().isSpirvLiteral()) - sequence[i]->getAsTyped()->getQualifier().setSpirvLiteral(); - } - - // Attach the function call to SPIR-V intruction - agg->setSpirvInstruction(function.getSpirvInstruction()); - } else if (auto unaryNode = result->getAsUnaryNode()) { - // Propogate spirv_by_reference/spirv_literal from parameters to arguments - if (function[0].type->getQualifier().isSpirvByReference()) - unaryNode->getOperand()->getQualifier().setSpirvByReference(); - if (function[0].type->getQualifier().isSpirvLiteral()) - unaryNode->getOperand()->getQualifier().setSpirvLiteral(); - - // Attach the function call to SPIR-V intruction - unaryNode->setSpirvInstruction(function.getSpirvInstruction()); - } else - assert(0); - } - - return result; -} - -// "The operation of a built-in function can have a different precision -// qualification than the precision qualification of the resulting value. -// These two precision qualifications are established as follows. -// -// The precision qualification of the operation of a built-in function is -// based on the precision qualification of its input arguments and formal -// parameters: When a formal parameter specifies a precision qualifier, -// that is used, otherwise, the precision qualification of the calling -// argument is used. The highest precision of these will be the precision -// qualification of the operation of the built-in function. Generally, -// this is applied across all arguments to a built-in function, with the -// exceptions being: -// - bitfieldExtract and bitfieldInsert ignore the 'offset' and 'bits' -// arguments. -// - interpolateAt* functions only look at the 'interpolant' argument. -// -// The precision qualification of the result of a built-in function is -// determined in one of the following ways: -// -// - For the texture sampling, image load, and image store functions, -// the precision of the return type matches the precision of the -// sampler type -// -// Otherwise: -// -// - For prototypes that do not specify a resulting precision qualifier, -// the precision will be the same as the precision of the operation. -// -// - For prototypes that do specify a resulting precision qualifier, -// the specified precision qualifier is the precision qualification of -// the result." -// -void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction& function) -{ - TPrecisionQualifier operationPrecision = EpqNone; - TPrecisionQualifier resultPrecision = EpqNone; - - TIntermOperator* opNode = node.getAsOperator(); - if (opNode == nullptr) - return; - - if (TIntermUnary* unaryNode = node.getAsUnaryNode()) { - operationPrecision = std::max(function[0].type->getQualifier().precision, - unaryNode->getOperand()->getType().getQualifier().precision); - if (function.getType().getBasicType() != EbtBool) - resultPrecision = function.getType().getQualifier().precision == EpqNone ? - operationPrecision : - function.getType().getQualifier().precision; - } else if (TIntermAggregate* agg = node.getAsAggregate()) { - TIntermSequence& sequence = agg->getSequence(); - unsigned int numArgs = (unsigned int)sequence.size(); - switch (agg->getOp()) { - case EOpBitfieldExtract: - numArgs = 1; - break; - case EOpBitfieldInsert: - numArgs = 2; - break; - case EOpInterpolateAtCentroid: - case EOpInterpolateAtOffset: - case EOpInterpolateAtSample: - numArgs = 1; - break; - case EOpDebugPrintf: - numArgs = 0; - break; - default: - break; - } - // find the maximum precision from the arguments and parameters - for (unsigned int arg = 0; arg < numArgs; ++arg) { - operationPrecision = std::max(operationPrecision, sequence[arg]->getAsTyped()->getQualifier().precision); - operationPrecision = std::max(operationPrecision, function[arg].type->getQualifier().precision); - } - // compute the result precision - if (agg->isSampling() || - agg->getOp() == EOpImageLoad || agg->getOp() == EOpImageStore || - agg->getOp() == EOpImageLoadLod || agg->getOp() == EOpImageStoreLod) - resultPrecision = sequence[0]->getAsTyped()->getQualifier().precision; - else if (function.getType().getBasicType() != EbtBool) - resultPrecision = function.getType().getQualifier().precision == EpqNone ? - operationPrecision : - function.getType().getQualifier().precision; - } - - // Propagate precision through this node and its children. That algorithm stops - // when a precision is found, so start by clearing this subroot precision - opNode->getQualifier().precision = EpqNone; - if (operationPrecision != EpqNone) { - opNode->propagatePrecision(operationPrecision); - opNode->setOperationPrecision(operationPrecision); - } - // Now, set the result precision, which might not match - opNode->getQualifier().precision = resultPrecision; -} - -TIntermNode* TParseContext::handleReturnValue(const TSourceLoc& loc, TIntermTyped* value) -{ - storage16BitAssignmentCheck(loc, value->getType(), "return"); - - functionReturnsValue = true; - TIntermBranch* branch = nullptr; - if (currentFunctionType->getBasicType() == EbtVoid) { - error(loc, "void function cannot return a value", "return", ""); - branch = intermediate.addBranch(EOpReturn, loc); - } else if (*currentFunctionType != value->getType()) { - TIntermTyped* converted = intermediate.addConversion(EOpReturn, *currentFunctionType, value); - if (converted) { - if (*currentFunctionType != converted->getType()) - error(loc, "cannot convert return value to function return type", "return", ""); - if (version < 420) - warn(loc, "type conversion on return values was not explicitly allowed until version 420", - "return", ""); - branch = intermediate.addBranch(EOpReturn, converted, loc); - } else { - error(loc, "type does not match, or is not convertible to, the function's return type", "return", ""); - branch = intermediate.addBranch(EOpReturn, value, loc); - } - } else { - if (value->getType().isTexture() || value->getType().isImage()) { - if (spvVersion.spv != 0) - error(loc, "sampler or image cannot be used as return type when generating SPIR-V", "return", ""); - else if (!extensionTurnedOn(E_GL_ARB_bindless_texture)) - error(loc, "sampler or image can be used as return type only when the extension GL_ARB_bindless_texture enabled", "return", ""); - } - branch = intermediate.addBranch(EOpReturn, value, loc); - } - branch->updatePrecision(currentFunctionType->getQualifier().precision); - return branch; -} - -// See if the operation is being done in an illegal location. -void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op) -{ - switch (op) { - case EOpBarrier: - if (language == EShLangTessControl) { - if (controlFlowNestingLevel > 0) - error(loc, "tessellation control barrier() cannot be placed within flow control", "", ""); - if (! inMain) - error(loc, "tessellation control barrier() must be in main()", "", ""); - else if (postEntryPointReturn) - error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", ""); - } - break; - case EOpBeginInvocationInterlock: - if (language != EShLangFragment) - error(loc, "beginInvocationInterlockARB() must be in a fragment shader", "", ""); - if (! inMain) - error(loc, "beginInvocationInterlockARB() must be in main()", "", ""); - else if (postEntryPointReturn) - error(loc, "beginInvocationInterlockARB() cannot be placed after a return from main()", "", ""); - if (controlFlowNestingLevel > 0) - error(loc, "beginInvocationInterlockARB() cannot be placed within flow control", "", ""); - - if (beginInvocationInterlockCount > 0) - error(loc, "beginInvocationInterlockARB() must only be called once", "", ""); - if (endInvocationInterlockCount > 0) - error(loc, "beginInvocationInterlockARB() must be called before endInvocationInterlockARB()", "", ""); - - beginInvocationInterlockCount++; - - // default to pixel_interlock_ordered - if (intermediate.getInterlockOrdering() == EioNone) - intermediate.setInterlockOrdering(EioPixelInterlockOrdered); - break; - case EOpEndInvocationInterlock: - if (language != EShLangFragment) - error(loc, "endInvocationInterlockARB() must be in a fragment shader", "", ""); - if (! inMain) - error(loc, "endInvocationInterlockARB() must be in main()", "", ""); - else if (postEntryPointReturn) - error(loc, "endInvocationInterlockARB() cannot be placed after a return from main()", "", ""); - if (controlFlowNestingLevel > 0) - error(loc, "endInvocationInterlockARB() cannot be placed within flow control", "", ""); - - if (endInvocationInterlockCount > 0) - error(loc, "endInvocationInterlockARB() must only be called once", "", ""); - if (beginInvocationInterlockCount == 0) - error(loc, "beginInvocationInterlockARB() must be called before endInvocationInterlockARB()", "", ""); - - endInvocationInterlockCount++; - break; - default: - break; - } -} - -// Finish processing object.length(). This started earlier in handleDotDereference(), where -// the ".length" part was recognized and semantically checked, and finished here where the -// function syntax "()" is recognized. -// -// Return resulting tree node. -TIntermTyped* TParseContext::handleLengthMethod(const TSourceLoc& loc, TFunction* function, TIntermNode* intermNode) -{ - int length = 0; - - if (function->getParamCount() > 0) - error(loc, "method does not accept any arguments", function->getName().c_str(), ""); - else { - const TType& type = intermNode->getAsTyped()->getType(); - if (type.isArray()) { - if (type.isUnsizedArray()) { - if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) { - // We could be between a layout declaration that gives a built-in io array implicit size and - // a user redeclaration of that array, meaning we have to substitute its implicit size here - // without actually redeclaring the array. (It is an error to use a member before the - // redeclaration, but not an error to use the array name itself.) - const TString& name = intermNode->getAsSymbolNode()->getName(); - if (name == "gl_in" || name == "gl_out" || name == "gl_MeshVerticesNV" || - name == "gl_MeshPrimitivesNV") { - length = getIoArrayImplicitSize(type.getQualifier()); - } - } - if (length == 0) { - if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) - error(loc, "", function->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier"); - else if (isRuntimeLength(*intermNode->getAsTyped())) { - // Create a unary op and let the back end handle it - return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt)); - } else - error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method"); - } - } else if (type.getOuterArrayNode()) { - // If the array's outer size is specified by an intermediate node, it means the array's length - // was specified by a specialization constant. In such a case, we should return the node of the - // specialization constants to represent the length. - return type.getOuterArrayNode(); - } else - length = type.getOuterArraySize(); - } else if (type.isMatrix()) - length = type.getMatrixCols(); - else if (type.isVector()) - length = type.getVectorSize(); - else if (type.isCoopMat()) - return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt)); - else { - // we should not get here, because earlier semantic checking should have prevented this path - error(loc, ".length()", "unexpected use of .length()", ""); - } - } - - if (length == 0) - length = 1; - - return intermediate.addConstantUnion(length, loc); -} - -// -// Add any needed implicit conversions for function-call arguments to input parameters. -// -void TParseContext::addInputArgumentConversions(const TFunction& function, TIntermNode*& arguments) const -{ - TIntermAggregate* aggregate = arguments->getAsAggregate(); - - // Process each argument's conversion - for (int i = 0; i < function.getParamCount(); ++i) { - // At this early point there is a slight ambiguity between whether an aggregate 'arguments' - // is the single argument itself or its children are the arguments. Only one argument - // means take 'arguments' itself as the one argument. - TIntermTyped* arg = function.getParamCount() == 1 ? arguments->getAsTyped() : (aggregate ? aggregate->getSequence()[i]->getAsTyped() : arguments->getAsTyped()); - if (*function[i].type != arg->getType()) { - if (function[i].type->getQualifier().isParamInput() && - !function[i].type->isCoopMat()) { - // In-qualified arguments just need an extra node added above the argument to - // convert to the correct type. - arg = intermediate.addConversion(EOpFunctionCall, *function[i].type, arg); - if (arg) { - if (function.getParamCount() == 1) - arguments = arg; - else { - if (aggregate) - aggregate->getSequence()[i] = arg; - else - arguments = arg; - } - } - } - } - } -} - -// -// Add any needed implicit output conversions for function-call arguments. This -// can require a new tree topology, complicated further by whether the function -// has a return value. -// -// Returns a node of a subtree that evaluates to the return value of the function. -// -TIntermTyped* TParseContext::addOutputArgumentConversions(const TFunction& function, TIntermAggregate& intermNode) const -{ - TIntermSequence& arguments = intermNode.getSequence(); - - // Will there be any output conversions? - bool outputConversions = false; - for (int i = 0; i < function.getParamCount(); ++i) { - if (*function[i].type != arguments[i]->getAsTyped()->getType() && function[i].type->getQualifier().isParamOutput()) { - outputConversions = true; - break; - } - } - - if (! outputConversions) - return &intermNode; - - // Setup for the new tree, if needed: - // - // Output conversions need a different tree topology. - // Out-qualified arguments need a temporary of the correct type, with the call - // followed by an assignment of the temporary to the original argument: - // void: function(arg, ...) -> ( function(tempArg, ...), arg = tempArg, ...) - // ret = function(arg, ...) -> ret = (tempRet = function(tempArg, ...), arg = tempArg, ..., tempRet) - // Where the "tempArg" type needs no conversion as an argument, but will convert on assignment. - TIntermTyped* conversionTree = nullptr; - TVariable* tempRet = nullptr; - if (intermNode.getBasicType() != EbtVoid) { - // do the "tempRet = function(...), " bit from above - tempRet = makeInternalVariable("tempReturn", intermNode.getType()); - TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc()); - conversionTree = intermediate.addAssign(EOpAssign, tempRetNode, &intermNode, intermNode.getLoc()); - } else - conversionTree = &intermNode; - - conversionTree = intermediate.makeAggregate(conversionTree); - - // Process each argument's conversion - for (int i = 0; i < function.getParamCount(); ++i) { - if (*function[i].type != arguments[i]->getAsTyped()->getType()) { - if (function[i].type->getQualifier().isParamOutput()) { - // Out-qualified arguments need to use the topology set up above. - // do the " ...(tempArg, ...), arg = tempArg" bit from above - TType paramType; - paramType.shallowCopy(*function[i].type); - if (arguments[i]->getAsTyped()->getType().isParameterized() && - !paramType.isParameterized()) { - paramType.shallowCopy(arguments[i]->getAsTyped()->getType()); - paramType.copyTypeParameters(*arguments[i]->getAsTyped()->getType().getTypeParameters()); - } - TVariable* tempArg = makeInternalVariable("tempArg", paramType); - tempArg->getWritableType().getQualifier().makeTemporary(); - TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, intermNode.getLoc()); - TIntermTyped* tempAssign = intermediate.addAssign(EOpAssign, arguments[i]->getAsTyped(), tempArgNode, arguments[i]->getLoc()); - conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc()); - // replace the argument with another node for the same tempArg variable - arguments[i] = intermediate.addSymbol(*tempArg, intermNode.getLoc()); - } - } - } - - // Finalize the tree topology (see bigger comment above). - if (tempRet) { - // do the "..., tempRet" bit from above - TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc()); - conversionTree = intermediate.growAggregate(conversionTree, tempRetNode, intermNode.getLoc()); - } - conversionTree = intermediate.setAggregateOperator(conversionTree, EOpComma, intermNode.getType(), intermNode.getLoc()); - - return conversionTree; -} - -TIntermTyped* TParseContext::addAssign(const TSourceLoc& loc, TOperator op, TIntermTyped* left, TIntermTyped* right) -{ - if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference()) - requireExtensions(loc, 1, &E_GL_EXT_buffer_reference2, "+= and -= on a buffer reference"); - - if (op == EOpAssign && left->getBasicType() == EbtSampler && right->getBasicType() == EbtSampler) - requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "sampler assignment for bindless texture"); - - return intermediate.addAssign(op, left, right, loc); -} - -void TParseContext::memorySemanticsCheck(const TSourceLoc& loc, const TFunction& fnCandidate, const TIntermOperator& callNode) -{ - const TIntermSequence* argp = &callNode.getAsAggregate()->getSequence(); - - //const int gl_SemanticsRelaxed = 0x0; - const int gl_SemanticsAcquire = 0x2; - const int gl_SemanticsRelease = 0x4; - const int gl_SemanticsAcquireRelease = 0x8; - const int gl_SemanticsMakeAvailable = 0x2000; - const int gl_SemanticsMakeVisible = 0x4000; - const int gl_SemanticsVolatile = 0x8000; - - //const int gl_StorageSemanticsNone = 0x0; - const int gl_StorageSemanticsBuffer = 0x40; - const int gl_StorageSemanticsShared = 0x100; - const int gl_StorageSemanticsImage = 0x800; - const int gl_StorageSemanticsOutput = 0x1000; - - - unsigned int semantics = 0, storageClassSemantics = 0; - unsigned int semantics2 = 0, storageClassSemantics2 = 0; - - const TIntermTyped* arg0 = (*argp)[0]->getAsTyped(); - const bool isMS = arg0->getBasicType() == EbtSampler && arg0->getType().getSampler().isMultiSample(); - - // Grab the semantics and storage class semantics from the operands, based on opcode - switch (callNode.getOp()) { - case EOpAtomicAdd: - case EOpAtomicSubtract: - case EOpAtomicMin: - case EOpAtomicMax: - case EOpAtomicAnd: - case EOpAtomicOr: - case EOpAtomicXor: - case EOpAtomicExchange: - case EOpAtomicStore: - storageClassSemantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst(); - break; - case EOpAtomicLoad: - storageClassSemantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst(); - break; - case EOpAtomicCompSwap: - storageClassSemantics = (*argp)[4]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[5]->getAsConstantUnion()->getConstArray()[0].getIConst(); - storageClassSemantics2 = (*argp)[6]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics2 = (*argp)[7]->getAsConstantUnion()->getConstArray()[0].getIConst(); - break; - - case EOpImageAtomicAdd: - case EOpImageAtomicMin: - case EOpImageAtomicMax: - case EOpImageAtomicAnd: - case EOpImageAtomicOr: - case EOpImageAtomicXor: - case EOpImageAtomicExchange: - case EOpImageAtomicStore: - storageClassSemantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst(); - break; - case EOpImageAtomicLoad: - storageClassSemantics = (*argp)[isMS ? 4 : 3]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[isMS ? 5 : 4]->getAsConstantUnion()->getConstArray()[0].getIConst(); - break; - case EOpImageAtomicCompSwap: - storageClassSemantics = (*argp)[isMS ? 6 : 5]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[isMS ? 7 : 6]->getAsConstantUnion()->getConstArray()[0].getIConst(); - storageClassSemantics2 = (*argp)[isMS ? 8 : 7]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics2 = (*argp)[isMS ? 9 : 8]->getAsConstantUnion()->getConstArray()[0].getIConst(); - break; - - case EOpBarrier: - storageClassSemantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[3]->getAsConstantUnion()->getConstArray()[0].getIConst(); - break; - case EOpMemoryBarrier: - storageClassSemantics = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getIConst(); - semantics = (*argp)[2]->getAsConstantUnion()->getConstArray()[0].getIConst(); - break; - default: - break; - } - - if ((semantics & gl_SemanticsAcquire) && - (callNode.getOp() == EOpAtomicStore || callNode.getOp() == EOpImageAtomicStore)) { - error(loc, "gl_SemanticsAcquire must not be used with (image) atomic store", - fnCandidate.getName().c_str(), ""); - } - if ((semantics & gl_SemanticsRelease) && - (callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpImageAtomicLoad)) { - error(loc, "gl_SemanticsRelease must not be used with (image) atomic load", - fnCandidate.getName().c_str(), ""); - } - if ((semantics & gl_SemanticsAcquireRelease) && - (callNode.getOp() == EOpAtomicStore || callNode.getOp() == EOpImageAtomicStore || - callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpImageAtomicLoad)) { - error(loc, "gl_SemanticsAcquireRelease must not be used with (image) atomic load/store", - fnCandidate.getName().c_str(), ""); - } - if (((semantics | semantics2) & ~(gl_SemanticsAcquire | - gl_SemanticsRelease | - gl_SemanticsAcquireRelease | - gl_SemanticsMakeAvailable | - gl_SemanticsMakeVisible | - gl_SemanticsVolatile))) { - error(loc, "Invalid semantics value", fnCandidate.getName().c_str(), ""); - } - if (((storageClassSemantics | storageClassSemantics2) & ~(gl_StorageSemanticsBuffer | - gl_StorageSemanticsShared | - gl_StorageSemanticsImage | - gl_StorageSemanticsOutput))) { - error(loc, "Invalid storage class semantics value", fnCandidate.getName().c_str(), ""); - } - - if (callNode.getOp() == EOpMemoryBarrier) { - if (!IsPow2(semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) { - error(loc, "Semantics must include exactly one of gl_SemanticsRelease, gl_SemanticsAcquire, or " - "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), ""); - } - } else { - if (semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease)) { - if (!IsPow2(semantics & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) { - error(loc, "Semantics must not include multiple of gl_SemanticsRelease, gl_SemanticsAcquire, or " - "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), ""); - } - } - if (semantics2 & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease)) { - if (!IsPow2(semantics2 & (gl_SemanticsAcquire | gl_SemanticsRelease | gl_SemanticsAcquireRelease))) { - error(loc, "semUnequal must not include multiple of gl_SemanticsRelease, gl_SemanticsAcquire, or " - "gl_SemanticsAcquireRelease", fnCandidate.getName().c_str(), ""); - } - } - } - if (callNode.getOp() == EOpMemoryBarrier) { - if (storageClassSemantics == 0) { - error(loc, "Storage class semantics must not be zero", fnCandidate.getName().c_str(), ""); - } - } - if (callNode.getOp() == EOpBarrier && semantics != 0 && storageClassSemantics == 0) { - error(loc, "Storage class semantics must not be zero", fnCandidate.getName().c_str(), ""); - } - if ((callNode.getOp() == EOpAtomicCompSwap || callNode.getOp() == EOpImageAtomicCompSwap) && - (semantics2 & (gl_SemanticsRelease | gl_SemanticsAcquireRelease))) { - error(loc, "semUnequal must not be gl_SemanticsRelease or gl_SemanticsAcquireRelease", - fnCandidate.getName().c_str(), ""); - } - if ((semantics & gl_SemanticsMakeAvailable) && - !(semantics & (gl_SemanticsRelease | gl_SemanticsAcquireRelease))) { - error(loc, "gl_SemanticsMakeAvailable requires gl_SemanticsRelease or gl_SemanticsAcquireRelease", - fnCandidate.getName().c_str(), ""); - } - if ((semantics & gl_SemanticsMakeVisible) && - !(semantics & (gl_SemanticsAcquire | gl_SemanticsAcquireRelease))) { - error(loc, "gl_SemanticsMakeVisible requires gl_SemanticsAcquire or gl_SemanticsAcquireRelease", - fnCandidate.getName().c_str(), ""); - } - if ((semantics & gl_SemanticsVolatile) && - (callNode.getOp() == EOpMemoryBarrier || callNode.getOp() == EOpBarrier)) { - error(loc, "gl_SemanticsVolatile must not be used with memoryBarrier or controlBarrier", - fnCandidate.getName().c_str(), ""); - } - if ((callNode.getOp() == EOpAtomicCompSwap || callNode.getOp() == EOpImageAtomicCompSwap) && - ((semantics ^ semantics2) & gl_SemanticsVolatile)) { - error(loc, "semEqual and semUnequal must either both include gl_SemanticsVolatile or neither", - fnCandidate.getName().c_str(), ""); - } -} - -// -// Do additional checking of built-in function calls that is not caught -// by normal semantic checks on argument type, extension tagging, etc. -// -// Assumes there has been a semantically correct match to a built-in function prototype. -// -void TParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermOperator& callNode) -{ - // Set up convenience accessors to the argument(s). There is almost always - // multiple arguments for the cases below, but when there might be one, - // check the unaryArg first. - const TIntermSequence* argp = nullptr; // confusing to use [] syntax on a pointer, so this is to help get a reference - const TIntermTyped* unaryArg = nullptr; - const TIntermTyped* arg0 = nullptr; - if (callNode.getAsAggregate()) { - argp = &callNode.getAsAggregate()->getSequence(); - if (argp->size() > 0) - arg0 = (*argp)[0]->getAsTyped(); - } else { - assert(callNode.getAsUnaryNode()); - unaryArg = callNode.getAsUnaryNode()->getOperand(); - arg0 = unaryArg; - } - - TString featureString; - const char* feature = nullptr; - switch (callNode.getOp()) { - case EOpTextureGather: - case EOpTextureGatherOffset: - case EOpTextureGatherOffsets: - { - // Figure out which variants are allowed by what extensions, - // and what arguments must be constant for which situations. - - featureString = fnCandidate.getName(); - featureString += "(...)"; - feature = featureString.c_str(); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - int compArg = -1; // track which argument, if any, is the constant component argument - switch (callNode.getOp()) { - case EOpTextureGather: - // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5, - // otherwise, need GL_ARB_texture_gather. - if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) { - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 2; - } else - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); - break; - case EOpTextureGatherOffset: - // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument - if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3) - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); - else - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion()) - profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, - "non-constant offset argument"); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - break; - case EOpTextureGatherOffsets: - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - // check for constant offsets - if (! (*argp)[fnCandidate[0].type->getSampler().shadow ? 3 : 2]->getAsConstantUnion()) - error(loc, "must be a compile-time constant:", feature, "offsets argument"); - break; - default: - break; - } - - if (compArg > 0 && compArg < fnCandidate.getParamCount()) { - if ((*argp)[compArg]->getAsConstantUnion()) { - int value = (*argp)[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (value < 0 || value > 3) - error(loc, "must be 0, 1, 2, or 3:", feature, "component argument"); - } else - error(loc, "must be a compile-time constant:", feature, "component argument"); - } - - bool bias = false; - if (callNode.getOp() == EOpTextureGather) - bias = fnCandidate.getParamCount() > 3; - else if (callNode.getOp() == EOpTextureGatherOffset || - callNode.getOp() == EOpTextureGatherOffsets) - bias = fnCandidate.getParamCount() > 4; - - if (bias) { - featureString = fnCandidate.getName(); - featureString += "with bias argument"; - feature = featureString.c_str(); - profileRequires(loc, ~EEsProfile, 450, nullptr, feature); - requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature); - } - break; - } - - case EOpTexture: - case EOpTextureLod: - { - if ((fnCandidate.getParamCount() > 2) && ((*argp)[1]->getAsTyped()->getType().getBasicType() == EbtFloat) && - ((*argp)[1]->getAsTyped()->getType().getVectorSize() == 4) && fnCandidate[0].type->getSampler().shadow) { - featureString = fnCandidate.getName(); - if (callNode.getOp() == EOpTexture) - featureString += "(..., float bias)"; - else - featureString += "(..., float lod)"; - feature = featureString.c_str(); - - if ((fnCandidate[0].type->getSampler().dim == Esd2D && fnCandidate[0].type->getSampler().arrayed) || //2D Array Shadow - (fnCandidate[0].type->getSampler().dim == EsdCube && fnCandidate[0].type->getSampler().arrayed && fnCandidate.getParamCount() > 3) || // Cube Array Shadow - (fnCandidate[0].type->getSampler().dim == EsdCube && callNode.getOp() == EOpTextureLod)) { // Cube Shadow - requireExtensions(loc, 1, &E_GL_EXT_texture_shadow_lod, feature); - if (isEsProfile()) { - if (version < 320 && - !extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) - error(loc, "GL_EXT_texture_shadow_lod not supported for this ES version", feature, ""); - else - profileRequires(loc, EEsProfile, 320, nullptr, feature); - } else { // Desktop - profileRequires(loc, ~EEsProfile, 130, nullptr, feature); - } - } - } - break; - } - - case EOpSparseTextureGather: - case EOpSparseTextureGatherOffset: - case EOpSparseTextureGatherOffsets: - { - bool bias = false; - if (callNode.getOp() == EOpSparseTextureGather) - bias = fnCandidate.getParamCount() > 4; - else if (callNode.getOp() == EOpSparseTextureGatherOffset || - callNode.getOp() == EOpSparseTextureGatherOffsets) - bias = fnCandidate.getParamCount() > 5; - - if (bias) { - featureString = fnCandidate.getName(); - featureString += "with bias argument"; - feature = featureString.c_str(); - profileRequires(loc, ~EEsProfile, 450, nullptr, feature); - requireExtensions(loc, 1, &E_GL_AMD_texture_gather_bias_lod, feature); - } - // As per GL_ARB_sparse_texture2 extension "Offsets" parameter must be constant integral expression - // for sparseTextureGatherOffsetsARB just as textureGatherOffsets - if (callNode.getOp() == EOpSparseTextureGatherOffsets) { - int offsetsArg = arg0->getType().getSampler().shadow ? 3 : 2; - if (!(*argp)[offsetsArg]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "offsets", ""); - } - break; - } - - case EOpSparseTextureGatherLod: - case EOpSparseTextureGatherLodOffset: - case EOpSparseTextureGatherLodOffsets: - { - requireExtensions(loc, 1, &E_GL_ARB_sparse_texture2, fnCandidate.getName().c_str()); - break; - } - - case EOpSwizzleInvocations: - { - if (! (*argp)[1]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "offset", ""); - else { - unsigned offset[4] = {}; - offset[0] = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst(); - offset[1] = (*argp)[1]->getAsConstantUnion()->getConstArray()[1].getUConst(); - offset[2] = (*argp)[1]->getAsConstantUnion()->getConstArray()[2].getUConst(); - offset[3] = (*argp)[1]->getAsConstantUnion()->getConstArray()[3].getUConst(); - if (offset[0] > 3 || offset[1] > 3 || offset[2] > 3 || offset[3] > 3) - error(loc, "components must be in the range [0, 3]", "offset", ""); - } - - break; - } - - case EOpSwizzleInvocationsMasked: - { - if (! (*argp)[1]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "mask", ""); - else { - unsigned mask[3] = {}; - mask[0] = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst(); - mask[1] = (*argp)[1]->getAsConstantUnion()->getConstArray()[1].getUConst(); - mask[2] = (*argp)[1]->getAsConstantUnion()->getConstArray()[2].getUConst(); - if (mask[0] > 31 || mask[1] > 31 || mask[2] > 31) - error(loc, "components must be in the range [0, 31]", "mask", ""); - } - - break; - } - - case EOpTextureOffset: - case EOpTextureFetchOffset: - case EOpTextureProjOffset: - case EOpTextureLodOffset: - case EOpTextureProjLodOffset: - case EOpTextureGradOffset: - case EOpTextureProjGradOffset: - { - // Handle texture-offset limits checking - // Pick which argument has to hold constant offsets - int arg = -1; - switch (callNode.getOp()) { - case EOpTextureOffset: arg = 2; break; - case EOpTextureFetchOffset: arg = (arg0->getType().getSampler().isRect()) ? 2 : 3; break; - case EOpTextureProjOffset: arg = 2; break; - case EOpTextureLodOffset: arg = 3; break; - case EOpTextureProjLodOffset: arg = 3; break; - case EOpTextureGradOffset: arg = 4; break; - case EOpTextureProjGradOffset: arg = 4; break; - default: - assert(0); - break; - } - - if (arg > 0) { - - bool f16ShadowCompare = (*argp)[1]->getAsTyped()->getBasicType() == EbtFloat16 && - arg0->getType().getSampler().shadow; - if (f16ShadowCompare) - ++arg; - if (! (*argp)[arg]->getAsTyped()->getQualifier().isConstant()) - error(loc, "argument must be compile-time constant", "texel offset", ""); - else if ((*argp)[arg]->getAsConstantUnion()) { - const TType& type = (*argp)[arg]->getAsTyped()->getType(); - for (int c = 0; c < type.getVectorSize(); ++c) { - int offset = (*argp)[arg]->getAsConstantUnion()->getConstArray()[c].getIConst(); - if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset) - error(loc, "value is out of range:", "texel offset", - "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); - } - } - - if (callNode.getOp() == EOpTextureOffset) { - TSampler s = arg0->getType().getSampler(); - if (s.is2D() && s.isArrayed() && s.isShadow()) { - if ( - ((*argp)[1]->getAsTyped()->getType().getBasicType() == EbtFloat) && - ((*argp)[1]->getAsTyped()->getType().getVectorSize() == 4) && - (fnCandidate.getParamCount() == 4)) { - featureString = fnCandidate.getName() + " for sampler2DArrayShadow"; - feature = featureString.c_str(); - requireExtensions(loc, 1, &E_GL_EXT_texture_shadow_lod, feature); - profileRequires(loc, EEsProfile, 300, nullptr, feature); - profileRequires(loc, ~EEsProfile, 130, nullptr, feature); - } - else if (isEsProfile()) - error(loc, "TextureOffset does not support sampler2DArrayShadow : ", "sampler", "ES Profile"); - else if (version <= 420) - error(loc, "TextureOffset does not support sampler2DArrayShadow : ", "sampler", "version <= 420"); - } - } - - if (callNode.getOp() == EOpTextureLodOffset) { - TSampler s = arg0->getType().getSampler(); - if (s.is2D() && s.isArrayed() && s.isShadow() && - ((*argp)[1]->getAsTyped()->getType().getBasicType() == EbtFloat) && - ((*argp)[1]->getAsTyped()->getType().getVectorSize() == 4) && - (fnCandidate.getParamCount() == 4)) { - featureString = fnCandidate.getName() + " for sampler2DArrayShadow"; - feature = featureString.c_str(); - profileRequires(loc, EEsProfile, 300, nullptr, feature); - profileRequires(loc, ~EEsProfile, 130, nullptr, feature); - requireExtensions(loc, 1, &E_GL_EXT_texture_shadow_lod, feature); - } - } - } - - break; - } - - case EOpTraceNV: - if (!(*argp)[10]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "payload number", "a"); - break; - case EOpTraceRayMotionNV: - if (!(*argp)[11]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "payload number", "a"); - break; - case EOpTraceKHR: - if (!(*argp)[10]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "payload number", "a"); - else { - unsigned int location = (*argp)[10]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(0, location) < 0) - error(loc, "with layout(location =", "no rayPayloadEXT/rayPayloadInEXT declared", "%d)", location); - } - break; - case EOpExecuteCallableNV: - if (!(*argp)[1]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "callable data number", ""); - break; - case EOpExecuteCallableKHR: - if (!(*argp)[1]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "callable data number", ""); - else { - unsigned int location = (*argp)[1]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(1, location) < 0) - error(loc, "with layout(location =", "no callableDataEXT/callableDataInEXT declared", "%d)", location); - } - break; - - case EOpHitObjectTraceRayNV: - if (!(*argp)[11]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "payload number", ""); - else { - unsigned int location = (*argp)[11]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(0, location) < 0) - error(loc, "with layout(location =", "no rayPayloadEXT/rayPayloadInEXT declared", "%d)", location); - } - break; - case EOpHitObjectTraceRayMotionNV: - if (!(*argp)[12]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "payload number", ""); - else { - unsigned int location = (*argp)[12]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(0, location) < 0) - error(loc, "with layout(location =", "no rayPayloadEXT/rayPayloadInEXT declared", "%d)", location); - } - break; - case EOpHitObjectExecuteShaderNV: - if (!(*argp)[1]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "payload number", ""); - else { - unsigned int location = (*argp)[1]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(0, location) < 0) - error(loc, "with layout(location =", "no rayPayloadEXT/rayPayloadInEXT declared", "%d)", location); - } - break; - case EOpHitObjectRecordHitNV: - if (!(*argp)[12]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "hitobjectattribute number", ""); - else { - unsigned int location = (*argp)[12]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(2, location) < 0) - error(loc, "with layout(location =", "no hitObjectAttributeNV declared", "%d)", location); - } - break; - case EOpHitObjectRecordHitMotionNV: - if (!(*argp)[13]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "hitobjectattribute number", ""); - else { - unsigned int location = (*argp)[13]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(2, location) < 0) - error(loc, "with layout(location =", "no hitObjectAttributeNV declared", "%d)", location); - } - break; - case EOpHitObjectRecordHitWithIndexNV: - if (!(*argp)[11]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "hitobjectattribute number", ""); - else { - unsigned int location = (*argp)[11]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(2, location) < 0) - error(loc, "with layout(location =", "no hitObjectAttributeNV declared", "%d)", location); - } - break; - case EOpHitObjectRecordHitWithIndexMotionNV: - if (!(*argp)[12]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "hitobjectattribute number", ""); - else { - unsigned int location = (*argp)[12]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(2, location) < 0) - error(loc, "with layout(location =", "no hitObjectAttributeNV declared", "%d)", location); - } - break; - case EOpHitObjectGetAttributesNV: - if (!(*argp)[1]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "hitobjectattribute number", ""); - else { - unsigned int location = (*argp)[1]->getAsConstantUnion()->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (!extensionTurnedOn(E_GL_EXT_spirv_intrinsics) && intermediate.checkLocationRT(2, location) < 0) - error(loc, "with layout(location =", "no hitObjectAttributeNV declared", "%d)", location); - } - break; - - case EOpRayQueryGetIntersectionType: - case EOpRayQueryGetIntersectionT: - case EOpRayQueryGetIntersectionInstanceCustomIndex: - case EOpRayQueryGetIntersectionInstanceId: - case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: - case EOpRayQueryGetIntersectionGeometryIndex: - case EOpRayQueryGetIntersectionPrimitiveIndex: - case EOpRayQueryGetIntersectionBarycentrics: - case EOpRayQueryGetIntersectionFrontFace: - case EOpRayQueryGetIntersectionObjectRayDirection: - case EOpRayQueryGetIntersectionObjectRayOrigin: - case EOpRayQueryGetIntersectionObjectToWorld: - case EOpRayQueryGetIntersectionWorldToObject: - case EOpRayQueryGetIntersectionTriangleVertexPositionsEXT: - if (!(*argp)[1]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "committed", ""); - break; - - case EOpTextureQuerySamples: - case EOpImageQuerySamples: - // GL_ARB_shader_texture_image_samples - profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples"); - break; - - case EOpImageAtomicAdd: - case EOpImageAtomicMin: - case EOpImageAtomicMax: - case EOpImageAtomicAnd: - case EOpImageAtomicOr: - case EOpImageAtomicXor: - case EOpImageAtomicExchange: - case EOpImageAtomicCompSwap: - case EOpImageAtomicLoad: - case EOpImageAtomicStore: - { - // Make sure the image types have the correct layout() format and correct argument types - const TType& imageType = arg0->getType(); - if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint || - imageType.getSampler().type == EbtInt64 || imageType.getSampler().type == EbtUint64) { - if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui && - imageType.getQualifier().getFormat() != ElfR64i && imageType.getQualifier().getFormat() != ElfR64ui) - error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), ""); - if (callNode.getType().getBasicType() == EbtInt64 && imageType.getQualifier().getFormat() != ElfR64i) - error(loc, "only supported on image with format r64i", fnCandidate.getName().c_str(), ""); - else if (callNode.getType().getBasicType() == EbtUint64 && imageType.getQualifier().getFormat() != ElfR64ui) - error(loc, "only supported on image with format r64ui", fnCandidate.getName().c_str(), ""); - } else if (imageType.getSampler().type == EbtFloat) { - if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") == 0) { - // imageAtomicExchange doesn't require an extension - } else if ((fnCandidate.getName().compare(0, 14, "imageAtomicAdd") == 0) || - (fnCandidate.getName().compare(0, 15, "imageAtomicLoad") == 0) || - (fnCandidate.getName().compare(0, 16, "imageAtomicStore") == 0)) { - requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str()); - } else if ((fnCandidate.getName().compare(0, 14, "imageAtomicMin") == 0) || - (fnCandidate.getName().compare(0, 14, "imageAtomicMax") == 0)) { - requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str()); - } else { - error(loc, "only supported on integer images", fnCandidate.getName().c_str(), ""); - } - if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile()) - error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), ""); - } else { - error(loc, "not supported on this image type", fnCandidate.getName().c_str(), ""); - } - - const size_t maxArgs = imageType.getSampler().isMultiSample() ? 5 : 4; - if (argp->size() > maxArgs) { - requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str()); - memorySemanticsCheck(loc, fnCandidate, callNode); - } - - break; - } - - case EOpAtomicAdd: - case EOpAtomicSubtract: - case EOpAtomicMin: - case EOpAtomicMax: - case EOpAtomicAnd: - case EOpAtomicOr: - case EOpAtomicXor: - case EOpAtomicExchange: - case EOpAtomicCompSwap: - case EOpAtomicLoad: - case EOpAtomicStore: - { - if (argp->size() > 3) { - requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str()); - memorySemanticsCheck(loc, fnCandidate, callNode); - if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange || - callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore) && - (arg0->getType().getBasicType() == EbtFloat || - arg0->getType().getBasicType() == EbtDouble)) { - requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str()); - } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange || - callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore || - callNode.getOp() == EOpAtomicMin || callNode.getOp() == EOpAtomicMax) && - arg0->getType().isFloatingDomain()) { - requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str()); - } - } else if (arg0->getType().getBasicType() == EbtInt64 || arg0->getType().getBasicType() == EbtUint64) { - const char* const extensions[2] = { E_GL_NV_shader_atomic_int64, - E_GL_EXT_shader_atomic_int64 }; - requireExtensions(loc, 2, extensions, fnCandidate.getName().c_str()); - } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange) && - (arg0->getType().getBasicType() == EbtFloat || - arg0->getType().getBasicType() == EbtDouble)) { - requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float, fnCandidate.getName().c_str()); - } else if ((callNode.getOp() == EOpAtomicAdd || callNode.getOp() == EOpAtomicExchange || - callNode.getOp() == EOpAtomicLoad || callNode.getOp() == EOpAtomicStore || - callNode.getOp() == EOpAtomicMin || callNode.getOp() == EOpAtomicMax) && - arg0->getType().isFloatingDomain()) { - requireExtensions(loc, 1, &E_GL_EXT_shader_atomic_float2, fnCandidate.getName().c_str()); - } - - const TIntermTyped* base = TIntermediate::traverseLValueBase(arg0, true, true); - const char* errMsg = "Only l-values corresponding to shader block storage or shared variables can be used with " - "atomic memory functions."; - if (base) { - const TType* refType = (base->getType().isReference()) ? base->getType().getReferentType() : nullptr; - const TQualifier& qualifier = - (refType != nullptr) ? refType->getQualifier() : base->getType().getQualifier(); - if (qualifier.storage != EvqShared && qualifier.storage != EvqBuffer && - qualifier.storage != EvqtaskPayloadSharedEXT) - error(loc, errMsg, fnCandidate.getName().c_str(), ""); - } else { - error(loc, errMsg, fnCandidate.getName().c_str(), ""); - } - - break; - } - - case EOpInterpolateAtCentroid: - case EOpInterpolateAtSample: - case EOpInterpolateAtOffset: - case EOpInterpolateAtVertex: { - if (arg0->getType().getQualifier().storage != EvqVaryingIn) { - // Traverse down the left branch of arg0 to ensure this argument is a valid interpolant. - // - // For desktop GL >4.3 we effectively only need to ensure that arg0 represents an l-value from an - // input declaration. - // - // For desktop GL <= 4.3 and ES, we must also ensure that swizzling is not used - // - // For ES, we must also ensure that a field selection operator (i.e., '.') is not used on a named - // struct. - - const bool esProfile = isEsProfile(); - const bool swizzleOkay = !esProfile && (version >= 440); - - std::string interpolantErrorMsg = "first argument must be an interpolant, or interpolant-array element"; - bool isValid = true; // Assume that the interpolant is valid until we find a condition making it invalid - bool isIn = false; // Checks whether or not the interpolant is a shader input - bool structAccessOp = false; // Whether or not the previous node in the chain is a struct accessor - TIntermediate::traverseLValueBase( - arg0, swizzleOkay, false, - [&isValid, &isIn, &interpolantErrorMsg, esProfile, &structAccessOp](const TIntermNode& n) -> bool { - auto* type = n.getAsTyped(); - if (type) { - if (type->getType().getQualifier().storage == EvqVaryingIn) { - isIn = true; - } - // If a field accessor was used, it can only be used to access a field with an input block, not a struct. - if (structAccessOp && (type->getType().getBasicType() != EbtBlock)) { - interpolantErrorMsg += - ". Using the field of a named struct as an interpolant argument is not " - "allowed (ES-only)."; - isValid = false; - } - } - - // ES has different requirements for interpolants than GL - if (esProfile) { - // Swizzling will be taken care of by the 'swizzleOkay' argument passsed to traverseLValueBase, - // so we only ned to check whether or not a field accessor has been used with a named struct. - auto* binary = n.getAsBinaryNode(); - if (binary && (binary->getOp() == EOpIndexDirectStruct)) { - structAccessOp = true; - } - } - // Don't continue traversing if we know we have an invalid interpolant at this point. - return isValid; - }); - if (!isIn || !isValid) { - error(loc, interpolantErrorMsg.c_str(), fnCandidate.getName().c_str(), ""); - } - } - - if (callNode.getOp() == EOpInterpolateAtVertex) { - if (!arg0->getType().getQualifier().isExplicitInterpolation()) - error(loc, "argument must be qualified as __explicitInterpAMD in", "interpolant", ""); - else { - if (! (*argp)[1]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "vertex index", ""); - else { - unsigned vertexIdx = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getUConst(); - if (vertexIdx > 2) - error(loc, "must be in the range [0, 2]", "vertex index", ""); - } - } - } - } break; - - case EOpEmitStreamVertex: - case EOpEndStreamPrimitive: - if (version == 150) - requireExtensions(loc, 1, &E_GL_ARB_gpu_shader5, "if the verison is 150 , the EmitStreamVertex and EndStreamPrimitive only support at extension GL_ARB_gpu_shader5"); - intermediate.setMultiStream(); - break; - - case EOpSubgroupClusteredAdd: - case EOpSubgroupClusteredMul: - case EOpSubgroupClusteredMin: - case EOpSubgroupClusteredMax: - case EOpSubgroupClusteredAnd: - case EOpSubgroupClusteredOr: - case EOpSubgroupClusteredXor: - // The as used in the subgroupClustered() operations must be: - // - An integral constant expression. - // - At least 1. - // - A power of 2. - if ((*argp)[1]->getAsConstantUnion() == nullptr) - error(loc, "argument must be compile-time constant", "cluster size", ""); - else { - int size = (*argp)[1]->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (size < 1) - error(loc, "argument must be at least 1", "cluster size", ""); - else if (!IsPow2(size)) - error(loc, "argument must be a power of 2", "cluster size", ""); - } - break; - - case EOpSubgroupBroadcast: - case EOpSubgroupQuadBroadcast: - if (spvVersion.spv < EShTargetSpv_1_5) { - // must be an integral constant expression. - if ((*argp)[1]->getAsConstantUnion() == nullptr) - error(loc, "argument must be compile-time constant", "id", ""); - } - break; - - case EOpBarrier: - case EOpMemoryBarrier: - if (argp->size() > 0) { - requireExtensions(loc, 1, &E_GL_KHR_memory_scope_semantics, fnCandidate.getName().c_str()); - memorySemanticsCheck(loc, fnCandidate, callNode); - } - break; - - case EOpMix: - if (profile == EEsProfile && version < 310) { - // Look for specific signatures - if ((*argp)[0]->getAsTyped()->getBasicType() != EbtFloat && - (*argp)[1]->getAsTyped()->getBasicType() != EbtFloat && - (*argp)[2]->getAsTyped()->getBasicType() == EbtBool) { - requireExtensions(loc, 1, &E_GL_EXT_shader_integer_mix, "specific signature of builtin mix"); - } - } - - if (profile != EEsProfile && version < 450) { - if ((*argp)[0]->getAsTyped()->getBasicType() != EbtFloat && - (*argp)[0]->getAsTyped()->getBasicType() != EbtDouble && - (*argp)[1]->getAsTyped()->getBasicType() != EbtFloat && - (*argp)[1]->getAsTyped()->getBasicType() != EbtDouble && - (*argp)[2]->getAsTyped()->getBasicType() == EbtBool) { - requireExtensions(loc, 1, &E_GL_EXT_shader_integer_mix, fnCandidate.getName().c_str()); - } - } - - break; - - default: - break; - } - - // Texture operations on texture objects (aside from texelFetch on a - // textureBuffer) require EXT_samplerless_texture_functions. - switch (callNode.getOp()) { - case EOpTextureQuerySize: - case EOpTextureQueryLevels: - case EOpTextureQuerySamples: - case EOpTextureFetch: - case EOpTextureFetchOffset: - { - const TSampler& sampler = fnCandidate[0].type->getSampler(); - - const bool isTexture = sampler.isTexture() && !sampler.isCombined(); - const bool isBuffer = sampler.isBuffer(); - const bool isFetch = callNode.getOp() == EOpTextureFetch || callNode.getOp() == EOpTextureFetchOffset; - - if (isTexture && (!isBuffer || !isFetch)) - requireExtensions(loc, 1, &E_GL_EXT_samplerless_texture_functions, fnCandidate.getName().c_str()); - - break; - } - - default: - break; - } - - if (callNode.isSubgroup()) { - // these require SPIR-V 1.3 - if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_3) - error(loc, "requires SPIR-V 1.3", "subgroup op", ""); - - // Check that if extended types are being used that the correct extensions are enabled. - if (arg0 != nullptr) { - const TType& type = arg0->getType(); - bool enhanced = intermediate.getEnhancedMsgs(); - switch (type.getBasicType()) { - default: - break; - case EbtInt8: - case EbtUint8: - requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int8, type.getCompleteString(enhanced).c_str()); - break; - case EbtInt16: - case EbtUint16: - requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int16, type.getCompleteString(enhanced).c_str()); - break; - case EbtInt64: - case EbtUint64: - requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_int64, type.getCompleteString(enhanced).c_str()); - break; - case EbtFloat16: - requireExtensions(loc, 1, &E_GL_EXT_shader_subgroup_extended_types_float16, type.getCompleteString(enhanced).c_str()); - break; - } - } - } -} - - -// Deprecated! Use PureOperatorBuiltins == true instead, in which case this -// functionality is handled in builtInOpCheck() instead of here. -// -// Do additional checking of built-in function calls that were not mapped -// to built-in operations (e.g., texturing functions). -// -// Assumes there has been a semantically correct match to a built-in function. -// -void TParseContext::nonOpBuiltInCheck(const TSourceLoc& loc, const TFunction& fnCandidate, TIntermAggregate& callNode) -{ - // Further maintenance of this function is deprecated, because the "correct" - // future-oriented design is to not have to do string compares on function names. - - // If PureOperatorBuiltins == true, then all built-ins should be mapped - // to a TOperator, and this function would then never get called. - - assert(PureOperatorBuiltins == false); - - // built-in texturing functions get their return value precision from the precision of the sampler - if (fnCandidate.getType().getQualifier().precision == EpqNone && - fnCandidate.getParamCount() > 0 && fnCandidate[0].type->getBasicType() == EbtSampler) - callNode.getQualifier().precision = callNode.getSequence()[0]->getAsTyped()->getQualifier().precision; - - if (fnCandidate.getName().compare(0, 7, "texture") == 0) { - if (fnCandidate.getName().compare(0, 13, "textureGather") == 0) { - TString featureString = fnCandidate.getName() + "(...)"; - const char* feature = featureString.c_str(); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - - int compArg = -1; // track which argument, if any, is the constant component argument - if (fnCandidate.getName().compare("textureGatherOffset") == 0) { - // GL_ARB_texture_gather is good enough for 2D non-shadow textures with no component argument - if (fnCandidate[0].type->getSampler().dim == Esd2D && ! fnCandidate[0].type->getSampler().shadow && fnCandidate.getParamCount() == 3) - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); - else - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2; - if (! callNode.getSequence()[offsetArg]->getAsConstantUnion()) - profileRequires(loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, - "non-constant offset argument"); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - } else if (fnCandidate.getName().compare("textureGatherOffsets") == 0) { - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 3; - // check for constant offsets - int offsetArg = fnCandidate[0].type->getSampler().shadow ? 3 : 2; - if (! callNode.getSequence()[offsetArg]->getAsConstantUnion()) - error(loc, "must be a compile-time constant:", feature, "offsets argument"); - } else if (fnCandidate.getName().compare("textureGather") == 0) { - // More than two arguments needs gpu_shader5, and rectangular or shadow needs gpu_shader5, - // otherwise, need GL_ARB_texture_gather. - if (fnCandidate.getParamCount() > 2 || fnCandidate[0].type->getSampler().dim == EsdRect || fnCandidate[0].type->getSampler().shadow) { - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_gpu_shader5, feature); - if (! fnCandidate[0].type->getSampler().shadow) - compArg = 2; - } else - profileRequires(loc, ~EEsProfile, 400, E_GL_ARB_texture_gather, feature); - } - - if (compArg > 0 && compArg < fnCandidate.getParamCount()) { - if (callNode.getSequence()[compArg]->getAsConstantUnion()) { - int value = callNode.getSequence()[compArg]->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (value < 0 || value > 3) - error(loc, "must be 0, 1, 2, or 3:", feature, "component argument"); - } else - error(loc, "must be a compile-time constant:", feature, "component argument"); - } - } else { - // this is only for functions not starting "textureGather"... - if (fnCandidate.getName().find("Offset") != TString::npos) { - - // Handle texture-offset limits checking - int arg = -1; - if (fnCandidate.getName().compare("textureOffset") == 0) - arg = 2; - else if (fnCandidate.getName().compare("texelFetchOffset") == 0) - arg = 3; - else if (fnCandidate.getName().compare("textureProjOffset") == 0) - arg = 2; - else if (fnCandidate.getName().compare("textureLodOffset") == 0) - arg = 3; - else if (fnCandidate.getName().compare("textureProjLodOffset") == 0) - arg = 3; - else if (fnCandidate.getName().compare("textureGradOffset") == 0) - arg = 4; - else if (fnCandidate.getName().compare("textureProjGradOffset") == 0) - arg = 4; - - if (arg > 0) { - if (! callNode.getSequence()[arg]->getAsConstantUnion()) - error(loc, "argument must be compile-time constant", "texel offset", ""); - else { - const TType& type = callNode.getSequence()[arg]->getAsTyped()->getType(); - for (int c = 0; c < type.getVectorSize(); ++c) { - int offset = callNode.getSequence()[arg]->getAsConstantUnion()->getConstArray()[c].getIConst(); - if (offset > resources.maxProgramTexelOffset || offset < resources.minProgramTexelOffset) - error(loc, "value is out of range:", "texel offset", "[gl_MinProgramTexelOffset, gl_MaxProgramTexelOffset]"); - } - } - } - } - } - } - - // GL_ARB_shader_texture_image_samples - if (fnCandidate.getName().compare(0, 14, "textureSamples") == 0 || fnCandidate.getName().compare(0, 12, "imageSamples") == 0) - profileRequires(loc, ~EEsProfile, 450, E_GL_ARB_shader_texture_image_samples, "textureSamples and imageSamples"); - - if (fnCandidate.getName().compare(0, 11, "imageAtomic") == 0) { - const TType& imageType = callNode.getSequence()[0]->getAsTyped()->getType(); - if (imageType.getSampler().type == EbtInt || imageType.getSampler().type == EbtUint) { - if (imageType.getQualifier().getFormat() != ElfR32i && imageType.getQualifier().getFormat() != ElfR32ui) - error(loc, "only supported on image with format r32i or r32ui", fnCandidate.getName().c_str(), ""); - } else { - if (fnCandidate.getName().compare(0, 19, "imageAtomicExchange") != 0) - error(loc, "only supported on integer images", fnCandidate.getName().c_str(), ""); - else if (imageType.getQualifier().getFormat() != ElfR32f && isEsProfile()) - error(loc, "only supported on image with format r32f", fnCandidate.getName().c_str(), ""); - } - } -} - -// -// Do any extra checking for a user function call. -// -void TParseContext::userFunctionCallCheck(const TSourceLoc& loc, TIntermAggregate& callNode) -{ - TIntermSequence& arguments = callNode.getSequence(); - - for (int i = 0; i < (int)arguments.size(); ++i) - samplerConstructorLocationCheck(loc, "call argument", arguments[i]); -} - -// -// Emit an error if this is a sampler constructor -// -void TParseContext::samplerConstructorLocationCheck(const TSourceLoc& loc, const char* token, TIntermNode* node) -{ - if (node->getAsOperator() && node->getAsOperator()->getOp() == EOpConstructTextureSampler) - error(loc, "sampler constructor must appear at point of use", token, ""); -} - -// -// Handle seeing a built-in constructor in a grammar production. -// -TFunction* TParseContext::handleConstructorCall(const TSourceLoc& loc, const TPublicType& publicType) -{ - TType type(publicType); - type.getQualifier().precision = EpqNone; - - if (type.isArray()) { - profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed constructor"); - profileRequires(loc, EEsProfile, 300, nullptr, "arrayed constructor"); - } - - // Reuse EOpConstructTextureSampler for bindless image constructor - // uvec2 imgHandle; - // imageLoad(image1D(imgHandle), 0); - if (type.isImage() && extensionTurnedOn(E_GL_ARB_bindless_texture)) - { - intermediate.setBindlessImageMode(currentCaller, AstRefTypeFunc); - } - - TOperator op = intermediate.mapTypeToConstructorOp(type); - - if (op == EOpNull) { - if (intermediate.getEnhancedMsgs() && type.getBasicType() == EbtSampler) - error(loc, "function not supported in this version; use texture() instead", "texture*D*", ""); - else - error(loc, "cannot construct this type", type.getBasicString(), ""); - op = EOpConstructFloat; - TType errorType(EbtFloat); - type.shallowCopy(errorType); - } - - TString empty(""); - - return new TFunction(&empty, type, op); -} - -// Handle seeing a precision qualifier in the grammar. -void TParseContext::handlePrecisionQualifier(const TSourceLoc& /*loc*/, TQualifier& qualifier, TPrecisionQualifier precision) -{ - if (obeyPrecisionQualifiers()) - qualifier.precision = precision; -} - -// Check for messages to give on seeing a precision qualifier used in a -// declaration in the grammar. -void TParseContext::checkPrecisionQualifier(const TSourceLoc& loc, TPrecisionQualifier) -{ - if (precisionManager.shouldWarnAboutDefaults()) { - warn(loc, "all default precisions are highp; use precision statements to quiet warning, e.g.:\n" - " \"precision mediump int; precision highp float;\"", "", ""); - precisionManager.defaultWarningGiven(); - } -} - -// -// Same error message for all places assignments don't work. -// -void TParseContext::assignError(const TSourceLoc& loc, const char* op, TString left, TString right) -{ - error(loc, "", op, "cannot convert from '%s' to '%s'", - right.c_str(), left.c_str()); -} - -// -// Same error message for all places unary operations don't work. -// -void TParseContext::unaryOpError(const TSourceLoc& loc, const char* op, TString operand) -{ - error(loc, " wrong operand type", op, - "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)", - op, operand.c_str()); -} - -// -// Same error message for all binary operations don't work. -// -void TParseContext::binaryOpError(const TSourceLoc& loc, const char* op, TString left, TString right) -{ - error(loc, " wrong operand types:", op, - "no operation '%s' exists that takes a left-hand operand of type '%s' and " - "a right operand of type '%s' (or there is no acceptable conversion)", - op, left.c_str(), right.c_str()); -} - -// -// A basic type of EbtVoid is a key that the name string was seen in the source, but -// it was not found as a variable in the symbol table. If so, give the error -// message and insert a dummy variable in the symbol table to prevent future errors. -// -void TParseContext::variableCheck(TIntermTyped*& nodePtr) -{ - TIntermSymbol* symbol = nodePtr->getAsSymbolNode(); - if (! symbol) - return; - - if (symbol->getType().getBasicType() == EbtVoid) { - const char *extraInfoFormat = ""; - if (spvVersion.vulkan != 0 && symbol->getName() == "gl_VertexID") { - extraInfoFormat = "(Did you mean gl_VertexIndex?)"; - } else if (spvVersion.vulkan != 0 && symbol->getName() == "gl_InstanceID") { - extraInfoFormat = "(Did you mean gl_InstanceIndex?)"; - } - error(symbol->getLoc(), "undeclared identifier", symbol->getName().c_str(), extraInfoFormat); - - // Add to symbol table to prevent future error messages on the same name - if (symbol->getName().size() > 0) { - TVariable* fakeVariable = new TVariable(&symbol->getName(), TType(EbtFloat)); - symbolTable.insert(*fakeVariable); - - // substitute a symbol node for this new variable - nodePtr = intermediate.addSymbol(*fakeVariable, symbol->getLoc()); - } - } else { - switch (symbol->getQualifier().storage) { - case EvqPointCoord: - profileRequires(symbol->getLoc(), ENoProfile, 120, nullptr, "gl_PointCoord"); - break; - default: break; // some compilers want this - } - } -} - -// -// Both test and if necessary, spit out an error, to see if the node is really -// an l-value that can be operated on this way. -// -// Returns true if there was an error. -// -bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) -{ - TIntermBinary* binaryNode = node->getAsBinaryNode(); - - if (binaryNode) { - bool errorReturn = false; - - switch(binaryNode->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: - // ... tessellation control shader ... - // If a per-vertex output variable is used as an l-value, it is a - // compile-time or link-time error if the expression indicating the - // vertex index is not the identifier gl_InvocationID. - if (language == EShLangTessControl) { - const TType& leftType = binaryNode->getLeft()->getType(); - if (leftType.getQualifier().storage == EvqVaryingOut && ! leftType.getQualifier().patch && binaryNode->getLeft()->getAsSymbolNode()) { - // we have a per-vertex output - const TIntermSymbol* rightSymbol = binaryNode->getRight()->getAsSymbolNode(); - if (! rightSymbol || rightSymbol->getQualifier().builtIn != EbvInvocationId) - error(loc, "tessellation-control per-vertex output l-value must be indexed with gl_InvocationID", "[]", ""); - } - } - break; // left node is checked by base class - case EOpVectorSwizzle: - errorReturn = lValueErrorCheck(loc, op, binaryNode->getLeft()); - if (!errorReturn) { - int offset[4] = {0,0,0,0}; - - TIntermTyped* rightNode = binaryNode->getRight(); - TIntermAggregate *aggrNode = rightNode->getAsAggregate(); - - for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); - p != aggrNode->getSequence().end(); p++) { - int value = (*p)->getAsTyped()->getAsConstantUnion()->getConstArray()[0].getIConst(); - offset[value]++; - if (offset[value] > 1) { - error(loc, " l-value of swizzle cannot have duplicate components", op, "", ""); - - return true; - } - } - } - - return errorReturn; - default: - break; - } - - if (errorReturn) { - error(loc, " l-value required", op, "", ""); - return true; - } - } - - if (binaryNode && binaryNode->getOp() == EOpIndexDirectStruct && binaryNode->getLeft()->isReference()) - return false; - - // Let the base class check errors - if (TParseContextBase::lValueErrorCheck(loc, op, node)) - return true; - - const char* symbol = nullptr; - TIntermSymbol* symNode = node->getAsSymbolNode(); - if (symNode != nullptr) - symbol = symNode->getName().c_str(); - - const char* message = nullptr; - switch (node->getQualifier().storage) { - case EvqVaryingIn: message = "can't modify shader input"; break; - case EvqInstanceId: message = "can't modify gl_InstanceID"; break; - case EvqVertexId: message = "can't modify gl_VertexID"; break; - case EvqFace: message = "can't modify gl_FrontFace"; break; - case EvqFragCoord: message = "can't modify gl_FragCoord"; break; - case EvqPointCoord: message = "can't modify gl_PointCoord"; break; - case EvqFragDepth: - intermediate.setDepthReplacing(); - // "In addition, it is an error to statically write to gl_FragDepth in the fragment shader." - if (isEsProfile() && intermediate.getEarlyFragmentTests()) - message = "can't modify gl_FragDepth if using early_fragment_tests"; - break; - case EvqFragStencil: - intermediate.setStencilReplacing(); - // "In addition, it is an error to statically write to gl_FragDepth in the fragment shader." - if (isEsProfile() && intermediate.getEarlyFragmentTests()) - message = "can't modify EvqFragStencil if using early_fragment_tests"; - break; - - case EvqtaskPayloadSharedEXT: - if (language == EShLangMesh) - message = "can't modify variable with storage qualifier taskPayloadSharedEXT in mesh shaders"; - break; - default: - break; - } - - if (message == nullptr && binaryNode == nullptr && symNode == nullptr) { - error(loc, " l-value required", op, "", ""); - - return true; - } - - // - // Everything else is okay, no error. - // - if (message == nullptr) - return false; - - // - // If we get here, we have an error and a message. - // - if (symNode) - error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message); - else - error(loc, " l-value required", op, "(%s)", message); - - return true; -} - -// Test for and give an error if the node can't be read from. -void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) -{ - // Let the base class check errors - TParseContextBase::rValueErrorCheck(loc, op, node); - - TIntermSymbol* symNode = node->getAsSymbolNode(); - if (!(symNode && symNode->getQualifier().isWriteOnly())) // base class checks - if (symNode && symNode->getQualifier().isExplicitInterpolation()) - error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str()); - - // local_size_{xyz} must be assigned or specialized before gl_WorkGroupSize can be assigned. - if(node->getQualifier().builtIn == EbvWorkGroupSize && - !(intermediate.isLocalSizeSet() || intermediate.isLocalSizeSpecialized())) - error(loc, "can't read from gl_WorkGroupSize before a fixed workgroup size has been declared", op, ""); -} - -// -// Both test, and if necessary spit out an error, to see if the node is really -// a constant. -// -void TParseContext::constantValueCheck(TIntermTyped* node, const char* token) -{ - if (! node->getQualifier().isConstant()) - error(node->getLoc(), "constant expression required", token, ""); -} - -// -// Both test, and if necessary spit out an error, to see if the node is really -// a 32-bit integer or can implicitly convert to one. -// -void TParseContext::integerCheck(const TIntermTyped* node, const char* token) -{ - auto from_type = node->getBasicType(); - if ((from_type == EbtInt || from_type == EbtUint || - intermediate.canImplicitlyPromote(from_type, EbtInt, EOpNull) || - intermediate.canImplicitlyPromote(from_type, EbtUint, EOpNull)) && node->isScalar()) - return; - - error(node->getLoc(), "scalar integer expression required", token, ""); -} - -// -// Both test, and if necessary spit out an error, to see if we are currently -// globally scoped. -// -void TParseContext::globalCheck(const TSourceLoc& loc, const char* token) -{ - if (! symbolTable.atGlobalLevel()) - error(loc, "not allowed in nested scope", token, ""); -} - -// -// Reserved errors for GLSL. -// -void TParseContext::reservedErrorCheck(const TSourceLoc& loc, const TString& identifier) -{ - // "Identifiers starting with "gl_" are reserved for use by OpenGL, and may not be - // declared in a shader; this results in a compile-time error." - if (! symbolTable.atBuiltInLevel()) { - if (builtInName(identifier) && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) - // The extension GL_EXT_spirv_intrinsics allows us to declare identifiers starting with "gl_". - error(loc, "identifiers starting with \"gl_\" are reserved", identifier.c_str(), ""); - - // "__" are not supposed to be an error. ES 300 (and desktop) added the clarification: - // "In addition, all identifiers containing two consecutive underscores (__) are - // reserved; using such a name does not itself result in an error, but may result - // in undefined behavior." - // however, before that, ES tests required an error. - if (identifier.find("__") != TString::npos && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) { - // The extension GL_EXT_spirv_intrinsics allows us to declare identifiers starting with "__". - if (isEsProfile() && version < 300) - error(loc, "identifiers containing consecutive underscores (\"__\") are reserved, and an error if version < 300", identifier.c_str(), ""); - else - warn(loc, "identifiers containing consecutive underscores (\"__\") are reserved", identifier.c_str(), ""); - } - } -} - -// -// Reserved errors for the preprocessor. -// -void TParseContext::reservedPpErrorCheck(const TSourceLoc& loc, const char* identifier, const char* op) -{ - // "__" are not supposed to be an error. ES 300 (and desktop) added the clarification: - // "All macro names containing two consecutive underscores ( __ ) are reserved; - // defining such a name does not itself result in an error, but may result in - // undefined behavior. All macro names prefixed with "GL_" ("GL" followed by a - // single underscore) are also reserved, and defining such a name results in a - // compile-time error." - // however, before that, ES tests required an error. - if (strncmp(identifier, "GL_", 3) == 0 && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) - // The extension GL_EXT_spirv_intrinsics allows us to declare macros prefixed with "GL_". - ppError(loc, "names beginning with \"GL_\" can't be (un)defined:", op, identifier); - else if (strncmp(identifier, "defined", 8) == 0) - if (relaxedErrors()) - ppWarn(loc, "\"defined\" is (un)defined:", op, identifier); - else - ppError(loc, "\"defined\" can't be (un)defined:", op, identifier); - else if (strstr(identifier, "__") != nullptr && !extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) { - // The extension GL_EXT_spirv_intrinsics allows us to declare macros prefixed with "__". - if (isEsProfile() && version >= 300 && - (strcmp(identifier, "__LINE__") == 0 || - strcmp(identifier, "__FILE__") == 0 || - strcmp(identifier, "__VERSION__") == 0)) - ppError(loc, "predefined names can't be (un)defined:", op, identifier); - else { - if (isEsProfile() && version < 300 && !relaxedErrors()) - ppError(loc, "names containing consecutive underscores are reserved, and an error if version < 300:", op, identifier); - else - ppWarn(loc, "names containing consecutive underscores are reserved:", op, identifier); - } - } -} - -// -// See if this version/profile allows use of the line-continuation character '\'. -// -// Returns true if a line continuation should be done. -// -bool TParseContext::lineContinuationCheck(const TSourceLoc& loc, bool endOfComment) -{ - const char* message = "line continuation"; - - bool lineContinuationAllowed = (isEsProfile() && version >= 300) || - (!isEsProfile() && (version >= 420 || extensionTurnedOn(E_GL_ARB_shading_language_420pack))); - - if (endOfComment) { - if (lineContinuationAllowed) - warn(loc, "used at end of comment; the following line is still part of the comment", message, ""); - else - warn(loc, "used at end of comment, but this version does not provide line continuation", message, ""); - - return lineContinuationAllowed; - } - - if (relaxedErrors()) { - if (! lineContinuationAllowed) - warn(loc, "not allowed in this version", message, ""); - return true; - } else { - profileRequires(loc, EEsProfile, 300, nullptr, message); - profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, message); - } - - return lineContinuationAllowed; -} - -bool TParseContext::builtInName(const TString& identifier) -{ - return identifier.compare(0, 3, "gl_") == 0; -} - -// -// Make sure there is enough data and not too many arguments provided to the -// constructor to build something of the type of the constructor. Also returns -// the type of the constructor. -// -// Part of establishing type is establishing specialization-constness. -// We don't yet know "top down" whether type is a specialization constant, -// but a const constructor can becomes a specialization constant if any of -// its children are, subject to KHR_vulkan_glsl rules: -// -// - int(), uint(), and bool() constructors for type conversions -// from any of the following types to any of the following types: -// * int -// * uint -// * bool -// - vector versions of the above conversion constructors -// -// Returns true if there was an error in construction. -// -bool TParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node, TFunction& function, TOperator op, TType& type) -{ - // See if the constructor does not establish the main type, only requalifies - // it, in which case the type comes from the argument instead of from the - // constructor function. - switch (op) { - case EOpConstructNonuniform: - if (node != nullptr && node->getAsTyped() != nullptr) { - type.shallowCopy(node->getAsTyped()->getType()); - type.getQualifier().makeTemporary(); - type.getQualifier().nonUniform = true; - } - break; - default: - type.shallowCopy(function.getType()); - break; - } - - TString constructorString; - if (intermediate.getEnhancedMsgs()) - constructorString.append(type.getCompleteString(true, false, false, true)).append(" constructor"); - else - constructorString.append("constructor"); - - // See if it's a matrix - bool constructingMatrix = false; - switch (op) { - case EOpConstructTextureSampler: - return constructorTextureSamplerError(loc, function); - case EOpConstructMat2x2: - case EOpConstructMat2x3: - case EOpConstructMat2x4: - case EOpConstructMat3x2: - case EOpConstructMat3x3: - case EOpConstructMat3x4: - case EOpConstructMat4x2: - case EOpConstructMat4x3: - case EOpConstructMat4x4: - case EOpConstructDMat2x2: - case EOpConstructDMat2x3: - case EOpConstructDMat2x4: - case EOpConstructDMat3x2: - case EOpConstructDMat3x3: - case EOpConstructDMat3x4: - case EOpConstructDMat4x2: - case EOpConstructDMat4x3: - case EOpConstructDMat4x4: - case EOpConstructF16Mat2x2: - case EOpConstructF16Mat2x3: - case EOpConstructF16Mat2x4: - case EOpConstructF16Mat3x2: - case EOpConstructF16Mat3x3: - case EOpConstructF16Mat3x4: - case EOpConstructF16Mat4x2: - case EOpConstructF16Mat4x3: - case EOpConstructF16Mat4x4: - constructingMatrix = true; - break; - default: - break; - } - - // - // Walk the arguments for first-pass checks and collection of information. - // - - int size = 0; - bool constType = true; - bool specConstType = false; // value is only valid if constType is true - bool full = false; - bool overFull = false; - bool matrixInMatrix = false; - bool arrayArg = false; - bool floatArgument = false; - bool intArgument = false; - for (int arg = 0; arg < function.getParamCount(); ++arg) { - if (function[arg].type->isArray()) { - if (function[arg].type->isUnsizedArray()) { - // Can't construct from an unsized array. - error(loc, "array argument must be sized", constructorString.c_str(), ""); - return true; - } - arrayArg = true; - } - if (constructingMatrix && function[arg].type->isMatrix()) - matrixInMatrix = true; - - // 'full' will go to true when enough args have been seen. If we loop - // again, there is an extra argument. - if (full) { - // For vectors and matrices, it's okay to have too many components - // available, but not okay to have unused arguments. - overFull = true; - } - - size += function[arg].type->computeNumComponents(); - if (op != EOpConstructStruct && ! type.isArray() && size >= type.computeNumComponents()) - full = true; - - if (! function[arg].type->getQualifier().isConstant()) - constType = false; - if (function[arg].type->getQualifier().isSpecConstant()) - specConstType = true; - if (function[arg].type->isFloatingDomain()) - floatArgument = true; - if (function[arg].type->isIntegerDomain()) - intArgument = true; - if (type.isStruct()) { - if (function[arg].type->contains16BitFloat()) { - requireFloat16Arithmetic(loc, constructorString.c_str(), "can't construct structure containing 16-bit type"); - } - if (function[arg].type->contains16BitInt()) { - requireInt16Arithmetic(loc, constructorString.c_str(), "can't construct structure containing 16-bit type"); - } - if (function[arg].type->contains8BitInt()) { - requireInt8Arithmetic(loc, constructorString.c_str(), "can't construct structure containing 8-bit type"); - } - } - } - if (op == EOpConstructNonuniform) - constType = false; - - switch (op) { - case EOpConstructFloat16: - case EOpConstructF16Vec2: - case EOpConstructF16Vec3: - case EOpConstructF16Vec4: - if (type.isArray()) - requireFloat16Arithmetic(loc, constructorString.c_str(), "16-bit arrays not supported"); - if (type.isVector() && function.getParamCount() != 1) - requireFloat16Arithmetic(loc, constructorString.c_str(), "16-bit vectors only take vector types"); - break; - case EOpConstructUint16: - case EOpConstructU16Vec2: - case EOpConstructU16Vec3: - case EOpConstructU16Vec4: - case EOpConstructInt16: - case EOpConstructI16Vec2: - case EOpConstructI16Vec3: - case EOpConstructI16Vec4: - if (type.isArray()) - requireInt16Arithmetic(loc, constructorString.c_str(), "16-bit arrays not supported"); - if (type.isVector() && function.getParamCount() != 1) - requireInt16Arithmetic(loc, constructorString.c_str(), "16-bit vectors only take vector types"); - break; - case EOpConstructUint8: - case EOpConstructU8Vec2: - case EOpConstructU8Vec3: - case EOpConstructU8Vec4: - case EOpConstructInt8: - case EOpConstructI8Vec2: - case EOpConstructI8Vec3: - case EOpConstructI8Vec4: - if (type.isArray()) - requireInt8Arithmetic(loc, constructorString.c_str(), "8-bit arrays not supported"); - if (type.isVector() && function.getParamCount() != 1) - requireInt8Arithmetic(loc, constructorString.c_str(), "8-bit vectors only take vector types"); - break; - default: - break; - } - - // inherit constness from children - if (constType) { - bool makeSpecConst; - // Finish pinning down spec-const semantics - if (specConstType) { - switch (op) { - case EOpConstructInt8: - case EOpConstructInt: - case EOpConstructUint: - case EOpConstructBool: - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructUint8: - case EOpConstructInt16: - case EOpConstructUint16: - case EOpConstructInt64: - case EOpConstructUint64: - case EOpConstructI8Vec2: - case EOpConstructI8Vec3: - case EOpConstructI8Vec4: - case EOpConstructU8Vec2: - case EOpConstructU8Vec3: - case EOpConstructU8Vec4: - case EOpConstructI16Vec2: - case EOpConstructI16Vec3: - case EOpConstructI16Vec4: - case EOpConstructU16Vec2: - case EOpConstructU16Vec3: - case EOpConstructU16Vec4: - case EOpConstructI64Vec2: - case EOpConstructI64Vec3: - case EOpConstructI64Vec4: - case EOpConstructU64Vec2: - case EOpConstructU64Vec3: - case EOpConstructU64Vec4: - // This was the list of valid ones, if they aren't converting from float - // and aren't making an array. - makeSpecConst = ! floatArgument && ! type.isArray(); - break; - - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - // This was the list of valid ones, if they aren't converting from int - // and aren't making an array. - makeSpecConst = ! intArgument && !type.isArray(); - break; - - default: - // anything else wasn't white-listed in the spec as a conversion - makeSpecConst = false; - break; - } - } else - makeSpecConst = false; - - if (makeSpecConst) - type.getQualifier().makeSpecConstant(); - else if (specConstType) - type.getQualifier().makeTemporary(); - else - type.getQualifier().storage = EvqConst; - } - - if (type.isArray()) { - if (function.getParamCount() == 0) { - error(loc, "array constructor must have at least one argument", constructorString.c_str(), ""); - return true; - } - - if (type.isUnsizedArray()) { - // auto adapt the constructor type to the number of arguments - type.changeOuterArraySize(function.getParamCount()); - } else if (type.getOuterArraySize() != function.getParamCount()) { - error(loc, "array constructor needs one argument per array element", constructorString.c_str(), ""); - return true; - } - - if (type.isArrayOfArrays()) { - // Types have to match, but we're still making the type. - // Finish making the type, and the comparison is done later - // when checking for conversion. - TArraySizes& arraySizes = *type.getArraySizes(); - - // At least the dimensionalities have to match. - if (! function[0].type->isArray() || - arraySizes.getNumDims() != function[0].type->getArraySizes()->getNumDims() + 1) { - error(loc, "array constructor argument not correct type to construct array element", constructorString.c_str(), ""); - return true; - } - - if (arraySizes.isInnerUnsized()) { - // "Arrays of arrays ..., and the size for any dimension is optional" - // That means we need to adopt (from the first argument) the other array sizes into the type. - for (int d = 1; d < arraySizes.getNumDims(); ++d) { - if (arraySizes.getDimSize(d) == UnsizedArraySize) { - arraySizes.setDimSize(d, function[0].type->getArraySizes()->getDimSize(d - 1)); - } - } - } - } - } - - if (arrayArg && op != EOpConstructStruct && ! type.isArrayOfArrays()) { - error(loc, "constructing non-array constituent from array argument", constructorString.c_str(), ""); - return true; - } - - if (matrixInMatrix && ! type.isArray()) { - profileRequires(loc, ENoProfile, 120, nullptr, "constructing matrix from matrix"); - - // "If a matrix argument is given to a matrix constructor, - // it is a compile-time error to have any other arguments." - if (function.getParamCount() != 1) - error(loc, "matrix constructed from matrix can only have one argument", constructorString.c_str(), ""); - return false; - } - - if (overFull) { - error(loc, "too many arguments", constructorString.c_str(), ""); - return true; - } - - if (op == EOpConstructStruct && ! type.isArray() && (int)type.getStruct()->size() != function.getParamCount()) { - error(loc, "Number of constructor parameters does not match the number of structure fields", constructorString.c_str(), ""); - return true; - } - - if ((op != EOpConstructStruct && size != 1 && size < type.computeNumComponents()) || - (op == EOpConstructStruct && size < type.computeNumComponents())) { - error(loc, "not enough data provided for construction", constructorString.c_str(), ""); - return true; - } - - if (type.isCoopMat() && function.getParamCount() != 1) { - error(loc, "wrong number of arguments", constructorString.c_str(), ""); - return true; - } - if (type.isCoopMat() && - !(function[0].type->isScalar() || function[0].type->isCoopMat())) { - error(loc, "Cooperative matrix constructor argument must be scalar or cooperative matrix", constructorString.c_str(), ""); - return true; - } - - TIntermTyped* typed = node->getAsTyped(); - if (type.isCoopMat() && typed->getType().isCoopMat() && - !type.sameCoopMatShapeAndUse(typed->getType())) { - error(loc, "Cooperative matrix type parameters mismatch", constructorString.c_str(), ""); - return true; - } - - if (typed == nullptr) { - error(loc, "constructor argument does not have a type", constructorString.c_str(), ""); - return true; - } - if (op != EOpConstructStruct && op != EOpConstructNonuniform && typed->getBasicType() == EbtSampler) { - if (op == EOpConstructUVec2 && extensionTurnedOn(E_GL_ARB_bindless_texture)) { - intermediate.setBindlessTextureMode(currentCaller, AstRefTypeFunc); - } - else { - error(loc, "cannot convert a sampler", constructorString.c_str(), ""); - return true; - } - } - if (op != EOpConstructStruct && typed->isAtomic()) { - error(loc, "cannot convert an atomic_uint", constructorString.c_str(), ""); - return true; - } - if (typed->getBasicType() == EbtVoid) { - error(loc, "cannot convert a void", constructorString.c_str(), ""); - return true; - } - - return false; -} - -// Verify all the correct semantics for constructing a combined texture/sampler. -// Return true if the semantics are incorrect. -bool TParseContext::constructorTextureSamplerError(const TSourceLoc& loc, const TFunction& function) -{ - TString constructorName = function.getType().getBasicTypeString(); // TODO: performance: should not be making copy; interface needs to change - const char* token = constructorName.c_str(); - // verify the constructor for bindless texture, the input must be ivec2 or uvec2 - if (function.getParamCount() == 1) { - TType* pType = function[0].type; - TBasicType basicType = pType->getBasicType(); - bool isIntegerVec2 = ((basicType == EbtUint || basicType == EbtInt) && pType->getVectorSize() == 2); - bool bindlessMode = extensionTurnedOn(E_GL_ARB_bindless_texture); - if (isIntegerVec2 && bindlessMode) { - if (pType->getSampler().isImage()) - intermediate.setBindlessImageMode(currentCaller, AstRefTypeFunc); - else - intermediate.setBindlessTextureMode(currentCaller, AstRefTypeFunc); - return false; - } else { - if (!bindlessMode) - error(loc, "sampler-constructor requires the extension GL_ARB_bindless_texture enabled", token, ""); - else - error(loc, "sampler-constructor requires the input to be ivec2 or uvec2", token, ""); - return true; - } - } - - // exactly two arguments needed - if (function.getParamCount() != 2) { - error(loc, "sampler-constructor requires two arguments", token, ""); - return true; - } - - // For now, not allowing arrayed constructors, the rest of this function - // is set up to allow them, if this test is removed: - if (function.getType().isArray()) { - error(loc, "sampler-constructor cannot make an array of samplers", token, ""); - return true; - } - - // first argument - // * the constructor's first argument must be a texture type - // * the dimensionality (1D, 2D, 3D, Cube, Rect, Buffer, MS, and Array) - // of the texture type must match that of the constructed sampler type - // (that is, the suffixes of the type of the first argument and the - // type of the constructor will be spelled the same way) - if (function[0].type->getBasicType() != EbtSampler || - ! function[0].type->getSampler().isTexture() || - function[0].type->isArray()) { - error(loc, "sampler-constructor first argument must be a scalar *texture* type", token, ""); - return true; - } - // simulate the first argument's impact on the result type, so it can be compared with the encapsulated operator!=() - TSampler texture = function.getType().getSampler(); - texture.setCombined(false); - texture.shadow = false; - if (texture != function[0].type->getSampler()) { - error(loc, "sampler-constructor first argument must be a *texture* type" - " matching the dimensionality and sampled type of the constructor", token, ""); - return true; - } - - // second argument - // * the constructor's second argument must be a scalar of type - // *sampler* or *samplerShadow* - if ( function[1].type->getBasicType() != EbtSampler || - ! function[1].type->getSampler().isPureSampler() || - function[1].type->isArray()) { - error(loc, "sampler-constructor second argument must be a scalar sampler or samplerShadow", token, ""); - return true; - } - - return false; -} - -// Checks to see if a void variable has been declared and raise an error message for such a case -// -// returns true in case of an error -// -bool TParseContext::voidErrorCheck(const TSourceLoc& loc, const TString& identifier, const TBasicType basicType) -{ - if (basicType == EbtVoid) { - error(loc, "illegal use of type 'void'", identifier.c_str(), ""); - return true; - } - - return false; -} - -// Checks to see if the node (for the expression) contains a scalar boolean expression or not -void TParseContext::boolCheck(const TSourceLoc& loc, const TIntermTyped* type) -{ - if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) - error(loc, "boolean expression expected", "", ""); -} - -// This function checks to see if the node (for the expression) contains a scalar boolean expression or not -void TParseContext::boolCheck(const TSourceLoc& loc, const TPublicType& pType) -{ - if (pType.basicType != EbtBool || pType.arraySizes || pType.matrixCols > 1 || (pType.vectorSize > 1)) - error(loc, "boolean expression expected", "", ""); -} - -void TParseContext::samplerCheck(const TSourceLoc& loc, const TType& type, const TString& identifier, TIntermTyped* /*initializer*/) -{ - // Check that the appropriate extension is enabled if external sampler is used. - // There are two extensions. The correct one must be used based on GLSL version. - if (type.getBasicType() == EbtSampler && type.getSampler().isExternal()) { - if (version < 300) { - requireExtensions(loc, 1, &E_GL_OES_EGL_image_external, "samplerExternalOES"); - } else { - requireExtensions(loc, 1, &E_GL_OES_EGL_image_external_essl3, "samplerExternalOES"); - } - } - if (type.getSampler().isYuv()) { - requireExtensions(loc, 1, &E_GL_EXT_YUV_target, "__samplerExternal2DY2YEXT"); - } - - if (type.getQualifier().storage == EvqUniform) - return; - - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtSampler)) { - // For bindless texture, sampler can be declared as an struct member - if (extensionTurnedOn(E_GL_ARB_bindless_texture)) { - if (type.getSampler().isImage()) - intermediate.setBindlessImageMode(currentCaller, AstRefTypeVar); - else - intermediate.setBindlessTextureMode(currentCaller, AstRefTypeVar); - } - else { - error(loc, "non-uniform struct contains a sampler or image:", type.getBasicTypeString().c_str(), identifier.c_str()); - } - } - else if (type.getBasicType() == EbtSampler && type.getQualifier().storage != EvqUniform) { - // For bindless texture, sampler can be declared as an input/output/block member - if (extensionTurnedOn(E_GL_ARB_bindless_texture)) { - if (type.getSampler().isImage()) - intermediate.setBindlessImageMode(currentCaller, AstRefTypeVar); - else - intermediate.setBindlessTextureMode(currentCaller, AstRefTypeVar); - } - else { - // non-uniform sampler - // not yet: okay if it has an initializer - // if (! initializer) - if (type.getSampler().isAttachmentEXT() && type.getQualifier().storage != EvqTileImageEXT) - error(loc, "can only be used in tileImageEXT variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); - else if (type.getQualifier().storage != EvqTileImageEXT) - error(loc, "sampler/image types can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); - } - } -} - -void TParseContext::atomicUintCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) -{ - if (type.getQualifier().storage == EvqUniform) - return; - - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAtomicUint)) - error(loc, "non-uniform struct contains an atomic_uint:", type.getBasicTypeString().c_str(), identifier.c_str()); - else if (type.getBasicType() == EbtAtomicUint && type.getQualifier().storage != EvqUniform) - error(loc, "atomic_uints can only be used in uniform variables or function parameters:", type.getBasicTypeString().c_str(), identifier.c_str()); -} - -void TParseContext::accStructCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) -{ - if (type.getQualifier().storage == EvqUniform) - return; - - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtAccStruct)) - error(loc, "non-uniform struct contains an accelerationStructureNV:", type.getBasicTypeString().c_str(), identifier.c_str()); - else if (type.getBasicType() == EbtAccStruct && type.getQualifier().storage != EvqUniform) - error(loc, "accelerationStructureNV can only be used in uniform variables or function parameters:", - type.getBasicTypeString().c_str(), identifier.c_str()); - -} - -void TParseContext::transparentOpaqueCheck(const TSourceLoc& loc, const TType& type, const TString& identifier) -{ - if (parsingBuiltins) - return; - - if (type.getQualifier().storage != EvqUniform) - return; - - if (type.containsNonOpaque()) { - // Vulkan doesn't allow transparent uniforms outside of blocks - if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed) - vulkanRemoved(loc, "non-opaque uniforms outside a block"); - // OpenGL wants locations on these (unless they are getting automapped) - if (spvVersion.openGl > 0 && !type.getQualifier().hasLocation() && !intermediate.getAutoMapLocations()) - error(loc, "non-opaque uniform variables need a layout(location=L)", identifier.c_str(), ""); - } -} - -// -// Qualifier checks knowing the qualifier and that it is a member of a struct/block. -// -void TParseContext::memberQualifierCheck(glslang::TPublicType& publicType) -{ - globalQualifierFixCheck(publicType.loc, publicType.qualifier, true); - checkNoShaderLayouts(publicType.loc, publicType.shaderQualifiers); - if (publicType.qualifier.isNonUniform()) { - error(publicType.loc, "not allowed on block or structure members", "nonuniformEXT", ""); - publicType.qualifier.nonUniform = false; - } -} - -// -// Check/fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level. -// -void TParseContext::globalQualifierFixCheck(const TSourceLoc& loc, TQualifier& qualifier, bool isMemberCheck, const TPublicType* publicType) -{ - bool nonuniformOkay = false; - - // move from parameter/unknown qualifiers to pipeline in/out qualifiers - switch (qualifier.storage) { - case EvqIn: - profileRequires(loc, ENoProfile, 130, nullptr, "in for stage inputs"); - profileRequires(loc, EEsProfile, 300, nullptr, "in for stage inputs"); - qualifier.storage = EvqVaryingIn; - nonuniformOkay = true; - break; - case EvqOut: - profileRequires(loc, ENoProfile, 130, nullptr, "out for stage outputs"); - profileRequires(loc, EEsProfile, 300, nullptr, "out for stage outputs"); - qualifier.storage = EvqVaryingOut; - if (intermediate.isInvariantAll()) - qualifier.invariant = true; - break; - case EvqInOut: - qualifier.storage = EvqVaryingIn; - error(loc, "cannot use 'inout' at global scope", "", ""); - break; - case EvqGlobal: - case EvqTemporary: - nonuniformOkay = true; - break; - case EvqUniform: - // According to GLSL spec: The std430 qualifier is supported only for shader storage blocks; a shader using - // the std430 qualifier on a uniform block will fail to compile. - // Only check the global declaration: layout(std430) uniform; - if (blockName == nullptr && - qualifier.layoutPacking == ElpStd430) - { - requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "default std430 layout for uniform"); - } - - if (publicType != nullptr && publicType->isImage() && - (qualifier.layoutFormat > ElfExtSizeGuard && qualifier.layoutFormat < ElfCount)) - qualifier.layoutFormat = mapLegacyLayoutFormat(qualifier.layoutFormat, publicType->sampler.getBasicType()); - - break; - default: - break; - } - - if (!nonuniformOkay && qualifier.isNonUniform()) - error(loc, "for non-parameter, can only apply to 'in' or no storage qualifier", "nonuniformEXT", ""); - - if (qualifier.isSpirvByReference()) - error(loc, "can only apply to parameter", "spirv_by_reference", ""); - - if (qualifier.isSpirvLiteral()) - error(loc, "can only apply to parameter", "spirv_literal", ""); - - // Storage qualifier isn't ready for memberQualifierCheck, we should skip invariantCheck for it. - if (!isMemberCheck || structNestingLevel > 0) - invariantCheck(loc, qualifier); -} - -// -// Check a full qualifier and type (no variable yet) at global level. -// -void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQualifier& qualifier, const TPublicType& publicType) -{ - if (! symbolTable.atGlobalLevel()) - return; - - if (!(publicType.userDef && publicType.userDef->isReference()) && !parsingBuiltins) { - if (qualifier.isMemoryQualifierImageAndSSBOOnly() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) { - error(loc, "memory qualifiers cannot be used on this type", "", ""); - } else if (qualifier.isMemory() && (publicType.basicType != EbtSampler) && !publicType.qualifier.isUniformOrBuffer()) { - error(loc, "memory qualifiers cannot be used on this type", "", ""); - } - } - - if (qualifier.storage == EvqBuffer && - publicType.basicType != EbtBlock && - !qualifier.hasBufferReference()) - error(loc, "buffers can be declared only as blocks", "buffer", ""); - - if (qualifier.storage != EvqVaryingIn && publicType.basicType == EbtDouble && - extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit) && language == EShLangVertex && - version < 400) { - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, E_GL_ARB_gpu_shader_fp64, "vertex-shader `double` type"); - } - if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut) - return; - - if (publicType.shaderQualifiers.hasBlendEquation()) - error(loc, "can only be applied to a standalone 'out'", "blend equation", ""); - - // now, knowing it is a shader in/out, do all the in/out semantic checks - - if (publicType.basicType == EbtBool && !parsingBuiltins) { - error(loc, "cannot be bool", GetStorageQualifierString(qualifier.storage), ""); - return; - } - - if (isTypeInt(publicType.basicType) || publicType.basicType == EbtDouble) { - profileRequires(loc, EEsProfile, 300, nullptr, "non-float shader input/output"); - profileRequires(loc, ~EEsProfile, 130, nullptr, "non-float shader input/output"); - } - - if (!qualifier.flat && !qualifier.isExplicitInterpolation() && !qualifier.isPervertexNV() && !qualifier.isPervertexEXT()) { - if (isTypeInt(publicType.basicType) || - publicType.basicType == EbtDouble || - (publicType.userDef && ( publicType.userDef->containsBasicType(EbtInt) - || publicType.userDef->containsBasicType(EbtUint) - || publicType.userDef->contains16BitInt() - || publicType.userDef->contains8BitInt() - || publicType.userDef->contains64BitInt() - || publicType.userDef->containsDouble()))) { - if (qualifier.storage == EvqVaryingIn && language == EShLangFragment) - error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage)); - else if (qualifier.storage == EvqVaryingOut && language == EShLangVertex && version == 300) - error(loc, "must be qualified as flat", TType::getBasicString(publicType.basicType), GetStorageQualifierString(qualifier.storage)); - } - } - - if (qualifier.isPatch() && qualifier.isInterpolation()) - error(loc, "cannot use interpolation qualifiers with patch", "patch", ""); - - if (qualifier.isTaskPayload() && publicType.basicType == EbtBlock) - error(loc, "taskPayloadSharedEXT variables should not be declared as interface blocks", "taskPayloadSharedEXT", ""); - - if (qualifier.isTaskMemory() && publicType.basicType != EbtBlock) - error(loc, "taskNV variables can be declared only as blocks", "taskNV", ""); - - if (qualifier.storage == EvqVaryingIn) { - switch (language) { - case EShLangVertex: - if (publicType.basicType == EbtStruct) { - error(loc, "cannot be a structure", GetStorageQualifierString(qualifier.storage), ""); - return; - } - if (publicType.arraySizes) { - requireProfile(loc, ~EEsProfile, "vertex input arrays"); - profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays"); - } - if (publicType.basicType == EbtDouble) - profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_vertex_attrib_64bit, "vertex-shader `double` type input"); - if (qualifier.isAuxiliary() || qualifier.isInterpolation() || qualifier.isMemory() || qualifier.invariant) - error(loc, "vertex input cannot be further qualified", "", ""); - break; - case EShLangFragment: - if (publicType.userDef) { - profileRequires(loc, EEsProfile, 300, nullptr, "fragment-shader struct input"); - profileRequires(loc, ~EEsProfile, 150, nullptr, "fragment-shader struct input"); - if (publicType.userDef->containsStructure()) - requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing structure"); - if (publicType.userDef->containsArray()) - requireProfile(loc, ~EEsProfile, "fragment-shader struct input containing an array"); - } - break; - case EShLangCompute: - if (! symbolTable.atBuiltInLevel()) - error(loc, "global storage input qualifier cannot be used in a compute shader", "in", ""); - break; - case EShLangTessControl: - if (qualifier.patch) - error(loc, "can only use on output in tessellation-control shader", "patch", ""); - break; - default: - break; - } - } else { - // qualifier.storage == EvqVaryingOut - switch (language) { - case EShLangVertex: - if (publicType.userDef) { - profileRequires(loc, EEsProfile, 300, nullptr, "vertex-shader struct output"); - profileRequires(loc, ~EEsProfile, 150, nullptr, "vertex-shader struct output"); - if (publicType.userDef->containsStructure()) - requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing structure"); - if (publicType.userDef->containsArray()) - requireProfile(loc, ~EEsProfile, "vertex-shader struct output containing an array"); - } - - break; - case EShLangFragment: - profileRequires(loc, EEsProfile, 300, nullptr, "fragment shader output"); - if (publicType.basicType == EbtStruct) { - error(loc, "cannot be a structure", GetStorageQualifierString(qualifier.storage), ""); - return; - } - if (publicType.matrixRows > 0) { - error(loc, "cannot be a matrix", GetStorageQualifierString(qualifier.storage), ""); - return; - } - if (qualifier.isAuxiliary()) - error(loc, "can't use auxiliary qualifier on a fragment output", "centroid/sample/patch", ""); - if (qualifier.isInterpolation()) - error(loc, "can't use interpolation qualifier on a fragment output", "flat/smooth/noperspective", ""); - if (publicType.basicType == EbtDouble || publicType.basicType == EbtInt64 || publicType.basicType == EbtUint64) - error(loc, "cannot contain a double, int64, or uint64", GetStorageQualifierString(qualifier.storage), ""); - break; - - case EShLangCompute: - error(loc, "global storage output qualifier cannot be used in a compute shader", "out", ""); - break; - case EShLangTessEvaluation: - if (qualifier.patch) - error(loc, "can only use on input in tessellation-evaluation shader", "patch", ""); - break; - default: - break; - } - } -} - -// -// Merge characteristics of the 'src' qualifier into the 'dst'. -// If there is duplication, issue error messages, unless 'force' -// is specified, which means to just override default settings. -// -// Also, when force is false, it will be assumed that 'src' follows -// 'dst', for the purpose of error checking order for versions -// that require specific orderings of qualifiers. -// -void TParseContext::mergeQualifiers(const TSourceLoc& loc, TQualifier& dst, const TQualifier& src, bool force) -{ - // Multiple auxiliary qualifiers (mostly done later by 'individual qualifiers') - if (src.isAuxiliary() && dst.isAuxiliary()) - error(loc, "can only have one auxiliary qualifier (centroid, patch, and sample)", "", ""); - - // Multiple interpolation qualifiers (mostly done later by 'individual qualifiers') - if (src.isInterpolation() && dst.isInterpolation()) - error(loc, "can only have one interpolation qualifier (flat, smooth, noperspective, __explicitInterpAMD)", "", ""); - - // Ordering - if (! force && ((!isEsProfile() && version < 420) || - (isEsProfile() && version < 310)) - && ! extensionTurnedOn(E_GL_ARB_shading_language_420pack)) { - // non-function parameters - if (src.isNoContraction() && (dst.invariant || dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) - error(loc, "precise qualifier must appear first", "", ""); - if (src.invariant && (dst.isInterpolation() || dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) - error(loc, "invariant qualifier must appear before interpolation, storage, and precision qualifiers ", "", ""); - else if (src.isInterpolation() && (dst.isAuxiliary() || dst.storage != EvqTemporary || dst.precision != EpqNone)) - error(loc, "interpolation qualifiers must appear before storage and precision qualifiers", "", ""); - else if (src.isAuxiliary() && (dst.storage != EvqTemporary || dst.precision != EpqNone)) - error(loc, "Auxiliary qualifiers (centroid, patch, and sample) must appear before storage and precision qualifiers", "", ""); - else if (src.storage != EvqTemporary && (dst.precision != EpqNone)) - error(loc, "precision qualifier must appear as last qualifier", "", ""); - - // function parameters - if (src.isNoContraction() && (dst.storage == EvqConst || dst.storage == EvqIn || dst.storage == EvqOut)) - error(loc, "precise qualifier must appear first", "", ""); - if (src.storage == EvqConst && (dst.storage == EvqIn || dst.storage == EvqOut)) - error(loc, "in/out must appear before const", "", ""); - } - - // Storage qualification - if (dst.storage == EvqTemporary || dst.storage == EvqGlobal) - dst.storage = src.storage; - else if ((dst.storage == EvqIn && src.storage == EvqOut) || - (dst.storage == EvqOut && src.storage == EvqIn)) - dst.storage = EvqInOut; - else if ((dst.storage == EvqIn && src.storage == EvqConst) || - (dst.storage == EvqConst && src.storage == EvqIn)) - dst.storage = EvqConstReadOnly; - else if (src.storage != EvqTemporary && - src.storage != EvqGlobal) - error(loc, "too many storage qualifiers", GetStorageQualifierString(src.storage), ""); - - // Precision qualifiers - if (! force && src.precision != EpqNone && dst.precision != EpqNone) - error(loc, "only one precision qualifier allowed", GetPrecisionQualifierString(src.precision), ""); - if (dst.precision == EpqNone || (force && src.precision != EpqNone)) - dst.precision = src.precision; - - if (!force && ((src.coherent && (dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || - (src.devicecoherent && (dst.coherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || - (src.queuefamilycoherent && (dst.coherent || dst.devicecoherent || dst.workgroupcoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || - (src.workgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.subgroupcoherent || dst.shadercallcoherent)) || - (src.subgroupcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.shadercallcoherent)) || - (src.shadercallcoherent && (dst.coherent || dst.devicecoherent || dst.queuefamilycoherent || dst.workgroupcoherent || dst.subgroupcoherent)))) { - error(loc, "only one coherent/devicecoherent/queuefamilycoherent/workgroupcoherent/subgroupcoherent/shadercallcoherent qualifier allowed", - GetPrecisionQualifierString(src.precision), ""); - } - - // Layout qualifiers - mergeObjectLayoutQualifiers(dst, src, false); - - // individual qualifiers - bool repeated = false; - #define MERGE_SINGLETON(field) repeated |= dst.field && src.field; dst.field |= src.field; - MERGE_SINGLETON(invariant); - MERGE_SINGLETON(centroid); - MERGE_SINGLETON(smooth); - MERGE_SINGLETON(flat); - MERGE_SINGLETON(specConstant); - MERGE_SINGLETON(noContraction); - MERGE_SINGLETON(nopersp); - MERGE_SINGLETON(explicitInterp); - MERGE_SINGLETON(perPrimitiveNV); - MERGE_SINGLETON(perViewNV); - MERGE_SINGLETON(perTaskNV); - MERGE_SINGLETON(patch); - MERGE_SINGLETON(sample); - MERGE_SINGLETON(coherent); - MERGE_SINGLETON(devicecoherent); - MERGE_SINGLETON(queuefamilycoherent); - MERGE_SINGLETON(workgroupcoherent); - MERGE_SINGLETON(subgroupcoherent); - MERGE_SINGLETON(shadercallcoherent); - MERGE_SINGLETON(nonprivate); - MERGE_SINGLETON(volatil); - MERGE_SINGLETON(restrict); - MERGE_SINGLETON(readonly); - MERGE_SINGLETON(writeonly); - MERGE_SINGLETON(nonUniform); - - // SPIR-V storage class qualifier (GL_EXT_spirv_intrinsics) - dst.spirvStorageClass = src.spirvStorageClass; - - // SPIR-V decorate qualifiers (GL_EXT_spirv_intrinsics) - if (src.hasSpirvDecorate()) { - if (dst.hasSpirvDecorate()) { - const TSpirvDecorate& srcSpirvDecorate = src.getSpirvDecorate(); - TSpirvDecorate& dstSpirvDecorate = dst.getSpirvDecorate(); - for (auto& decorate : srcSpirvDecorate.decorates) { - if (dstSpirvDecorate.decorates.find(decorate.first) != dstSpirvDecorate.decorates.end()) - error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate", "(decoration=%u)", decorate.first); - else - dstSpirvDecorate.decorates.insert(decorate); - } - - for (auto& decorateId : srcSpirvDecorate.decorateIds) { - if (dstSpirvDecorate.decorateIds.find(decorateId.first) != dstSpirvDecorate.decorateIds.end()) - error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate_id", "(decoration=%u)", decorateId.first); - else - dstSpirvDecorate.decorateIds.insert(decorateId); - } - - for (auto& decorateString : srcSpirvDecorate.decorateStrings) { - if (dstSpirvDecorate.decorates.find(decorateString.first) != dstSpirvDecorate.decorates.end()) - error(loc, "too many SPIR-V decorate qualifiers", "spirv_decorate_string", "(decoration=%u)", decorateString.first); - else - dstSpirvDecorate.decorateStrings.insert(decorateString); - } - } else { - dst.spirvDecorate = src.spirvDecorate; - } - } - - if (repeated) - error(loc, "replicated qualifiers", "", ""); -} - -void TParseContext::setDefaultPrecision(const TSourceLoc& loc, TPublicType& publicType, TPrecisionQualifier qualifier) -{ - TBasicType basicType = publicType.basicType; - - if (basicType == EbtSampler) { - defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)] = qualifier; - - return; // all is well - } - - if (basicType == EbtInt || basicType == EbtFloat) { - if (publicType.isScalar()) { - defaultPrecision[basicType] = qualifier; - if (basicType == EbtInt) { - defaultPrecision[EbtUint] = qualifier; - precisionManager.explicitIntDefaultSeen(); - } else - precisionManager.explicitFloatDefaultSeen(); - - return; // all is well - } - } - - if (basicType == EbtAtomicUint) { - if (qualifier != EpqHigh) - error(loc, "can only apply highp to atomic_uint", "precision", ""); - - return; - } - - error(loc, "cannot apply precision statement to this type; use 'float', 'int' or a sampler type", TType::getBasicString(basicType), ""); -} - -// used to flatten the sampler type space into a single dimension -// correlates with the declaration of defaultSamplerPrecision[] -int TParseContext::computeSamplerTypeIndex(TSampler& sampler) -{ - int arrayIndex = sampler.arrayed ? 1 : 0; - int shadowIndex = sampler.shadow ? 1 : 0; - int externalIndex = sampler.isExternal() ? 1 : 0; - int imageIndex = sampler.isImageClass() ? 1 : 0; - int msIndex = sampler.isMultiSample() ? 1 : 0; - - int flattened = EsdNumDims * (EbtNumTypes * (2 * (2 * (2 * (2 * arrayIndex + msIndex) + imageIndex) + shadowIndex) + - externalIndex) + sampler.type) + sampler.dim; - assert(flattened < maxSamplerIndex); - - return flattened; -} - -TPrecisionQualifier TParseContext::getDefaultPrecision(TPublicType& publicType) -{ - if (publicType.basicType == EbtSampler) - return defaultSamplerPrecision[computeSamplerTypeIndex(publicType.sampler)]; - else - return defaultPrecision[publicType.basicType]; -} - -void TParseContext::precisionQualifierCheck(const TSourceLoc& loc, TBasicType baseType, TQualifier& qualifier, bool isCoopMat) -{ - // Built-in symbols are allowed some ambiguous precisions, to be pinned down - // later by context. - if (! obeyPrecisionQualifiers() || parsingBuiltins) - return; - - if (baseType == EbtAtomicUint && qualifier.precision != EpqNone && qualifier.precision != EpqHigh) - error(loc, "atomic counters can only be highp", "atomic_uint", ""); - - if (isCoopMat) - return; - - if (baseType == EbtFloat || baseType == EbtUint || baseType == EbtInt || baseType == EbtSampler || baseType == EbtAtomicUint) { - if (qualifier.precision == EpqNone) { - if (relaxedErrors()) - warn(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), "substituting 'mediump'"); - else - error(loc, "type requires declaration of default precision qualifier", TType::getBasicString(baseType), ""); - qualifier.precision = EpqMedium; - defaultPrecision[baseType] = EpqMedium; - } - } else if (qualifier.precision != EpqNone) - error(loc, "type cannot have precision qualifier", TType::getBasicString(baseType), ""); -} - -void TParseContext::parameterTypeCheck(const TSourceLoc& loc, TStorageQualifier qualifier, const TType& type) -{ - if ((qualifier == EvqOut || qualifier == EvqInOut) && type.isOpaque() && !intermediate.getBindlessMode()) - error(loc, "samplers and atomic_uints cannot be output parameters", type.getBasicTypeString().c_str(), ""); - if (!parsingBuiltins && type.contains16BitFloat()) - requireFloat16Arithmetic(loc, type.getBasicTypeString().c_str(), "float16 types can only be in uniform block or buffer storage"); - if (!parsingBuiltins && type.contains16BitInt()) - requireInt16Arithmetic(loc, type.getBasicTypeString().c_str(), "(u)int16 types can only be in uniform block or buffer storage"); - if (!parsingBuiltins && type.contains8BitInt()) - requireInt8Arithmetic(loc, type.getBasicTypeString().c_str(), "(u)int8 types can only be in uniform block or buffer storage"); -} - -bool TParseContext::containsFieldWithBasicType(const TType& type, TBasicType basicType) -{ - if (type.getBasicType() == basicType) - return true; - - if (type.getBasicType() == EbtStruct) { - const TTypeList& structure = *type.getStruct(); - for (unsigned int i = 0; i < structure.size(); ++i) { - if (containsFieldWithBasicType(*structure[i].type, basicType)) - return true; - } - } - - return false; -} - -// -// Do size checking for an array type's size. -// -void TParseContext::arraySizeCheck(const TSourceLoc& loc, TIntermTyped* expr, TArraySize& sizePair, - const char* sizeType, const bool allowZero) -{ - bool isConst = false; - sizePair.node = nullptr; - - int size = 1; - - TIntermConstantUnion* constant = expr->getAsConstantUnion(); - if (constant) { - // handle true (non-specialization) constant - size = constant->getConstArray()[0].getIConst(); - isConst = true; - } else { - // see if it's a specialization constant instead - if (expr->getQualifier().isSpecConstant()) { - isConst = true; - sizePair.node = expr; - TIntermSymbol* symbol = expr->getAsSymbolNode(); - if (symbol && symbol->getConstArray().size() > 0) - size = symbol->getConstArray()[0].getIConst(); - } else if (expr->getAsUnaryNode() && expr->getAsUnaryNode()->getOp() == glslang::EOpArrayLength && - expr->getAsUnaryNode()->getOperand()->getType().isCoopMatNV()) { - isConst = true; - size = 1; - sizePair.node = expr->getAsUnaryNode(); - } - } - - sizePair.size = size; - - if (! isConst || (expr->getBasicType() != EbtInt && expr->getBasicType() != EbtUint)) { - error(loc, sizeType, "", "must be a constant integer expression"); - return; - } - - if (allowZero) { - if (size < 0) { - error(loc, sizeType, "", "must be a non-negative integer"); - return; - } - } else { - if (size <= 0) { - error(loc, sizeType, "", "must be a positive integer"); - return; - } - } -} - -// -// See if this qualifier can be an array. -// -// Returns true if there is an error. -// -bool TParseContext::arrayQualifierError(const TSourceLoc& loc, const TQualifier& qualifier) -{ - if (qualifier.storage == EvqConst) { - profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "const array"); - profileRequires(loc, EEsProfile, 300, nullptr, "const array"); - } - - if (qualifier.storage == EvqVaryingIn && language == EShLangVertex) { - requireProfile(loc, ~EEsProfile, "vertex input arrays"); - profileRequires(loc, ENoProfile, 150, nullptr, "vertex input arrays"); - } - - return false; -} - -// -// See if this qualifier and type combination can be an array. -// Assumes arrayQualifierError() was also called to catch the type-invariant tests. -// -// Returns true if there is an error. -// -bool TParseContext::arrayError(const TSourceLoc& loc, const TType& type) -{ - if (type.getQualifier().storage == EvqVaryingOut && language == EShLangVertex) { - if (type.isArrayOfArrays()) - requireProfile(loc, ~EEsProfile, "vertex-shader array-of-array output"); - else if (type.isStruct()) - requireProfile(loc, ~EEsProfile, "vertex-shader array-of-struct output"); - } - if (type.getQualifier().storage == EvqVaryingIn && language == EShLangFragment) { - if (type.isArrayOfArrays()) - requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array input"); - else if (type.isStruct()) - requireProfile(loc, ~EEsProfile, "fragment-shader array-of-struct input"); - } - if (type.getQualifier().storage == EvqVaryingOut && language == EShLangFragment) { - if (type.isArrayOfArrays()) - requireProfile(loc, ~EEsProfile, "fragment-shader array-of-array output"); - } - - return false; -} - -// -// Require array to be completely sized -// -void TParseContext::arraySizeRequiredCheck(const TSourceLoc& loc, const TArraySizes& arraySizes) -{ - if (!parsingBuiltins && arraySizes.hasUnsized()) - error(loc, "array size required", "", ""); -} - -void TParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType& type) -{ - const TTypeList& structure = *type.getStruct(); - for (int m = 0; m < (int)structure.size(); ++m) { - const TType& member = *structure[m].type; - if (member.isArray()) - arraySizeRequiredCheck(structure[m].loc, *member.getArraySizes()); - } -} - -void TParseContext::arraySizesCheck(const TSourceLoc& loc, const TQualifier& qualifier, TArraySizes* arraySizes, - const TIntermTyped* initializer, bool lastMember) -{ - assert(arraySizes); - - // always allow special built-in ins/outs sized to topologies - if (parsingBuiltins) - return; - - // initializer must be a sized array, in which case - // allow the initializer to set any unknown array sizes - if (initializer != nullptr) { - if (initializer->getType().isUnsizedArray()) - error(loc, "array initializer must be sized", "[]", ""); - return; - } - - // No environment allows any non-outer-dimension to be implicitly sized - if (arraySizes->isInnerUnsized()) { - error(loc, "only outermost dimension of an array of arrays can be implicitly sized", "[]", ""); - arraySizes->clearInnerUnsized(); - } - - if (arraySizes->isInnerSpecialization() && - (qualifier.storage != EvqTemporary && qualifier.storage != EvqGlobal && qualifier.storage != EvqShared && qualifier.storage != EvqConst)) - error(loc, "only outermost dimension of an array of arrays can be a specialization constant", "[]", ""); - - // desktop always allows outer-dimension-unsized variable arrays, - if (!isEsProfile()) - return; - - // for ES, if size isn't coming from an initializer, it has to be explicitly declared now, - // with very few exceptions - - // implicitly-sized io exceptions: - switch (language) { - case EShLangGeometry: - if (qualifier.storage == EvqVaryingIn) - if ((isEsProfile() && version >= 320) || - extensionsTurnedOn(Num_AEP_geometry_shader, AEP_geometry_shader)) - return; - break; - case EShLangTessControl: - if ( qualifier.storage == EvqVaryingIn || - (qualifier.storage == EvqVaryingOut && ! qualifier.isPatch())) - if ((isEsProfile() && version >= 320) || - extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) - return; - break; - case EShLangTessEvaluation: - if ((qualifier.storage == EvqVaryingIn && ! qualifier.isPatch()) || - qualifier.storage == EvqVaryingOut) - if ((isEsProfile() && version >= 320) || - extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader)) - return; - break; - case EShLangMesh: - if (qualifier.storage == EvqVaryingOut) - if ((isEsProfile() && version >= 320) || - extensionsTurnedOn(Num_AEP_mesh_shader, AEP_mesh_shader)) - return; - break; - default: - break; - } - - // last member of ssbo block exception: - if (qualifier.storage == EvqBuffer && lastMember) - return; - - arraySizeRequiredCheck(loc, *arraySizes); -} - -void TParseContext::arrayOfArrayVersionCheck(const TSourceLoc& loc, const TArraySizes* sizes) -{ - if (sizes == nullptr || sizes->getNumDims() == 1) - return; - - const char* feature = "arrays of arrays"; - - requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, nullptr, feature); -} - -// -// Do all the semantic checking for declaring or redeclaring an array, with and -// without a size, and make the right changes to the symbol table. -// -void TParseContext::declareArray(const TSourceLoc& loc, const TString& identifier, const TType& type, TSymbol*& symbol) -{ - if (symbol == nullptr) { - bool currentScope; - symbol = symbolTable.find(identifier, nullptr, ¤tScope); - - if (symbol && builtInName(identifier) && ! symbolTable.atBuiltInLevel()) { - // bad shader (errors already reported) trying to redeclare a built-in name as an array - symbol = nullptr; - return; - } - if (symbol == nullptr || ! currentScope) { - // - // Successfully process a new definition. - // (Redeclarations have to take place at the same scope; otherwise they are hiding declarations) - // - symbol = new TVariable(&identifier, type); - symbolTable.insert(*symbol); - if (symbolTable.atGlobalLevel()) - trackLinkage(*symbol); - - if (! symbolTable.atBuiltInLevel()) { - if (isIoResizeArray(type)) { - ioArraySymbolResizeList.push_back(symbol); - checkIoArraysConsistency(loc, true); - } else - fixIoArraySize(loc, symbol->getWritableType()); - } - - return; - } - if (symbol->getAsAnonMember()) { - error(loc, "cannot redeclare a user-block member array", identifier.c_str(), ""); - symbol = nullptr; - return; - } - } - - // - // Process a redeclaration. - // - - if (symbol == nullptr) { - error(loc, "array variable name expected", identifier.c_str(), ""); - return; - } - - // redeclareBuiltinVariable() should have already done the copyUp() - TType& existingType = symbol->getWritableType(); - - if (! existingType.isArray()) { - error(loc, "redeclaring non-array as array", identifier.c_str(), ""); - return; - } - - if (! existingType.sameElementType(type)) { - error(loc, "redeclaration of array with a different element type", identifier.c_str(), ""); - return; - } - - if (! existingType.sameInnerArrayness(type)) { - error(loc, "redeclaration of array with a different array dimensions or sizes", identifier.c_str(), ""); - return; - } - - if (existingType.isSizedArray()) { - // be more leniant for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size - if (! (isIoResizeArray(type) && existingType.getOuterArraySize() == type.getOuterArraySize())) - error(loc, "redeclaration of array with size", identifier.c_str(), ""); - return; - } - - arrayLimitCheck(loc, identifier, type.getOuterArraySize()); - - existingType.updateArraySizes(type); - - if (isIoResizeArray(type)) - checkIoArraysConsistency(loc); -} - -// Policy and error check for needing a runtime sized array. -void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermTyped& base) -{ - // runtime length implies runtime sizeable, so no problem - if (isRuntimeLength(base)) - return; - - if (base.getType().getQualifier().builtIn == EbvSampleMask) - return; - - // Check for last member of a bufferreference type, which is runtime sizeable - // but doesn't support runtime length - if (base.getType().getQualifier().storage == EvqBuffer) { - const TIntermBinary* binary = base.getAsBinaryNode(); - if (binary != nullptr && - binary->getOp() == EOpIndexDirectStruct && - binary->getLeft()->isReference()) { - - const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - const int memberCount = (int)binary->getLeft()->getType().getReferentType()->getStruct()->size(); - if (index == memberCount - 1) - return; - } - } - - // check for additional things allowed by GL_EXT_nonuniform_qualifier - if (base.getBasicType() == EbtSampler || base.getBasicType() == EbtAccStruct || base.getBasicType() == EbtRayQuery || - base.getBasicType() == EbtHitObjectNV || (base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer())) - requireExtensions(loc, 1, &E_GL_EXT_nonuniform_qualifier, "variable index"); - else - error(loc, "", "[", "array must be redeclared with a size before being indexed with a variable"); -} - -// Policy decision for whether a run-time .length() is allowed. -bool TParseContext::isRuntimeLength(const TIntermTyped& base) const -{ - if (base.getType().getQualifier().storage == EvqBuffer) { - // in a buffer block - const TIntermBinary* binary = base.getAsBinaryNode(); - if (binary != nullptr && binary->getOp() == EOpIndexDirectStruct) { - // is it the last member? - const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - - if (binary->getLeft()->isReference()) - return false; - - const int memberCount = (int)binary->getLeft()->getType().getStruct()->size(); - if (index == memberCount - 1) - return true; - } - } - - return false; -} - -// Check if mesh perviewNV attributes have a view dimension -// and resize it to gl_MaxMeshViewCountNV when implicitly sized. -void TParseContext::checkAndResizeMeshViewDim(const TSourceLoc& loc, TType& type, bool isBlockMember) -{ - // see if member is a per-view attribute - if (!type.getQualifier().isPerView()) - return; - - if ((isBlockMember && type.isArray()) || (!isBlockMember && type.isArrayOfArrays())) { - // since we don't have the maxMeshViewCountNV set during parsing builtins, we hardcode the value. - int maxViewCount = parsingBuiltins ? 4 : resources.maxMeshViewCountNV; - // For block members, outermost array dimension is the view dimension. - // For non-block members, outermost array dimension is the vertex/primitive dimension - // and 2nd outermost is the view dimension. - int viewDim = isBlockMember ? 0 : 1; - int viewDimSize = type.getArraySizes()->getDimSize(viewDim); - - if (viewDimSize != UnsizedArraySize && viewDimSize != maxViewCount) - error(loc, "mesh view output array size must be gl_MaxMeshViewCountNV or implicitly sized", "[]", ""); - else if (viewDimSize == UnsizedArraySize) - type.getArraySizes()->setDimSize(viewDim, maxViewCount); - } - else { - error(loc, "requires a view array dimension", "perviewNV", ""); - } -} - -// Returns true if the first argument to the #line directive is the line number for the next line. -// -// Desktop, pre-version 3.30: "After processing this directive -// (including its new-line), the implementation will behave as if it is compiling at line number line+1 and -// source string number source-string-number." -// -// Desktop, version 3.30 and later, and ES: "After processing this directive -// (including its new-line), the implementation will behave as if it is compiling at line number line and -// source string number source-string-number. -bool TParseContext::lineDirectiveShouldSetNextLine() const -{ - return isEsProfile() || version >= 330; -} - -// -// Enforce non-initializer type/qualifier rules. -// -void TParseContext::nonInitConstCheck(const TSourceLoc& loc, TString& identifier, TType& type) -{ - // - // Make the qualifier make sense, given that there is not an initializer. - // - if (type.getQualifier().storage == EvqConst || - type.getQualifier().storage == EvqConstReadOnly) { - type.getQualifier().makeTemporary(); - error(loc, "variables with qualifier 'const' must be initialized", identifier.c_str(), ""); - } -} - -// -// See if the identifier is a built-in symbol that can be redeclared, and if so, -// copy the symbol table's read-only built-in variable to the current -// global level, where it can be modified based on the passed in type. -// -// Returns nullptr if no redeclaration took place; meaning a normal declaration still -// needs to occur for it, not necessarily an error. -// -// Returns a redeclared and type-modified variable if a redeclarated occurred. -// -TSymbol* TParseContext::redeclareBuiltinVariable(const TSourceLoc& loc, const TString& identifier, - const TQualifier& qualifier, const TShaderQualifiers& publicType) -{ - if (! builtInName(identifier) || symbolTable.atBuiltInLevel() || ! symbolTable.atGlobalLevel()) - return nullptr; - - bool nonEsRedecls = (!isEsProfile() && (version >= 130 || identifier == "gl_TexCoord")); - bool esRedecls = (isEsProfile() && - (version >= 320 || extensionsTurnedOn(Num_AEP_shader_io_blocks, AEP_shader_io_blocks))); - if (! esRedecls && ! nonEsRedecls) - return nullptr; - - // Special case when using GL_ARB_separate_shader_objects - bool ssoPre150 = false; // means the only reason this variable is redeclared is due to this combination - if (!isEsProfile() && version <= 140 && extensionTurnedOn(E_GL_ARB_separate_shader_objects)) { - if (identifier == "gl_Position" || - identifier == "gl_PointSize" || - identifier == "gl_ClipVertex" || - identifier == "gl_FogFragCoord") - ssoPre150 = true; - } - - // Potentially redeclaring a built-in variable... - - if (ssoPre150 || - (identifier == "gl_FragDepth" && ((nonEsRedecls && version >= 420) || esRedecls)) || - (identifier == "gl_FragCoord" && ((nonEsRedecls && version >= 140) || esRedecls)) || - identifier == "gl_ClipDistance" || - identifier == "gl_CullDistance" || - identifier == "gl_ShadingRateEXT" || - identifier == "gl_PrimitiveShadingRateEXT" || - identifier == "gl_FrontColor" || - identifier == "gl_BackColor" || - identifier == "gl_FrontSecondaryColor" || - identifier == "gl_BackSecondaryColor" || - identifier == "gl_SecondaryColor" || - (identifier == "gl_Color" && language == EShLangFragment) || - (identifier == "gl_FragStencilRefARB" && (nonEsRedecls && version >= 140) - && language == EShLangFragment) || - identifier == "gl_SampleMask" || - identifier == "gl_Layer" || - identifier == "gl_PrimitiveIndicesNV" || - identifier == "gl_PrimitivePointIndicesEXT" || - identifier == "gl_PrimitiveLineIndicesEXT" || - identifier == "gl_PrimitiveTriangleIndicesEXT" || - identifier == "gl_TexCoord") { - - // Find the existing symbol, if any. - bool builtIn; - TSymbol* symbol = symbolTable.find(identifier, &builtIn); - - // If the symbol was not found, this must be a version/profile/stage - // that doesn't have it. - if (! symbol) - return nullptr; - - // If it wasn't at a built-in level, then it's already been redeclared; - // that is, this is a redeclaration of a redeclaration; reuse that initial - // redeclaration. Otherwise, make the new one. - if (builtIn) { - makeEditable(symbol); - symbolTable.amendSymbolIdLevel(*symbol); - } - - // Now, modify the type of the copy, as per the type of the current redeclaration. - - TQualifier& symbolQualifier = symbol->getWritableType().getQualifier(); - if (ssoPre150) { - if (intermediate.inIoAccessed(identifier)) - error(loc, "cannot redeclare after use", identifier.c_str(), ""); - if (qualifier.hasLayout()) - error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); - if (qualifier.isMemory() || qualifier.isAuxiliary() || (language == EShLangVertex && qualifier.storage != EvqVaryingOut) || - (language == EShLangFragment && qualifier.storage != EvqVaryingIn)) - error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str()); - if (! qualifier.smooth) - error(loc, "cannot change interpolation qualification of", "redeclaration", symbol->getName().c_str()); - } else if (identifier == "gl_FrontColor" || - identifier == "gl_BackColor" || - identifier == "gl_FrontSecondaryColor" || - identifier == "gl_BackSecondaryColor" || - identifier == "gl_SecondaryColor" || - identifier == "gl_Color") { - symbolQualifier.flat = qualifier.flat; - symbolQualifier.smooth = qualifier.smooth; - symbolQualifier.nopersp = qualifier.nopersp; - if (qualifier.hasLayout()) - error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); - if (qualifier.isMemory() || qualifier.isAuxiliary() || symbol->getType().getQualifier().storage != qualifier.storage) - error(loc, "cannot change storage, memory, or auxiliary qualification of", "redeclaration", symbol->getName().c_str()); - } else if (identifier == "gl_TexCoord" || - identifier == "gl_ClipDistance" || - identifier == "gl_CullDistance") { - if (qualifier.hasLayout() || qualifier.isMemory() || qualifier.isAuxiliary() || - qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || - symbolQualifier.storage != qualifier.storage) - error(loc, "cannot change qualification of", "redeclaration", symbol->getName().c_str()); - } else if (identifier == "gl_FragCoord") { - if (!intermediate.getTexCoordRedeclared() && intermediate.inIoAccessed("gl_FragCoord")) - error(loc, "cannot redeclare after use", "gl_FragCoord", ""); - if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || - qualifier.isMemory() || qualifier.isAuxiliary()) - error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); - if (qualifier.storage != EvqVaryingIn) - error(loc, "cannot change input storage qualification of", "redeclaration", symbol->getName().c_str()); - if (! builtIn && (publicType.pixelCenterInteger != intermediate.getPixelCenterInteger() || - publicType.originUpperLeft != intermediate.getOriginUpperLeft())) - error(loc, "cannot redeclare with different qualification:", "redeclaration", symbol->getName().c_str()); - - - intermediate.setTexCoordRedeclared(); - if (publicType.pixelCenterInteger) - intermediate.setPixelCenterInteger(); - if (publicType.originUpperLeft) - intermediate.setOriginUpperLeft(); - } else if (identifier == "gl_FragDepth") { - if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || - qualifier.isMemory() || qualifier.isAuxiliary()) - error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); - if (qualifier.storage != EvqVaryingOut) - error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str()); - if (publicType.layoutDepth != EldNone) { - if (intermediate.inIoAccessed("gl_FragDepth")) - error(loc, "cannot redeclare after use", "gl_FragDepth", ""); - if (! intermediate.setDepth(publicType.layoutDepth)) - error(loc, "all redeclarations must use the same depth layout on", "redeclaration", symbol->getName().c_str()); - } - } else if (identifier == "gl_FragStencilRefARB") { - if (qualifier.nopersp != symbolQualifier.nopersp || qualifier.flat != symbolQualifier.flat || - qualifier.isMemory() || qualifier.isAuxiliary()) - error(loc, "can only change layout qualification of", "redeclaration", symbol->getName().c_str()); - if (qualifier.storage != EvqVaryingOut) - error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str()); - if (publicType.layoutStencil != ElsNone) { - if (intermediate.inIoAccessed("gl_FragStencilRefARB")) - error(loc, "cannot redeclare after use", "gl_FragStencilRefARB", ""); - if (!intermediate.setStencil(publicType.layoutStencil)) - error(loc, "all redeclarations must use the same stencil layout on", "redeclaration", - symbol->getName().c_str()); - } - } - else if ( - identifier == "gl_PrimitiveIndicesNV") { - if (qualifier.hasLayout()) - error(loc, "cannot apply layout qualifier to", "redeclaration", symbol->getName().c_str()); - if (qualifier.storage != EvqVaryingOut) - error(loc, "cannot change output storage qualification of", "redeclaration", symbol->getName().c_str()); - } - else if (identifier == "gl_SampleMask") { - if (!publicType.layoutOverrideCoverage) { - error(loc, "redeclaration only allowed for override_coverage layout", "redeclaration", symbol->getName().c_str()); - } - intermediate.setLayoutOverrideCoverage(); - } - else if (identifier == "gl_Layer") { - if (!qualifier.layoutViewportRelative && qualifier.layoutSecondaryViewportRelativeOffset == -2048) - error(loc, "redeclaration only allowed for viewport_relative or secondary_view_offset layout", "redeclaration", symbol->getName().c_str()); - symbolQualifier.layoutViewportRelative = qualifier.layoutViewportRelative; - symbolQualifier.layoutSecondaryViewportRelativeOffset = qualifier.layoutSecondaryViewportRelativeOffset; - } - - // TODO: semantics quality: separate smooth from nothing declared, then use IsInterpolation for several tests above - - return symbol; - } - - return nullptr; -} - -// -// Either redeclare the requested block, or give an error message why it can't be done. -// -// TODO: functionality: explicitly sizing members of redeclared blocks is not giving them an explicit size -void TParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& newTypeList, const TString& blockName, - const TString* instanceName, TArraySizes* arraySizes) -{ - const char* feature = "built-in block redeclaration"; - profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature); - profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); - - if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment" && - blockName != "gl_MeshPerVertexNV" && blockName != "gl_MeshPerPrimitiveNV" && - blockName != "gl_MeshPerVertexEXT" && blockName != "gl_MeshPerPrimitiveEXT") { - error(loc, "cannot redeclare block: ", "block declaration", blockName.c_str()); - return; - } - - // Redeclaring a built-in block... - - if (instanceName && ! builtInName(*instanceName)) { - error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), ""); - return; - } - - // Blocks with instance names are easy to find, lookup the instance name, - // Anonymous blocks need to be found via a member. - bool builtIn; - TSymbol* block; - if (instanceName) - block = symbolTable.find(*instanceName, &builtIn); - else - block = symbolTable.find(newTypeList.front().type->getFieldName(), &builtIn); - - // If the block was not found, this must be a version/profile/stage - // that doesn't have it, or the instance name is wrong. - const char* errorName = instanceName ? instanceName->c_str() : newTypeList.front().type->getFieldName().c_str(); - if (! block) { - error(loc, "no declaration found for redeclaration", errorName, ""); - return; - } - // Built-in blocks cannot be redeclared more than once, which if happened, - // we'd be finding the already redeclared one here, rather than the built in. - if (! builtIn) { - error(loc, "can only redeclare a built-in block once, and before any use", blockName.c_str(), ""); - return; - } - - // Copy the block to make a writable version, to insert into the block table after editing. - block = symbolTable.copyUpDeferredInsert(block); - - if (block->getType().getBasicType() != EbtBlock) { - error(loc, "cannot redeclare a non block as a block", errorName, ""); - return; - } - - // Fix XFB stuff up, it applies to the order of the redeclaration, not - // the order of the original members. - if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) { - if (!currentBlockQualifier.hasXfbBuffer()) - currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; - if (!currentBlockQualifier.hasStream()) - currentBlockQualifier.layoutStream = globalOutputDefaults.layoutStream; - fixXfbOffsets(currentBlockQualifier, newTypeList); - } - - // Edit and error check the container against the redeclaration - // - remove unused members - // - ensure remaining qualifiers/types match - - TType& type = block->getWritableType(); - - // if gl_PerVertex is redeclared for the purpose of passing through "gl_Position" - // for passthrough purpose, the redeclared block should have the same qualifers as - // the current one - if (currentBlockQualifier.layoutPassthrough) { - type.getQualifier().layoutPassthrough = currentBlockQualifier.layoutPassthrough; - type.getQualifier().storage = currentBlockQualifier.storage; - type.getQualifier().layoutStream = currentBlockQualifier.layoutStream; - type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer; - } - - TTypeList::iterator member = type.getWritableStruct()->begin(); - size_t numOriginalMembersFound = 0; - while (member != type.getStruct()->end()) { - // look for match - bool found = false; - TTypeList::const_iterator newMember; - TSourceLoc memberLoc; - memberLoc.init(); - for (newMember = newTypeList.begin(); newMember != newTypeList.end(); ++newMember) { - if (member->type->getFieldName() == newMember->type->getFieldName()) { - found = true; - memberLoc = newMember->loc; - break; - } - } - - if (found) { - ++numOriginalMembersFound; - // - ensure match between redeclared members' types - // - check for things that can't be changed - // - update things that can be changed - TType& oldType = *member->type; - const TType& newType = *newMember->type; - if (! newType.sameElementType(oldType)) - error(memberLoc, "cannot redeclare block member with a different type", member->type->getFieldName().c_str(), ""); - if (oldType.isArray() != newType.isArray()) - error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), ""); - else if (! oldType.getQualifier().isPerView() && ! oldType.sameArrayness(newType) && oldType.isSizedArray()) - error(memberLoc, "cannot change array size of redeclared block member", member->type->getFieldName().c_str(), ""); - else if (! oldType.getQualifier().isPerView() && newType.isArray()) - arrayLimitCheck(loc, member->type->getFieldName(), newType.getOuterArraySize()); - if (oldType.getQualifier().isPerView() && ! newType.getQualifier().isPerView()) - error(memberLoc, "missing perviewNV qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); - else if (! oldType.getQualifier().isPerView() && newType.getQualifier().isPerView()) - error(memberLoc, "cannot add perviewNV qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); - else if (newType.getQualifier().isPerView()) { - if (oldType.getArraySizes()->getNumDims() != newType.getArraySizes()->getNumDims()) - error(memberLoc, "cannot change arrayness of redeclared block member", member->type->getFieldName().c_str(), ""); - else if (! newType.isUnsizedArray() && newType.getOuterArraySize() != resources.maxMeshViewCountNV) - error(loc, "mesh view output array size must be gl_MaxMeshViewCountNV or implicitly sized", "[]", ""); - else if (newType.getArraySizes()->getNumDims() == 2) { - int innerDimSize = newType.getArraySizes()->getDimSize(1); - arrayLimitCheck(memberLoc, member->type->getFieldName(), innerDimSize); - oldType.getArraySizes()->setDimSize(1, innerDimSize); - } - } - if (oldType.getQualifier().isPerPrimitive() && ! newType.getQualifier().isPerPrimitive()) - error(memberLoc, "missing perprimitiveNV qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); - else if (! oldType.getQualifier().isPerPrimitive() && newType.getQualifier().isPerPrimitive()) - error(memberLoc, "cannot add perprimitiveNV qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); - if (newType.getQualifier().isMemory()) - error(memberLoc, "cannot add memory qualifier to redeclared block member", member->type->getFieldName().c_str(), ""); - if (newType.getQualifier().hasNonXfbLayout()) - error(memberLoc, "cannot add non-XFB layout to redeclared block member", member->type->getFieldName().c_str(), ""); - if (newType.getQualifier().patch) - error(memberLoc, "cannot add patch to redeclared block member", member->type->getFieldName().c_str(), ""); - if (newType.getQualifier().hasXfbBuffer() && - newType.getQualifier().layoutXfbBuffer != currentBlockQualifier.layoutXfbBuffer) - error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", ""); - if (newType.getQualifier().hasStream() && - newType.getQualifier().layoutStream != currentBlockQualifier.layoutStream) - error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_stream", ""); - oldType.getQualifier().centroid = newType.getQualifier().centroid; - oldType.getQualifier().sample = newType.getQualifier().sample; - oldType.getQualifier().invariant = newType.getQualifier().invariant; - oldType.getQualifier().noContraction = newType.getQualifier().noContraction; - oldType.getQualifier().smooth = newType.getQualifier().smooth; - oldType.getQualifier().flat = newType.getQualifier().flat; - oldType.getQualifier().nopersp = newType.getQualifier().nopersp; - oldType.getQualifier().layoutXfbOffset = newType.getQualifier().layoutXfbOffset; - oldType.getQualifier().layoutXfbBuffer = newType.getQualifier().layoutXfbBuffer; - oldType.getQualifier().layoutXfbStride = newType.getQualifier().layoutXfbStride; - if (oldType.getQualifier().layoutXfbOffset != TQualifier::layoutXfbBufferEnd) { - // If any member has an xfb_offset, then the block's xfb_buffer inherents current xfb_buffer, - // and for xfb processing, the member needs it as well, along with xfb_stride. - type.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer; - oldType.getQualifier().layoutXfbBuffer = currentBlockQualifier.layoutXfbBuffer; - } - if (oldType.isUnsizedArray() && newType.isSizedArray()) - oldType.changeOuterArraySize(newType.getOuterArraySize()); - - // check and process the member's type, which will include managing xfb information - layoutTypeCheck(loc, oldType); - - // go to next member - ++member; - } else { - // For missing members of anonymous blocks that have been redeclared, - // hide the original (shared) declaration. - // Instance-named blocks can just have the member removed. - if (instanceName) - member = type.getWritableStruct()->erase(member); - else { - member->type->hideMember(); - ++member; - } - } - } - - if (spvVersion.vulkan > 0) { - // ...then streams apply to built-in blocks, instead of them being only on stream 0 - type.getQualifier().layoutStream = currentBlockQualifier.layoutStream; - } - - if (numOriginalMembersFound < newTypeList.size()) - error(loc, "block redeclaration has extra members", blockName.c_str(), ""); - if (type.isArray() != (arraySizes != nullptr) || - (type.isArray() && arraySizes != nullptr && type.getArraySizes()->getNumDims() != arraySizes->getNumDims())) - error(loc, "cannot change arrayness of redeclared block", blockName.c_str(), ""); - else if (type.isArray()) { - // At this point, we know both are arrays and both have the same number of dimensions. - - // It is okay for a built-in block redeclaration to be unsized, and keep the size of the - // original block declaration. - if (!arraySizes->isSized() && type.isSizedArray()) - arraySizes->changeOuterSize(type.getOuterArraySize()); - - // And, okay to be giving a size to the array, by the redeclaration - if (!type.isSizedArray() && arraySizes->isSized()) - type.changeOuterArraySize(arraySizes->getOuterSize()); - - // Now, they must match in all dimensions. - if (type.isSizedArray() && *type.getArraySizes() != *arraySizes) - error(loc, "cannot change array size of redeclared block", blockName.c_str(), ""); - } - - symbolTable.insert(*block); - - // Check for general layout qualifier errors - layoutObjectCheck(loc, *block); - - // Tracking for implicit sizing of array - if (isIoResizeArray(block->getType())) { - ioArraySymbolResizeList.push_back(block); - checkIoArraysConsistency(loc, true); - } else if (block->getType().isArray()) - fixIoArraySize(loc, block->getWritableType()); - - // Save it in the AST for linker use. - trackLinkage(*block); -} - -void TParseContext::paramCheckFixStorage(const TSourceLoc& loc, const TStorageQualifier& qualifier, TType& type) -{ - switch (qualifier) { - case EvqConst: - case EvqConstReadOnly: - type.getQualifier().storage = EvqConstReadOnly; - break; - case EvqIn: - case EvqOut: - case EvqInOut: - case EvqTileImageEXT: - type.getQualifier().storage = qualifier; - break; - case EvqGlobal: - case EvqTemporary: - type.getQualifier().storage = EvqIn; - break; - default: - type.getQualifier().storage = EvqIn; - error(loc, "storage qualifier not allowed on function parameter", GetStorageQualifierString(qualifier), ""); - break; - } -} - -void TParseContext::paramCheckFix(const TSourceLoc& loc, const TQualifier& qualifier, TType& type) -{ - if (qualifier.isMemory()) { - type.getQualifier().volatil = qualifier.volatil; - type.getQualifier().coherent = qualifier.coherent; - type.getQualifier().devicecoherent = qualifier.devicecoherent ; - type.getQualifier().queuefamilycoherent = qualifier.queuefamilycoherent; - type.getQualifier().workgroupcoherent = qualifier.workgroupcoherent; - type.getQualifier().subgroupcoherent = qualifier.subgroupcoherent; - type.getQualifier().shadercallcoherent = qualifier.shadercallcoherent; - type.getQualifier().nonprivate = qualifier.nonprivate; - type.getQualifier().readonly = qualifier.readonly; - type.getQualifier().writeonly = qualifier.writeonly; - type.getQualifier().restrict = qualifier.restrict; - } - - if (qualifier.isAuxiliary() || - qualifier.isInterpolation()) - error(loc, "cannot use auxiliary or interpolation qualifiers on a function parameter", "", ""); - if (qualifier.hasLayout()) - error(loc, "cannot use layout qualifiers on a function parameter", "", ""); - if (qualifier.invariant) - error(loc, "cannot use invariant qualifier on a function parameter", "", ""); - if (qualifier.isNoContraction()) { - if (qualifier.isParamOutput()) - type.getQualifier().setNoContraction(); - else - warn(loc, "qualifier has no effect on non-output parameters", "precise", ""); - } - if (qualifier.isNonUniform()) - type.getQualifier().nonUniform = qualifier.nonUniform; - if (qualifier.isSpirvByReference()) - type.getQualifier().setSpirvByReference(); - if (qualifier.isSpirvLiteral()) { - if (type.getBasicType() == EbtFloat || type.getBasicType() == EbtInt || type.getBasicType() == EbtUint || - type.getBasicType() == EbtBool) - type.getQualifier().setSpirvLiteral(); - else - error(loc, "cannot use spirv_literal qualifier", type.getBasicTypeString().c_str(), ""); - } - - paramCheckFixStorage(loc, qualifier.storage, type); -} - -void TParseContext::nestedBlockCheck(const TSourceLoc& loc) -{ - if (structNestingLevel > 0 || blockNestingLevel > 0) - error(loc, "cannot nest a block definition inside a structure or block", "", ""); - ++blockNestingLevel; -} - -void TParseContext::nestedStructCheck(const TSourceLoc& loc) -{ - if (structNestingLevel > 0 || blockNestingLevel > 0) - error(loc, "cannot nest a structure definition inside a structure or block", "", ""); - ++structNestingLevel; -} - -void TParseContext::arrayObjectCheck(const TSourceLoc& loc, const TType& type, const char* op) -{ - // Some versions don't allow comparing arrays or structures containing arrays - if (type.containsArray()) { - profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, op); - profileRequires(loc, EEsProfile, 300, nullptr, op); - } -} - -void TParseContext::opaqueCheck(const TSourceLoc& loc, const TType& type, const char* op) -{ - if (containsFieldWithBasicType(type, EbtSampler) && !extensionTurnedOn(E_GL_ARB_bindless_texture)) - error(loc, "can't use with samplers or structs containing samplers", op, ""); -} - -void TParseContext::referenceCheck(const TSourceLoc& loc, const TType& type, const char* op) -{ - if (containsFieldWithBasicType(type, EbtReference)) - error(loc, "can't use with reference types", op, ""); -} - -void TParseContext::storage16BitAssignmentCheck(const TSourceLoc& loc, const TType& type, const char* op) -{ - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtFloat16)) - requireFloat16Arithmetic(loc, op, "can't use with structs containing float16"); - - if (type.isArray() && type.getBasicType() == EbtFloat16) - requireFloat16Arithmetic(loc, op, "can't use with arrays containing float16"); - - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtInt16)) - requireInt16Arithmetic(loc, op, "can't use with structs containing int16"); - - if (type.isArray() && type.getBasicType() == EbtInt16) - requireInt16Arithmetic(loc, op, "can't use with arrays containing int16"); - - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtUint16)) - requireInt16Arithmetic(loc, op, "can't use with structs containing uint16"); - - if (type.isArray() && type.getBasicType() == EbtUint16) - requireInt16Arithmetic(loc, op, "can't use with arrays containing uint16"); - - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtInt8)) - requireInt8Arithmetic(loc, op, "can't use with structs containing int8"); - - if (type.isArray() && type.getBasicType() == EbtInt8) - requireInt8Arithmetic(loc, op, "can't use with arrays containing int8"); - - if (type.getBasicType() == EbtStruct && containsFieldWithBasicType(type, EbtUint8)) - requireInt8Arithmetic(loc, op, "can't use with structs containing uint8"); - - if (type.isArray() && type.getBasicType() == EbtUint8) - requireInt8Arithmetic(loc, op, "can't use with arrays containing uint8"); -} - -void TParseContext::specializationCheck(const TSourceLoc& loc, const TType& type, const char* op) -{ - if (type.containsSpecializationSize()) - error(loc, "can't use with types containing arrays sized with a specialization constant", op, ""); -} - -void TParseContext::structTypeCheck(const TSourceLoc& /*loc*/, TPublicType& publicType) -{ - const TTypeList& typeList = *publicType.userDef->getStruct(); - - // fix and check for member storage qualifiers and types that don't belong within a structure - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - if (memberQualifier.isAuxiliary() || - memberQualifier.isInterpolation() || - (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal)) - error(memberLoc, "cannot use storage or interpolation qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); - if (memberQualifier.isMemory()) - error(memberLoc, "cannot use memory qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); - if (memberQualifier.hasLayout()) { - error(memberLoc, "cannot use layout qualifiers on structure members", typeList[member].type->getFieldName().c_str(), ""); - memberQualifier.clearLayout(); - } - if (memberQualifier.invariant) - error(memberLoc, "cannot use invariant qualifier on structure members", typeList[member].type->getFieldName().c_str(), ""); - } -} - -// -// See if this loop satisfies the limitations for ES 2.0 (version 100) for loops in Appendex A: -// -// "The loop index has type int or float. -// -// "The for statement has the form: -// for ( init-declaration ; condition ; expression ) -// init-declaration has the form: type-specifier identifier = constant-expression -// condition has the form: loop-index relational_operator constant-expression -// where relational_operator is one of: > >= < <= == or != -// expression [sic] has one of the following forms: -// loop-index++ -// loop-index-- -// loop-index += constant-expression -// loop-index -= constant-expression -// -// The body is handled in an AST traversal. -// -void TParseContext::inductiveLoopCheck(const TSourceLoc& loc, TIntermNode* init, TIntermLoop* loop) -{ - // loop index init must exist and be a declaration, which shows up in the AST as an aggregate of size 1 of the declaration - bool badInit = false; - if (! init || ! init->getAsAggregate() || init->getAsAggregate()->getSequence().size() != 1) - badInit = true; - TIntermBinary* binaryInit = nullptr; - if (! badInit) { - // get the declaration assignment - binaryInit = init->getAsAggregate()->getSequence()[0]->getAsBinaryNode(); - if (! binaryInit) - badInit = true; - } - if (badInit) { - error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); - return; - } - - // loop index must be type int or float - if (! binaryInit->getType().isScalar() || (binaryInit->getBasicType() != EbtInt && binaryInit->getBasicType() != EbtFloat)) { - error(loc, "inductive loop requires a scalar 'int' or 'float' loop index", "limitations", ""); - return; - } - - // init is the form "loop-index = constant" - if (binaryInit->getOp() != EOpAssign || ! binaryInit->getLeft()->getAsSymbolNode() || ! binaryInit->getRight()->getAsConstantUnion()) { - error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); - return; - } - - // get the unique id of the loop index - long long loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId(); - inductiveLoopIds.insert(loopIndex); - - // condition's form must be "loop-index relational-operator constant-expression" - bool badCond = ! loop->getTest(); - if (! badCond) { - TIntermBinary* binaryCond = loop->getTest()->getAsBinaryNode(); - badCond = ! binaryCond; - if (! badCond) { - switch (binaryCond->getOp()) { - case EOpGreaterThan: - case EOpGreaterThanEqual: - case EOpLessThan: - case EOpLessThanEqual: - case EOpEqual: - case EOpNotEqual: - break; - default: - badCond = true; - } - } - if (binaryCond && (! binaryCond->getLeft()->getAsSymbolNode() || - binaryCond->getLeft()->getAsSymbolNode()->getId() != loopIndex || - ! binaryCond->getRight()->getAsConstantUnion())) - badCond = true; - } - if (badCond) { - error(loc, "inductive-loop condition requires the form \"loop-index constant-expression\"", "limitations", ""); - return; - } - - // loop-index++ - // loop-index-- - // loop-index += constant-expression - // loop-index -= constant-expression - bool badTerminal = ! loop->getTerminal(); - if (! badTerminal) { - TIntermUnary* unaryTerminal = loop->getTerminal()->getAsUnaryNode(); - TIntermBinary* binaryTerminal = loop->getTerminal()->getAsBinaryNode(); - if (unaryTerminal || binaryTerminal) { - switch(loop->getTerminal()->getAsOperator()->getOp()) { - case EOpPostDecrement: - case EOpPostIncrement: - case EOpAddAssign: - case EOpSubAssign: - break; - default: - badTerminal = true; - } - } else - badTerminal = true; - if (binaryTerminal && (! binaryTerminal->getLeft()->getAsSymbolNode() || - binaryTerminal->getLeft()->getAsSymbolNode()->getId() != loopIndex || - ! binaryTerminal->getRight()->getAsConstantUnion())) - badTerminal = true; - if (unaryTerminal && (! unaryTerminal->getOperand()->getAsSymbolNode() || - unaryTerminal->getOperand()->getAsSymbolNode()->getId() != loopIndex)) - badTerminal = true; - } - if (badTerminal) { - error(loc, "inductive-loop termination requires the form \"loop-index++, loop-index--, loop-index += constant-expression, or loop-index -= constant-expression\"", "limitations", ""); - return; - } - - // the body - inductiveLoopBodyCheck(loop->getBody(), loopIndex, symbolTable); -} - -// Do limit checks for built-in arrays. -void TParseContext::arrayLimitCheck(const TSourceLoc& loc, const TString& identifier, int size) -{ - if (identifier.compare("gl_TexCoord") == 0) - limitCheck(loc, size, "gl_MaxTextureCoords", "gl_TexCoord array size"); - else if (identifier.compare("gl_ClipDistance") == 0) - limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistance array size"); - else if (identifier.compare("gl_CullDistance") == 0) - limitCheck(loc, size, "gl_MaxCullDistances", "gl_CullDistance array size"); - else if (identifier.compare("gl_ClipDistancePerViewNV") == 0) - limitCheck(loc, size, "gl_MaxClipDistances", "gl_ClipDistancePerViewNV array size"); - else if (identifier.compare("gl_CullDistancePerViewNV") == 0) - limitCheck(loc, size, "gl_MaxCullDistances", "gl_CullDistancePerViewNV array size"); -} - -// See if the provided value is less than or equal to the symbol indicated by limit, -// which should be a constant in the symbol table. -void TParseContext::limitCheck(const TSourceLoc& loc, int value, const char* limit, const char* feature) -{ - TSymbol* symbol = symbolTable.find(limit); - assert(symbol->getAsVariable()); - const TConstUnionArray& constArray = symbol->getAsVariable()->getConstArray(); - assert(! constArray.empty()); - if (value > constArray[0].getIConst()) - error(loc, "must be less than or equal to", feature, "%s (%d)", limit, constArray[0].getIConst()); -} - -// -// Do any additional error checking, etc., once we know the parsing is done. -// -void TParseContext::finish() -{ - TParseContextBase::finish(); - - if (parsingBuiltins) - return; - - // Check on array indexes for ES 2.0 (version 100) limitations. - for (size_t i = 0; i < needsIndexLimitationChecking.size(); ++i) - constantIndexExpressionCheck(needsIndexLimitationChecking[i]); - - // Check for stages that are enabled by extension. - // Can't do this at the beginning, it is chicken and egg to add a stage by - // extension. - // Stage-specific features were correctly tested for already, this is just - // about the stage itself. - switch (language) { - case EShLangGeometry: - if (isEsProfile() && version == 310) - requireExtensions(getCurrentLoc(), Num_AEP_geometry_shader, AEP_geometry_shader, "geometry shaders"); - break; - case EShLangTessControl: - case EShLangTessEvaluation: - if (isEsProfile() && version == 310) - requireExtensions(getCurrentLoc(), Num_AEP_tessellation_shader, AEP_tessellation_shader, "tessellation shaders"); - else if (!isEsProfile() && version < 400) - requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_tessellation_shader, "tessellation shaders"); - break; - case EShLangCompute: - if (!isEsProfile() && version < 430) - requireExtensions(getCurrentLoc(), 1, &E_GL_ARB_compute_shader, "compute shaders"); - break; - case EShLangTask: - requireExtensions(getCurrentLoc(), Num_AEP_mesh_shader, AEP_mesh_shader, "task shaders"); - break; - case EShLangMesh: - requireExtensions(getCurrentLoc(), Num_AEP_mesh_shader, AEP_mesh_shader, "mesh shaders"); - break; - default: - break; - } - - // Set default outputs for GL_NV_geometry_shader_passthrough - if (language == EShLangGeometry && extensionTurnedOn(E_SPV_NV_geometry_shader_passthrough)) { - if (intermediate.getOutputPrimitive() == ElgNone) { - switch (intermediate.getInputPrimitive()) { - case ElgPoints: intermediate.setOutputPrimitive(ElgPoints); break; - case ElgLines: intermediate.setOutputPrimitive(ElgLineStrip); break; - case ElgTriangles: intermediate.setOutputPrimitive(ElgTriangleStrip); break; - default: break; - } - } - if (intermediate.getVertices() == TQualifier::layoutNotSet) { - switch (intermediate.getInputPrimitive()) { - case ElgPoints: intermediate.setVertices(1); break; - case ElgLines: intermediate.setVertices(2); break; - case ElgTriangles: intermediate.setVertices(3); break; - default: break; - } - } - } -} - -// -// Layout qualifier stuff. -// - -// Put the id's layout qualification into the public type, for qualifiers not having a number set. -// This is before we know any type information for error checking. -void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id) -{ - std::transform(id.begin(), id.end(), id.begin(), ::tolower); - - if (id == TQualifier::getLayoutMatrixString(ElmColumnMajor)) { - publicType.qualifier.layoutMatrix = ElmColumnMajor; - return; - } - if (id == TQualifier::getLayoutMatrixString(ElmRowMajor)) { - publicType.qualifier.layoutMatrix = ElmRowMajor; - return; - } - if (id == TQualifier::getLayoutPackingString(ElpPacked)) { - if (spvVersion.spv != 0) { - if (spvVersion.vulkanRelaxed) - return; // silently ignore qualifier - else - spvRemoved(loc, "packed"); - } - publicType.qualifier.layoutPacking = ElpPacked; - return; - } - if (id == TQualifier::getLayoutPackingString(ElpShared)) { - if (spvVersion.spv != 0) { - if (spvVersion.vulkanRelaxed) - return; // silently ignore qualifier - else - spvRemoved(loc, "shared"); - } - publicType.qualifier.layoutPacking = ElpShared; - return; - } - if (id == TQualifier::getLayoutPackingString(ElpStd140)) { - publicType.qualifier.layoutPacking = ElpStd140; - return; - } - if (id == TQualifier::getLayoutPackingString(ElpStd430)) { - requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "std430"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_shader_storage_buffer_object, "std430"); - profileRequires(loc, EEsProfile, 310, nullptr, "std430"); - publicType.qualifier.layoutPacking = ElpStd430; - return; - } - if (id == TQualifier::getLayoutPackingString(ElpScalar)) { - requireVulkan(loc, "scalar"); - requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "scalar block layout"); - publicType.qualifier.layoutPacking = ElpScalar; - return; - } - // TODO: compile-time performance: may need to stop doing linear searches - for (TLayoutFormat format = (TLayoutFormat)(ElfNone + 1); format < ElfCount; format = (TLayoutFormat)(format + 1)) { - if (id == TQualifier::getLayoutFormatString(format)) { - if ((format > ElfEsFloatGuard && format < ElfFloatGuard) || - (format > ElfEsIntGuard && format < ElfIntGuard) || - (format > ElfEsUintGuard && format < ElfCount)) - requireProfile(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, "image load-store format"); - profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "image load store"); - profileRequires(loc, EEsProfile, 310, E_GL_ARB_shader_image_load_store, "image load store"); - publicType.qualifier.layoutFormat = format; - return; - } - } - if (id == "push_constant") { - requireVulkan(loc, "push_constant"); - publicType.qualifier.layoutPushConstant = true; - return; - } - if (id == "buffer_reference") { - requireVulkan(loc, "buffer_reference"); - requireExtensions(loc, 1, &E_GL_EXT_buffer_reference, "buffer_reference"); - publicType.qualifier.layoutBufferReference = true; - intermediate.setUseStorageBuffer(); - intermediate.setUsePhysicalStorageBuffer(); - return; - } - if (id == "bindless_sampler") { - requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bindless_sampler"); - publicType.qualifier.layoutBindlessSampler = true; - intermediate.setBindlessTextureMode(currentCaller, AstRefTypeLayout); - return; - } - if (id == "bindless_image") { - requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bindless_image"); - publicType.qualifier.layoutBindlessImage = true; - intermediate.setBindlessImageMode(currentCaller, AstRefTypeLayout); - return; - } - if (id == "bound_sampler") { - requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bound_sampler"); - publicType.qualifier.layoutBindlessSampler = false; - return; - } - if (id == "bound_image") { - requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "bound_image"); - publicType.qualifier.layoutBindlessImage = false; - return; - } - if (language == EShLangGeometry || language == EShLangTessEvaluation || language == EShLangMesh) { - if (id == TQualifier::getGeometryString(ElgTriangles)) { - publicType.shaderQualifiers.geometry = ElgTriangles; - return; - } - if (language == EShLangGeometry || language == EShLangMesh) { - if (id == TQualifier::getGeometryString(ElgPoints)) { - publicType.shaderQualifiers.geometry = ElgPoints; - return; - } - if (id == TQualifier::getGeometryString(ElgLines)) { - publicType.shaderQualifiers.geometry = ElgLines; - return; - } - if (language == EShLangGeometry) { - if (id == TQualifier::getGeometryString(ElgLineStrip)) { - publicType.shaderQualifiers.geometry = ElgLineStrip; - return; - } - if (id == TQualifier::getGeometryString(ElgLinesAdjacency)) { - publicType.shaderQualifiers.geometry = ElgLinesAdjacency; - return; - } - if (id == TQualifier::getGeometryString(ElgTrianglesAdjacency)) { - publicType.shaderQualifiers.geometry = ElgTrianglesAdjacency; - return; - } - if (id == TQualifier::getGeometryString(ElgTriangleStrip)) { - publicType.shaderQualifiers.geometry = ElgTriangleStrip; - return; - } - if (id == "passthrough") { - requireExtensions(loc, 1, &E_SPV_NV_geometry_shader_passthrough, "geometry shader passthrough"); - publicType.qualifier.layoutPassthrough = true; - intermediate.setGeoPassthroughEXT(); - return; - } - } - } else { - assert(language == EShLangTessEvaluation); - - // input primitive - if (id == TQualifier::getGeometryString(ElgTriangles)) { - publicType.shaderQualifiers.geometry = ElgTriangles; - return; - } - if (id == TQualifier::getGeometryString(ElgQuads)) { - publicType.shaderQualifiers.geometry = ElgQuads; - return; - } - if (id == TQualifier::getGeometryString(ElgIsolines)) { - publicType.shaderQualifiers.geometry = ElgIsolines; - return; - } - - // vertex spacing - if (id == TQualifier::getVertexSpacingString(EvsEqual)) { - publicType.shaderQualifiers.spacing = EvsEqual; - return; - } - if (id == TQualifier::getVertexSpacingString(EvsFractionalEven)) { - publicType.shaderQualifiers.spacing = EvsFractionalEven; - return; - } - if (id == TQualifier::getVertexSpacingString(EvsFractionalOdd)) { - publicType.shaderQualifiers.spacing = EvsFractionalOdd; - return; - } - - // triangle order - if (id == TQualifier::getVertexOrderString(EvoCw)) { - publicType.shaderQualifiers.order = EvoCw; - return; - } - if (id == TQualifier::getVertexOrderString(EvoCcw)) { - publicType.shaderQualifiers.order = EvoCcw; - return; - } - - // point mode - if (id == "point_mode") { - publicType.shaderQualifiers.pointMode = true; - return; - } - } - } - if (language == EShLangFragment) { - if (id == "origin_upper_left") { - requireProfile(loc, ECoreProfile | ECompatibilityProfile | ENoProfile, "origin_upper_left"); - if (profile == ENoProfile) { - profileRequires(loc,ECoreProfile | ECompatibilityProfile, 140, E_GL_ARB_fragment_coord_conventions, "origin_upper_left"); - } - - publicType.shaderQualifiers.originUpperLeft = true; - return; - } - if (id == "pixel_center_integer") { - requireProfile(loc, ECoreProfile | ECompatibilityProfile | ENoProfile, "pixel_center_integer"); - if (profile == ENoProfile) { - profileRequires(loc,ECoreProfile | ECompatibilityProfile, 140, E_GL_ARB_fragment_coord_conventions, "pixel_center_integer"); - } - publicType.shaderQualifiers.pixelCenterInteger = true; - return; - } - if (id == "early_fragment_tests") { - profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_ARB_shader_image_load_store, "early_fragment_tests"); - profileRequires(loc, EEsProfile, 310, nullptr, "early_fragment_tests"); - publicType.shaderQualifiers.earlyFragmentTests = true; - return; - } - if (id == "early_and_late_fragment_tests_amd") { - profileRequires(loc, ENoProfile | ECoreProfile | ECompatibilityProfile, 420, E_GL_AMD_shader_early_and_late_fragment_tests, "early_and_late_fragment_tests_amd"); - profileRequires(loc, EEsProfile, 310, nullptr, "early_and_late_fragment_tests_amd"); - publicType.shaderQualifiers.earlyAndLateFragmentTestsAMD = true; - return; - } - if (id == "post_depth_coverage") { - requireExtensions(loc, Num_post_depth_coverageEXTs, post_depth_coverageEXTs, "post depth coverage"); - if (extensionTurnedOn(E_GL_ARB_post_depth_coverage)) { - publicType.shaderQualifiers.earlyFragmentTests = true; - } - publicType.shaderQualifiers.postDepthCoverage = true; - return; - } - /* id is transformed into lower case in the beginning of this function. */ - if (id == "non_coherent_color_attachment_readext") { - requireExtensions(loc, 1, &E_GL_EXT_shader_tile_image, "non_coherent_color_attachment_readEXT"); - publicType.shaderQualifiers.nonCoherentColorAttachmentReadEXT = true; - return; - } - if (id == "non_coherent_depth_attachment_readext") { - requireExtensions(loc, 1, &E_GL_EXT_shader_tile_image, "non_coherent_depth_attachment_readEXT"); - publicType.shaderQualifiers.nonCoherentDepthAttachmentReadEXT = true; - return; - } - if (id == "non_coherent_stencil_attachment_readext") { - requireExtensions(loc, 1, &E_GL_EXT_shader_tile_image, "non_coherent_stencil_attachment_readEXT"); - publicType.shaderQualifiers.nonCoherentStencilAttachmentReadEXT = true; - return; - } - for (TLayoutDepth depth = (TLayoutDepth)(EldNone + 1); depth < EldCount; depth = (TLayoutDepth)(depth+1)) { - if (id == TQualifier::getLayoutDepthString(depth)) { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, "depth layout qualifier"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, nullptr, "depth layout qualifier"); - publicType.shaderQualifiers.layoutDepth = depth; - return; - } - } - for (TLayoutStencil stencil = (TLayoutStencil)(ElsNone + 1); stencil < ElsCount; stencil = (TLayoutStencil)(stencil+1)) { - if (id == TQualifier::getLayoutStencilString(stencil)) { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, "stencil layout qualifier"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, nullptr, "stencil layout qualifier"); - publicType.shaderQualifiers.layoutStencil = stencil; - return; - } - } - for (TInterlockOrdering order = (TInterlockOrdering)(EioNone + 1); order < EioCount; order = (TInterlockOrdering)(order+1)) { - if (id == TQualifier::getInterlockOrderingString(order)) { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, "fragment shader interlock layout qualifier"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 450, nullptr, "fragment shader interlock layout qualifier"); - requireExtensions(loc, 1, &E_GL_ARB_fragment_shader_interlock, TQualifier::getInterlockOrderingString(order)); - if (order == EioShadingRateInterlockOrdered || order == EioShadingRateInterlockUnordered) - requireExtensions(loc, 1, &E_GL_NV_shading_rate_image, TQualifier::getInterlockOrderingString(order)); - publicType.shaderQualifiers.interlockOrdering = order; - return; - } - } - if (id.compare(0, 13, "blend_support") == 0) { - bool found = false; - for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) { - if (id == TQualifier::getBlendEquationString(be)) { - profileRequires(loc, EEsProfile, 320, E_GL_KHR_blend_equation_advanced, "blend equation"); - profileRequires(loc, ~EEsProfile, 0, E_GL_KHR_blend_equation_advanced, "blend equation"); - intermediate.addBlendEquation(be); - publicType.shaderQualifiers.blendEquation = true; - found = true; - break; - } - } - if (! found) - error(loc, "unknown blend equation", "blend_support", ""); - return; - } - if (id == "override_coverage") { - requireExtensions(loc, 1, &E_GL_NV_sample_mask_override_coverage, "sample mask override coverage"); - publicType.shaderQualifiers.layoutOverrideCoverage = true; - return; - } - } - if (language == EShLangVertex || - language == EShLangTessControl || - language == EShLangTessEvaluation || - language == EShLangGeometry ) { - if (id == "viewport_relative") { - requireExtensions(loc, 1, &E_GL_NV_viewport_array2, "view port array2"); - publicType.qualifier.layoutViewportRelative = true; - return; - } - } else { - if (language == EShLangRayGen || language == EShLangIntersect || - language == EShLangAnyHit || language == EShLangClosestHit || - language == EShLangMiss || language == EShLangCallable) { - if (id == "shaderrecordnv" || id == "shaderrecordext") { - if (id == "shaderrecordnv") { - requireExtensions(loc, 1, &E_GL_NV_ray_tracing, "shader record NV"); - } else { - requireExtensions(loc, 1, &E_GL_EXT_ray_tracing, "shader record EXT"); - } - publicType.qualifier.layoutShaderRecord = true; - return; - } else if (id == "hitobjectshaderrecordnv") { - requireExtensions(loc, 1, &E_GL_NV_shader_invocation_reorder, "hitobject shader record NV"); - publicType.qualifier.layoutHitObjectShaderRecordNV = true; - return; - } - - } - } - if (language == EShLangCompute) { - if (id.compare(0, 17, "derivative_group_") == 0) { - requireExtensions(loc, 1, &E_GL_NV_compute_shader_derivatives, "compute shader derivatives"); - if (id == "derivative_group_quadsnv") { - publicType.shaderQualifiers.layoutDerivativeGroupQuads = true; - return; - } else if (id == "derivative_group_linearnv") { - publicType.shaderQualifiers.layoutDerivativeGroupLinear = true; - return; - } - } - } - - if (id == "primitive_culling") { - requireExtensions(loc, 1, &E_GL_EXT_ray_flags_primitive_culling, "primitive culling"); - publicType.shaderQualifiers.layoutPrimitiveCulling = true; - return; - } - - error(loc, "unrecognized layout identifier, or qualifier requires assignment (e.g., binding = 4)", id.c_str(), ""); -} - -// Put the id's layout qualifier value into the public type, for qualifiers having a number set. -// This is before we know any type information for error checking. -void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publicType, TString& id, const TIntermTyped* node) -{ - const char* feature = "layout-id value"; - const char* nonLiteralFeature = "non-literal layout-id value"; - - integerCheck(node, feature); - const TIntermConstantUnion* constUnion = node->getAsConstantUnion(); - int value; - bool nonLiteral = false; - if (constUnion) { - value = constUnion->getConstArray()[0].getIConst(); - if (! constUnion->isLiteral()) { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, nonLiteralFeature); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, nonLiteralFeature); - } - } else { - // grammar should have give out the error message - value = 0; - nonLiteral = true; - } - - if (value < 0) { - error(loc, "cannot be negative", feature, ""); - return; - } - - std::transform(id.begin(), id.end(), id.begin(), ::tolower); - - if (id == "offset") { - // "offset" can be for either - // - uniform offsets - // - atomic_uint offsets - const char* feature = "offset"; - if (spvVersion.spv == 0) { - requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, feature); - const char* exts[2] = { E_GL_ARB_enhanced_layouts, E_GL_ARB_shader_atomic_counters }; - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 420, 2, exts, feature); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - } - publicType.qualifier.layoutOffset = value; - publicType.qualifier.explicitOffset = true; - if (nonLiteral) - error(loc, "needs a literal integer", "offset", ""); - return; - } else if (id == "align") { - const char* feature = "uniform buffer-member align"; - if (spvVersion.spv == 0) { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); - } - // "The specified alignment must be a power of 2, or a compile-time error results." - if (! IsPow2(value)) - error(loc, "must be a power of 2", "align", ""); - else - publicType.qualifier.layoutAlign = value; - if (nonLiteral) - error(loc, "needs a literal integer", "align", ""); - return; - } else if (id == "location") { - profileRequires(loc, EEsProfile, 300, nullptr, "location"); - const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; - // GL_ARB_explicit_uniform_location requires 330 or GL_ARB_explicit_attrib_location we do not need to add it here - profileRequires(loc, ~EEsProfile, 330, 2, exts, "location"); - if ((unsigned int)value >= TQualifier::layoutLocationEnd) - error(loc, "location is too large", id.c_str(), ""); - else - publicType.qualifier.layoutLocation = value; - if (nonLiteral) - error(loc, "needs a literal integer", "location", ""); - return; - } else if (id == "set") { - if ((unsigned int)value >= TQualifier::layoutSetEnd) - error(loc, "set is too large", id.c_str(), ""); - else - publicType.qualifier.layoutSet = value; - if (value != 0) - requireVulkan(loc, "descriptor set"); - if (nonLiteral) - error(loc, "needs a literal integer", "set", ""); - return; - } else if (id == "binding") { - profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, "binding"); - profileRequires(loc, EEsProfile, 310, nullptr, "binding"); - if ((unsigned int)value >= TQualifier::layoutBindingEnd) - error(loc, "binding is too large", id.c_str(), ""); - else - publicType.qualifier.layoutBinding = value; - if (nonLiteral) - error(loc, "needs a literal integer", "binding", ""); - return; - } - if (id == "constant_id") { - requireSpv(loc, "constant_id"); - if (value >= (int)TQualifier::layoutSpecConstantIdEnd) { - error(loc, "specialization-constant id is too large", id.c_str(), ""); - } else { - publicType.qualifier.layoutSpecConstantId = value; - publicType.qualifier.specConstant = true; - if (! intermediate.addUsedConstantId(value)) - error(loc, "specialization-constant id already used", id.c_str(), ""); - } - if (nonLiteral) - error(loc, "needs a literal integer", "constant_id", ""); - return; - } - if (id == "component") { - requireProfile(loc, ECoreProfile | ECompatibilityProfile, "component"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "component"); - if ((unsigned)value >= TQualifier::layoutComponentEnd) - error(loc, "component is too large", id.c_str(), ""); - else - publicType.qualifier.layoutComponent = value; - if (nonLiteral) - error(loc, "needs a literal integer", "component", ""); - return; - } - if (id.compare(0, 4, "xfb_") == 0) { - // "Any shader making any static use (after preprocessing) of any of these - // *xfb_* qualifiers will cause the shader to be in a transform feedback - // capturing mode and hence responsible for describing the transform feedback - // setup." - intermediate.setXfbMode(); - const char* feature = "transform feedback qualifier"; - requireStage(loc, (EShLanguageMask)(EShLangVertexMask | EShLangGeometryMask | EShLangTessControlMask | EShLangTessEvaluationMask), feature); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, feature); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); - if (id == "xfb_buffer") { - // "It is a compile-time error to specify an *xfb_buffer* that is greater than - // the implementation-dependent constant gl_MaxTransformFeedbackBuffers." - if (value >= resources.maxTransformFeedbackBuffers) - error(loc, "buffer is too large:", id.c_str(), "gl_MaxTransformFeedbackBuffers is %d", resources.maxTransformFeedbackBuffers); - if (value >= (int)TQualifier::layoutXfbBufferEnd) - error(loc, "buffer is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbBufferEnd-1); - else - publicType.qualifier.layoutXfbBuffer = value; - if (nonLiteral) - error(loc, "needs a literal integer", "xfb_buffer", ""); - return; - } else if (id == "xfb_offset") { - if (value >= (int)TQualifier::layoutXfbOffsetEnd) - error(loc, "offset is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbOffsetEnd-1); - else - publicType.qualifier.layoutXfbOffset = value; - if (nonLiteral) - error(loc, "needs a literal integer", "xfb_offset", ""); - return; - } else if (id == "xfb_stride") { - // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the - // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents." - if (value > 4 * resources.maxTransformFeedbackInterleavedComponents) { - error(loc, "1/4 stride is too large:", id.c_str(), "gl_MaxTransformFeedbackInterleavedComponents is %d", - resources.maxTransformFeedbackInterleavedComponents); - } - if (value >= (int)TQualifier::layoutXfbStrideEnd) - error(loc, "stride is too large:", id.c_str(), "internal max is %d", TQualifier::layoutXfbStrideEnd-1); - else - publicType.qualifier.layoutXfbStride = value; - if (nonLiteral) - error(loc, "needs a literal integer", "xfb_stride", ""); - return; - } - } - if (id == "input_attachment_index") { - requireVulkan(loc, "input_attachment_index"); - if (value >= (int)TQualifier::layoutAttachmentEnd) - error(loc, "attachment index is too large", id.c_str(), ""); - else - publicType.qualifier.layoutAttachment = value; - if (nonLiteral) - error(loc, "needs a literal integer", "input_attachment_index", ""); - return; - } - if (id == "num_views") { - requireExtensions(loc, Num_OVR_multiview_EXTs, OVR_multiview_EXTs, "num_views"); - publicType.shaderQualifiers.numViews = value; - if (nonLiteral) - error(loc, "needs a literal integer", "num_views", ""); - return; - } - if (language == EShLangVertex || - language == EShLangTessControl || - language == EShLangTessEvaluation || - language == EShLangGeometry) { - if (id == "secondary_view_offset") { - requireExtensions(loc, 1, &E_GL_NV_stereo_view_rendering, "stereo view rendering"); - publicType.qualifier.layoutSecondaryViewportRelativeOffset = value; - if (nonLiteral) - error(loc, "needs a literal integer", "secondary_view_offset", ""); - return; - } - } - - if (id == "buffer_reference_align") { - requireExtensions(loc, 1, &E_GL_EXT_buffer_reference, "buffer_reference_align"); - if (! IsPow2(value)) - error(loc, "must be a power of 2", "buffer_reference_align", ""); - else - publicType.qualifier.layoutBufferReferenceAlign = IntLog2(value); - if (nonLiteral) - error(loc, "needs a literal integer", "buffer_reference_align", ""); - return; - } - - switch (language) { - case EShLangTessControl: - if (id == "vertices") { - if (value == 0) - error(loc, "must be greater than 0", "vertices", ""); - else - publicType.shaderQualifiers.vertices = value; - if (nonLiteral) - error(loc, "needs a literal integer", "vertices", ""); - return; - } - break; - - case EShLangGeometry: - if (id == "invocations") { - profileRequires(loc, ECompatibilityProfile | ECoreProfile, 400, nullptr, "invocations"); - if (value == 0) - error(loc, "must be at least 1", "invocations", ""); - else - publicType.shaderQualifiers.invocations = value; - if (nonLiteral) - error(loc, "needs a literal integer", "invocations", ""); - return; - } - if (id == "max_vertices") { - publicType.shaderQualifiers.vertices = value; - if (value > resources.maxGeometryOutputVertices) - error(loc, "too large, must be less than gl_MaxGeometryOutputVertices", "max_vertices", ""); - if (nonLiteral) - error(loc, "needs a literal integer", "max_vertices", ""); - return; - } - if (id == "stream") { - requireProfile(loc, ~EEsProfile, "selecting output stream"); - publicType.qualifier.layoutStream = value; - if (value > 0) - intermediate.setMultiStream(); - if (nonLiteral) - error(loc, "needs a literal integer", "stream", ""); - return; - } - break; - - case EShLangFragment: - if (id == "index") { - requireProfile(loc, ECompatibilityProfile | ECoreProfile | EEsProfile, "index layout qualifier on fragment output"); - const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; - profileRequires(loc, ECompatibilityProfile | ECoreProfile, 330, 2, exts, "index layout qualifier on fragment output"); - profileRequires(loc, EEsProfile ,310, E_GL_EXT_blend_func_extended, "index layout qualifier on fragment output"); - // "It is also a compile-time error if a fragment shader sets a layout index to less than 0 or greater than 1." - if (value < 0 || value > 1) { - value = 0; - error(loc, "value must be 0 or 1", "index", ""); - } - - publicType.qualifier.layoutIndex = value; - if (nonLiteral) - error(loc, "needs a literal integer", "index", ""); - return; - } - break; - - case EShLangMesh: - if (id == "max_vertices") { - requireExtensions(loc, Num_AEP_mesh_shader, AEP_mesh_shader, "max_vertices"); - publicType.shaderQualifiers.vertices = value; - int max = extensionTurnedOn(E_GL_EXT_mesh_shader) ? resources.maxMeshOutputVerticesEXT - : resources.maxMeshOutputVerticesNV; - if (value > max) { - TString maxsErrtring = "too large, must be less than "; - maxsErrtring.append(extensionTurnedOn(E_GL_EXT_mesh_shader) ? "gl_MaxMeshOutputVerticesEXT" - : "gl_MaxMeshOutputVerticesNV"); - error(loc, maxsErrtring.c_str(), "max_vertices", ""); - } - if (nonLiteral) - error(loc, "needs a literal integer", "max_vertices", ""); - return; - } - if (id == "max_primitives") { - requireExtensions(loc, Num_AEP_mesh_shader, AEP_mesh_shader, "max_primitives"); - publicType.shaderQualifiers.primitives = value; - int max = extensionTurnedOn(E_GL_EXT_mesh_shader) ? resources.maxMeshOutputPrimitivesEXT - : resources.maxMeshOutputPrimitivesNV; - if (value > max) { - TString maxsErrtring = "too large, must be less than "; - maxsErrtring.append(extensionTurnedOn(E_GL_EXT_mesh_shader) ? "gl_MaxMeshOutputPrimitivesEXT" - : "gl_MaxMeshOutputPrimitivesNV"); - error(loc, maxsErrtring.c_str(), "max_primitives", ""); - } - if (nonLiteral) - error(loc, "needs a literal integer", "max_primitives", ""); - return; - } - // Fall through - - case EShLangTask: - // Fall through - case EShLangCompute: - if (id.compare(0, 11, "local_size_") == 0) { - if (language == EShLangMesh || language == EShLangTask) { - requireExtensions(loc, Num_AEP_mesh_shader, AEP_mesh_shader, "gl_WorkGroupSize"); - } else { - profileRequires(loc, EEsProfile, 310, nullptr, "gl_WorkGroupSize"); - profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_compute_shader, "gl_WorkGroupSize"); - } - if (nonLiteral) - error(loc, "needs a literal integer", "local_size", ""); - if (id.size() == 12 && value == 0) { - error(loc, "must be at least 1", id.c_str(), ""); - return; - } - if (id == "local_size_x") { - publicType.shaderQualifiers.localSize[0] = value; - publicType.shaderQualifiers.localSizeNotDefault[0] = true; - return; - } - if (id == "local_size_y") { - publicType.shaderQualifiers.localSize[1] = value; - publicType.shaderQualifiers.localSizeNotDefault[1] = true; - return; - } - if (id == "local_size_z") { - publicType.shaderQualifiers.localSize[2] = value; - publicType.shaderQualifiers.localSizeNotDefault[2] = true; - return; - } - if (spvVersion.spv != 0) { - if (id == "local_size_x_id") { - publicType.shaderQualifiers.localSizeSpecId[0] = value; - return; - } - if (id == "local_size_y_id") { - publicType.shaderQualifiers.localSizeSpecId[1] = value; - return; - } - if (id == "local_size_z_id") { - publicType.shaderQualifiers.localSizeSpecId[2] = value; - return; - } - } - } - break; - - default: - break; - } - - error(loc, "there is no such layout identifier for this stage taking an assigned value", id.c_str(), ""); -} - -// Merge any layout qualifier information from src into dst, leaving everything else in dst alone -// -// "More than one layout qualifier may appear in a single declaration. -// Additionally, the same layout-qualifier-name can occur multiple times -// within a layout qualifier or across multiple layout qualifiers in the -// same declaration. When the same layout-qualifier-name occurs -// multiple times, in a single declaration, the last occurrence overrides -// the former occurrence(s). Further, if such a layout-qualifier-name -// will effect subsequent declarations or other observable behavior, it -// is only the last occurrence that will have any effect, behaving as if -// the earlier occurrence(s) within the declaration are not present. -// This is also true for overriding layout-qualifier-names, where one -// overrides the other (e.g., row_major vs. column_major); only the last -// occurrence has any effect." -void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifier& src, bool inheritOnly) -{ - if (src.hasMatrix()) - dst.layoutMatrix = src.layoutMatrix; - if (src.hasPacking()) - dst.layoutPacking = src.layoutPacking; - - if (src.hasStream()) - dst.layoutStream = src.layoutStream; - if (src.hasFormat()) - dst.layoutFormat = src.layoutFormat; - if (src.hasXfbBuffer()) - dst.layoutXfbBuffer = src.layoutXfbBuffer; - if (src.hasBufferReferenceAlign()) - dst.layoutBufferReferenceAlign = src.layoutBufferReferenceAlign; - - if (src.hasAlign()) - dst.layoutAlign = src.layoutAlign; - - if (! inheritOnly) { - if (src.hasLocation()) - dst.layoutLocation = src.layoutLocation; - if (src.hasOffset()) - dst.layoutOffset = src.layoutOffset; - if (src.hasSet()) - dst.layoutSet = src.layoutSet; - if (src.layoutBinding != TQualifier::layoutBindingEnd) - dst.layoutBinding = src.layoutBinding; - - if (src.hasSpecConstantId()) - dst.layoutSpecConstantId = src.layoutSpecConstantId; - - if (src.hasComponent()) - dst.layoutComponent = src.layoutComponent; - if (src.hasIndex()) - dst.layoutIndex = src.layoutIndex; - if (src.hasXfbStride()) - dst.layoutXfbStride = src.layoutXfbStride; - if (src.hasXfbOffset()) - dst.layoutXfbOffset = src.layoutXfbOffset; - if (src.hasAttachment()) - dst.layoutAttachment = src.layoutAttachment; - if (src.layoutPushConstant) - dst.layoutPushConstant = true; - - if (src.layoutBufferReference) - dst.layoutBufferReference = true; - - if (src.layoutPassthrough) - dst.layoutPassthrough = true; - if (src.layoutViewportRelative) - dst.layoutViewportRelative = true; - if (src.layoutSecondaryViewportRelativeOffset != -2048) - dst.layoutSecondaryViewportRelativeOffset = src.layoutSecondaryViewportRelativeOffset; - if (src.layoutShaderRecord) - dst.layoutShaderRecord = true; - if (src.layoutBindlessSampler) - dst.layoutBindlessSampler = true; - if (src.layoutBindlessImage) - dst.layoutBindlessImage = true; - if (src.pervertexNV) - dst.pervertexNV = true; - if (src.pervertexEXT) - dst.pervertexEXT = true; - if (src.layoutHitObjectShaderRecordNV) - dst.layoutHitObjectShaderRecordNV = true; - } -} - -// Do error layout error checking given a full variable/block declaration. -void TParseContext::layoutObjectCheck(const TSourceLoc& loc, const TSymbol& symbol) -{ - const TType& type = symbol.getType(); - const TQualifier& qualifier = type.getQualifier(); - - // first, cross check WRT to just the type - layoutTypeCheck(loc, type); - - // now, any remaining error checking based on the object itself - - if (qualifier.hasAnyLocation()) { - switch (qualifier.storage) { - case EvqUniform: - case EvqBuffer: - if (symbol.getAsVariable() == nullptr) - error(loc, "can only be used on variable declaration", "location", ""); - break; - default: - break; - } - } - - // user-variable location check, which are required for SPIR-V in/out: - // - variables have it directly, - // - blocks have it on each member (already enforced), so check first one - if (spvVersion.spv > 0 && !parsingBuiltins && qualifier.builtIn == EbvNone && - !qualifier.hasLocation() && !intermediate.getAutoMapLocations()) { - - switch (qualifier.storage) { - case EvqVaryingIn: - case EvqVaryingOut: - if (!type.getQualifier().isTaskMemory() && !type.getQualifier().hasSpirvDecorate() && - (type.getBasicType() != EbtBlock || - (!(*type.getStruct())[0].type->getQualifier().hasLocation() && - (*type.getStruct())[0].type->getQualifier().builtIn == EbvNone))) - error(loc, "SPIR-V requires location for user input/output", "location", ""); - break; - default: - break; - } - } - - // Check packing and matrix - if (qualifier.hasUniformLayout()) { - switch (qualifier.storage) { - case EvqUniform: - case EvqBuffer: - if (type.getBasicType() != EbtBlock) { - if (qualifier.hasMatrix()) - error(loc, "cannot specify matrix layout on a variable declaration", "layout", ""); - if (qualifier.hasPacking()) - error(loc, "cannot specify packing on a variable declaration", "layout", ""); - // "The offset qualifier can only be used on block members of blocks..." - if (qualifier.hasOffset() && !type.isAtomic()) - error(loc, "cannot specify on a variable declaration", "offset", ""); - // "The align qualifier can only be used on blocks or block members..." - if (qualifier.hasAlign()) - error(loc, "cannot specify on a variable declaration", "align", ""); - if (qualifier.isPushConstant()) - error(loc, "can only specify on a uniform block", "push_constant", ""); - if (qualifier.isShaderRecord()) - error(loc, "can only specify on a buffer block", "shaderRecordNV", ""); - if (qualifier.hasLocation() && type.isAtomic()) - error(loc, "cannot specify on atomic counter", "location", ""); - } - break; - default: - // these were already filtered by layoutTypeCheck() (or its callees) - break; - } - } -} - -// "For some blocks declared as arrays, the location can only be applied at the block level: -// When a block is declared as an array where additional locations are needed for each member -// for each block array element, it is a compile-time error to specify locations on the block -// members. That is, when locations would be under specified by applying them on block members, -// they are not allowed on block members. For arrayed interfaces (those generally having an -// extra level of arrayness due to interface expansion), the outer array is stripped before -// applying this rule." -void TParseContext::layoutMemberLocationArrayCheck(const TSourceLoc& loc, bool memberWithLocation, - TArraySizes* arraySizes) -{ - if (memberWithLocation && arraySizes != nullptr) { - if (arraySizes->getNumDims() > (currentBlockQualifier.isArrayedIo(language) ? 1 : 0)) - error(loc, "cannot use in a block array where new locations are needed for each block element", - "location", ""); - } -} - -// Do layout error checking with respect to a type. -void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) -{ - const TQualifier& qualifier = type.getQualifier(); - - // first, intra-layout qualifier-only error checking - layoutQualifierCheck(loc, qualifier); - - // now, error checking combining type and qualifier - - if (qualifier.hasAnyLocation()) { - if (qualifier.hasLocation()) { - if (qualifier.storage == EvqVaryingOut && language == EShLangFragment) { - if (qualifier.layoutLocation >= (unsigned int)resources.maxDrawBuffers) - error(loc, "too large for fragment output", "location", ""); - } - } - if (qualifier.hasComponent()) { - // "It is a compile-time error if this sequence of components gets larger than 3." - if (qualifier.layoutComponent + type.getVectorSize() * (type.getBasicType() == EbtDouble ? 2 : 1) > 4) - error(loc, "type overflows the available 4 components", "component", ""); - - // "It is a compile-time error to apply the component qualifier to a matrix, a structure, a block, or an array containing any of these." - if (type.isMatrix() || type.getBasicType() == EbtBlock || type.getBasicType() == EbtStruct) - error(loc, "cannot apply to a matrix, structure, or block", "component", ""); - - // " It is a compile-time error to use component 1 or 3 as the beginning of a double or dvec2." - if (type.getBasicType() == EbtDouble) - if (qualifier.layoutComponent & 1) - error(loc, "doubles cannot start on an odd-numbered component", "component", ""); - } - - switch (qualifier.storage) { - case EvqVaryingIn: - case EvqVaryingOut: - if (type.getBasicType() == EbtBlock) - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, "location qualifier on in/out block"); - if (type.getQualifier().isTaskMemory()) - error(loc, "cannot apply to taskNV in/out blocks", "location", ""); - break; - case EvqUniform: - case EvqBuffer: - if (type.getBasicType() == EbtBlock) - error(loc, "cannot apply to uniform or buffer block", "location", ""); - else if (type.getBasicType() == EbtSampler && type.getSampler().isAttachmentEXT()) - error(loc, "only applies to", "location", "%s with storage tileImageEXT", type.getBasicTypeString().c_str()); - break; - case EvqtaskPayloadSharedEXT: - error(loc, "cannot apply to taskPayloadSharedEXT", "location", ""); - break; - case EvqPayload: - case EvqPayloadIn: - case EvqHitAttr: - case EvqCallableData: - case EvqCallableDataIn: - case EvqHitObjectAttrNV: - case EvqSpirvStorageClass: - break; - case EvqTileImageEXT: - break; - default: - error(loc, "can only apply to uniform, buffer, in, or out storage qualifiers", "location", ""); - break; - } - - bool typeCollision; - int repeated = intermediate.addUsedLocation(qualifier, type, typeCollision); - if (repeated >= 0 && ! typeCollision) - error(loc, "overlapping use of location", "location", "%d", repeated); - // "fragment-shader outputs/tileImageEXT ... if two variables are placed within the same - // location, they must have the same underlying type (floating-point or integer)" - if (typeCollision && language == EShLangFragment && (qualifier.isPipeOutput() || qualifier.storage == EvqTileImageEXT)) - error(loc, "fragment outputs or tileImageEXTs sharing the same location", "location", "%d must be the same basic type", repeated); - } - - if (qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()) { - if (type.isUnsizedArray()) { - error(loc, "unsized array", "xfb_offset", "in buffer %d", qualifier.layoutXfbBuffer); - } else { - int repeated = intermediate.addXfbBufferOffset(type); - if (repeated >= 0) - error(loc, "overlapping offsets at", "xfb_offset", "offset %d in buffer %d", repeated, qualifier.layoutXfbBuffer); - } - - // "The offset must be a multiple of the size of the first component of the first - // qualified variable or block member, or a compile-time error results. Further, if applied to an aggregate - // containing a double or 64-bit integer, the offset must also be a multiple of 8..." - if ((type.containsBasicType(EbtDouble) || type.containsBasicType(EbtInt64) || type.containsBasicType(EbtUint64)) && - ! IsMultipleOfPow2(qualifier.layoutXfbOffset, 8)) - error(loc, "type contains double or 64-bit integer; xfb_offset must be a multiple of 8", "xfb_offset", ""); - else if ((type.containsBasicType(EbtBool) || type.containsBasicType(EbtFloat) || - type.containsBasicType(EbtInt) || type.containsBasicType(EbtUint)) && - ! IsMultipleOfPow2(qualifier.layoutXfbOffset, 4)) - error(loc, "must be a multiple of size of first component", "xfb_offset", ""); - // ..., if applied to an aggregate containing a half float or 16-bit integer, the offset must also be a multiple of 2..." - else if ((type.contains16BitFloat() || type.containsBasicType(EbtInt16) || type.containsBasicType(EbtUint16)) && - !IsMultipleOfPow2(qualifier.layoutXfbOffset, 2)) - error(loc, "type contains half float or 16-bit integer; xfb_offset must be a multiple of 2", "xfb_offset", ""); - } - if (qualifier.hasXfbStride() && qualifier.hasXfbBuffer()) { - if (! intermediate.setXfbBufferStride(qualifier.layoutXfbBuffer, qualifier.layoutXfbStride)) - error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer); - } - - if (qualifier.hasBinding()) { - // Binding checking, from the spec: - // - // "If the binding point for any uniform or shader storage block instance is less than zero, or greater than or - // equal to the implementation-dependent maximum number of uniform buffer bindings, a compile-time - // error will occur. When the binding identifier is used with a uniform or shader storage block instanced as - // an array of size N, all elements of the array from binding through binding + N - 1 must be within this - // range." - // - if (!type.isOpaque() && type.getBasicType() != EbtBlock && type.getBasicType() != EbtSpirvType) - error(loc, "requires block, or sampler/image, or atomic-counter type", "binding", ""); - if (type.getBasicType() == EbtSampler) { - int lastBinding = qualifier.layoutBinding; - if (type.isArray()) { - if (spvVersion.vulkan == 0) { - if (type.isSizedArray()) - lastBinding += (type.getCumulativeArraySize() - 1); - else { - warn(loc, "assuming binding count of one for compile-time checking of binding numbers for unsized array", "[]", ""); - } - } - } - if (spvVersion.vulkan == 0 && lastBinding >= resources.maxCombinedTextureImageUnits) - error(loc, "sampler binding not less than gl_MaxCombinedTextureImageUnits", "binding", type.isArray() ? "(using array)" : ""); - } - if (type.isAtomic() && !spvVersion.vulkanRelaxed) { - if (qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { - error(loc, "atomic_uint binding is too large; see gl_MaxAtomicCounterBindings", "binding", ""); - return; - } - } - } else if (!intermediate.getAutoMapBindings()) { - // some types require bindings - - // atomic_uint - if (type.isAtomic()) - error(loc, "layout(binding=X) is required", "atomic_uint", ""); - - // SPIR-V - if (spvVersion.spv > 0) { - if (qualifier.isUniformOrBuffer()) { - if (type.getBasicType() == EbtBlock && !qualifier.isPushConstant() && - !qualifier.isShaderRecord() && - !qualifier.hasAttachment() && - !qualifier.hasBufferReference()) - error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", ""); - else if (spvVersion.vulkan > 0 && type.getBasicType() == EbtSampler && !type.getSampler().isAttachmentEXT()) - error(loc, "sampler/texture/image requires layout(binding=X)", "binding", ""); - } - } - } - - // some things can't have arrays of arrays - if (type.isArrayOfArrays()) { - if (spvVersion.vulkan > 0) { - if (type.isOpaque() || (type.getQualifier().isUniformOrBuffer() && type.getBasicType() == EbtBlock)) - warn(loc, "Generating SPIR-V array-of-arrays, but Vulkan only supports single array level for this resource", "[][]", ""); - } - } - - // "The offset qualifier can only be used on block members of blocks..." - if (qualifier.hasOffset()) { - if (type.getBasicType() == EbtBlock) - error(loc, "only applies to block members, not blocks", "offset", ""); - } - - // Image format - if (qualifier.hasFormat()) { - if (! type.isImage() && !intermediate.getBindlessImageMode()) - error(loc, "only apply to images", TQualifier::getLayoutFormatString(qualifier.getFormat()), ""); - else { - if (type.getSampler().type == EbtFloat && qualifier.getFormat() > ElfFloatGuard) - error(loc, "does not apply to floating point images", TQualifier::getLayoutFormatString(qualifier.getFormat()), ""); - if (type.getSampler().type == EbtInt && (qualifier.getFormat() < ElfFloatGuard || qualifier.getFormat() > ElfIntGuard)) - error(loc, "does not apply to signed integer images", TQualifier::getLayoutFormatString(qualifier.getFormat()), ""); - if (type.getSampler().type == EbtUint && qualifier.getFormat() < ElfIntGuard) - error(loc, "does not apply to unsigned integer images", TQualifier::getLayoutFormatString(qualifier.getFormat()), ""); - - if (isEsProfile()) { - // "Except for image variables qualified with the format qualifiers r32f, r32i, and r32ui, image variables must - // specify either memory qualifier readonly or the memory qualifier writeonly." - if (! (qualifier.getFormat() == ElfR32f || qualifier.getFormat() == ElfR32i || qualifier.getFormat() == ElfR32ui)) { - if (! qualifier.isReadOnly() && ! qualifier.isWriteOnly()) - error(loc, "format requires readonly or writeonly memory qualifier", TQualifier::getLayoutFormatString(qualifier.getFormat()), ""); - } - } - } - } else if (type.isImage() && ! qualifier.isWriteOnly() && !intermediate.getBindlessImageMode()) { - const char *explanation = "image variables not declared 'writeonly' and without a format layout qualifier"; - requireProfile(loc, ECoreProfile | ECompatibilityProfile, explanation); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shader_image_load_formatted, explanation); - } - - if (qualifier.isPushConstant()) { - if (type.getBasicType() != EbtBlock) - error(loc, "can only be used with a block", "push_constant", ""); - if (type.isArray()) - error(loc, "Push constants blocks can't be an array", "push_constant", ""); - } - - if (qualifier.hasBufferReference() && type.getBasicType() != EbtBlock) - error(loc, "can only be used with a block", "buffer_reference", ""); - - if (qualifier.isShaderRecord() && type.getBasicType() != EbtBlock) - error(loc, "can only be used with a block", "shaderRecordNV", ""); - - // input attachment - if (type.isSubpass()) { - if (extensionTurnedOn(E_GL_EXT_shader_tile_image)) - error(loc, "can not be used with GL_EXT_shader_tile_image enabled", type.getSampler().getString().c_str(), ""); - if (! qualifier.hasAttachment()) - error(loc, "requires an input_attachment_index layout qualifier", "subpass", ""); - } else { - if (qualifier.hasAttachment()) - error(loc, "can only be used with a subpass", "input_attachment_index", ""); - } - - // specialization-constant id - if (qualifier.hasSpecConstantId()) { - if (type.getQualifier().storage != EvqConst) - error(loc, "can only be applied to 'const'-qualified scalar", "constant_id", ""); - if (! type.isScalar()) - error(loc, "can only be applied to a scalar", "constant_id", ""); - switch (type.getBasicType()) - { - case EbtInt8: - case EbtUint8: - case EbtInt16: - case EbtUint16: - case EbtInt: - case EbtUint: - case EbtInt64: - case EbtUint64: - case EbtBool: - case EbtFloat: - case EbtDouble: - case EbtFloat16: - break; - default: - error(loc, "cannot be applied to this type", "constant_id", ""); - break; - } - } -} - -static bool storageCanHaveLayoutInBlock(const enum TStorageQualifier storage) -{ - switch (storage) { - case EvqUniform: - case EvqBuffer: - case EvqShared: - return true; - default: - return false; - } -} - -// Do layout error checking that can be done within a layout qualifier proper, not needing to know -// if there are blocks, atomic counters, variables, etc. -void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier) -{ - if (qualifier.storage == EvqShared && qualifier.hasLayout()) { - if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4) { - error(loc, "shared block requires at least SPIR-V 1.4", "shared block", ""); - } - profileRequires(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shared_memory_block, "shared block"); - } - - // "It is a compile-time error to use *component* without also specifying the location qualifier (order does not matter)." - if (qualifier.hasComponent() && ! qualifier.hasLocation()) - error(loc, "must specify 'location' to use 'component'", "component", ""); - - if (qualifier.hasAnyLocation()) { - - // "As with input layout qualifiers, all shaders except compute shaders - // allow *location* layout qualifiers on output variable declarations, - // output block declarations, and output block member declarations." - - switch (qualifier.storage) { - case EvqVaryingIn: - { - const char* feature = "location qualifier on input"; - if (isEsProfile() && version < 310) - requireStage(loc, EShLangVertex, feature); - else - requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); - if (language == EShLangVertex) { - const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; - profileRequires(loc, ~EEsProfile, 330, 2, exts, feature); - profileRequires(loc, EEsProfile, 300, nullptr, feature); - } else { - profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - } - break; - } - case EvqVaryingOut: - { - const char* feature = "location qualifier on output"; - if (isEsProfile() && version < 310) - requireStage(loc, EShLangFragment, feature); - else - requireStage(loc, (EShLanguageMask)~EShLangComputeMask, feature); - if (language == EShLangFragment) { - const char* exts[2] = { E_GL_ARB_separate_shader_objects, E_GL_ARB_explicit_attrib_location }; - profileRequires(loc, ~EEsProfile, 330, 2, exts, feature); - profileRequires(loc, EEsProfile, 300, nullptr, feature); - } else { - profileRequires(loc, ~EEsProfile, 410, E_GL_ARB_separate_shader_objects, feature); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - } - break; - } - case EvqUniform: - case EvqBuffer: - { - const char* feature = "location qualifier on uniform or buffer"; - requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile | ENoProfile, feature); - profileRequires(loc, ~EEsProfile, 330, E_GL_ARB_explicit_attrib_location, feature); - profileRequires(loc, ~EEsProfile, 430, E_GL_ARB_explicit_uniform_location, feature); - profileRequires(loc, EEsProfile, 310, nullptr, feature); - break; - } - default: - break; - } - if (qualifier.hasIndex()) { - if (qualifier.storage != EvqVaryingOut) - error(loc, "can only be used on an output", "index", ""); - if (! qualifier.hasLocation()) - error(loc, "can only be used with an explicit location", "index", ""); - } - } - - if (qualifier.hasBinding()) { - if (! qualifier.isUniformOrBuffer() && !qualifier.isTaskMemory()) - error(loc, "requires uniform or buffer storage qualifier", "binding", ""); - } - if (qualifier.hasStream()) { - if (!qualifier.isPipeOutput()) - error(loc, "can only be used on an output", "stream", ""); - } - if (qualifier.hasXfb()) { - if (!qualifier.isPipeOutput()) - error(loc, "can only be used on an output", "xfb layout qualifier", ""); - } - if (qualifier.hasUniformLayout()) { - if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory()) { - if (qualifier.hasMatrix() || qualifier.hasPacking()) - error(loc, "matrix or packing qualifiers can only be used on a uniform or buffer", "layout", ""); - if (qualifier.hasOffset() || qualifier.hasAlign()) - error(loc, "offset/align can only be used on a uniform or buffer", "layout", ""); - } - } - if (qualifier.isPushConstant()) { - if (qualifier.storage != EvqUniform) - error(loc, "can only be used with a uniform", "push_constant", ""); - if (qualifier.hasSet()) - error(loc, "cannot be used with push_constant", "set", ""); - if (qualifier.hasBinding()) - error(loc, "cannot be used with push_constant", "binding", ""); - } - if (qualifier.hasBufferReference()) { - if (qualifier.storage != EvqBuffer) - error(loc, "can only be used with buffer", "buffer_reference", ""); - } - if (qualifier.isShaderRecord()) { - if (qualifier.storage != EvqBuffer) - error(loc, "can only be used with a buffer", "shaderRecordNV", ""); - if (qualifier.hasBinding()) - error(loc, "cannot be used with shaderRecordNV", "binding", ""); - if (qualifier.hasSet()) - error(loc, "cannot be used with shaderRecordNV", "set", ""); - - } - - if (qualifier.storage == EvqTileImageEXT) { - if (qualifier.hasSet()) - error(loc, "cannot be used with tileImageEXT", "set", ""); - if (!qualifier.hasLocation()) - error(loc, "can only be used with an explicit location", "tileImageEXT", ""); - } - - if (qualifier.storage == EvqHitAttr && qualifier.hasLayout()) { - error(loc, "cannot apply layout qualifiers to hitAttributeNV variable", "hitAttributeNV", ""); - } -} - -// For places that can't have shader-level layout qualifiers -void TParseContext::checkNoShaderLayouts(const TSourceLoc& loc, const TShaderQualifiers& shaderQualifiers) -{ - const char* message = "can only apply to a standalone qualifier"; - - if (shaderQualifiers.geometry != ElgNone) - error(loc, message, TQualifier::getGeometryString(shaderQualifiers.geometry), ""); - if (shaderQualifiers.spacing != EvsNone) - error(loc, message, TQualifier::getVertexSpacingString(shaderQualifiers.spacing), ""); - if (shaderQualifiers.order != EvoNone) - error(loc, message, TQualifier::getVertexOrderString(shaderQualifiers.order), ""); - if (shaderQualifiers.pointMode) - error(loc, message, "point_mode", ""); - if (shaderQualifiers.invocations != TQualifier::layoutNotSet) - error(loc, message, "invocations", ""); - for (int i = 0; i < 3; ++i) { - if (shaderQualifiers.localSize[i] > 1) - error(loc, message, "local_size", ""); - if (shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) - error(loc, message, "local_size id", ""); - } - if (shaderQualifiers.vertices != TQualifier::layoutNotSet) { - if (language == EShLangGeometry || language == EShLangMesh) - error(loc, message, "max_vertices", ""); - else if (language == EShLangTessControl) - error(loc, message, "vertices", ""); - else - assert(0); - } - if (shaderQualifiers.earlyFragmentTests) - error(loc, message, "early_fragment_tests", ""); - if (shaderQualifiers.postDepthCoverage) - error(loc, message, "post_depth_coverage", ""); - if (shaderQualifiers.nonCoherentColorAttachmentReadEXT) - error(loc, message, "non_coherent_color_attachment_readEXT", ""); - if (shaderQualifiers.nonCoherentDepthAttachmentReadEXT) - error(loc, message, "non_coherent_depth_attachment_readEXT", ""); - if (shaderQualifiers.nonCoherentStencilAttachmentReadEXT) - error(loc, message, "non_coherent_stencil_attachment_readEXT", ""); - if (shaderQualifiers.primitives != TQualifier::layoutNotSet) { - if (language == EShLangMesh) - error(loc, message, "max_primitives", ""); - else - assert(0); - } - if (shaderQualifiers.hasBlendEquation()) - error(loc, message, "blend equation", ""); - if (shaderQualifiers.numViews != TQualifier::layoutNotSet) - error(loc, message, "num_views", ""); - if (shaderQualifiers.interlockOrdering != EioNone) - error(loc, message, TQualifier::getInterlockOrderingString(shaderQualifiers.interlockOrdering), ""); - if (shaderQualifiers.layoutPrimitiveCulling) - error(loc, "can only be applied as standalone", "primitive_culling", ""); -} - -// Correct and/or advance an object's offset layout qualifier. -void TParseContext::fixOffset(const TSourceLoc& loc, TSymbol& symbol) -{ - const TQualifier& qualifier = symbol.getType().getQualifier(); - if (symbol.getType().isAtomic()) { - if (qualifier.hasBinding() && (int)qualifier.layoutBinding < resources.maxAtomicCounterBindings) { - - // Set the offset - int offset; - if (qualifier.hasOffset()) - offset = qualifier.layoutOffset; - else - offset = atomicUintOffsets[qualifier.layoutBinding]; - - if (offset % 4 != 0) - error(loc, "atomic counters offset should align based on 4:", "offset", "%d", offset); - - symbol.getWritableType().getQualifier().layoutOffset = offset; - - // Check for overlap - int numOffsets = 4; - if (symbol.getType().isArray()) { - if (symbol.getType().isSizedArray() && !symbol.getType().getArraySizes()->isInnerUnsized()) - numOffsets *= symbol.getType().getCumulativeArraySize(); - else { - // "It is a compile-time error to declare an unsized array of atomic_uint." - error(loc, "array must be explicitly sized", "atomic_uint", ""); - } - } - int repeated = intermediate.addUsedOffsets(qualifier.layoutBinding, offset, numOffsets); - if (repeated >= 0) - error(loc, "atomic counters sharing the same offset:", "offset", "%d", repeated); - - // Bump the default offset - atomicUintOffsets[qualifier.layoutBinding] = offset + numOffsets; - } - } -} - -// -// Look up a function name in the symbol table, and make sure it is a function. -// -// Return the function symbol if found, otherwise nullptr. -// -const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn) -{ - if (symbolTable.isFunctionNameVariable(call.getName())) { - error(loc, "can't use function syntax on variable", call.getName().c_str(), ""); - return nullptr; - } - - const TFunction* function = nullptr; - - // debugPrintfEXT has var args and is in the symbol table as "debugPrintfEXT()", - // mangled to "debugPrintfEXT(" - if (call.getName() == "debugPrintfEXT") { - TSymbol* symbol = symbolTable.find("debugPrintfEXT(", &builtIn); - if (symbol) - return symbol->getAsFunction(); - } - - bool explicitTypesEnabled = extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8) || - extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16) || - extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32) || - extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64) || - extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16) || - extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32) || - extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64); - - if (isEsProfile()) - function = (explicitTypesEnabled && version >= 310) - ? findFunctionExplicitTypes(loc, call, builtIn) - : ((extensionTurnedOn(E_GL_EXT_shader_implicit_conversions) && version >= 310) - ? findFunction120(loc, call, builtIn) - : findFunctionExact(loc, call, builtIn)); - else if (version < 120) - function = findFunctionExact(loc, call, builtIn); - else if (version < 400) { - bool needfindFunction400 = extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) || extensionTurnedOn(E_GL_ARB_gpu_shader5); - function = needfindFunction400 ? findFunction400(loc, call, builtIn) : findFunction120(loc, call, builtIn); - } - else if (explicitTypesEnabled) - function = findFunctionExplicitTypes(loc, call, builtIn); - else - function = findFunction400(loc, call, builtIn); - - return function; -} - -// Function finding algorithm for ES and desktop 110. -const TFunction* TParseContext::findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn) -{ - TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); - if (symbol == nullptr) { - error(loc, "no matching overloaded function found", call.getName().c_str(), ""); - - return nullptr; - } - - return symbol->getAsFunction(); -} - -// Function finding algorithm for desktop versions 120 through 330. -const TFunction* TParseContext::findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn) -{ - // first, look for an exact match - TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); - if (symbol) - return symbol->getAsFunction(); - - // exact match not found, look through a list of overloaded functions of the same name - - // "If no exact match is found, then [implicit conversions] will be applied to find a match. Mismatched types - // on input parameters (in or inout or default) must have a conversion from the calling argument type to the - // formal parameter type. Mismatched types on output parameters (out or inout) must have a conversion - // from the formal parameter type to the calling argument type. When argument conversions are used to find - // a match, it is a semantic error if there are multiple ways to apply these conversions to make the call match - // more than one function." - - const TFunction* candidate = nullptr; - TVector candidateList; - symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); - - for (auto it = candidateList.begin(); it != candidateList.end(); ++it) { - const TFunction& function = *(*it); - - // to even be a potential match, number of arguments has to match - if (call.getParamCount() != function.getParamCount()) - continue; - - bool possibleMatch = true; - for (int i = 0; i < function.getParamCount(); ++i) { - // same types is easy - if (*function[i].type == *call[i].type) - continue; - - // We have a mismatch in type, see if it is implicitly convertible - - if (function[i].type->isArray() || call[i].type->isArray() || - ! function[i].type->sameElementShape(*call[i].type)) - possibleMatch = false; - else { - // do direction-specific checks for conversion of basic type - if (function[i].type->getQualifier().isParamInput()) { - if (! intermediate.canImplicitlyPromote(call[i].type->getBasicType(), function[i].type->getBasicType())) - possibleMatch = false; - } - if (function[i].type->getQualifier().isParamOutput()) { - if (! intermediate.canImplicitlyPromote(function[i].type->getBasicType(), call[i].type->getBasicType())) - possibleMatch = false; - } - } - if (! possibleMatch) - break; - } - if (possibleMatch) { - if (candidate) { - // our second match, meaning ambiguity - error(loc, "ambiguous function signature match: multiple signatures match under implicit type conversion", call.getName().c_str(), ""); - } else - candidate = &function; - } - } - - if (candidate == nullptr) - error(loc, "no matching overloaded function found", call.getName().c_str(), ""); - - return candidate; -} - -// Function finding algorithm for desktop version 400 and above. -// -// "When function calls are resolved, an exact type match for all the arguments -// is sought. If an exact match is found, all other functions are ignored, and -// the exact match is used. If no exact match is found, then the implicit -// conversions in section 4.1.10 Implicit Conversions will be applied to find -// a match. Mismatched types on input parameters (in or inout or default) must -// have a conversion from the calling argument type to the formal parameter type. -// Mismatched types on output parameters (out or inout) must have a conversion -// from the formal parameter type to the calling argument type. -// -// "If implicit conversions can be used to find more than one matching function, -// a single best-matching function is sought. To determine a best match, the -// conversions between calling argument and formal parameter types are compared -// for each function argument and pair of matching functions. After these -// comparisons are performed, each pair of matching functions are compared. -// A function declaration A is considered a better match than function -// declaration B if -// -// * for at least one function argument, the conversion for that argument in A -// is better than the corresponding conversion in B; and -// * there is no function argument for which the conversion in B is better than -// the corresponding conversion in A. -// -// "If a single function declaration is considered a better match than every -// other matching function declaration, it will be used. Otherwise, a -// compile-time semantic error for an ambiguous overloaded function call occurs. -// -// "To determine whether the conversion for a single argument in one match is -// better than that for another match, the following rules are applied, in order: -// -// 1. An exact match is better than a match involving any implicit conversion. -// 2. A match involving an implicit conversion from float to double is better -// than a match involving any other implicit conversion. -// 3. A match involving an implicit conversion from either int or uint to float -// is better than a match involving an implicit conversion from either int -// or uint to double. -// -// "If none of the rules above apply to a particular pair of conversions, neither -// conversion is considered better than the other." -// -const TFunction* TParseContext::findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn) -{ - // first, look for an exact match - TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); - if (symbol) - return symbol->getAsFunction(); - - // no exact match, use the generic selector, parameterized by the GLSL rules - - // create list of candidates to send - TVector candidateList; - symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); - - // can 'from' convert to 'to'? - const auto convertible = [this,builtIn](const TType& from, const TType& to, TOperator, int) -> bool { - if (from == to) - return true; - if (from.coopMatParameterOK(to)) - return true; - // Allow a sized array to be passed through an unsized array parameter, for coopMatLoad/Store functions - if (builtIn && from.isArray() && to.isUnsizedArray()) { - TType fromElementType(from, 0); - TType toElementType(to, 0); - if (fromElementType == toElementType) - return true; - } - if (from.isArray() || to.isArray() || ! from.sameElementShape(to)) - return false; - if (from.isCoopMat() && to.isCoopMat()) - return from.sameCoopMatBaseType(to); - return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType()); - }; - - // Is 'to2' a better conversion than 'to1'? - // Ties should not be considered as better. - // Assumes 'convertible' already said true. - const auto better = [](const TType& from, const TType& to1, const TType& to2) -> bool { - // 1. exact match - if (from == to2) - return from != to1; - if (from == to1) - return false; - - // 2. float -> double is better - if (from.getBasicType() == EbtFloat) { - if (to2.getBasicType() == EbtDouble && to1.getBasicType() != EbtDouble) - return true; - } - - // 3. -> float is better than -> double - return to2.getBasicType() == EbtFloat && to1.getBasicType() == EbtDouble; - }; - - // for ambiguity reporting - bool tie = false; - - // send to the generic selector - const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie); - - if (bestMatch == nullptr) - error(loc, "no matching overloaded function found", call.getName().c_str(), ""); - else if (tie) - error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), ""); - - return bestMatch; -} - -// "To determine whether the conversion for a single argument in one match -// is better than that for another match, the conversion is assigned of the -// three ranks ordered from best to worst: -// 1. Exact match: no conversion. -// 2. Promotion: integral or floating-point promotion. -// 3. Conversion: integral conversion, floating-point conversion, -// floating-integral conversion. -// A conversion C1 is better than a conversion C2 if the rank of C1 is -// better than the rank of C2." -const TFunction* TParseContext::findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn) -{ - // first, look for an exact match - TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); - if (symbol) - return symbol->getAsFunction(); - - // no exact match, use the generic selector, parameterized by the GLSL rules - - // create list of candidates to send - TVector candidateList; - symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); - - // can 'from' convert to 'to'? - const auto convertible = [this,builtIn](const TType& from, const TType& to, TOperator, int) -> bool { - if (from == to) - return true; - if (from.coopMatParameterOK(to)) - return true; - // Allow a sized array to be passed through an unsized array parameter, for coopMatLoad/Store functions - if (builtIn && from.isArray() && to.isUnsizedArray()) { - TType fromElementType(from, 0); - TType toElementType(to, 0); - if (fromElementType == toElementType) - return true; - } - if (from.isArray() || to.isArray() || ! from.sameElementShape(to)) - return false; - if (from.isCoopMat() && to.isCoopMat()) - return from.sameCoopMatBaseType(to); - return intermediate.canImplicitlyPromote(from.getBasicType(), to.getBasicType()); - }; - - // Is 'to2' a better conversion than 'to1'? - // Ties should not be considered as better. - // Assumes 'convertible' already said true. - const auto better = [this](const TType& from, const TType& to1, const TType& to2) -> bool { - // 1. exact match - if (from == to2) - return from != to1; - if (from == to1) - return false; - - // 2. Promotion (integral, floating-point) is better - TBasicType from_type = from.getBasicType(); - TBasicType to1_type = to1.getBasicType(); - TBasicType to2_type = to2.getBasicType(); - bool isPromotion1 = (intermediate.isIntegralPromotion(from_type, to1_type) || - intermediate.isFPPromotion(from_type, to1_type)); - bool isPromotion2 = (intermediate.isIntegralPromotion(from_type, to2_type) || - intermediate.isFPPromotion(from_type, to2_type)); - if (isPromotion2) - return !isPromotion1; - if(isPromotion1) - return false; - - // 3. Conversion (integral, floating-point , floating-integral) - bool isConversion1 = (intermediate.isIntegralConversion(from_type, to1_type) || - intermediate.isFPConversion(from_type, to1_type) || - intermediate.isFPIntegralConversion(from_type, to1_type)); - bool isConversion2 = (intermediate.isIntegralConversion(from_type, to2_type) || - intermediate.isFPConversion(from_type, to2_type) || - intermediate.isFPIntegralConversion(from_type, to2_type)); - - return isConversion2 && !isConversion1; - }; - - // for ambiguity reporting - bool tie = false; - - // send to the generic selector - const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie); - - if (bestMatch == nullptr) - error(loc, "no matching overloaded function found", call.getName().c_str(), ""); - else if (tie) - error(loc, "ambiguous best function under implicit type conversion", call.getName().c_str(), ""); - - return bestMatch; -} - -// -// Adjust function calls that aren't declared in Vulkan to a -// calls with equivalent effects -// -TIntermTyped* TParseContext::vkRelaxedRemapFunctionCall(const TSourceLoc& loc, TFunction* function, TIntermNode* arguments) -{ - TIntermTyped* result = nullptr; - - if (function->getBuiltInOp() != EOpNull) { - return nullptr; - } - - if (function->getName() == "atomicCounterIncrement") { - // change atomicCounterIncrement into an atomicAdd of 1 - TString name("atomicAdd"); - TType uintType(EbtUint); - - TFunction realFunc(&name, function->getType()); - - // Use copyParam to avoid shared ownership of the 'type' field - // of the parameter. - for (int i = 0; i < function->getParamCount(); ++i) { - realFunc.addParameter(TParameter().copyParam((*function)[i])); - } - - TParameter tmpP = { nullptr, &uintType }; - realFunc.addParameter(TParameter().copyParam(tmpP)); - arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(1, loc, true)); - - result = handleFunctionCall(loc, &realFunc, arguments); - } else if (function->getName() == "atomicCounterDecrement") { - // change atomicCounterDecrement into an atomicAdd with -1 - // and subtract 1 from result, to return post-decrement value - TString name("atomicAdd"); - TType uintType(EbtUint); - - TFunction realFunc(&name, function->getType()); - - for (int i = 0; i < function->getParamCount(); ++i) { - realFunc.addParameter(TParameter().copyParam((*function)[i])); - } - - TParameter tmpP = { nullptr, &uintType }; - realFunc.addParameter(TParameter().copyParam(tmpP)); - arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(-1, loc, true)); - - result = handleFunctionCall(loc, &realFunc, arguments); - - // post decrement, so that it matches AtomicCounterDecrement semantics - if (result) { - result = handleBinaryMath(loc, "-", EOpSub, result, intermediate.addConstantUnion(1, loc, true)); - } - } else if (function->getName() == "atomicCounter") { - // change atomicCounter into a direct read of the variable - if (arguments->getAsTyped()) { - result = arguments->getAsTyped(); - } - } - - return result; -} - -// When a declaration includes a type, but not a variable name, it can be used -// to establish defaults. -void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType& publicType) -{ - if (publicType.basicType == EbtAtomicUint && publicType.qualifier.hasBinding()) { - if (publicType.qualifier.layoutBinding >= (unsigned int)resources.maxAtomicCounterBindings) { - error(loc, "atomic_uint binding is too large", "binding", ""); - return; - } - if (publicType.qualifier.hasOffset()) - atomicUintOffsets[publicType.qualifier.layoutBinding] = publicType.qualifier.layoutOffset; - return; - } - - if (publicType.arraySizes) { - error(loc, "expect an array name", "", ""); - } - - if (publicType.qualifier.hasLayout() && !publicType.qualifier.hasBufferReference()) - warn(loc, "useless application of layout qualifier", "layout", ""); -} - -void TParseContext::coopMatTypeParametersCheck(const TSourceLoc& loc, const TPublicType& publicType) -{ - if (parsingBuiltins) - return; - if (publicType.isCoopmatKHR()) { - if (publicType.typeParameters == nullptr) { - error(loc, "coopmat missing type parameters", "", ""); - return; - } - switch (publicType.typeParameters->basicType) { - case EbtFloat: - case EbtFloat16: - case EbtInt: - case EbtInt8: - case EbtInt16: - case EbtUint: - case EbtUint8: - case EbtUint16: - break; - default: - error(loc, "coopmat invalid basic type", TType::getBasicString(publicType.typeParameters->basicType), ""); - break; - } - if (publicType.typeParameters->arraySizes->getNumDims() != 4) { - error(loc, "coopmat incorrect number of type parameters", "", ""); - return; - } - int use = publicType.typeParameters->arraySizes->getDimSize(3); - if (use < 0 || use > 2) { - error(loc, "coopmat invalid matrix Use", "", ""); - return; - } - } -} - -bool TParseContext::vkRelaxedRemapUniformVariable(const TSourceLoc& loc, TString& identifier, const TPublicType& publicType, - TArraySizes*, TIntermTyped* initializer, TType& type) -{ - vkRelaxedRemapUniformMembers(loc, publicType, type, identifier); - - if (parsingBuiltins || symbolTable.atBuiltInLevel() || !symbolTable.atGlobalLevel() || - type.getQualifier().storage != EvqUniform || - !(type.containsNonOpaque() || type.getBasicType() == EbtAtomicUint || (type.containsSampler() && type.isStruct()))) { - return false; - } - - if (type.getQualifier().hasLocation()) { - warn(loc, "ignoring layout qualifier for uniform", identifier.c_str(), "location"); - type.getQualifier().layoutLocation = TQualifier::layoutLocationEnd; - } - - if (initializer) { - warn(loc, "Ignoring initializer for uniform", identifier.c_str(), ""); - initializer = nullptr; - } - - if (type.isArray()) { - // do array size checks here - arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer, false); - - if (arrayQualifierError(loc, type.getQualifier()) || arrayError(loc, type)) { - error(loc, "array param error", identifier.c_str(), ""); - } - } - - // do some checking on the type as it was declared - layoutTypeCheck(loc, type); - - int bufferBinding = TQualifier::layoutBindingEnd; - TVariable* updatedBlock = nullptr; - - // Convert atomic_uint into members of a buffer block - if (type.isAtomic()) { - type.setBasicType(EbtUint); - type.getQualifier().storage = EvqBuffer; - - type.getQualifier().volatil = true; - type.getQualifier().coherent = true; - - // xxTODO: use logic from fixOffset() to apply explicit member offset - bufferBinding = type.getQualifier().layoutBinding; - type.getQualifier().layoutBinding = TQualifier::layoutBindingEnd; - type.getQualifier().explicitOffset = false; - growAtomicCounterBlock(bufferBinding, loc, type, identifier, nullptr); - updatedBlock = atomicCounterBuffers[bufferBinding]; - } - - if (!updatedBlock) { - growGlobalUniformBlock(loc, type, identifier, nullptr); - updatedBlock = globalUniformBlock; - } - - // - // don't assign explicit member offsets here - // if any are assigned, need to be updated here and in the merge/link step - // fixBlockUniformOffsets(updatedBlock->getWritableType().getQualifier(), *updatedBlock->getWritableType().getWritableStruct()); - - // checks on update buffer object - layoutObjectCheck(loc, *updatedBlock); - - TSymbol* symbol = symbolTable.find(identifier); - - if (!symbol) { - if (updatedBlock == globalUniformBlock) - error(loc, "error adding uniform to default uniform block", identifier.c_str(), ""); - else - error(loc, "error adding atomic counter to atomic counter block", identifier.c_str(), ""); - return false; - } - - // merge qualifiers - mergeObjectLayoutQualifiers(updatedBlock->getWritableType().getQualifier(), type.getQualifier(), true); - - return true; -} - -template -static void ForEachOpaque(const TType& type, const TString& path, Function callback) -{ - auto recursion = [&callback](const TType& type, const TString& path, bool skipArray, auto& recursion) -> void { - if (!skipArray && type.isArray()) - { - std::vector indices(type.getArraySizes()->getNumDims()); - for (int flatIndex = 0; - flatIndex < type.getArraySizes()->getCumulativeSize(); - ++flatIndex) - { - TString subscriptPath = path; - for (size_t dimIndex = 0; dimIndex < indices.size(); ++dimIndex) - { - int index = indices[dimIndex]; - subscriptPath.append("["); - subscriptPath.append(String(index)); - subscriptPath.append("]"); - } - - recursion(type, subscriptPath, true, recursion); - - for (size_t dimIndex = 0; dimIndex < indices.size(); ++dimIndex) - { - ++indices[dimIndex]; - if (indices[dimIndex] < type.getArraySizes()->getDimSize(dimIndex)) - break; - else - indices[dimIndex] = 0; - } - } - } - - else if (type.isStruct() && type.containsOpaque()) - { - const TTypeList& types = *type.getStruct(); - for (const TTypeLoc& typeLoc : types) - { - TString nextPath = path; - nextPath.append("."); - nextPath.append(typeLoc.type->getFieldName()); - - recursion(*(typeLoc.type), nextPath, false, recursion); - } - } - - else if (type.isOpaque()) - { - callback(type, path); - } - }; - - recursion(type, path, false, recursion); -} - -void TParseContext::vkRelaxedRemapUniformMembers(const TSourceLoc& loc, const TPublicType& publicType, const TType& type, - const TString& identifier) -{ - if (!type.isStruct() || !type.containsOpaque()) - return; - - ForEachOpaque(type, identifier, - [&publicType, &loc, this](const TType& type, const TString& path) { - TArraySizes arraySizes = {}; - if (type.getArraySizes()) arraySizes = *type.getArraySizes(); - TTypeParameters typeParameters = {}; - if (type.getTypeParameters()) typeParameters = *type.getTypeParameters(); - - TPublicType memberType{}; - memberType.basicType = type.getBasicType(); - memberType.sampler = type.getSampler(); - memberType.qualifier = type.getQualifier(); - memberType.vectorSize = type.getVectorSize(); - memberType.matrixCols = type.getMatrixCols(); - memberType.matrixRows = type.getMatrixRows(); - memberType.coopmatNV = type.isCoopMatNV(); - memberType.coopmatKHR = type.isCoopMatKHR(); - memberType.arraySizes = nullptr; - memberType.userDef = nullptr; - memberType.loc = loc; - memberType.typeParameters = (type.getTypeParameters() ? &typeParameters : nullptr); - memberType.spirvType = nullptr; - - memberType.qualifier.storage = publicType.qualifier.storage; - memberType.shaderQualifiers = publicType.shaderQualifiers; - - TString& structMemberName = *NewPoolTString(path.c_str()); // A copy is required due to declareVariable() signature. - declareVariable(loc, structMemberName, memberType, nullptr, nullptr); - }); -} - -void TParseContext::vkRelaxedRemapFunctionParameter(TFunction* function, TParameter& param, std::vector* newParams) -{ - function->addParameter(param); - - if (!param.type->isStruct() || !param.type->containsOpaque()) - return; - - ForEachOpaque(*param.type, (param.name ? *param.name : param.type->getFieldName()), - [function, param, newParams](const TType& type, const TString& path) { - TString* memberName = NewPoolTString(path.c_str()); - - TType* memberType = new TType(); - memberType->shallowCopy(type); - memberType->getQualifier().storage = param.type->getQualifier().storage; - memberType->clearArraySizes(); - - TParameter memberParam = {}; - memberParam.name = memberName; - memberParam.type = memberType; - memberParam.defaultValue = nullptr; - function->addParameter(memberParam); - if (newParams) - newParams->push_back(function->getParamCount()-1); - }); -} - -// -// Generates a valid GLSL dereferencing string for the input TIntermNode -// -struct AccessChainTraverser : public TIntermTraverser { - AccessChainTraverser() : TIntermTraverser(false, false, true) - {} - - TString path = ""; - - bool visitBinary(TVisit, TIntermBinary* binary) override { - if (binary->getOp() == EOpIndexDirectStruct) - { - const TTypeList& members = *binary->getLeft()->getType().getStruct(); - const TTypeLoc& member = - members[binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()]; - TString memberName = member.type->getFieldName(); - - if (path != "") - path.append("."); - - path.append(memberName); - } - - if (binary->getOp() == EOpIndexDirect) - { - const TConstUnionArray& indices = binary->getRight()->getAsConstantUnion()->getConstArray(); - for (int index = 0; index < indices.size(); ++index) - { - path.append("["); - path.append(String(indices[index].getIConst())); - path.append("]"); - } - } - - return true; - } - - void visitSymbol(TIntermSymbol* symbol) override { - if (!IsAnonymous(symbol->getName())) - path.append(symbol->getName()); - } -}; - -TIntermNode* TParseContext::vkRelaxedRemapFunctionArgument(const TSourceLoc& loc, TFunction* function, TIntermTyped* intermTyped) -{ - AccessChainTraverser accessChainTraverser{}; - intermTyped->traverse(&accessChainTraverser); - - TParameter param = { NewPoolTString(accessChainTraverser.path.c_str()), new TType }; - param.type->shallowCopy(intermTyped->getType()); - - std::vector newParams = {}; - vkRelaxedRemapFunctionParameter(function, param, &newParams); - - if (intermTyped->getType().isOpaque()) - { - TIntermNode* remappedArgument = intermTyped; - { - TIntermSymbol* intermSymbol = nullptr; - TSymbol* symbol = symbolTable.find(*param.name); - if (symbol && symbol->getAsVariable()) - intermSymbol = intermediate.addSymbol(*symbol->getAsVariable(), loc); - else - { - TVariable* variable = new TVariable(param.name, *param.type); - intermSymbol = intermediate.addSymbol(*variable, loc); - } - - remappedArgument = intermSymbol; - } - - return remappedArgument; - } - else if (!(intermTyped->isStruct() && intermTyped->getType().containsOpaque())) - return intermTyped; - else - { - TIntermNode* remappedArgument = intermTyped; - { - TSymbol* symbol = symbolTable.find(*param.name); - if (symbol && symbol->getAsVariable()) - remappedArgument = intermediate.addSymbol(*symbol->getAsVariable(), loc); - } - - if (!newParams.empty()) - remappedArgument = intermediate.makeAggregate(remappedArgument, loc); - - for (int paramIndex : newParams) - { - TParameter& newParam = function->operator[](paramIndex); - TIntermSymbol* intermSymbol = nullptr; - TSymbol* symbol = symbolTable.find(*newParam.name); - if (symbol && symbol->getAsVariable()) - intermSymbol = intermediate.addSymbol(*symbol->getAsVariable(), loc); - else - { - TVariable* variable = new TVariable(newParam.name, *newParam.type); - intermSymbol = intermediate.addSymbol(*variable, loc); - } - - remappedArgument = intermediate.growAggregate(remappedArgument, intermSymbol); - } - - return remappedArgument; - } -} - -TIntermTyped* TParseContext::vkRelaxedRemapDotDereference(const TSourceLoc&, TIntermTyped& base, const TType& member, - const TString& identifier) -{ - if (!member.isOpaque()) - return &base; - - AccessChainTraverser traverser{}; - base.traverse(&traverser); - if (!traverser.path.empty()) - traverser.path.append("."); - traverser.path.append(identifier); - - const TSymbol* symbol = symbolTable.find(traverser.path); - if (!symbol) - return &base; - - TIntermTyped* result = intermediate.addSymbol(*symbol->getAsVariable()); - result->setType(symbol->getType()); - return result; -} - -// -// Do everything necessary to handle a variable (non-block) declaration. -// Either redeclaring a variable, or making a new one, updating the symbol -// table, and all error checking. -// -// Returns a subtree node that computes an initializer, if needed. -// Returns nullptr if there is no code to execute for initialization. -// -// 'publicType' is the type part of the declaration (to the left) -// 'arraySizes' is the arrayness tagged on the identifier (to the right) -// -TIntermNode* TParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TPublicType& publicType, - TArraySizes* arraySizes, TIntermTyped* initializer) -{ - // Make a fresh type that combines the characteristics from the individual - // identifier syntax and the declaration-type syntax. - TType type(publicType); - type.transferArraySizes(arraySizes); - type.copyArrayInnerSizes(publicType.arraySizes); - arrayOfArrayVersionCheck(loc, type.getArraySizes()); - - if (initializer) { - if (type.getBasicType() == EbtRayQuery) { - error(loc, "ray queries can only be initialized by using the rayQueryInitializeEXT intrinsic:", "=", identifier.c_str()); - } else if (type.getBasicType() == EbtHitObjectNV) { - error(loc, "hit objects cannot be initialized using initializers", "=", identifier.c_str()); - } - - } - - if (type.isCoopMatKHR()) { - intermediate.setUseVulkanMemoryModel(); - intermediate.setUseStorageBuffer(); - - if (!publicType.typeParameters || !publicType.typeParameters->arraySizes || - publicType.typeParameters->arraySizes->getNumDims() != 3) { - error(loc, "unexpected number type parameters", identifier.c_str(), ""); - } - if (publicType.typeParameters) { - if (!isTypeFloat(publicType.typeParameters->basicType) && !isTypeInt(publicType.typeParameters->basicType)) { - error(loc, "expected 8, 16, 32, or 64 bit signed or unsigned integer or 16, 32, or 64 bit float type", identifier.c_str(), ""); - } - } - } - else if (type.isCoopMatNV()) { - intermediate.setUseVulkanMemoryModel(); - intermediate.setUseStorageBuffer(); - - if (!publicType.typeParameters || publicType.typeParameters->arraySizes->getNumDims() != 4) { - error(loc, "expected four type parameters", identifier.c_str(), ""); - } - if (publicType.typeParameters) { - if (isTypeFloat(publicType.basicType) && - publicType.typeParameters->arraySizes->getDimSize(0) != 16 && - publicType.typeParameters->arraySizes->getDimSize(0) != 32 && - publicType.typeParameters->arraySizes->getDimSize(0) != 64) { - error(loc, "expected 16, 32, or 64 bits for first type parameter", identifier.c_str(), ""); - } - if (isTypeInt(publicType.basicType) && - publicType.typeParameters->arraySizes->getDimSize(0) != 8 && - publicType.typeParameters->arraySizes->getDimSize(0) != 16 && - publicType.typeParameters->arraySizes->getDimSize(0) != 32) { - error(loc, "expected 8, 16, or 32 bits for first type parameter", identifier.c_str(), ""); - } - } - } else { - if (publicType.typeParameters && publicType.typeParameters->arraySizes->getNumDims() != 0) { - error(loc, "unexpected type parameters", identifier.c_str(), ""); - } - } - - if (voidErrorCheck(loc, identifier, type.getBasicType())) - return nullptr; - - if (initializer) - rValueErrorCheck(loc, "initializer", initializer); - else - nonInitConstCheck(loc, identifier, type); - - samplerCheck(loc, type, identifier, initializer); - transparentOpaqueCheck(loc, type, identifier); - atomicUintCheck(loc, type, identifier); - accStructCheck(loc, type, identifier); - checkAndResizeMeshViewDim(loc, type, /*isBlockMember*/ false); - if (type.getQualifier().storage == EvqConst && type.containsReference()) { - error(loc, "variables with reference type can't have qualifier 'const'", "qualifier", ""); - } - - if (type.getQualifier().storage != EvqUniform && type.getQualifier().storage != EvqBuffer) { - if (type.contains16BitFloat()) - requireFloat16Arithmetic(loc, "qualifier", "float16 types can only be in uniform block or buffer storage"); - if (type.contains16BitInt()) - requireInt16Arithmetic(loc, "qualifier", "(u)int16 types can only be in uniform block or buffer storage"); - if (type.contains8BitInt()) - requireInt8Arithmetic(loc, "qualifier", "(u)int8 types can only be in uniform block or buffer storage"); - } - - if (type.getQualifier().storage == EvqtaskPayloadSharedEXT) - intermediate.addTaskPayloadEXTCount(); - if (type.getQualifier().storage == EvqShared && type.containsCoopMat()) - error(loc, "qualifier", "Cooperative matrix types must not be used in shared memory", ""); - - if (profile == EEsProfile) { - if (type.getQualifier().isPipeInput() && type.getBasicType() == EbtStruct) { - if (type.getQualifier().isArrayedIo(language)) { - TType perVertexType(type, 0); - if (perVertexType.containsArray() && perVertexType.containsBuiltIn() == false) { - error(loc, "A per vertex structure containing an array is not allowed as input in ES", type.getTypeName().c_str(), ""); - } - } - else if (type.containsArray() && type.containsBuiltIn() == false) { - error(loc, "A structure containing an array is not allowed as input in ES", type.getTypeName().c_str(), ""); - } - if (type.containsStructure()) - error(loc, "A structure containing an struct is not allowed as input in ES", type.getTypeName().c_str(), ""); - } - } - - if (identifier != "gl_FragCoord" && (publicType.shaderQualifiers.originUpperLeft || publicType.shaderQualifiers.pixelCenterInteger)) - error(loc, "can only apply origin_upper_left and pixel_center_origin to gl_FragCoord", "layout qualifier", ""); - if (identifier != "gl_FragDepth" && publicType.shaderQualifiers.getDepth() != EldNone) - error(loc, "can only apply depth layout to gl_FragDepth", "layout qualifier", ""); - if (identifier != "gl_FragStencilRefARB" && publicType.shaderQualifiers.getStencil() != ElsNone) - error(loc, "can only apply depth layout to gl_FragStencilRefARB", "layout qualifier", ""); - - // Check for redeclaration of built-ins and/or attempting to declare a reserved name - TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), publicType.shaderQualifiers); - if (symbol == nullptr) - reservedErrorCheck(loc, identifier); - - if (symbol == nullptr && spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) { - bool remapped = vkRelaxedRemapUniformVariable(loc, identifier, publicType, arraySizes, initializer, type); - - if (remapped) { - return nullptr; - } - } - - inheritGlobalDefaults(type.getQualifier()); - - // Declare the variable - if (type.isArray()) { - // Check that implicit sizing is only where allowed. - arraySizesCheck(loc, type.getQualifier(), type.getArraySizes(), initializer, false); - - if (! arrayQualifierError(loc, type.getQualifier()) && ! arrayError(loc, type)) - declareArray(loc, identifier, type, symbol); - - if (initializer) { - profileRequires(loc, ENoProfile, 120, E_GL_3DL_array_objects, "initializer"); - profileRequires(loc, EEsProfile, 300, nullptr, "initializer"); - } - } else { - // non-array case - if (symbol == nullptr) - symbol = declareNonArray(loc, identifier, type); - else if (type != symbol->getType()) - error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str()); - } - - if (symbol == nullptr) - return nullptr; - - // Deal with initializer - TIntermNode* initNode = nullptr; - if (symbol != nullptr && initializer) { - TVariable* variable = symbol->getAsVariable(); - if (! variable) { - error(loc, "initializer requires a variable, not a member", identifier.c_str(), ""); - return nullptr; - } - initNode = executeInitializer(loc, initializer, variable); - } - - // look for errors in layout qualifier use - layoutObjectCheck(loc, *symbol); - - // fix up - fixOffset(loc, *symbol); - - return initNode; -} - -// Pick up global defaults from the provide global defaults into dst. -void TParseContext::inheritGlobalDefaults(TQualifier& dst) const -{ - if (dst.storage == EvqVaryingOut) { - if (! dst.hasStream() && language == EShLangGeometry) - dst.layoutStream = globalOutputDefaults.layoutStream; - if (! dst.hasXfbBuffer()) - dst.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; - } -} - -// -// Make an internal-only variable whose name is for debug purposes only -// and won't be searched for. Callers will only use the return value to use -// the variable, not the name to look it up. It is okay if the name -// is the same as other names; there won't be any conflict. -// -TVariable* TParseContext::makeInternalVariable(const char* name, const TType& type) const -{ - TString* nameString = NewPoolTString(name); - TVariable* variable = new TVariable(nameString, type); - symbolTable.makeInternalVariable(*variable); - - return variable; -} - -// -// Declare a non-array variable, the main point being there is no redeclaration -// for resizing allowed. -// -// Return the successfully declared variable. -// -TVariable* TParseContext::declareNonArray(const TSourceLoc& loc, const TString& identifier, const TType& type) -{ - // make a new variable - TVariable* variable = new TVariable(&identifier, type); - - ioArrayCheck(loc, type, identifier); - - // add variable to symbol table - if (symbolTable.insert(*variable)) { - if (symbolTable.atGlobalLevel()) - trackLinkage(*variable); - return variable; - } - - error(loc, "redefinition", variable->getName().c_str(), ""); - return nullptr; -} - -// -// Handle all types of initializers from the grammar. -// -// Returning nullptr just means there is no code to execute to handle the -// initializer, which will, for example, be the case for constant initializers. -// -TIntermNode* TParseContext::executeInitializer(const TSourceLoc& loc, TIntermTyped* initializer, TVariable* variable) -{ - // A null initializer is an aggregate that hasn't had an op assigned yet - // (still EOpNull, no relation to nullInit), and has no children. - bool nullInit = initializer->getAsAggregate() && initializer->getAsAggregate()->getOp() == EOpNull && - initializer->getAsAggregate()->getSequence().size() == 0; - - // - // Identifier must be of type constant, a global, or a temporary, and - // starting at version 120, desktop allows uniforms to have initializers. - // - TStorageQualifier qualifier = variable->getType().getQualifier().storage; - if (! (qualifier == EvqTemporary || qualifier == EvqGlobal || qualifier == EvqConst || - (qualifier == EvqUniform && !isEsProfile() && version >= 120))) { - if (qualifier == EvqShared) { - // GL_EXT_null_initializer allows this for shared, if it's a null initializer - if (nullInit) { - const char* feature = "initialization with shared qualifier"; - profileRequires(loc, EEsProfile, 0, E_GL_EXT_null_initializer, feature); - profileRequires(loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, feature); - } else { - error(loc, "initializer can only be a null initializer ('{}')", "shared", ""); - } - } else { - error(loc, " cannot initialize this type of qualifier ", - variable->getType().getStorageQualifierString(), ""); - return nullptr; - } - } - - if (nullInit) { - // only some types can be null initialized - if (variable->getType().containsUnsizedArray()) { - error(loc, "null initializers can't size unsized arrays", "{}", ""); - return nullptr; - } - if (variable->getType().containsOpaque()) { - error(loc, "null initializers can't be used on opaque values", "{}", ""); - return nullptr; - } - variable->getWritableType().getQualifier().setNullInit(); - return nullptr; - } - - arrayObjectCheck(loc, variable->getType(), "array initializer"); - - // - // If the initializer was from braces { ... }, we convert the whole subtree to a - // constructor-style subtree, allowing the rest of the code to operate - // identically for both kinds of initializers. - // - // Type can't be deduced from the initializer list, so a skeletal type to - // follow has to be passed in. Constness and specialization-constness - // should be deduced bottom up, not dictated by the skeletal type. - // - TType skeletalType; - skeletalType.shallowCopy(variable->getType()); - skeletalType.getQualifier().makeTemporary(); - initializer = convertInitializerList(loc, skeletalType, initializer); - if (! initializer) { - // error recovery; don't leave const without constant values - if (qualifier == EvqConst) - variable->getWritableType().getQualifier().makeTemporary(); - return nullptr; - } - - // Fix outer arrayness if variable is unsized, getting size from the initializer - if (initializer->getType().isSizedArray() && variable->getType().isUnsizedArray()) - variable->getWritableType().changeOuterArraySize(initializer->getType().getOuterArraySize()); - - // Inner arrayness can also get set by an initializer - if (initializer->getType().isArrayOfArrays() && variable->getType().isArrayOfArrays() && - initializer->getType().getArraySizes()->getNumDims() == - variable->getType().getArraySizes()->getNumDims()) { - // adopt unsized sizes from the initializer's sizes - for (int d = 1; d < variable->getType().getArraySizes()->getNumDims(); ++d) { - if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize) { - variable->getWritableType().getArraySizes()->setDimSize(d, - initializer->getType().getArraySizes()->getDimSize(d)); - } - } - } - - // Uniforms require a compile-time constant initializer - if (qualifier == EvqUniform && ! initializer->getType().getQualifier().isFrontEndConstant()) { - error(loc, "uniform initializers must be constant", "=", "'%s'", - variable->getType().getCompleteString(intermediate.getEnhancedMsgs()).c_str()); - variable->getWritableType().getQualifier().makeTemporary(); - return nullptr; - } - // Global consts require a constant initializer (specialization constant is okay) - if (qualifier == EvqConst && symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { - error(loc, "global const initializers must be constant", "=", "'%s'", - variable->getType().getCompleteString(intermediate.getEnhancedMsgs()).c_str()); - variable->getWritableType().getQualifier().makeTemporary(); - return nullptr; - } - - // Const variables require a constant initializer, depending on version - if (qualifier == EvqConst) { - if (! initializer->getType().getQualifier().isConstant()) { - const char* initFeature = "non-constant initializer"; - requireProfile(loc, ~EEsProfile, initFeature); - profileRequires(loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - variable->getWritableType().getQualifier().storage = EvqConstReadOnly; - qualifier = EvqConstReadOnly; - } - } else { - // Non-const global variables in ES need a const initializer. - // - // "In declarations of global variables with no storage qualifier or with a const - // qualifier any initializer must be a constant expression." - if (symbolTable.atGlobalLevel() && ! initializer->getType().getQualifier().isConstant()) { - const char* initFeature = - "non-constant global initializer (needs GL_EXT_shader_non_constant_global_initializers)"; - if (isEsProfile()) { - if (relaxedErrors() && ! extensionTurnedOn(E_GL_EXT_shader_non_constant_global_initializers)) - warn(loc, "not allowed in this version", initFeature, ""); - else - profileRequires(loc, EEsProfile, 0, E_GL_EXT_shader_non_constant_global_initializers, initFeature); - } - } - } - - if (qualifier == EvqConst || qualifier == EvqUniform) { - // Compile-time tagging of the variable with its constant value... - - initializer = intermediate.addConversion(EOpAssign, variable->getType(), initializer); - if (! initializer || ! initializer->getType().getQualifier().isConstant() || - variable->getType() != initializer->getType()) { - error(loc, "non-matching or non-convertible constant type for const initializer", - variable->getType().getStorageQualifierString(), ""); - variable->getWritableType().getQualifier().makeTemporary(); - return nullptr; - } - - // We either have a folded constant in getAsConstantUnion, or we have to use - // the initializer's subtree in the AST to represent the computation of a - // specialization constant. - assert(initializer->getAsConstantUnion() || initializer->getType().getQualifier().isSpecConstant()); - if (initializer->getAsConstantUnion()) - variable->setConstArray(initializer->getAsConstantUnion()->getConstArray()); - else { - // It's a specialization constant. - variable->getWritableType().getQualifier().makeSpecConstant(); - - // Keep the subtree that computes the specialization constant with the variable. - // Later, a symbol node will adopt the subtree from the variable. - variable->setConstSubtree(initializer); - } - } else { - // normal assigning of a value to a variable... - specializationCheck(loc, initializer->getType(), "initializer"); - TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc); - TIntermTyped* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc); - if (! initNode) - assignError(loc, "=", intermSymbol->getCompleteString(intermediate.getEnhancedMsgs()), initializer->getCompleteString(intermediate.getEnhancedMsgs())); - - return initNode; - } - - return nullptr; -} - -// -// Reprocess any initializer-list (the "{ ... }" syntax) parts of the -// initializer. -// -// Need to hierarchically assign correct types and implicit -// conversions. Will do this mimicking the same process used for -// creating a constructor-style initializer, ensuring we get the -// same form. However, it has to in parallel walk the 'type' -// passed in, as type cannot be deduced from an initializer list. -// -TIntermTyped* TParseContext::convertInitializerList(const TSourceLoc& loc, const TType& type, TIntermTyped* initializer) -{ - // Will operate recursively. Once a subtree is found that is constructor style, - // everything below it is already good: Only the "top part" of the initializer - // can be an initializer list, where "top part" can extend for several (or all) levels. - - // see if we have bottomed out in the tree within the initializer-list part - TIntermAggregate* initList = initializer->getAsAggregate(); - if (! initList || initList->getOp() != EOpNull) - return initializer; - - // Of the initializer-list set of nodes, need to process bottom up, - // so recurse deep, then process on the way up. - - // Go down the tree here... - if (type.isArray()) { - // The type's array might be unsized, which could be okay, so base sizes on the size of the aggregate. - // Later on, initializer execution code will deal with array size logic. - TType arrayType; - arrayType.shallowCopy(type); // sharing struct stuff is fine - arrayType.copyArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below - - // edit array sizes to fill in unsized dimensions - arrayType.changeOuterArraySize((int)initList->getSequence().size()); - TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped(); - if (arrayType.isArrayOfArrays() && firstInit->getType().isArray() && - arrayType.getArraySizes()->getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) { - for (int d = 1; d < arrayType.getArraySizes()->getNumDims(); ++d) { - if (arrayType.getArraySizes()->getDimSize(d) == UnsizedArraySize) - arrayType.getArraySizes()->setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1)); - } - } - - TType elementType(arrayType, 0); // dereferenced type - for (size_t i = 0; i < initList->getSequence().size(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, elementType, initList->getSequence()[i]->getAsTyped()); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - - return addConstructor(loc, initList, arrayType); - } else if (type.isStruct()) { - if (type.getStruct()->size() != initList->getSequence().size()) { - error(loc, "wrong number of structure members", "initializer list", ""); - return nullptr; - } - for (size_t i = 0; i < type.getStruct()->size(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, *(*type.getStruct())[i].type, initList->getSequence()[i]->getAsTyped()); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - } else if (type.isMatrix()) { - if (type.getMatrixCols() != (int)initList->getSequence().size()) { - error(loc, "wrong number of matrix columns:", "initializer list", type.getCompleteString(intermediate.getEnhancedMsgs()).c_str()); - return nullptr; - } - TType vectorType(type, 0); // dereferenced type - for (int i = 0; i < type.getMatrixCols(); ++i) { - initList->getSequence()[i] = convertInitializerList(loc, vectorType, initList->getSequence()[i]->getAsTyped()); - if (initList->getSequence()[i] == nullptr) - return nullptr; - } - } else if (type.isVector()) { - if (type.getVectorSize() != (int)initList->getSequence().size()) { - error(loc, "wrong vector size (or rows in a matrix column):", "initializer list", type.getCompleteString(intermediate.getEnhancedMsgs()).c_str()); - return nullptr; - } - TBasicType destType = type.getBasicType(); - for (int i = 0; i < type.getVectorSize(); ++i) { - TBasicType initType = initList->getSequence()[i]->getAsTyped()->getBasicType(); - if (destType != initType && !intermediate.canImplicitlyPromote(initType, destType)) { - error(loc, "type mismatch in initializer list", "initializer list", type.getCompleteString(intermediate.getEnhancedMsgs()).c_str()); - return nullptr; - } - - } - } else { - error(loc, "unexpected initializer-list type:", "initializer list", type.getCompleteString(intermediate.getEnhancedMsgs()).c_str()); - return nullptr; - } - - // Now that the subtree is processed, process this node as if the - // initializer list is a set of arguments to a constructor. - TIntermNode* emulatedConstructorArguments; - if (initList->getSequence().size() == 1) - emulatedConstructorArguments = initList->getSequence()[0]; - else - emulatedConstructorArguments = initList; - return addConstructor(loc, emulatedConstructorArguments, type); -} - -// -// Test for the correctness of the parameters passed to various constructor functions -// and also convert them to the right data type, if allowed and required. -// -// 'node' is what to construct from. -// 'type' is what type to construct. -// -// Returns nullptr for an error or the constructed node (aggregate or typed) for no error. -// -TIntermTyped* TParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type) -{ - if (node == nullptr || node->getAsTyped() == nullptr) - return nullptr; - rValueErrorCheck(loc, "constructor", node->getAsTyped()); - - TIntermAggregate* aggrNode = node->getAsAggregate(); - TOperator op = intermediate.mapTypeToConstructorOp(type); - - // Combined texture-sampler constructors are completely semantic checked - // in constructorTextureSamplerError() - if (op == EOpConstructTextureSampler) { - if (aggrNode != nullptr) { - if (aggrNode->getSequence()[1]->getAsTyped()->getType().getSampler().shadow) { - // Transfer depth into the texture (SPIR-V image) type, as a hint - // for tools to know this texture/image is a depth image. - aggrNode->getSequence()[0]->getAsTyped()->getWritableType().getSampler().shadow = true; - } - return intermediate.setAggregateOperator(aggrNode, op, type, loc); - } - } - - TTypeList::const_iterator memberTypes; - if (op == EOpConstructStruct) - memberTypes = type.getStruct()->begin(); - - TType elementType; - if (type.isArray()) { - TType dereferenced(type, 0); - elementType.shallowCopy(dereferenced); - } else - elementType.shallowCopy(type); - - bool singleArg; - if (aggrNode) { - if (aggrNode->getOp() != EOpNull) - singleArg = true; - else - singleArg = false; - } else - singleArg = true; - - TIntermTyped *newNode; - if (singleArg) { - // If structure constructor or array constructor is being called - // for only one parameter inside the structure, we need to call constructAggregate function once. - if (type.isArray()) - newNode = constructAggregate(node, elementType, 1, node->getLoc()); - else if (op == EOpConstructStruct) - newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc()); - else - newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false); - - if (newNode && (type.isArray() || op == EOpConstructStruct)) - newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc); - - return newNode; - } - - // - // Handle list of arguments. - // - TIntermSequence &sequenceVector = aggrNode->getSequence(); // Stores the information about the parameter to the constructor - // if the structure constructor contains more than one parameter, then construct - // each parameter - - int paramCount = 0; // keeps track of the constructor parameter number being checked - - // for each parameter to the constructor call, check to see if the right type is passed or convert them - // to the right type if possible (and allowed). - // for structure constructors, just check if the right type is passed, no conversion is allowed. - for (TIntermSequence::iterator p = sequenceVector.begin(); - p != sequenceVector.end(); p++, paramCount++) { - if (type.isArray()) - newNode = constructAggregate(*p, elementType, paramCount+1, node->getLoc()); - else if (op == EOpConstructStruct) - newNode = constructAggregate(*p, *(memberTypes[paramCount]).type, paramCount+1, node->getLoc()); - else - newNode = constructBuiltIn(type, op, (*p)->getAsTyped(), node->getLoc(), true); - - if (newNode) - *p = newNode; - else - return nullptr; - } - - TIntermTyped *ret_node = intermediate.setAggregateOperator(aggrNode, op, type, loc); - - TIntermAggregate *agg_node = ret_node->getAsAggregate(); - if (agg_node && (agg_node->isVector() || agg_node->isArray() || agg_node->isMatrix())) - agg_node->updatePrecision(); - - return ret_node; -} - -// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value -// for the parameter to the constructor (passed to this function). Essentially, it converts -// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a -// float, then float is converted to int. -// -// Returns nullptr for an error or the constructed node. -// -TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, TIntermTyped* node, const TSourceLoc& loc, - bool subset) -{ - // If we are changing a matrix in both domain of basic type and to a non matrix, - // do the shape change first (by default, below, basic type is changed before shape). - // This avoids requesting a matrix of a new type that is going to be discarded anyway. - // TODO: This could be generalized to more type combinations, but that would require - // more extensive testing and full algorithm rework. For now, the need to do two changes makes - // the recursive call work, and avoids the most egregious case of creating integer matrices. - if (node->getType().isMatrix() && (type.isScalar() || type.isVector()) && - type.isFloatingDomain() != node->getType().isFloatingDomain()) { - TType transitionType(node->getBasicType(), glslang::EvqTemporary, type.getVectorSize(), 0, 0, node->isVector()); - TOperator transitionOp = intermediate.mapTypeToConstructorOp(transitionType); - node = constructBuiltIn(transitionType, transitionOp, node, loc, false); - } - - TIntermTyped* newNode; - TOperator basicOp; - - // - // First, convert types as needed. - // - switch (op) { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2x2: - case EOpConstructMat2x3: - case EOpConstructMat2x4: - case EOpConstructMat3x2: - case EOpConstructMat3x3: - case EOpConstructMat3x4: - case EOpConstructMat4x2: - case EOpConstructMat4x3: - case EOpConstructMat4x4: - case EOpConstructFloat: - basicOp = EOpConstructFloat; - break; - - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - basicOp = EOpConstructInt; - break; - - case EOpConstructUVec2: - if (node->getType().getBasicType() == EbtReference) { - requireExtensions(loc, 1, &E_GL_EXT_buffer_reference_uvec2, "reference conversion to uvec2"); - TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUvec2, true, node, - type); - return newNode; - } else if (node->getType().getBasicType() == EbtSampler) { - requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "sampler conversion to uvec2"); - // force the basic type of the constructor param to uvec2, otherwise spv builder will - // report some errors - TIntermTyped* newSrcNode = intermediate.createConversion(EbtUint, node); - newSrcNode->getAsTyped()->getWritableType().setVectorSize(2); - - TIntermTyped* newNode = - intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConstructUVec2, false, newSrcNode, type); - return newNode; - } - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructUint: - basicOp = EOpConstructUint; - break; - - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - basicOp = EOpConstructBool; - break; - case EOpConstructTextureSampler: - if ((node->getType().getBasicType() == EbtUint || node->getType().getBasicType() == EbtInt) && - node->getType().getVectorSize() == 2) { - requireExtensions(loc, 1, &E_GL_ARB_bindless_texture, "ivec2/uvec2 convert to texture handle"); - // No matter ivec2 or uvec2, Set EOpPackUint2x32 just to generate an opBitcast op code - TIntermTyped* newNode = - intermediate.addBuiltInFunctionCall(node->getLoc(), EOpPackUint2x32, true, node, type); - return newNode; - } - case EOpConstructDVec2: - case EOpConstructDVec3: - case EOpConstructDVec4: - case EOpConstructDMat2x2: - case EOpConstructDMat2x3: - case EOpConstructDMat2x4: - case EOpConstructDMat3x2: - case EOpConstructDMat3x3: - case EOpConstructDMat3x4: - case EOpConstructDMat4x2: - case EOpConstructDMat4x3: - case EOpConstructDMat4x4: - case EOpConstructDouble: - basicOp = EOpConstructDouble; - break; - - case EOpConstructF16Vec2: - case EOpConstructF16Vec3: - case EOpConstructF16Vec4: - case EOpConstructF16Mat2x2: - case EOpConstructF16Mat2x3: - case EOpConstructF16Mat2x4: - case EOpConstructF16Mat3x2: - case EOpConstructF16Mat3x3: - case EOpConstructF16Mat3x4: - case EOpConstructF16Mat4x2: - case EOpConstructF16Mat4x3: - case EOpConstructF16Mat4x4: - case EOpConstructFloat16: - basicOp = EOpConstructFloat16; - // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types, - // so construct a 32-bit type and convert - if (!intermediate.getArithemeticFloat16Enabled()) { - TType tempType(EbtFloat, EvqTemporary, type.getVectorSize()); - newNode = node; - if (tempType != newNode->getType()) { - TOperator aggregateOp; - if (op == EOpConstructFloat16) - aggregateOp = EOpConstructFloat; - else - aggregateOp = (TOperator)(EOpConstructVec2 + op - EOpConstructF16Vec2); - newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc()); - } - newNode = intermediate.addConversion(EbtFloat16, newNode); - return newNode; - } - break; - - case EOpConstructI8Vec2: - case EOpConstructI8Vec3: - case EOpConstructI8Vec4: - case EOpConstructInt8: - basicOp = EOpConstructInt8; - // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types, - // so construct a 32-bit type and convert - if (!intermediate.getArithemeticInt8Enabled()) { - TType tempType(EbtInt, EvqTemporary, type.getVectorSize()); - newNode = node; - if (tempType != newNode->getType()) { - TOperator aggregateOp; - if (op == EOpConstructInt8) - aggregateOp = EOpConstructInt; - else - aggregateOp = (TOperator)(EOpConstructIVec2 + op - EOpConstructI8Vec2); - newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc()); - } - newNode = intermediate.addConversion(EbtInt8, newNode); - return newNode; - } - break; - - case EOpConstructU8Vec2: - case EOpConstructU8Vec3: - case EOpConstructU8Vec4: - case EOpConstructUint8: - basicOp = EOpConstructUint8; - // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types, - // so construct a 32-bit type and convert - if (!intermediate.getArithemeticInt8Enabled()) { - TType tempType(EbtUint, EvqTemporary, type.getVectorSize()); - newNode = node; - if (tempType != newNode->getType()) { - TOperator aggregateOp; - if (op == EOpConstructUint8) - aggregateOp = EOpConstructUint; - else - aggregateOp = (TOperator)(EOpConstructUVec2 + op - EOpConstructU8Vec2); - newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc()); - } - newNode = intermediate.addConversion(EbtUint8, newNode); - return newNode; - } - break; - - case EOpConstructI16Vec2: - case EOpConstructI16Vec3: - case EOpConstructI16Vec4: - case EOpConstructInt16: - basicOp = EOpConstructInt16; - // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types, - // so construct a 32-bit type and convert - if (!intermediate.getArithemeticInt16Enabled()) { - TType tempType(EbtInt, EvqTemporary, type.getVectorSize()); - newNode = node; - if (tempType != newNode->getType()) { - TOperator aggregateOp; - if (op == EOpConstructInt16) - aggregateOp = EOpConstructInt; - else - aggregateOp = (TOperator)(EOpConstructIVec2 + op - EOpConstructI16Vec2); - newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc()); - } - newNode = intermediate.addConversion(EbtInt16, newNode); - return newNode; - } - break; - - case EOpConstructU16Vec2: - case EOpConstructU16Vec3: - case EOpConstructU16Vec4: - case EOpConstructUint16: - basicOp = EOpConstructUint16; - // 8/16-bit storage extensions don't support constructing composites of 8/16-bit types, - // so construct a 32-bit type and convert - if (!intermediate.getArithemeticInt16Enabled()) { - TType tempType(EbtUint, EvqTemporary, type.getVectorSize()); - newNode = node; - if (tempType != newNode->getType()) { - TOperator aggregateOp; - if (op == EOpConstructUint16) - aggregateOp = EOpConstructUint; - else - aggregateOp = (TOperator)(EOpConstructUVec2 + op - EOpConstructU16Vec2); - newNode = intermediate.setAggregateOperator(newNode, aggregateOp, tempType, node->getLoc()); - } - newNode = intermediate.addConversion(EbtUint16, newNode); - return newNode; - } - break; - - case EOpConstructI64Vec2: - case EOpConstructI64Vec3: - case EOpConstructI64Vec4: - case EOpConstructInt64: - basicOp = EOpConstructInt64; - break; - - case EOpConstructUint64: - if (type.isScalar() && node->getType().isReference()) { - TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvPtrToUint64, true, node, type); - return newNode; - } - // fall through - case EOpConstructU64Vec2: - case EOpConstructU64Vec3: - case EOpConstructU64Vec4: - basicOp = EOpConstructUint64; - break; - - case EOpConstructNonuniform: - // Make a nonuniform copy of node - newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpCopyObject, true, node, type); - return newNode; - - case EOpConstructReference: - // construct reference from reference - if (node->getType().isReference()) { - newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConstructReference, true, node, type); - return newNode; - // construct reference from uint64 - } else if (node->getType().isScalar() && node->getType().getBasicType() == EbtUint64) { - TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUint64ToPtr, true, node, - type); - return newNode; - // construct reference from uvec2 - } else if (node->getType().isVector() && node->getType().getBasicType() == EbtUint && - node->getVectorSize() == 2) { - requireExtensions(loc, 1, &E_GL_EXT_buffer_reference_uvec2, "uvec2 conversion to reference"); - TIntermTyped* newNode = intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUvec2ToPtr, true, node, - type); - return newNode; - } else { - return nullptr; - } - - case EOpConstructCooperativeMatrixNV: - case EOpConstructCooperativeMatrixKHR: - if (node->getType() == type) { - return node; - } - if (!node->getType().isCoopMat()) { - if (type.getBasicType() != node->getType().getBasicType()) { - node = intermediate.addConversion(type.getBasicType(), node); - if (node == nullptr) - return nullptr; - } - node = intermediate.setAggregateOperator(node, op, type, node->getLoc()); - } else { - TOperator op = EOpNull; - switch (type.getBasicType()) { - default: - assert(0); - break; - case EbtInt: - switch (node->getType().getBasicType()) { - case EbtFloat: op = EOpConvFloatToInt; break; - case EbtFloat16: op = EOpConvFloat16ToInt; break; - case EbtUint8: op = EOpConvUint8ToInt; break; - case EbtInt8: op = EOpConvInt8ToInt; break; - case EbtUint16: op = EOpConvUint16ToInt; break; - case EbtInt16: op = EOpConvInt16ToInt; break; - case EbtUint: op = EOpConvUintToInt; break; - default: assert(0); - } - break; - case EbtUint: - switch (node->getType().getBasicType()) { - case EbtFloat: op = EOpConvFloatToUint; break; - case EbtFloat16: op = EOpConvFloat16ToUint; break; - case EbtUint8: op = EOpConvUint8ToUint; break; - case EbtInt8: op = EOpConvInt8ToUint; break; - case EbtUint16: op = EOpConvUint16ToUint; break; - case EbtInt16: op = EOpConvInt16ToUint; break; - case EbtInt: op = EOpConvIntToUint; break; - default: assert(0); - } - break; - case EbtInt16: - switch (node->getType().getBasicType()) { - case EbtFloat: op = EOpConvFloatToInt16; break; - case EbtFloat16: op = EOpConvFloat16ToInt16; break; - case EbtUint8: op = EOpConvUint8ToInt16; break; - case EbtInt8: op = EOpConvInt8ToInt16; break; - case EbtUint16: op = EOpConvUint16ToInt16; break; - case EbtInt: op = EOpConvIntToInt16; break; - case EbtUint: op = EOpConvUintToInt16; break; - default: assert(0); - } - break; - case EbtUint16: - switch (node->getType().getBasicType()) { - case EbtFloat: op = EOpConvFloatToUint16; break; - case EbtFloat16: op = EOpConvFloat16ToUint16; break; - case EbtUint8: op = EOpConvUint8ToUint16; break; - case EbtInt8: op = EOpConvInt8ToUint16; break; - case EbtInt16: op = EOpConvInt16ToUint16; break; - case EbtInt: op = EOpConvIntToUint16; break; - case EbtUint: op = EOpConvUintToUint16; break; - default: assert(0); - } - break; - case EbtInt8: - switch (node->getType().getBasicType()) { - case EbtFloat: op = EOpConvFloatToInt8; break; - case EbtFloat16: op = EOpConvFloat16ToInt8; break; - case EbtUint8: op = EOpConvUint8ToInt8; break; - case EbtInt16: op = EOpConvInt16ToInt8; break; - case EbtUint16: op = EOpConvUint16ToInt8; break; - case EbtInt: op = EOpConvIntToInt8; break; - case EbtUint: op = EOpConvUintToInt8; break; - default: assert(0); - } - break; - case EbtUint8: - switch (node->getType().getBasicType()) { - case EbtFloat: op = EOpConvFloatToUint8; break; - case EbtFloat16: op = EOpConvFloat16ToUint8; break; - case EbtInt8: op = EOpConvInt8ToUint8; break; - case EbtInt16: op = EOpConvInt16ToUint8; break; - case EbtUint16: op = EOpConvUint16ToUint8; break; - case EbtInt: op = EOpConvIntToUint8; break; - case EbtUint: op = EOpConvUintToUint8; break; - default: assert(0); - } - break; - case EbtFloat: - switch (node->getType().getBasicType()) { - case EbtFloat16: op = EOpConvFloat16ToFloat; break; - case EbtInt8: op = EOpConvInt8ToFloat; break; - case EbtUint8: op = EOpConvUint8ToFloat; break; - case EbtInt16: op = EOpConvInt16ToFloat; break; - case EbtUint16: op = EOpConvUint16ToFloat; break; - case EbtInt: op = EOpConvIntToFloat; break; - case EbtUint: op = EOpConvUintToFloat; break; - default: assert(0); - } - break; - case EbtFloat16: - switch (node->getType().getBasicType()) { - case EbtFloat: op = EOpConvFloatToFloat16; break; - case EbtInt8: op = EOpConvInt8ToFloat16; break; - case EbtUint8: op = EOpConvUint8ToFloat16; break; - case EbtInt16: op = EOpConvInt16ToFloat16; break; - case EbtUint16: op = EOpConvUint16ToFloat16; break; - case EbtInt: op = EOpConvIntToFloat16; break; - case EbtUint: op = EOpConvUintToFloat16; break; - default: assert(0); - } - break; - } - - node = intermediate.addUnaryNode(op, node, node->getLoc(), type); - // If it's a (non-specialization) constant, it must be folded. - if (node->getAsUnaryNode()->getOperand()->getAsConstantUnion()) - return node->getAsUnaryNode()->getOperand()->getAsConstantUnion()->fold(op, node->getType()); - } - - return node; - - case EOpConstructAccStruct: - if ((node->getType().isScalar() && node->getType().getBasicType() == EbtUint64)) { - // construct acceleration structure from uint64 - requireExtensions(loc, Num_ray_tracing_EXTs, ray_tracing_EXTs, "uint64_t conversion to acclerationStructureEXT"); - return intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUint64ToAccStruct, true, node, - type); - } else if (node->getType().isVector() && node->getType().getBasicType() == EbtUint && node->getVectorSize() == 2) { - // construct acceleration structure from uint64 - requireExtensions(loc, Num_ray_tracing_EXTs, ray_tracing_EXTs, "uvec2 conversion to accelerationStructureEXT"); - return intermediate.addBuiltInFunctionCall(node->getLoc(), EOpConvUvec2ToAccStruct, true, node, - type); - } else - return nullptr; - - default: - error(loc, "unsupported construction", "", ""); - - return nullptr; - } - newNode = intermediate.addUnaryMath(basicOp, node, node->getLoc()); - if (newNode == nullptr) { - error(loc, "can't convert", "constructor", ""); - return nullptr; - } - - // - // Now, if there still isn't an operation to do the construction, and we need one, add one. - // - - // Otherwise, skip out early. - if (subset || (newNode != node && newNode->getType() == type)) - return newNode; - - // setAggregateOperator will insert a new node for the constructor, as needed. - return intermediate.setAggregateOperator(newNode, op, type, loc); -} - -// This function tests for the type of the parameters to the structure or array constructor. Raises -// an error message if the expected type does not match the parameter passed to the constructor. -// -// Returns nullptr for an error or the input node itself if the expected and the given parameter types match. -// -TIntermTyped* TParseContext::constructAggregate(TIntermNode* node, const TType& type, int paramCount, const TSourceLoc& loc) -{ - TIntermTyped* converted = intermediate.addConversion(EOpConstructStruct, type, node->getAsTyped()); - if (! converted || converted->getType() != type) { - bool enhanced = intermediate.getEnhancedMsgs(); - error(loc, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount, - node->getAsTyped()->getType().getCompleteString(enhanced).c_str(), type.getCompleteString(enhanced).c_str()); - - return nullptr; - } - - return converted; -} - -// If a memory qualifier is present in 'to', also make it present in 'from'. -void TParseContext::inheritMemoryQualifiers(const TQualifier& from, TQualifier& to) -{ - if (from.isReadOnly()) - to.readonly = from.readonly; - if (from.isWriteOnly()) - to.writeonly = from.writeonly; - if (from.coherent) - to.coherent = from.coherent; - if (from.volatil) - to.volatil = from.volatil; - if (from.restrict) - to.restrict = from.restrict; -} - -// -// Update qualifier layoutBindlessImage & layoutBindlessSampler on block member -// -void TParseContext::updateBindlessQualifier(TType& memberType) -{ - if (memberType.containsSampler()) { - if (memberType.isStruct()) { - TTypeList* typeList = memberType.getWritableStruct(); - for (unsigned int member = 0; member < typeList->size(); ++member) { - TType* subMemberType = (*typeList)[member].type; - updateBindlessQualifier(*subMemberType); - } - } - else if (memberType.getSampler().isImage()) { - intermediate.setBindlessImageMode(currentCaller, AstRefTypeLayout); - memberType.getQualifier().layoutBindlessImage = true; - } - else { - intermediate.setBindlessTextureMode(currentCaller, AstRefTypeLayout); - memberType.getQualifier().layoutBindlessSampler = true; - } - } -} - -// -// Do everything needed to add an interface block. -// -void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, const TString* instanceName, - TArraySizes* arraySizes) -{ - if (spvVersion.vulkan > 0 && spvVersion.vulkanRelaxed) - blockStorageRemap(loc, blockName, currentBlockQualifier); - blockStageIoCheck(loc, currentBlockQualifier); - blockQualifierCheck(loc, currentBlockQualifier, instanceName != nullptr); - if (arraySizes != nullptr) { - arraySizesCheck(loc, currentBlockQualifier, arraySizes, nullptr, false); - arrayOfArrayVersionCheck(loc, arraySizes); - if (arraySizes->getNumDims() > 1) - requireProfile(loc, ~EEsProfile, "array-of-array of block"); - } - - // Inherit and check member storage qualifiers WRT to the block-level qualifier. - for (unsigned int member = 0; member < typeList.size(); ++member) { - TType& memberType = *typeList[member].type; - TQualifier& memberQualifier = memberType.getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - if (memberQualifier.storage != EvqTemporary && memberQualifier.storage != EvqGlobal && memberQualifier.storage != currentBlockQualifier.storage) - error(memberLoc, "member storage qualifier cannot contradict block storage qualifier", memberType.getFieldName().c_str(), ""); - memberQualifier.storage = currentBlockQualifier.storage; - globalQualifierFixCheck(memberLoc, memberQualifier); - inheritMemoryQualifiers(currentBlockQualifier, memberQualifier); - if (currentBlockQualifier.perPrimitiveNV) - memberQualifier.perPrimitiveNV = currentBlockQualifier.perPrimitiveNV; - if (currentBlockQualifier.perViewNV) - memberQualifier.perViewNV = currentBlockQualifier.perViewNV; - if (currentBlockQualifier.perTaskNV) - memberQualifier.perTaskNV = currentBlockQualifier.perTaskNV; - if (currentBlockQualifier.storage == EvqtaskPayloadSharedEXT) - memberQualifier.storage = EvqtaskPayloadSharedEXT; - if (memberQualifier.storage == EvqSpirvStorageClass) - error(memberLoc, "member cannot have a spirv_storage_class qualifier", memberType.getFieldName().c_str(), ""); - if (memberQualifier.hasSpirvDecorate() && !memberQualifier.getSpirvDecorate().decorateIds.empty()) - error(memberLoc, "member cannot have a spirv_decorate_id qualifier", memberType.getFieldName().c_str(), ""); - if ((currentBlockQualifier.storage == EvqUniform || currentBlockQualifier.storage == EvqBuffer) && (memberQualifier.isInterpolation() || memberQualifier.isAuxiliary())) - error(memberLoc, "member of uniform or buffer block cannot have an auxiliary or interpolation qualifier", memberType.getFieldName().c_str(), ""); - if (memberType.isArray()) - arraySizesCheck(memberLoc, currentBlockQualifier, memberType.getArraySizes(), nullptr, member == typeList.size() - 1); - if (memberQualifier.hasOffset()) { - if (spvVersion.spv == 0) { - profileRequires(memberLoc, ~EEsProfile, 440, E_GL_ARB_enhanced_layouts, "\"offset\" on block member"); - profileRequires(memberLoc, EEsProfile, 300, E_GL_ARB_enhanced_layouts, "\"offset\" on block member"); - } - } - - // For bindless texture, sampler can be declared as uniform/storage block member, - if (memberType.containsOpaque()) { - if (memberType.containsSampler() && extensionTurnedOn(E_GL_ARB_bindless_texture)) - updateBindlessQualifier(memberType); - else - error(memberLoc, "member of block cannot be or contain a sampler, image, or atomic_uint type", typeList[member].type->getFieldName().c_str(), ""); - } - - if (memberType.containsCoopMat()) - error(memberLoc, "member of block cannot be or contain a cooperative matrix type", typeList[member].type->getFieldName().c_str(), ""); - } - - // This might be a redeclaration of a built-in block. If so, redeclareBuiltinBlock() will - // do all the rest. - if (! symbolTable.atBuiltInLevel() && builtInName(*blockName)) { - redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes); - return; - } - - // Not a redeclaration of a built-in; check that all names are user names. - reservedErrorCheck(loc, *blockName); - if (instanceName) - reservedErrorCheck(loc, *instanceName); - for (unsigned int member = 0; member < typeList.size(); ++member) - reservedErrorCheck(typeList[member].loc, typeList[member].type->getFieldName()); - - // Make default block qualification, and adjust the member qualifications - - TQualifier defaultQualification; - switch (currentBlockQualifier.storage) { - case EvqUniform: defaultQualification = globalUniformDefaults; break; - case EvqBuffer: defaultQualification = globalBufferDefaults; break; - case EvqVaryingIn: defaultQualification = globalInputDefaults; break; - case EvqVaryingOut: defaultQualification = globalOutputDefaults; break; - case EvqShared: defaultQualification = globalSharedDefaults; break; - default: defaultQualification.clear(); break; - } - - // Special case for "push_constant uniform", which has a default of std430, - // contrary to normal uniform defaults, and can't have a default tracked for it. - if ((currentBlockQualifier.isPushConstant() && !currentBlockQualifier.hasPacking()) || - (currentBlockQualifier.isShaderRecord() && !currentBlockQualifier.hasPacking())) - currentBlockQualifier.layoutPacking = ElpStd430; - - // Special case for "taskNV in/out", which has a default of std430, - if (currentBlockQualifier.isTaskMemory() && !currentBlockQualifier.hasPacking()) - currentBlockQualifier.layoutPacking = ElpStd430; - - // fix and check for member layout qualifiers - - mergeObjectLayoutQualifiers(defaultQualification, currentBlockQualifier, true); - - // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts." - if (currentBlockQualifier.hasAlign()) { - if (defaultQualification.layoutPacking != ElpStd140 && - defaultQualification.layoutPacking != ElpStd430 && - defaultQualification.layoutPacking != ElpScalar) { - error(loc, "can only be used with std140, std430, or scalar layout packing", "align", ""); - defaultQualification.layoutAlign = -1; - } - } - - bool memberWithLocation = false; - bool memberWithoutLocation = false; - bool memberWithPerViewQualifier = false; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - if (memberQualifier.hasStream()) { - if (defaultQualification.layoutStream != memberQualifier.layoutStream) - error(memberLoc, "member cannot contradict block", "stream", ""); - } - - // "This includes a block's inheritance of the - // current global default buffer, a block member's inheritance of the block's - // buffer, and the requirement that any *xfb_buffer* declared on a block - // member must match the buffer inherited from the block." - if (memberQualifier.hasXfbBuffer()) { - if (defaultQualification.layoutXfbBuffer != memberQualifier.layoutXfbBuffer) - error(memberLoc, "member cannot contradict block (or what block inherited from global)", "xfb_buffer", ""); - } - - if (memberQualifier.hasPacking()) - error(memberLoc, "member of block cannot have a packing layout qualifier", typeList[member].type->getFieldName().c_str(), ""); - if (memberQualifier.hasLocation()) { - const char* feature = "location on block member"; - switch (currentBlockQualifier.storage) { - case EvqVaryingIn: - case EvqVaryingOut: - requireProfile(memberLoc, ECoreProfile | ECompatibilityProfile | EEsProfile, feature); - profileRequires(memberLoc, ECoreProfile | ECompatibilityProfile, 440, E_GL_ARB_enhanced_layouts, feature); - profileRequires(memberLoc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, feature); - memberWithLocation = true; - break; - default: - error(memberLoc, "can only use in an in/out block", feature, ""); - break; - } - } else - memberWithoutLocation = true; - - // "The offset qualifier can only be used on block members of blocks declared with std140 or std430 layouts." - // "The align qualifier can only be used on blocks or block members, and only for blocks declared with std140 or std430 layouts." - if (memberQualifier.hasAlign() || memberQualifier.hasOffset()) { - if (defaultQualification.layoutPacking != ElpStd140 && - defaultQualification.layoutPacking != ElpStd430 && - defaultQualification.layoutPacking != ElpScalar) - error(memberLoc, "can only be used with std140, std430, or scalar layout packing", "offset/align", ""); - } - - if (memberQualifier.isPerView()) { - memberWithPerViewQualifier = true; - } - - TQualifier newMemberQualification = defaultQualification; - mergeQualifiers(memberLoc, newMemberQualification, memberQualifier, false); - memberQualifier = newMemberQualification; - } - - layoutMemberLocationArrayCheck(loc, memberWithLocation, arraySizes); - - // Ensure that the block has an XfbBuffer assigned. This is needed - // because if the block has a XfbOffset assigned, then it is - // assumed that it has implicitly assigned the current global - // XfbBuffer, and because it's members need to be assigned a - // XfbOffset if they lack it. - if (currentBlockQualifier.storage == EvqVaryingOut && globalOutputDefaults.hasXfbBuffer()) { - if (!currentBlockQualifier.hasXfbBuffer() && currentBlockQualifier.hasXfbOffset()) - currentBlockQualifier.layoutXfbBuffer = globalOutputDefaults.layoutXfbBuffer; - } - - // Process the members - fixBlockLocations(loc, currentBlockQualifier, typeList, memberWithLocation, memberWithoutLocation); - fixXfbOffsets(currentBlockQualifier, typeList); - fixBlockUniformOffsets(currentBlockQualifier, typeList); - fixBlockUniformLayoutMatrix(currentBlockQualifier, &typeList, nullptr); - fixBlockUniformLayoutPacking(currentBlockQualifier, &typeList, nullptr); - for (unsigned int member = 0; member < typeList.size(); ++member) - layoutTypeCheck(typeList[member].loc, *typeList[member].type); - - if (memberWithPerViewQualifier) { - for (unsigned int member = 0; member < typeList.size(); ++member) { - checkAndResizeMeshViewDim(typeList[member].loc, *typeList[member].type, /*isBlockMember*/ true); - } - } - - // reverse merge, so that currentBlockQualifier now has all layout information - // (can't use defaultQualification directly, it's missing other non-layout-default-class qualifiers) - mergeObjectLayoutQualifiers(currentBlockQualifier, defaultQualification, true); - - // - // Build and add the interface block as a new type named 'blockName' - // - - TType blockType(&typeList, *blockName, currentBlockQualifier); - if (arraySizes != nullptr) - blockType.transferArraySizes(arraySizes); - - if (arraySizes == nullptr) - ioArrayCheck(loc, blockType, instanceName ? *instanceName : *blockName); - if (currentBlockQualifier.hasBufferReference()) { - - if (currentBlockQualifier.storage != EvqBuffer) - error(loc, "can only be used with buffer", "buffer_reference", ""); - - // Create the block reference type. If it was forward-declared, detect that - // as a referent struct type with no members. Replace the referent type with - // blockType. - TType blockNameType(EbtReference, blockType, *blockName); - TVariable* blockNameVar = new TVariable(blockName, blockNameType, true); - if (! symbolTable.insert(*blockNameVar)) { - TSymbol* existingName = symbolTable.find(*blockName); - if (existingName->getType().isReference() && - existingName->getType().getReferentType()->getStruct() && - existingName->getType().getReferentType()->getStruct()->size() == 0 && - existingName->getType().getQualifier().storage == blockType.getQualifier().storage) { - existingName->getType().getReferentType()->deepCopy(blockType); - } else { - error(loc, "block name cannot be redefined", blockName->c_str(), ""); - } - } - if (!instanceName) { - return; - } - } else { - // - // Don't make a user-defined type out of block name; that will cause an error - // if the same block name gets reused in a different interface. - // - // "Block names have no other use within a shader - // beyond interface matching; it is a compile-time error to use a block name at global scope for anything - // other than as a block name (e.g., use of a block name for a global variable name or function name is - // currently reserved)." - // - // Use the symbol table to prevent normal reuse of the block's name, as a variable entry, - // whose type is EbtBlock, but without all the structure; that will come from the type - // the instances point to. - // - TType blockNameType(EbtBlock, blockType.getQualifier().storage); - TVariable* blockNameVar = new TVariable(blockName, blockNameType); - if (! symbolTable.insert(*blockNameVar)) { - TSymbol* existingName = symbolTable.find(*blockName); - if (existingName->getType().getBasicType() == EbtBlock) { - if (existingName->getType().getQualifier().storage == blockType.getQualifier().storage) { - error(loc, "Cannot reuse block name within the same interface:", blockName->c_str(), blockType.getStorageQualifierString()); - return; - } - } else { - error(loc, "block name cannot redefine a non-block name", blockName->c_str(), ""); - return; - } - } - } - - // Add the variable, as anonymous or named instanceName. - // Make an anonymous variable if no name was provided. - if (! instanceName) - instanceName = NewPoolTString(""); - - TVariable& variable = *new TVariable(instanceName, blockType); - if (! symbolTable.insert(variable)) { - if (*instanceName == "") - error(loc, "nameless block contains a member that already has a name at global scope", blockName->c_str(), ""); - else - error(loc, "block instance name redefinition", variable.getName().c_str(), ""); - - return; - } - - // Check for general layout qualifier errors - layoutObjectCheck(loc, variable); - - // fix up - if (isIoResizeArray(blockType)) { - ioArraySymbolResizeList.push_back(&variable); - checkIoArraysConsistency(loc, true); - } else - fixIoArraySize(loc, variable.getWritableType()); - - // Save it in the AST for linker use. - trackLinkage(variable); -} - -// -// allow storage type of block to be remapped at compile time -// -void TParseContext::blockStorageRemap(const TSourceLoc&, const TString* instanceName, TQualifier& qualifier) -{ - TBlockStorageClass type = intermediate.getBlockStorageOverride(instanceName->c_str()); - if (type != EbsNone) { - qualifier.setBlockStorage(type); - } -} - -// Do all block-declaration checking regarding the combination of in/out/uniform/buffer -// with a particular stage. -void TParseContext::blockStageIoCheck(const TSourceLoc& loc, const TQualifier& qualifier) -{ - const char *extsrt[2] = { E_GL_NV_ray_tracing, E_GL_EXT_ray_tracing }; - switch (qualifier.storage) { - case EvqUniform: - profileRequires(loc, EEsProfile, 300, nullptr, "uniform block"); - profileRequires(loc, ENoProfile, 140, E_GL_ARB_uniform_buffer_object, "uniform block"); - if (currentBlockQualifier.layoutPacking == ElpStd430 && ! currentBlockQualifier.isPushConstant()) - requireExtensions(loc, 1, &E_GL_EXT_scalar_block_layout, "std430 requires the buffer storage qualifier"); - break; - case EvqBuffer: - requireProfile(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, "buffer block"); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_shader_storage_buffer_object, "buffer block"); - profileRequires(loc, EEsProfile, 310, nullptr, "buffer block"); - break; - case EvqVaryingIn: - profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "input block"); - // It is a compile-time error to have an input block in a vertex shader or an output block in a fragment shader - // "Compute shaders do not permit user-defined input variables..." - requireStage(loc, (EShLanguageMask)(EShLangTessControlMask|EShLangTessEvaluationMask|EShLangGeometryMask| - EShLangFragmentMask|EShLangMeshMask), "input block"); - if (language == EShLangFragment) { - profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "fragment input block"); - } else if (language == EShLangMesh && ! qualifier.isTaskMemory()) { - error(loc, "input blocks cannot be used in a mesh shader", "out", ""); - } - break; - case EvqVaryingOut: - profileRequires(loc, ~EEsProfile, 150, E_GL_ARB_separate_shader_objects, "output block"); - requireStage(loc, (EShLanguageMask)(EShLangVertexMask|EShLangTessControlMask|EShLangTessEvaluationMask| - EShLangGeometryMask|EShLangMeshMask|EShLangTaskMask), "output block"); - // ES 310 can have a block before shader_io is turned on, so skip this test for built-ins - if (language == EShLangVertex && ! parsingBuiltins) { - profileRequires(loc, EEsProfile, 320, Num_AEP_shader_io_blocks, AEP_shader_io_blocks, "vertex output block"); - } else if (language == EShLangMesh && qualifier.isTaskMemory()) { - error(loc, "can only use on input blocks in mesh shader", "taskNV", ""); - } else if (language == EShLangTask && ! qualifier.isTaskMemory()) { - error(loc, "output blocks cannot be used in a task shader", "out", ""); - } - break; - case EvqShared: - if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4) { - error(loc, "shared block requires at least SPIR-V 1.4", "shared block", ""); - } - profileRequires(loc, EEsProfile | ECoreProfile | ECompatibilityProfile, 0, E_GL_EXT_shared_memory_block, "shared block"); - break; - case EvqPayload: - profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadNV block"); - requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask), - "rayPayloadNV block"); - break; - case EvqPayloadIn: - profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "rayPayloadInNV block"); - requireStage(loc, (EShLanguageMask)(EShLangAnyHitMask | EShLangClosestHitMask | EShLangMissMask), - "rayPayloadInNV block"); - break; - case EvqHitAttr: - profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "hitAttributeNV block"); - requireStage(loc, (EShLanguageMask)(EShLangIntersectMask | EShLangAnyHitMask | EShLangClosestHitMask), "hitAttributeNV block"); - break; - case EvqCallableData: - profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataNV block"); - requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), - "callableDataNV block"); - break; - case EvqCallableDataIn: - profileRequires(loc, ~EEsProfile, 460, 2, extsrt, "callableDataInNV block"); - requireStage(loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV block"); - break; - case EvqHitObjectAttrNV: - profileRequires(loc, ~EEsProfile, 460, E_GL_NV_shader_invocation_reorder, "hitObjectAttributeNV block"); - requireStage(loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | EShLangMissMask), "hitObjectAttributeNV block"); - break; - default: - error(loc, "only uniform, buffer, in, or out blocks are supported", blockName->c_str(), ""); - break; - } -} - -// Do all block-declaration checking regarding its qualifiers. -void TParseContext::blockQualifierCheck(const TSourceLoc& loc, const TQualifier& qualifier, bool /*instanceName*/) -{ - // The 4.5 specification says: - // - // interface-block : - // layout-qualifieropt interface-qualifier block-name { member-list } instance-nameopt ; - // - // interface-qualifier : - // in - // out - // patch in - // patch out - // uniform - // buffer - // - // Note however memory qualifiers aren't included, yet the specification also says - // - // "...memory qualifiers may also be used in the declaration of shader storage blocks..." - - if (qualifier.isInterpolation()) - error(loc, "cannot use interpolation qualifiers on an interface block", "flat/smooth/noperspective", ""); - if (qualifier.centroid) - error(loc, "cannot use centroid qualifier on an interface block", "centroid", ""); - if (qualifier.isSample()) - error(loc, "cannot use sample qualifier on an interface block", "sample", ""); - if (qualifier.invariant) - error(loc, "cannot use invariant qualifier on an interface block", "invariant", ""); - if (qualifier.isPushConstant()) - intermediate.addPushConstantCount(); - if (qualifier.isShaderRecord()) - intermediate.addShaderRecordCount(); - if (qualifier.isTaskMemory()) - intermediate.addTaskNVCount(); -} - -// -// "For a block, this process applies to the entire block, or until the first member -// is reached that has a location layout qualifier. When a block member is declared with a location -// qualifier, its location comes from that qualifier: The member's location qualifier overrides the block-level -// declaration. Subsequent members are again assigned consecutive locations, based on the newest location, -// until the next member declared with a location qualifier. The values used for locations do not have to be -// declared in increasing order." -void TParseContext::fixBlockLocations(const TSourceLoc& loc, TQualifier& qualifier, TTypeList& typeList, bool memberWithLocation, bool memberWithoutLocation) -{ - // "If a block has no block-level location layout qualifier, it is required that either all or none of its members - // have a location layout qualifier, or a compile-time error results." - if (! qualifier.hasLocation() && memberWithLocation && memberWithoutLocation) - error(loc, "either the block needs a location, or all members need a location, or no members have a location", "location", ""); - else { - if (memberWithLocation) { - // remove any block-level location and make it per *every* member - int nextLocation = 0; // by the rule above, initial value is not relevant - if (qualifier.hasAnyLocation()) { - nextLocation = qualifier.layoutLocation; - qualifier.layoutLocation = TQualifier::layoutLocationEnd; - if (qualifier.hasComponent()) { - // "It is a compile-time error to apply the *component* qualifier to a ... block" - error(loc, "cannot apply to a block", "component", ""); - } - if (qualifier.hasIndex()) { - error(loc, "cannot apply to a block", "index", ""); - } - } - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - if (! memberQualifier.hasLocation()) { - if (nextLocation >= (int)TQualifier::layoutLocationEnd) - error(memberLoc, "location is too large", "location", ""); - memberQualifier.layoutLocation = nextLocation; - memberQualifier.layoutComponent = TQualifier::layoutComponentEnd; - } - nextLocation = memberQualifier.layoutLocation + intermediate.computeTypeLocationSize( - *typeList[member].type, language); - } - } - } -} - -void TParseContext::fixXfbOffsets(TQualifier& qualifier, TTypeList& typeList) -{ - // "If a block is qualified with xfb_offset, all its - // members are assigned transform feedback buffer offsets. If a block is not qualified with xfb_offset, any - // members of that block not qualified with an xfb_offset will not be assigned transform feedback buffer - // offsets." - - if (! qualifier.hasXfbBuffer() || ! qualifier.hasXfbOffset()) - return; - - int nextOffset = qualifier.layoutXfbOffset; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - bool contains64BitType = false; - bool contains32BitType = false; - bool contains16BitType = false; - int memberSize = intermediate.computeTypeXfbSize(*typeList[member].type, contains64BitType, contains32BitType, contains16BitType); - // see if we need to auto-assign an offset to this member - if (! memberQualifier.hasXfbOffset()) { - // "if applied to an aggregate containing a double or 64-bit integer, the offset must also be a multiple of 8" - if (contains64BitType) - RoundToPow2(nextOffset, 8); - else if (contains32BitType) - RoundToPow2(nextOffset, 4); - else if (contains16BitType) - RoundToPow2(nextOffset, 2); - memberQualifier.layoutXfbOffset = nextOffset; - } else - nextOffset = memberQualifier.layoutXfbOffset; - nextOffset += memberSize; - } - - // The above gave all block members an offset, so we can take it off the block now, - // which will avoid double counting the offset usage. - qualifier.layoutXfbOffset = TQualifier::layoutXfbOffsetEnd; -} - -// Calculate and save the offset of each block member, using the recursively -// defined block offset rules and the user-provided offset and align. -// -// Also, compute and save the total size of the block. For the block's size, arrayness -// is not taken into account, as each element is backed by a separate buffer. -// -void TParseContext::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typeList) -{ - if (!storageCanHaveLayoutInBlock(qualifier.storage) && !qualifier.isTaskMemory()) - return; - if (qualifier.layoutPacking != ElpStd140 && qualifier.layoutPacking != ElpStd430 && qualifier.layoutPacking != ElpScalar) - return; - - int offset = 0; - int memberSize; - for (unsigned int member = 0; member < typeList.size(); ++member) { - TQualifier& memberQualifier = typeList[member].type->getQualifier(); - const TSourceLoc& memberLoc = typeList[member].loc; - - // "When align is applied to an array, it effects only the start of the array, not the array's internal stride." - - // modify just the children's view of matrix layout, if there is one for this member - TLayoutMatrix subMatrixLayout = typeList[member].type->getQualifier().layoutMatrix; - int dummyStride; - int memberAlignment = intermediate.getMemberAlignment(*typeList[member].type, memberSize, dummyStride, qualifier.layoutPacking, - subMatrixLayout != ElmNone ? subMatrixLayout == ElmRowMajor : qualifier.layoutMatrix == ElmRowMajor); - if (memberQualifier.hasOffset()) { - // "The specified offset must be a multiple - // of the base alignment of the type of the block member it qualifies, or a compile-time error results." - if (! IsMultipleOfPow2(memberQualifier.layoutOffset, memberAlignment)) - error(memberLoc, "must be a multiple of the member's alignment", "offset", - "(layout offset = %d | member alignment = %d)", memberQualifier.layoutOffset, memberAlignment); - - // GLSL: "It is a compile-time error to specify an offset that is smaller than the offset of the previous - // member in the block or that lies within the previous member of the block" - if (spvVersion.spv == 0) { - if (memberQualifier.layoutOffset < offset) - error(memberLoc, "cannot lie in previous members", "offset", ""); - - // "The offset qualifier forces the qualified member to start at or after the specified - // integral-constant expression, which will be its byte offset from the beginning of the buffer. - // "The actual offset of a member is computed as - // follows: If offset was declared, start with that offset, otherwise start with the next available offset." - offset = std::max(offset, memberQualifier.layoutOffset); - } else { - // TODO: Vulkan: "It is a compile-time error to have any offset, explicit or assigned, - // that lies within another member of the block." - - offset = memberQualifier.layoutOffset; - } - } - - // "The actual alignment of a member will be the greater of the specified align alignment and the standard - // (e.g., std140) base alignment for the member's type." - if (memberQualifier.hasAlign()) - memberAlignment = std::max(memberAlignment, memberQualifier.layoutAlign); - - // "If the resulting offset is not a multiple of the actual alignment, - // increase it to the first offset that is a multiple of - // the actual alignment." - RoundToPow2(offset, memberAlignment); - typeList[member].type->getQualifier().layoutOffset = offset; - offset += memberSize; - } -} - -// -// Spread LayoutMatrix to uniform block member, if a uniform block member is a struct, -// we need spread LayoutMatrix to this struct member too. and keep this rule for recursive. -// -void TParseContext::fixBlockUniformLayoutMatrix(TQualifier& qualifier, TTypeList* originTypeList, - TTypeList* tmpTypeList) -{ - assert(tmpTypeList == nullptr || originTypeList->size() == tmpTypeList->size()); - for (unsigned int member = 0; member < originTypeList->size(); ++member) { - if (qualifier.layoutPacking != ElpNone) { - if (tmpTypeList == nullptr) { - if (((*originTypeList)[member].type->isMatrix() || - (*originTypeList)[member].type->getBasicType() == EbtStruct) && - (*originTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) { - (*originTypeList)[member].type->getQualifier().layoutMatrix = qualifier.layoutMatrix; - } - } else { - if (((*tmpTypeList)[member].type->isMatrix() || - (*tmpTypeList)[member].type->getBasicType() == EbtStruct) && - (*tmpTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) { - (*tmpTypeList)[member].type->getQualifier().layoutMatrix = qualifier.layoutMatrix; - } - } - } - - if ((*originTypeList)[member].type->getBasicType() == EbtStruct) { - TQualifier* memberQualifier = nullptr; - // block member can be declare a matrix style, so it should be update to the member's style - if ((*originTypeList)[member].type->getQualifier().layoutMatrix == ElmNone) { - memberQualifier = &qualifier; - } else { - memberQualifier = &((*originTypeList)[member].type->getQualifier()); - } - - const TType* tmpType = tmpTypeList == nullptr ? - (*originTypeList)[member].type->clone() : (*tmpTypeList)[member].type; - - fixBlockUniformLayoutMatrix(*memberQualifier, (*originTypeList)[member].type->getWritableStruct(), - tmpType->getWritableStruct()); - - const TTypeList* structure = recordStructCopy(matrixFixRecord, (*originTypeList)[member].type, tmpType); - - if (tmpTypeList == nullptr) { - (*originTypeList)[member].type->setStruct(const_cast(structure)); - } - if (tmpTypeList != nullptr) { - (*tmpTypeList)[member].type->setStruct(const_cast(structure)); - } - } - } -} - -// -// Spread LayoutPacking to matrix or aggregate block members. If a block member is a struct or -// array of struct, spread LayoutPacking recursively to its matrix or aggregate members. -// -void TParseContext::fixBlockUniformLayoutPacking(TQualifier& qualifier, TTypeList* originTypeList, - TTypeList* tmpTypeList) -{ - assert(tmpTypeList == nullptr || originTypeList->size() == tmpTypeList->size()); - for (unsigned int member = 0; member < originTypeList->size(); ++member) { - if (qualifier.layoutPacking != ElpNone) { - if (tmpTypeList == nullptr) { - if ((*originTypeList)[member].type->getQualifier().layoutPacking == ElpNone && - !(*originTypeList)[member].type->isScalarOrVector()) { - (*originTypeList)[member].type->getQualifier().layoutPacking = qualifier.layoutPacking; - } - } else { - if ((*tmpTypeList)[member].type->getQualifier().layoutPacking == ElpNone && - !(*tmpTypeList)[member].type->isScalarOrVector()) { - (*tmpTypeList)[member].type->getQualifier().layoutPacking = qualifier.layoutPacking; - } - } - } - - if ((*originTypeList)[member].type->getBasicType() == EbtStruct) { - // Deep copy the type in pool. - // Because, struct use in different block may have different layout qualifier. - // We have to new a object to distinguish between them. - const TType* tmpType = tmpTypeList == nullptr ? - (*originTypeList)[member].type->clone() : (*tmpTypeList)[member].type; - - fixBlockUniformLayoutPacking(qualifier, (*originTypeList)[member].type->getWritableStruct(), - tmpType->getWritableStruct()); - - const TTypeList* structure = recordStructCopy(packingFixRecord, (*originTypeList)[member].type, tmpType); - - if (tmpTypeList == nullptr) { - (*originTypeList)[member].type->setStruct(const_cast(structure)); - } - if (tmpTypeList != nullptr) { - (*tmpTypeList)[member].type->setStruct(const_cast(structure)); - } - } - } -} - -// For an identifier that is already declared, add more qualification to it. -void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier) -{ - TSymbol* symbol = symbolTable.find(identifier); - - // A forward declaration of a block reference looks to the grammar like adding - // a qualifier to an existing symbol. Detect this and create the block reference - // type with an empty type list, which will be filled in later in - // TParseContext::declareBlock. - if (!symbol && qualifier.hasBufferReference()) { - TTypeList typeList; - TType blockType(&typeList, identifier, qualifier); - TType blockNameType(EbtReference, blockType, identifier); - TVariable* blockNameVar = new TVariable(&identifier, blockNameType, true); - if (! symbolTable.insert(*blockNameVar)) { - error(loc, "block name cannot redefine a non-block name", blockName->c_str(), ""); - } - return; - } - - if (! symbol) { - error(loc, "identifier not previously declared", identifier.c_str(), ""); - return; - } - if (symbol->getAsFunction()) { - error(loc, "cannot re-qualify a function name", identifier.c_str(), ""); - return; - } - - if (qualifier.isAuxiliary() || - qualifier.isMemory() || - qualifier.isInterpolation() || - qualifier.hasLayout() || - qualifier.storage != EvqTemporary || - qualifier.precision != EpqNone) { - error(loc, "cannot add storage, auxiliary, memory, interpolation, layout, or precision qualifier to an existing variable", identifier.c_str(), ""); - return; - } - - // For read-only built-ins, add a new symbol for holding the modified qualifier. - // This will bring up an entire block, if a block type has to be modified (e.g., gl_Position inside a block) - if (symbol->isReadOnly()) - symbol = symbolTable.copyUp(symbol); - - if (qualifier.invariant) { - if (intermediate.inIoAccessed(identifier)) - error(loc, "cannot change qualification after use", "invariant", ""); - symbol->getWritableType().getQualifier().invariant = true; - invariantCheck(loc, symbol->getType().getQualifier()); - } else if (qualifier.isNoContraction()) { - if (intermediate.inIoAccessed(identifier)) - error(loc, "cannot change qualification after use", "precise", ""); - symbol->getWritableType().getQualifier().setNoContraction(); - } else if (qualifier.specConstant) { - symbol->getWritableType().getQualifier().makeSpecConstant(); - if (qualifier.hasSpecConstantId()) - symbol->getWritableType().getQualifier().layoutSpecConstantId = qualifier.layoutSpecConstantId; - } else - warn(loc, "unknown requalification", "", ""); -} - -void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, TIdentifierList& identifiers) -{ - for (unsigned int i = 0; i < identifiers.size(); ++i) - addQualifierToExisting(loc, qualifier, *identifiers[i]); -} - -// Make sure 'invariant' isn't being applied to a non-allowed object. -void TParseContext::invariantCheck(const TSourceLoc& loc, const TQualifier& qualifier) -{ - if (! qualifier.invariant) - return; - - bool pipeOut = qualifier.isPipeOutput(); - bool pipeIn = qualifier.isPipeInput(); - if ((version >= 300 && isEsProfile()) || (!isEsProfile() && version >= 420)) { - if (! pipeOut) - error(loc, "can only apply to an output", "invariant", ""); - } else { - if ((language == EShLangVertex && pipeIn) || (! pipeOut && ! pipeIn)) - error(loc, "can only apply to an output, or to an input in a non-vertex stage\n", "invariant", ""); - } -} - -// -// Updating default qualifier for the case of a declaration with just a qualifier, -// no type, block, or identifier. -// -void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, const TPublicType& publicType) -{ - if (publicType.shaderQualifiers.vertices != TQualifier::layoutNotSet) { - assert(language == EShLangTessControl || language == EShLangGeometry || language == EShLangMesh); - const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices"; - - if (publicType.qualifier.storage != EvqVaryingOut) - error(loc, "can only apply to 'out'", id, ""); - if (! intermediate.setVertices(publicType.shaderQualifiers.vertices)) - error(loc, "cannot change previously set layout value", id, ""); - - if (language == EShLangTessControl) - checkIoArraysConsistency(loc); - } - if (publicType.shaderQualifiers.primitives != TQualifier::layoutNotSet) { - assert(language == EShLangMesh); - const char* id = "max_primitives"; - - if (publicType.qualifier.storage != EvqVaryingOut) - error(loc, "can only apply to 'out'", id, ""); - if (! intermediate.setPrimitives(publicType.shaderQualifiers.primitives)) - error(loc, "cannot change previously set layout value", id, ""); - } - if (publicType.shaderQualifiers.invocations != TQualifier::layoutNotSet) { - if (publicType.qualifier.storage != EvqVaryingIn) - error(loc, "can only apply to 'in'", "invocations", ""); - if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations)) - error(loc, "cannot change previously set layout value", "invocations", ""); - } - if (publicType.shaderQualifiers.geometry != ElgNone) { - if (publicType.qualifier.storage == EvqVaryingIn) { - switch (publicType.shaderQualifiers.geometry) { - case ElgPoints: - case ElgLines: - case ElgLinesAdjacency: - case ElgTriangles: - case ElgTrianglesAdjacency: - case ElgQuads: - case ElgIsolines: - if (language == EShLangMesh) { - error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); - break; - } - if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) { - if (language == EShLangGeometry) - checkIoArraysConsistency(loc); - } else - error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); - break; - default: - error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); - } - } else if (publicType.qualifier.storage == EvqVaryingOut) { - switch (publicType.shaderQualifiers.geometry) { - case ElgLines: - case ElgTriangles: - if (language != EShLangMesh) { - error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); - break; - } - // Fall through - case ElgPoints: - case ElgLineStrip: - case ElgTriangleStrip: - if (! intermediate.setOutputPrimitive(publicType.shaderQualifiers.geometry)) - error(loc, "cannot change previously set output primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); - break; - default: - error(loc, "cannot apply to 'out'", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); - } - } else - error(loc, "cannot apply to:", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), GetStorageQualifierString(publicType.qualifier.storage)); - } - if (publicType.shaderQualifiers.spacing != EvsNone) { - if (publicType.qualifier.storage == EvqVaryingIn) { - if (! intermediate.setVertexSpacing(publicType.shaderQualifiers.spacing)) - error(loc, "cannot change previously set vertex spacing", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), ""); - } else - error(loc, "can only apply to 'in'", TQualifier::getVertexSpacingString(publicType.shaderQualifiers.spacing), ""); - } - if (publicType.shaderQualifiers.order != EvoNone) { - if (publicType.qualifier.storage == EvqVaryingIn) { - if (! intermediate.setVertexOrder(publicType.shaderQualifiers.order)) - error(loc, "cannot change previously set vertex order", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), ""); - } else - error(loc, "can only apply to 'in'", TQualifier::getVertexOrderString(publicType.shaderQualifiers.order), ""); - } - if (publicType.shaderQualifiers.pointMode) { - if (publicType.qualifier.storage == EvqVaryingIn) - intermediate.setPointMode(); - else - error(loc, "can only apply to 'in'", "point_mode", ""); - } - - for (int i = 0; i < 3; ++i) { - if (publicType.shaderQualifiers.localSizeNotDefault[i]) { - if (publicType.qualifier.storage == EvqVaryingIn) { - if (! intermediate.setLocalSize(i, publicType.shaderQualifiers.localSize[i])) - error(loc, "cannot change previously set size", "local_size", ""); - else { - int max = 0; - if (language == EShLangCompute) { - switch (i) { - case 0: max = resources.maxComputeWorkGroupSizeX; break; - case 1: max = resources.maxComputeWorkGroupSizeY; break; - case 2: max = resources.maxComputeWorkGroupSizeZ; break; - default: break; - } - if (intermediate.getLocalSize(i) > (unsigned int)max) - error(loc, "too large; see gl_MaxComputeWorkGroupSize", "local_size", ""); - } else if (language == EShLangMesh) { - switch (i) { - case 0: - max = extensionTurnedOn(E_GL_EXT_mesh_shader) ? - resources.maxMeshWorkGroupSizeX_EXT : - resources.maxMeshWorkGroupSizeX_NV; - break; - case 1: - max = extensionTurnedOn(E_GL_EXT_mesh_shader) ? - resources.maxMeshWorkGroupSizeY_EXT : - resources.maxMeshWorkGroupSizeY_NV ; - break; - case 2: - max = extensionTurnedOn(E_GL_EXT_mesh_shader) ? - resources.maxMeshWorkGroupSizeZ_EXT : - resources.maxMeshWorkGroupSizeZ_NV ; - break; - default: break; - } - if (intermediate.getLocalSize(i) > (unsigned int)max) { - TString maxsErrtring = "too large, see "; - maxsErrtring.append(extensionTurnedOn(E_GL_EXT_mesh_shader) ? - "gl_MaxMeshWorkGroupSizeEXT" : "gl_MaxMeshWorkGroupSizeNV"); - error(loc, maxsErrtring.c_str(), "local_size", ""); - } - } else if (language == EShLangTask) { - switch (i) { - case 0: - max = extensionTurnedOn(E_GL_EXT_mesh_shader) ? - resources.maxTaskWorkGroupSizeX_EXT : - resources.maxTaskWorkGroupSizeX_NV; - break; - case 1: - max = extensionTurnedOn(E_GL_EXT_mesh_shader) ? - resources.maxTaskWorkGroupSizeY_EXT: - resources.maxTaskWorkGroupSizeY_NV; - break; - case 2: - max = extensionTurnedOn(E_GL_EXT_mesh_shader) ? - resources.maxTaskWorkGroupSizeZ_EXT: - resources.maxTaskWorkGroupSizeZ_NV; - break; - default: break; - } - if (intermediate.getLocalSize(i) > (unsigned int)max) { - TString maxsErrtring = "too large, see "; - maxsErrtring.append(extensionTurnedOn(E_GL_EXT_mesh_shader) ? - "gl_MaxTaskWorkGroupSizeEXT" : "gl_MaxTaskWorkGroupSizeNV"); - error(loc, maxsErrtring.c_str(), "local_size", ""); - } - } else { - assert(0); - } - - // Fix the existing constant gl_WorkGroupSize with this new information. - TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); - if (workGroupSize != nullptr) - workGroupSize->getWritableConstArray()[i].setUConst(intermediate.getLocalSize(i)); - } - } else - error(loc, "can only apply to 'in'", "local_size", ""); - } - if (publicType.shaderQualifiers.localSizeSpecId[i] != TQualifier::layoutNotSet) { - if (publicType.qualifier.storage == EvqVaryingIn) { - if (! intermediate.setLocalSizeSpecId(i, publicType.shaderQualifiers.localSizeSpecId[i])) - error(loc, "cannot change previously set size", "local_size", ""); - } else - error(loc, "can only apply to 'in'", "local_size id", ""); - // Set the workgroup built-in variable as a specialization constant - TVariable* workGroupSize = getEditableVariable("gl_WorkGroupSize"); - if (workGroupSize != nullptr) - workGroupSize->getWritableType().getQualifier().specConstant = true; - } - } - - if (publicType.shaderQualifiers.earlyFragmentTests) { - if (publicType.qualifier.storage == EvqVaryingIn) - intermediate.setEarlyFragmentTests(); - else - error(loc, "can only apply to 'in'", "early_fragment_tests", ""); - } - if (publicType.shaderQualifiers.earlyAndLateFragmentTestsAMD) { - if (publicType.qualifier.storage == EvqVaryingIn) - intermediate.setEarlyAndLateFragmentTestsAMD(); - else - error(loc, "can only apply to 'in'", "early_and_late_fragment_tests_amd", ""); - } - if (publicType.shaderQualifiers.postDepthCoverage) { - if (publicType.qualifier.storage == EvqVaryingIn) - intermediate.setPostDepthCoverage(); - else - error(loc, "can only apply to 'in'", "post_coverage_coverage", ""); - } - if (publicType.shaderQualifiers.nonCoherentColorAttachmentReadEXT) { - if (publicType.qualifier.storage == EvqVaryingIn) - intermediate.setNonCoherentColorAttachmentReadEXT(); - else - error(loc, "can only apply to 'in'", "non_coherent_color_attachment_readEXT", ""); - } - if (publicType.shaderQualifiers.nonCoherentDepthAttachmentReadEXT) { - if (publicType.qualifier.storage == EvqVaryingIn) - intermediate.setNonCoherentDepthAttachmentReadEXT(); - else - error(loc, "can only apply to 'in'", "non_coherent_depth_attachment_readEXT", ""); - } - if (publicType.shaderQualifiers.nonCoherentStencilAttachmentReadEXT) { - if (publicType.qualifier.storage == EvqVaryingIn) - intermediate.setNonCoherentStencilAttachmentReadEXT(); - else - error(loc, "can only apply to 'in'", "non_coherent_stencil_attachment_readEXT", ""); - } - if (publicType.shaderQualifiers.hasBlendEquation()) { - if (publicType.qualifier.storage != EvqVaryingOut) - error(loc, "can only apply to 'out'", "blend equation", ""); - } - if (publicType.shaderQualifiers.interlockOrdering) { - if (publicType.qualifier.storage == EvqVaryingIn) { - if (!intermediate.setInterlockOrdering(publicType.shaderQualifiers.interlockOrdering)) - error(loc, "cannot change previously set fragment shader interlock ordering", TQualifier::getInterlockOrderingString(publicType.shaderQualifiers.interlockOrdering), ""); - } - else - error(loc, "can only apply to 'in'", TQualifier::getInterlockOrderingString(publicType.shaderQualifiers.interlockOrdering), ""); - } - - if (publicType.shaderQualifiers.layoutDerivativeGroupQuads && - publicType.shaderQualifiers.layoutDerivativeGroupLinear) { - error(loc, "cannot be both specified", "derivative_group_quadsNV and derivative_group_linearNV", ""); - } - - if (publicType.shaderQualifiers.layoutDerivativeGroupQuads) { - if (publicType.qualifier.storage == EvqVaryingIn) { - if ((intermediate.getLocalSize(0) & 1) || - (intermediate.getLocalSize(1) & 1)) - error(loc, "requires local_size_x and local_size_y to be multiple of two", "derivative_group_quadsNV", ""); - else - intermediate.setLayoutDerivativeMode(LayoutDerivativeGroupQuads); - } - else - error(loc, "can only apply to 'in'", "derivative_group_quadsNV", ""); - } - if (publicType.shaderQualifiers.layoutDerivativeGroupLinear) { - if (publicType.qualifier.storage == EvqVaryingIn) { - if((intermediate.getLocalSize(0) * - intermediate.getLocalSize(1) * - intermediate.getLocalSize(2)) % 4 != 0) - error(loc, "requires total group size to be multiple of four", "derivative_group_linearNV", ""); - else - intermediate.setLayoutDerivativeMode(LayoutDerivativeGroupLinear); - } - else - error(loc, "can only apply to 'in'", "derivative_group_linearNV", ""); - } - // Check mesh out array sizes, once all the necessary out qualifiers are defined. - if ((language == EShLangMesh) && - (intermediate.getVertices() != TQualifier::layoutNotSet) && - (intermediate.getPrimitives() != TQualifier::layoutNotSet) && - (intermediate.getOutputPrimitive() != ElgNone)) - { - checkIoArraysConsistency(loc); - } - - if (publicType.shaderQualifiers.layoutPrimitiveCulling) { - if (publicType.qualifier.storage != EvqTemporary) - error(loc, "layout qualifier can not have storage qualifiers", "primitive_culling","", ""); - else { - intermediate.setLayoutPrimitiveCulling(); - } - // Exit early as further checks are not valid - return; - } - - const TQualifier& qualifier = publicType.qualifier; - - if (qualifier.isAuxiliary() || - qualifier.isMemory() || - qualifier.isInterpolation() || - qualifier.precision != EpqNone) - error(loc, "cannot use auxiliary, memory, interpolation, or precision qualifier in a default qualifier declaration (declaration with no type)", "qualifier", ""); - - // "The offset qualifier can only be used on block members of blocks..." - // "The align qualifier can only be used on blocks or block members..." - if (qualifier.hasOffset() || - qualifier.hasAlign()) - error(loc, "cannot use offset or align qualifiers in a default qualifier declaration (declaration with no type)", "layout qualifier", ""); - - layoutQualifierCheck(loc, qualifier); - - switch (qualifier.storage) { - case EvqUniform: - if (qualifier.hasMatrix()) - globalUniformDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.hasPacking()) - globalUniformDefaults.layoutPacking = qualifier.layoutPacking; - break; - case EvqBuffer: - if (qualifier.hasMatrix()) - globalBufferDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.hasPacking()) - globalBufferDefaults.layoutPacking = qualifier.layoutPacking; - break; - case EvqVaryingIn: - break; - case EvqVaryingOut: - if (qualifier.hasStream()) - globalOutputDefaults.layoutStream = qualifier.layoutStream; - if (qualifier.hasXfbBuffer()) - globalOutputDefaults.layoutXfbBuffer = qualifier.layoutXfbBuffer; - if (globalOutputDefaults.hasXfbBuffer() && qualifier.hasXfbStride()) { - if (! intermediate.setXfbBufferStride(globalOutputDefaults.layoutXfbBuffer, qualifier.layoutXfbStride)) - error(loc, "all stride settings must match for xfb buffer", "xfb_stride", "%d", qualifier.layoutXfbBuffer); - } - break; - case EvqShared: - if (qualifier.hasMatrix()) - globalSharedDefaults.layoutMatrix = qualifier.layoutMatrix; - if (qualifier.hasPacking()) - globalSharedDefaults.layoutPacking = qualifier.layoutPacking; - break; - default: - error(loc, "default qualifier requires 'uniform', 'buffer', 'in', 'out' or 'shared' storage qualification", "", ""); - return; - } - - if (qualifier.hasBinding()) - error(loc, "cannot declare a default, include a type or full declaration", "binding", ""); - if (qualifier.hasAnyLocation()) - error(loc, "cannot declare a default, use a full declaration", "location/component/index", ""); - if (qualifier.hasXfbOffset()) - error(loc, "cannot declare a default, use a full declaration", "xfb_offset", ""); - if (qualifier.isPushConstant()) - error(loc, "cannot declare a default, can only be used on a block", "push_constant", ""); - if (qualifier.hasBufferReference()) - error(loc, "cannot declare a default, can only be used on a block", "buffer_reference", ""); - if (qualifier.hasSpecConstantId()) - error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", ""); - if (qualifier.isShaderRecord()) - error(loc, "cannot declare a default, can only be used on a block", "shaderRecordNV", ""); -} - -// -// Take the sequence of statements that has been built up since the last case/default, -// put it on the list of top-level nodes for the current (inner-most) switch statement, -// and follow that by the case/default we are on now. (See switch topology comment on -// TIntermSwitch.) -// -void TParseContext::wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode) -{ - TIntermSequence* switchSequence = switchSequenceStack.back(); - - if (statements) { - if (switchSequence->size() == 0) - error(statements->getLoc(), "cannot have statements before first case/default label", "switch", ""); - statements->setOperator(EOpSequence); - switchSequence->push_back(statements); - } - if (branchNode) { - // check all previous cases for the same label (or both are 'default') - for (unsigned int s = 0; s < switchSequence->size(); ++s) { - TIntermBranch* prevBranch = (*switchSequence)[s]->getAsBranchNode(); - if (prevBranch) { - TIntermTyped* prevExpression = prevBranch->getExpression(); - TIntermTyped* newExpression = branchNode->getAsBranchNode()->getExpression(); - if (prevExpression == nullptr && newExpression == nullptr) - error(branchNode->getLoc(), "duplicate label", "default", ""); - else if (prevExpression != nullptr && - newExpression != nullptr && - prevExpression->getAsConstantUnion() && - newExpression->getAsConstantUnion() && - prevExpression->getAsConstantUnion()->getConstArray()[0].getIConst() == - newExpression->getAsConstantUnion()->getConstArray()[0].getIConst()) - error(branchNode->getLoc(), "duplicated value", "case", ""); - } - } - switchSequence->push_back(branchNode); - } -} - -// -// Turn the top-level node sequence built up of wrapupSwitchSubsequence9) -// into a switch node. -// -TIntermNode* TParseContext::addSwitch(const TSourceLoc& loc, TIntermTyped* expression, TIntermAggregate* lastStatements) -{ - profileRequires(loc, EEsProfile, 300, nullptr, "switch statements"); - profileRequires(loc, ENoProfile, 130, nullptr, "switch statements"); - - wrapupSwitchSubsequence(lastStatements, nullptr); - - if (expression == nullptr || - (expression->getBasicType() != EbtInt && expression->getBasicType() != EbtUint) || - expression->getType().isArray() || expression->getType().isMatrix() || expression->getType().isVector()) - error(loc, "condition must be a scalar integer expression", "switch", ""); - - // If there is nothing to do, drop the switch but still execute the expression - TIntermSequence* switchSequence = switchSequenceStack.back(); - if (switchSequence->size() == 0) - return expression; - - if (lastStatements == nullptr) { - // This was originally an ERRROR, because early versions of the specification said - // "it is an error to have no statement between a label and the end of the switch statement." - // The specifications were updated to remove this (being ill-defined what a "statement" was), - // so, this became a warning. However, 3.0 tests still check for the error. - if (isEsProfile() && (version <= 300 || version >= 320) && ! relaxedErrors()) - error(loc, "last case/default label not followed by statements", "switch", ""); - else if (!isEsProfile() && (version <= 430 || version >= 460)) - error(loc, "last case/default label not followed by statements", "switch", ""); - else - warn(loc, "last case/default label not followed by statements", "switch", ""); - - - // emulate a break for error recovery - lastStatements = intermediate.makeAggregate(intermediate.addBranch(EOpBreak, loc)); - lastStatements->setOperator(EOpSequence); - switchSequence->push_back(lastStatements); - } - - TIntermAggregate* body = new TIntermAggregate(EOpSequence); - body->getSequence() = *switchSequenceStack.back(); - body->setLoc(loc); - - TIntermSwitch* switchNode = new TIntermSwitch(expression, body); - switchNode->setLoc(loc); - - return switchNode; -} - -// -// When a struct used in block, and has it's own layout packing, layout matrix, -// record the origin structure of a struct to map, and Record the structure copy to the copy table, -// -const TTypeList* TParseContext::recordStructCopy(TStructRecord& record, const TType* originType, const TType* tmpType) -{ - size_t memberCount = tmpType->getStruct()->size(); - size_t originHash = 0, tmpHash = 0; - std::hash hasher; - for (size_t i = 0; i < memberCount; i++) { - size_t originMemberHash = hasher(originType->getStruct()->at(i).type->getQualifier().layoutPacking + - originType->getStruct()->at(i).type->getQualifier().layoutMatrix); - size_t tmpMemberHash = hasher(tmpType->getStruct()->at(i).type->getQualifier().layoutPacking + - tmpType->getStruct()->at(i).type->getQualifier().layoutMatrix); - originHash = hasher((originHash ^ originMemberHash) << 1); - tmpHash = hasher((tmpHash ^ tmpMemberHash) << 1); - } - const TTypeList* originStruct = originType->getStruct(); - const TTypeList* tmpStruct = tmpType->getStruct(); - if (originHash != tmpHash) { - auto fixRecords = record.find(originStruct); - if (fixRecords != record.end()) { - auto fixRecord = fixRecords->second.find(tmpHash); - if (fixRecord != fixRecords->second.end()) { - return fixRecord->second; - } else { - record[originStruct][tmpHash] = tmpStruct; - return tmpStruct; - } - } else { - record[originStruct] = std::map(); - record[originStruct][tmpHash] = tmpStruct; - return tmpStruct; - } - } - return originStruct; -} - -TLayoutFormat TParseContext::mapLegacyLayoutFormat(TLayoutFormat legacyLayoutFormat, TBasicType imageType) -{ - TLayoutFormat layoutFormat = ElfNone; - if (imageType == EbtFloat) { - switch (legacyLayoutFormat) { - case ElfSize1x16: layoutFormat = ElfR16f; break; - case ElfSize1x32: layoutFormat = ElfR32f; break; - case ElfSize2x32: layoutFormat = ElfRg32f; break; - case ElfSize4x32: layoutFormat = ElfRgba32f; break; - default: break; - } - } else if (imageType == EbtUint) { - switch (legacyLayoutFormat) { - case ElfSize1x8: layoutFormat = ElfR8ui; break; - case ElfSize1x16: layoutFormat = ElfR16ui; break; - case ElfSize1x32: layoutFormat = ElfR32ui; break; - case ElfSize2x32: layoutFormat = ElfRg32ui; break; - case ElfSize4x32: layoutFormat = ElfRgba32ui; break; - default: break; - } - } else if (imageType == EbtInt) { - switch (legacyLayoutFormat) { - case ElfSize1x8: layoutFormat = ElfR8i; break; - case ElfSize1x16: layoutFormat = ElfR16i; break; - case ElfSize1x32: layoutFormat = ElfR32i; break; - case ElfSize2x32: layoutFormat = ElfRg32i; break; - case ElfSize4x32: layoutFormat = ElfRgba32i; break; - default: break; - } - } - - return layoutFormat; -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h b/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h deleted file mode 100644 index 16902aef..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/ParseHelper.h +++ /dev/null @@ -1,591 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// This header defines a two-level parse-helper hierarchy, derived from -// TParseVersions: -// - TParseContextBase: sharable across multiple parsers -// - TParseContext: GLSL specific helper -// - -#ifndef _PARSER_HELPER_INCLUDED_ -#define _PARSER_HELPER_INCLUDED_ - -#include -#include - -#include "parseVersions.h" -#include "../Include/ShHandle.h" -#include "SymbolTable.h" -#include "localintermediate.h" -#include "Scan.h" -#include "attribute.h" - -namespace glslang { - -struct TPragma { - TPragma(bool o, bool d) : optimize(o), debug(d) { } - bool optimize; - bool debug; - TPragmaTable pragmaTable; -}; - -class TScanContext; -class TPpContext; - -typedef std::set TIdSetType; -typedef std::map> TStructRecord; - -// -// Sharable code (as well as what's in TParseVersions) across -// parse helpers. -// -class TParseContextBase : public TParseVersions { -public: - TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version, - EProfile profile, const SpvVersion& spvVersion, EShLanguage language, - TInfoSink& infoSink, bool forwardCompatible, EShMessages messages, - const TString* entryPoint = nullptr) - : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), - scopeMangler("::"), - symbolTable(symbolTable), - statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), blockNestingLevel(0), controlFlowNestingLevel(0), - currentFunctionType(nullptr), - postEntryPointReturn(false), - contextPragma(true, false), - beginInvocationInterlockCount(0), endInvocationInterlockCount(0), - parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr), - limits(resources.limits), - globalUniformBlock(nullptr), - globalUniformBinding(TQualifier::layoutBindingEnd), - globalUniformSet(TQualifier::layoutSetEnd), - atomicCounterBlockSet(TQualifier::layoutSetEnd) - { - // use storage buffer on SPIR-V 1.3 and up - if (spvVersion.spv >= EShTargetSpv_1_3) - intermediate.setUseStorageBuffer(); - - if (entryPoint != nullptr) - sourceEntryPointName = *entryPoint; - } - virtual ~TParseContextBase() { } - - virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...); - virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...); - virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...); - virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...); - - virtual void setLimits(const TBuiltInResource&) = 0; - - void checkIndex(const TSourceLoc&, const TType&, int& index); - - EShLanguage getLanguage() const { return language; } - void setScanContext(TScanContext* c) { scanContext = c; } - TScanContext* getScanContext() const { return scanContext; } - void setPpContext(TPpContext* c) { ppContext = c; } - TPpContext* getPpContext() const { return ppContext; } - - virtual void setLineCallback(const std::function& func) { lineCallback = func; } - virtual void setExtensionCallback(const std::function& func) { extensionCallback = func; } - virtual void setVersionCallback(const std::function& func) { versionCallback = func; } - virtual void setPragmaCallback(const std::function&)>& func) { pragmaCallback = func; } - virtual void setErrorCallback(const std::function& func) { errorCallback = func; } - - virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0; - virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0; - virtual bool lineDirectiveShouldSetNextLine() const = 0; - virtual void handlePragma(const TSourceLoc&, const TVector&) = 0; - - virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0; - - virtual void notifyVersion(int line, int version, const char* type_string) - { - if (versionCallback) - versionCallback(line, version, type_string); - } - virtual void notifyErrorDirective(int line, const char* error_message) - { - if (errorCallback) - errorCallback(line, error_message); - } - virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName) - { - if (lineCallback) - lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName); - } - virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior) - { - if (extensionCallback) - extensionCallback(line, extension, behavior); - } - - // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) - virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); - - // Manage global buffer (used for backing atomic counters in GLSL when using relaxed Vulkan semantics) - virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); - - // Potentially rename shader entry point function - void renameShaderFunction(TString*& name) const - { - // Replace the entry point name given in the shader with the real entry point name, - // if there is a substitution. - if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0) - name = NewPoolTString(intermediate.getEntryPointName().c_str()); - } - - virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); - virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); - - const char* const scopeMangler; - - // Basic parsing state, easily accessible to the grammar - - TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile - TVector relaxedSymbols; - int statementNestingLevel; // 0 if outside all flow control or compound statements - int loopNestingLevel; // 0 if outside all loops - int structNestingLevel; // 0 if outside structures - int blockNestingLevel; // 0 if outside blocks - int controlFlowNestingLevel; // 0 if outside all flow control - const TType* currentFunctionType; // the return type of the function that's currently being parsed - bool functionReturnsValue; // true if a non-void function has a return - // if inside a function, true if the function is the entry point and this is after a return statement - bool postEntryPointReturn; - // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting - TList switchSequenceStack; - // the statementNestingLevel the current switch statement is at, which must match the level of its case statements - TList switchLevel; - struct TPragma contextPragma; - int beginInvocationInterlockCount; - int endInvocationInterlockCount; - bool compileOnly = false; - -protected: - TParseContextBase(TParseContextBase&); - TParseContextBase& operator=(TParseContextBase&); - - const bool parsingBuiltins; // true if parsing built-in symbols/functions - TVector linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving - TScanContext* scanContext; - TPpContext* ppContext; - TBuiltInResource resources; - TLimits& limits; - TString sourceEntryPointName; - - // These, if set, will be called when a line, pragma ... is preprocessed. - // They will be called with any parameters to the original directive. - std::function lineCallback; - std::function&)> pragmaCallback; - std::function versionCallback; - std::function extensionCallback; - std::function errorCallback; - - // see implementation for detail - const TFunction* selectFunction(const TVector, const TFunction&, - std::function, - std::function, - /* output */ bool& tie); - - virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size, - TSwizzleSelectors&); - - // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) - TVariable* globalUniformBlock; // the actual block, inserted into the symbol table - unsigned int globalUniformBinding; // the block's binding number - unsigned int globalUniformSet; // the block's set number - int firstNewMember; // the index of the first member not yet inserted into the symbol table - // override this to set the language-specific name - virtual const char* getGlobalUniformBlockName() const { return ""; } - virtual void setUniformBlockDefaults(TType&) const { } - virtual void finalizeGlobalUniformBlockLayout(TVariable&) {} - - // Manage the atomic counter block (used for atomic_uints with Vulkan-Relaxed) - TMap atomicCounterBuffers; - unsigned int atomicCounterBlockSet; - TMap atomicCounterBlockFirstNewMember; - // override this to set the language-specific name - virtual const char* getAtomicCounterBlockName() const { return ""; } - virtual void setAtomicCounterBlockDefaults(TType&) const {} - virtual void setInvariant(const TSourceLoc&, const char*) {} - virtual void finalizeAtomicCounterBlockLayout(TVariable&) {} - bool isAtomicCounterBlock(const TSymbol& symbol) { - const TVariable* var = symbol.getAsVariable(); - if (!var) - return false; - const auto& at = atomicCounterBuffers.find(var->getType().getQualifier().layoutBinding); - return (at != atomicCounterBuffers.end() && (*at).second->getType() == var->getType()); - } - - virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, TPrefixType prefix, - va_list args); - virtual void trackLinkage(TSymbol& symbol); - virtual void makeEditable(TSymbol*&); - virtual TVariable* getEditableVariable(const char* name); - virtual void finish(); -}; - -// -// Manage the state for when to respect precision qualifiers and when to warn about -// the defaults being different than might be expected. -// -class TPrecisionManager { -public: - TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ } - virtual ~TPrecisionManager() {} - - void respectPrecisionQualifiers() { obey = true; } - bool respectingPrecisionQualifiers() const { return obey; } - bool shouldWarnAboutDefaults() const { return warn; } - void defaultWarningGiven() { warn = false; } - void warnAboutDefaults() { warn = true; } - void explicitIntDefaultSeen() - { - explicitIntDefault = true; - if (explicitFloatDefault) - warn = false; - } - void explicitFloatDefaultSeen() - { - explicitFloatDefault = true; - if (explicitIntDefault) - warn = false; - } - -protected: - bool obey; // respect precision qualifiers - bool warn; // need to give a warning about the defaults - bool explicitIntDefault; // user set the default for int/uint - bool explicitFloatDefault; // user set the default for float -}; - -// -// GLSL-specific parse helper. Should have GLSL in the name, but that's -// too big of a change for comparing branches at the moment, and perhaps -// impacts downstream consumers as well. -// -class TParseContext : public TParseContextBase { -public: - TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, - bool forwardCompatible = false, EShMessages messages = EShMsgDefault, - const TString* entryPoint = nullptr); - virtual ~TParseContext(); - - bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); } - void setPrecisionDefaults(); - - void setLimits(const TBuiltInResource&) override; - bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; - void parserError(const char* s); // for bison's yyerror - - virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override; - virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override; - - void reservedErrorCheck(const TSourceLoc&, const TString&); - void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override; - bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override; - bool lineDirectiveShouldSetNextLine() const override; - bool builtInName(const TString&); - - void handlePragma(const TSourceLoc&, const TVector&) override; - TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string); - TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); - void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); - - void makeEditable(TSymbol*&) override; - void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); - bool isIoResizeArray(const TType&) const; - void fixIoArraySize(const TSourceLoc&, TType&); - void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); - void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); - int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const; - void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); - - TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); - TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); - TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); - TIntermTyped* handleDotSwizzle(const TSourceLoc&, TIntermTyped* base, const TString& field); - void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName); - TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); - TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); - TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); - TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function); - void computeBuiltinPrecisions(TIntermTyped&, const TFunction&); - TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); - void checkLocation(const TSourceLoc&, TOperator); - TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); - void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; - TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const; - TIntermTyped* addAssign(const TSourceLoc&, TOperator op, TIntermTyped* left, TIntermTyped* right); - void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); - void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&); - void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&); - void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*); - TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&); - void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier); - void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); - void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode); - - TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); - // returns true if the variable was remapped to something else - bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&); - void vkRelaxedRemapUniformMembers(const TSourceLoc&, const TPublicType&, const TType&, const TString&); - void vkRelaxedRemapFunctionParameter(TFunction*, TParameter&, std::vector* newParams = nullptr); - TIntermNode* vkRelaxedRemapFunctionArgument(const TSourceLoc&, TFunction*, TIntermTyped*); - TIntermTyped* vkRelaxedRemapDotDereference(const TSourceLoc&, TIntermTyped&, const TType&, const TString&); - - void assignError(const TSourceLoc&, const char* op, TString left, TString right); - void unaryOpError(const TSourceLoc&, const char* op, TString operand); - void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); - void variableCheck(TIntermTyped*& nodePtr); - bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; - void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; - void constantValueCheck(TIntermTyped* node, const char* token); - void integerCheck(const TIntermTyped* node, const char* token); - void globalCheck(const TSourceLoc&, const char* token); - bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&); - bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&); - void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType, const bool allowZero = false); - bool arrayQualifierError(const TSourceLoc&, const TQualifier&); - bool arrayError(const TSourceLoc&, const TType&); - void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); - void structArrayCheck(const TSourceLoc&, const TType& structure); - void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember); - void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*); - bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); - void boolCheck(const TSourceLoc&, const TIntermTyped*); - void boolCheck(const TSourceLoc&, const TPublicType&); - void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); - void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); - void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); - void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); - void memberQualifierCheck(glslang::TPublicType&); - void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false, const TPublicType* publicType = nullptr); - void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&); - bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); - void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force); - void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier); - int computeSamplerTypeIndex(TSampler&); - TPrecisionQualifier getDefaultPrecision(TPublicType&); - void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&, bool isCoopMat); - void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type); - bool containsFieldWithBasicType(const TType& type ,TBasicType basicType); - TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&); - void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes); - void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type); - void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type); - void nestedBlockCheck(const TSourceLoc&); - void nestedStructCheck(const TSourceLoc&); - void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op); - void opaqueCheck(const TSourceLoc&, const TType&, const char* op); - void referenceCheck(const TSourceLoc&, const TType&, const char* op); - void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op); - void specializationCheck(const TSourceLoc&, const TType&, const char* op); - void structTypeCheck(const TSourceLoc&, TPublicType&); - void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop); - void arrayLimitCheck(const TSourceLoc&, const TString&, int size); - void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature); - void coopMatTypeParametersCheck(const TSourceLoc&, const TPublicType&); - - void inductiveLoopBodyCheck(TIntermNode*, long long loopIndexId, TSymbolTable&); - void constantIndexExpressionCheck(TIntermNode*); - - void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&); - void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*); - void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); - void layoutObjectCheck(const TSourceLoc&, const TSymbol&); - void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes); - void layoutTypeCheck(const TSourceLoc&, const TType&); - void layoutQualifierCheck(const TSourceLoc&, const TQualifier&); - void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); - void fixOffset(const TSourceLoc&, TSymbol&); - - const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn); - const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn); - const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn); - const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn); - const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn); - void declareTypeDefaults(const TSourceLoc&, const TPublicType&); - TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = nullptr, TIntermTyped* initializer = nullptr); - TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); - TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); - TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); - void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to); - void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = nullptr, TArraySizes* arraySizes = nullptr); - void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&); - void blockStageIoCheck(const TSourceLoc&, const TQualifier&); - void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); - void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); - void fixXfbOffsets(TQualifier&, TTypeList&); - void fixBlockUniformOffsets(TQualifier&, TTypeList&); - void fixBlockUniformLayoutMatrix(TQualifier&, TTypeList*, TTypeList*); - void fixBlockUniformLayoutPacking(TQualifier&, TTypeList*, TTypeList*); - void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); - void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); - void invariantCheck(const TSourceLoc&, const TQualifier&); - void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); - void updateBindlessQualifier(TType& memberType); - void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); - TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body); - const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*); - TLayoutFormat mapLegacyLayoutFormat(TLayoutFormat legacyLayoutFormat, TBasicType imageType); - - TAttributeType attributeFromName(const TString& name) const; - TAttributes* makeAttributes(const TString& identifier) const; - TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const; - TAttributes* mergeAttributes(TAttributes*, TAttributes*) const; - - // Determine selection control from attributes - void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*); - void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*); - // Determine loop control from attributes - void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); - // Function attributes - void handleFunctionAttributes(const TSourceLoc&, const TAttributes&); - - // GL_EXT_spirv_intrinsics - TSpirvRequirement* makeSpirvRequirement(const TSourceLoc& loc, const TString& name, - const TIntermAggregate* extensions, const TIntermAggregate* capabilities); - TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1, - TSpirvRequirement* spirvReq2); - TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant); - TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TPublicType& type); - TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, - TSpirvTypeParameters* spirvTypeParams2); - TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value); - TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value); - TSpirvInstruction* mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1, - TSpirvInstruction* spirvInst2); - void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember); - -protected: - void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type); - void inheritGlobalDefaults(TQualifier& dst) const; - TVariable* makeInternalVariable(const char* name, const TType&) const; - TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&); - void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&); - void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&); - bool isRuntimeLength(const TIntermTyped&) const; - TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable); - TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer); - void finish() override; - - virtual const char* getGlobalUniformBlockName() const override; - virtual void finalizeGlobalUniformBlockLayout(TVariable&) override; - virtual void setUniformBlockDefaults(TType& block) const override; - - virtual const char* getAtomicCounterBlockName() const override; - virtual void finalizeAtomicCounterBlockLayout(TVariable&) override; - virtual void setAtomicCounterBlockDefaults(TType& block) const override; - virtual void setInvariant(const TSourceLoc& loc, const char* builtin) override; - -public: - // - // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access - // - - // Current state of parsing - bool inMain; // if inside a function, true if the function is main - const TString* blockName; - TQualifier currentBlockQualifier; - TPrecisionQualifier defaultPrecision[EbtNumTypes]; - TBuiltInResource resources; - TLimits& limits; - -protected: - TParseContext(TParseContext&); - TParseContext& operator=(TParseContext&); - - static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex() - TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex]; - TPrecisionManager precisionManager; - TQualifier globalBufferDefaults; - TQualifier globalUniformDefaults; - TQualifier globalInputDefaults; - TQualifier globalOutputDefaults; - TQualifier globalSharedDefaults; - TString currentCaller; // name of last function body entered (not valid when at global scope) - int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point - bool anyIndexLimits; - TIdSetType inductiveLoopIds; - TVector needsIndexLimitationChecking; - TStructRecord matrixFixRecord; - TStructRecord packingFixRecord; - - // - // Geometry shader input arrays: - // - array sizing is based on input primitive and/or explicit size - // - // Tessellation control output arrays: - // - array sizing is based on output layout(vertices=...) and/or explicit size - // - // Both: - // - array sizing is retroactive - // - built-in block redeclarations interact with this - // - // Design: - // - use a per-context "resize-list", a list of symbols whose array sizes - // can be fixed - // - // - the resize-list starts empty at beginning of user-shader compilation, it does - // not have built-ins in it - // - // - on built-in array use: copyUp() symbol and add it to the resize-list - // - // - on user array declaration: add it to the resize-list - // - // - on block redeclaration: copyUp() symbol and add it to the resize-list - // * note, that appropriately gives an error if redeclaring a block that - // was already used and hence already copied-up - // - // - on seeing a layout declaration that sizes the array, fix everything in the - // resize-list, giving errors for mismatch - // - // - on seeing an array size declaration, give errors on mismatch between it and previous - // array-sizing declarations - // - TVector ioArraySymbolResizeList; -}; - -} // end namespace glslang - -#endif // _PARSER_HELPER_INCLUDED_ diff --git a/3rdparty/glslang/glslang/MachineIndependent/PoolAlloc.cpp b/3rdparty/glslang/glslang/MachineIndependent/PoolAlloc.cpp deleted file mode 100644 index 5d7173c9..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/PoolAlloc.cpp +++ /dev/null @@ -1,299 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/Common.h" -#include "../Include/PoolAlloc.h" - -namespace glslang { - -namespace { -thread_local TPoolAllocator* threadPoolAllocator = nullptr; - -TPoolAllocator* GetDefaultThreadPoolAllocator() -{ - thread_local TPoolAllocator defaultAllocator; - return &defaultAllocator; -} -} // anonymous namespace - -// Return the thread-specific current pool. -TPoolAllocator& GetThreadPoolAllocator() -{ - return *(threadPoolAllocator ? threadPoolAllocator : GetDefaultThreadPoolAllocator()); -} - -// Set the thread-specific current pool. -void SetThreadPoolAllocator(TPoolAllocator* poolAllocator) -{ - threadPoolAllocator = poolAllocator; -} - -// -// Implement the functionality of the TPoolAllocator class, which -// is documented in PoolAlloc.h. -// -TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) : - pageSize(growthIncrement), - alignment(allocationAlignment), - freeList(nullptr), - inUseList(nullptr), - numCalls(0) -{ - // - // Don't allow page sizes we know are smaller than all common - // OS page sizes. - // - if (pageSize < 4*1024) - pageSize = 4*1024; - - // - // A large currentPageOffset indicates a new page needs to - // be obtained to allocate memory. - // - currentPageOffset = pageSize; - - // - // Adjust alignment to be at least pointer aligned and - // power of 2. - // - size_t minAlign = sizeof(void*); - alignment &= ~(minAlign - 1); - if (alignment < minAlign) - alignment = minAlign; - size_t a = 1; - while (a < alignment) - a <<= 1; - alignment = a; - alignmentMask = a - 1; - - // - // Align header skip - // - headerSkip = minAlign; - if (headerSkip < sizeof(tHeader)) { - headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask; - } - - push(); -} - -TPoolAllocator::~TPoolAllocator() -{ - while (inUseList) { - tHeader* next = inUseList->nextPage; - inUseList->~tHeader(); - delete [] reinterpret_cast(inUseList); - inUseList = next; - } - - // - // Always delete the free list memory - it can't be being - // (correctly) referenced, whether the pool allocator was - // global or not. We should not check the guard blocks - // here, because we did it already when the block was - // placed into the free list. - // - while (freeList) { - tHeader* next = freeList->nextPage; - delete [] reinterpret_cast(freeList); - freeList = next; - } -} - -// -// Check a single guard block for damage -// -#ifdef GUARD_BLOCKS -void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const -#else -void TAllocation::checkGuardBlock(unsigned char*, unsigned char, const char*) const -#endif -{ -#ifdef GUARD_BLOCKS - for (size_t x = 0; x < guardBlockSize; x++) { - if (blockMem[x] != val) { - const int maxSize = 80; - char assertMsg[maxSize]; - - // We don't print the assert message. It's here just to be helpful. - snprintf(assertMsg, maxSize, "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n", - locText, size, data()); - assert(0 && "PoolAlloc: Damage in guard block"); - } - } -#else - assert(guardBlockSize == 0); -#endif -} - -void TPoolAllocator::push() -{ - tAllocState state = { currentPageOffset, inUseList }; - - stack.push_back(state); - - // - // Indicate there is no current page to allocate from. - // - currentPageOffset = pageSize; -} - -// -// Do a mass-deallocation of all the individual allocations -// that have occurred since the last push(), or since the -// last pop(), or since the object's creation. -// -// The deallocated pages are saved for future allocations. -// -void TPoolAllocator::pop() -{ - if (stack.size() < 1) - return; - - tHeader* page = stack.back().page; - currentPageOffset = stack.back().offset; - - while (inUseList != page) { - tHeader* nextInUse = inUseList->nextPage; - size_t pageCount = inUseList->pageCount; - - // This technically ends the lifetime of the header as C++ object, - // but we will still control the memory and reuse it. - inUseList->~tHeader(); // currently, just a debug allocation checker - - if (pageCount > 1) { - delete [] reinterpret_cast(inUseList); - } else { - inUseList->nextPage = freeList; - freeList = inUseList; - } - inUseList = nextInUse; - } - - stack.pop_back(); -} - -// -// Do a mass-deallocation of all the individual allocations -// that have occurred. -// -void TPoolAllocator::popAll() -{ - while (stack.size() > 0) - pop(); -} - -void* TPoolAllocator::allocate(size_t numBytes) -{ - // If we are using guard blocks, all allocations are bracketed by - // them: [guardblock][allocation][guardblock]. numBytes is how - // much memory the caller asked for. allocationSize is the total - // size including guard blocks. In release build, - // guardBlockSize=0 and this all gets optimized away. - size_t allocationSize = TAllocation::allocationSize(numBytes); - - // - // Just keep some interesting statistics. - // - ++numCalls; - totalBytes += numBytes; - - // - // Do the allocation, most likely case first, for efficiency. - // This step could be moved to be inline sometime. - // - if (currentPageOffset + allocationSize <= pageSize) { - // - // Safe to allocate from currentPageOffset. - // - unsigned char* memory = reinterpret_cast(inUseList) + currentPageOffset; - currentPageOffset += allocationSize; - currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask; - - return initializeAllocation(inUseList, memory, numBytes); - } - - if (allocationSize + headerSkip > pageSize) { - // - // Do a multi-page allocation. Don't mix these with the others. - // The OS is efficient and allocating and free-ing multiple pages. - // - size_t numBytesToAlloc = allocationSize + headerSkip; - tHeader* memory = reinterpret_cast(::new char[numBytesToAlloc]); - if (memory == nullptr) - return nullptr; - - // Use placement-new to initialize header - new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize); - inUseList = memory; - - currentPageOffset = pageSize; // make next allocation come from a new page - - // No guard blocks for multi-page allocations (yet) - return reinterpret_cast(reinterpret_cast(memory) + headerSkip); - } - - // - // Need a simple page to allocate from. - // - tHeader* memory; - if (freeList) { - memory = freeList; - freeList = freeList->nextPage; - } else { - memory = reinterpret_cast(::new char[pageSize]); - if (memory == nullptr) - return nullptr; - } - - // Use placement-new to initialize header - new(memory) tHeader(inUseList, 1); - inUseList = memory; - - unsigned char* ret = reinterpret_cast(inUseList) + headerSkip; - currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask; - - return initializeAllocation(inUseList, ret, numBytes); -} - -// -// Check all allocations in a list for damage by calling check on each. -// -void TAllocation::checkAllocList() const -{ - for (const TAllocation* alloc = this; alloc != nullptr; alloc = alloc->prevAlloc) - alloc->check(); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/RemoveTree.cpp b/3rdparty/glslang/glslang/MachineIndependent/RemoveTree.cpp deleted file mode 100644 index 1d33bfd2..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/RemoveTree.cpp +++ /dev/null @@ -1,118 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/intermediate.h" -#include "RemoveTree.h" - -namespace glslang { - -// -// Code to recursively delete the intermediate tree. -// -struct TRemoveTraverser : TIntermTraverser { - TRemoveTraverser() : TIntermTraverser(false, false, true, false) {} - - virtual void visitSymbol(TIntermSymbol* node) - { - delete node; - } - - virtual bool visitBinary(TVisit /* visit*/ , TIntermBinary* node) - { - delete node; - - return true; - } - - virtual bool visitUnary(TVisit /* visit */, TIntermUnary* node) - { - delete node; - - return true; - } - - virtual bool visitAggregate(TVisit /* visit*/ , TIntermAggregate* node) - { - delete node; - - return true; - } - - virtual bool visitSelection(TVisit /* visit*/ , TIntermSelection* node) - { - delete node; - - return true; - } - - virtual bool visitSwitch(TVisit /* visit*/ , TIntermSwitch* node) - { - delete node; - - return true; - } - - virtual void visitConstantUnion(TIntermConstantUnion* node) - { - delete node; - } - - virtual bool visitLoop(TVisit /* visit*/ , TIntermLoop* node) - { - delete node; - - return true; - } - - virtual bool visitBranch(TVisit /* visit*/ , TIntermBranch* node) - { - delete node; - - return true; - } -}; - -// -// Entry point. -// -void RemoveAllTreeNodes(TIntermNode* root) -{ - TRemoveTraverser it; - - root->traverse(&it); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/RemoveTree.h b/3rdparty/glslang/glslang/MachineIndependent/RemoveTree.h deleted file mode 100644 index 1ed01562..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/RemoveTree.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#pragma once - -namespace glslang { - -void RemoveAllTreeNodes(TIntermNode*); - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/Scan.cpp b/3rdparty/glslang/glslang/MachineIndependent/Scan.cpp deleted file mode 100644 index 44546596..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/Scan.cpp +++ /dev/null @@ -1,2005 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Copyright (C) 2020 Google, Inc. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// GLSL scanning, leveraging the scanning done by the preprocessor. -// - -#include -#include -#include - -#include "../Include/Types.h" -#include "SymbolTable.h" -#include "ParseHelper.h" -#include "attribute.h" -#include "glslang_tab.cpp.h" -#include "ScanContext.h" -#include "Scan.h" - -// preprocessor includes -#include "preprocessor/PpContext.h" -#include "preprocessor/PpTokens.h" - -// Required to avoid missing prototype warnings for some compilers -int yylex(YYSTYPE*, glslang::TParseContext&); - -namespace glslang { - -// read past any white space -void TInputScanner::consumeWhiteSpace(bool& foundNonSpaceTab) -{ - int c = peek(); // don't accidentally consume anything other than whitespace - while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { - if (c == '\r' || c == '\n') - foundNonSpaceTab = true; - get(); - c = peek(); - } -} - -// return true if a comment was actually consumed -bool TInputScanner::consumeComment() -{ - if (peek() != '/') - return false; - - get(); // consume the '/' - int c = peek(); - if (c == '/') { - - // a '//' style comment - get(); // consume the second '/' - c = get(); - do { - while (c != EndOfInput && c != '\\' && c != '\r' && c != '\n') - c = get(); - - if (c == EndOfInput || c == '\r' || c == '\n') { - while (c == '\r' || c == '\n') - c = get(); - - // we reached the end of the comment - break; - } else { - // it's a '\', so we need to keep going, after skipping what's escaped - - // read the skipped character - c = get(); - - // if it's a two-character newline, skip both characters - if (c == '\r' && peek() == '\n') - get(); - c = get(); - } - } while (true); - - // put back the last non-comment character - if (c != EndOfInput) - unget(); - - return true; - } else if (c == '*') { - - // a '/*' style comment - get(); // consume the '*' - c = get(); - do { - while (c != EndOfInput && c != '*') - c = get(); - if (c == '*') { - c = get(); - if (c == '/') - break; // end of comment - // not end of comment - } else // end of input - break; - } while (true); - - return true; - } else { - // it's not a comment, put the '/' back - unget(); - - return false; - } -} - -// skip whitespace, then skip a comment, rinse, repeat -void TInputScanner::consumeWhitespaceComment(bool& foundNonSpaceTab) -{ - do { - consumeWhiteSpace(foundNonSpaceTab); - - // if not starting a comment now, then done - int c = peek(); - if (c != '/' || c == EndOfInput) - return; - - // skip potential comment - foundNonSpaceTab = true; - if (! consumeComment()) - return; - - } while (true); -} - -// Returns true if there was non-white space (e.g., a comment, newline) before the #version -// or no #version was found; otherwise, returns false. There is no error case, it always -// succeeds, but will leave version == 0 if no #version was found. -// -// Sets notFirstToken based on whether tokens (beyond white space and comments) -// appeared before the #version. -// -// N.B. does not attempt to leave input in any particular known state. The assumption -// is that scanning will start anew, following the rules for the chosen version/profile, -// and with a corresponding parsing context. -// -bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstToken) -{ - // This function doesn't have to get all the semantics correct, - // just find the #version if there is a correct one present. - // The preprocessor will have the responsibility of getting all the semantics right. - - bool versionNotFirst = false; // means not first WRT comments and white space, nothing more - notFirstToken = false; // means not first WRT to real tokens - version = 0; // means not found - profile = ENoProfile; - - bool foundNonSpaceTab = false; - bool lookingInMiddle = false; - int c; - do { - if (lookingInMiddle) { - notFirstToken = true; - // make forward progress by finishing off the current line plus extra new lines - if (peek() != '\n' && peek() != '\r') { - do { - c = get(); - } while (c != EndOfInput && c != '\n' && c != '\r'); - } - while (peek() == '\n' || peek() == '\r') - get(); - if (peek() == EndOfInput) - return true; - } - lookingInMiddle = true; - - // Nominal start, skipping the desktop allowed comments and white space, but tracking if - // something else was found for ES: - consumeWhitespaceComment(foundNonSpaceTab); - if (foundNonSpaceTab) - versionNotFirst = true; - - // "#" - if (get() != '#') { - versionNotFirst = true; - continue; - } - - // whitespace - do { - c = get(); - } while (c == ' ' || c == '\t'); - - // "version" - if ( c != 'v' || - get() != 'e' || - get() != 'r' || - get() != 's' || - get() != 'i' || - get() != 'o' || - get() != 'n') { - versionNotFirst = true; - continue; - } - - // whitespace - do { - c = get(); - } while (c == ' ' || c == '\t'); - - // version number - while (c >= '0' && c <= '9') { - version = 10 * version + (c - '0'); - c = get(); - } - if (version == 0) { - versionNotFirst = true; - continue; - } - - // whitespace - while (c == ' ' || c == '\t') - c = get(); - - // profile - const int maxProfileLength = 13; // not including any 0 - char profileString[maxProfileLength]; - int profileLength; - for (profileLength = 0; profileLength < maxProfileLength; ++profileLength) { - if (c == EndOfInput || c == ' ' || c == '\t' || c == '\n' || c == '\r') - break; - profileString[profileLength] = (char)c; - c = get(); - } - if (c != EndOfInput && c != ' ' && c != '\t' && c != '\n' && c != '\r') { - versionNotFirst = true; - continue; - } - - if (profileLength == 2 && strncmp(profileString, "es", profileLength) == 0) - profile = EEsProfile; - else if (profileLength == 4 && strncmp(profileString, "core", profileLength) == 0) - profile = ECoreProfile; - else if (profileLength == 13 && strncmp(profileString, "compatibility", profileLength) == 0) - profile = ECompatibilityProfile; - - return versionNotFirst; - } while (true); -} - -// Fill this in when doing glslang-level scanning, to hand back to the parser. -class TParserToken { -public: - explicit TParserToken(YYSTYPE& b) : sType(b) { } - - YYSTYPE& sType; -protected: - TParserToken(TParserToken&); - TParserToken& operator=(TParserToken&); -}; - -} // end namespace glslang - -// This is the function the glslang parser (i.e., bison) calls to get its next token -int yylex(YYSTYPE* glslangTokenDesc, glslang::TParseContext& parseContext) -{ - glslang::TParserToken token(*glslangTokenDesc); - - return parseContext.getScanContext()->tokenize(parseContext.getPpContext(), token); -} - -namespace { - -struct str_eq -{ - bool operator()(const char* lhs, const char* rhs) const - { - return strcmp(lhs, rhs) == 0; - } -}; - -struct str_hash -{ - size_t operator()(const char* str) const - { - // djb2 - unsigned long hash = 5381; - int c; - - while ((c = *str++) != 0) - hash = ((hash << 5) + hash) + c; - - return hash; - } -}; - -// A single global usable by all threads, by all versions, by all languages. -// After a single process-level initialization, this is read only and thread safe -std::unordered_map* KeywordMap = nullptr; -std::unordered_set* ReservedSet = nullptr; - -} - -namespace glslang { - -void TScanContext::fillInKeywordMap() -{ - if (KeywordMap != nullptr) { - // this is really an error, as this should called only once per process - // but, the only risk is if two threads called simultaneously - return; - } - KeywordMap = new std::unordered_map; - - (*KeywordMap)["const"] = CONST; - (*KeywordMap)["uniform"] = UNIFORM; - (*KeywordMap)["tileImageEXT"] = TILEIMAGEEXT; - (*KeywordMap)["buffer"] = BUFFER; - (*KeywordMap)["in"] = IN; - (*KeywordMap)["out"] = OUT; - (*KeywordMap)["smooth"] = SMOOTH; - (*KeywordMap)["flat"] = FLAT; - (*KeywordMap)["centroid"] = CENTROID; - (*KeywordMap)["invariant"] = INVARIANT; - (*KeywordMap)["packed"] = PACKED; - (*KeywordMap)["resource"] = RESOURCE; - (*KeywordMap)["inout"] = INOUT; - (*KeywordMap)["struct"] = STRUCT; - (*KeywordMap)["break"] = BREAK; - (*KeywordMap)["continue"] = CONTINUE; - (*KeywordMap)["do"] = DO; - (*KeywordMap)["for"] = FOR; - (*KeywordMap)["while"] = WHILE; - (*KeywordMap)["switch"] = SWITCH; - (*KeywordMap)["case"] = CASE; - (*KeywordMap)["default"] = DEFAULT; - (*KeywordMap)["if"] = IF; - (*KeywordMap)["else"] = ELSE; - (*KeywordMap)["discard"] = DISCARD; - (*KeywordMap)["terminateInvocation"] = TERMINATE_INVOCATION; - (*KeywordMap)["terminateRayEXT"] = TERMINATE_RAY; - (*KeywordMap)["ignoreIntersectionEXT"] = IGNORE_INTERSECTION; - (*KeywordMap)["return"] = RETURN; - (*KeywordMap)["void"] = VOID; - (*KeywordMap)["bool"] = BOOL; - (*KeywordMap)["float"] = FLOAT; - (*KeywordMap)["int"] = INT; - (*KeywordMap)["bvec2"] = BVEC2; - (*KeywordMap)["bvec3"] = BVEC3; - (*KeywordMap)["bvec4"] = BVEC4; - (*KeywordMap)["vec2"] = VEC2; - (*KeywordMap)["vec3"] = VEC3; - (*KeywordMap)["vec4"] = VEC4; - (*KeywordMap)["ivec2"] = IVEC2; - (*KeywordMap)["ivec3"] = IVEC3; - (*KeywordMap)["ivec4"] = IVEC4; - (*KeywordMap)["mat2"] = MAT2; - (*KeywordMap)["mat3"] = MAT3; - (*KeywordMap)["mat4"] = MAT4; - (*KeywordMap)["true"] = BOOLCONSTANT; - (*KeywordMap)["false"] = BOOLCONSTANT; - (*KeywordMap)["layout"] = LAYOUT; - (*KeywordMap)["shared"] = SHARED; - (*KeywordMap)["highp"] = HIGH_PRECISION; - (*KeywordMap)["mediump"] = MEDIUM_PRECISION; - (*KeywordMap)["lowp"] = LOW_PRECISION; - (*KeywordMap)["superp"] = SUPERP; - (*KeywordMap)["precision"] = PRECISION; - (*KeywordMap)["mat2x2"] = MAT2X2; - (*KeywordMap)["mat2x3"] = MAT2X3; - (*KeywordMap)["mat2x4"] = MAT2X4; - (*KeywordMap)["mat3x2"] = MAT3X2; - (*KeywordMap)["mat3x3"] = MAT3X3; - (*KeywordMap)["mat3x4"] = MAT3X4; - (*KeywordMap)["mat4x2"] = MAT4X2; - (*KeywordMap)["mat4x3"] = MAT4X3; - (*KeywordMap)["mat4x4"] = MAT4X4; - (*KeywordMap)["uint"] = UINT; - (*KeywordMap)["uvec2"] = UVEC2; - (*KeywordMap)["uvec3"] = UVEC3; - (*KeywordMap)["uvec4"] = UVEC4; - - (*KeywordMap)["nonuniformEXT"] = NONUNIFORM; - (*KeywordMap)["demote"] = DEMOTE; - (*KeywordMap)["attribute"] = ATTRIBUTE; - (*KeywordMap)["varying"] = VARYING; - (*KeywordMap)["noperspective"] = NOPERSPECTIVE; - (*KeywordMap)["coherent"] = COHERENT; - (*KeywordMap)["devicecoherent"] = DEVICECOHERENT; - (*KeywordMap)["queuefamilycoherent"] = QUEUEFAMILYCOHERENT; - (*KeywordMap)["workgroupcoherent"] = WORKGROUPCOHERENT; - (*KeywordMap)["subgroupcoherent"] = SUBGROUPCOHERENT; - (*KeywordMap)["shadercallcoherent"] = SHADERCALLCOHERENT; - (*KeywordMap)["nonprivate"] = NONPRIVATE; - (*KeywordMap)["restrict"] = RESTRICT; - (*KeywordMap)["readonly"] = READONLY; - (*KeywordMap)["writeonly"] = WRITEONLY; - (*KeywordMap)["atomic_uint"] = ATOMIC_UINT; - (*KeywordMap)["volatile"] = VOLATILE; - (*KeywordMap)["patch"] = PATCH; - (*KeywordMap)["sample"] = SAMPLE; - (*KeywordMap)["subroutine"] = SUBROUTINE; - (*KeywordMap)["dmat2"] = DMAT2; - (*KeywordMap)["dmat3"] = DMAT3; - (*KeywordMap)["dmat4"] = DMAT4; - (*KeywordMap)["dmat2x2"] = DMAT2X2; - (*KeywordMap)["dmat2x3"] = DMAT2X3; - (*KeywordMap)["dmat2x4"] = DMAT2X4; - (*KeywordMap)["dmat3x2"] = DMAT3X2; - (*KeywordMap)["dmat3x3"] = DMAT3X3; - (*KeywordMap)["dmat3x4"] = DMAT3X4; - (*KeywordMap)["dmat4x2"] = DMAT4X2; - (*KeywordMap)["dmat4x3"] = DMAT4X3; - (*KeywordMap)["dmat4x4"] = DMAT4X4; - (*KeywordMap)["image1D"] = IMAGE1D; - (*KeywordMap)["iimage1D"] = IIMAGE1D; - (*KeywordMap)["uimage1D"] = UIMAGE1D; - (*KeywordMap)["image2D"] = IMAGE2D; - (*KeywordMap)["iimage2D"] = IIMAGE2D; - (*KeywordMap)["uimage2D"] = UIMAGE2D; - (*KeywordMap)["image3D"] = IMAGE3D; - (*KeywordMap)["iimage3D"] = IIMAGE3D; - (*KeywordMap)["uimage3D"] = UIMAGE3D; - (*KeywordMap)["image2DRect"] = IMAGE2DRECT; - (*KeywordMap)["iimage2DRect"] = IIMAGE2DRECT; - (*KeywordMap)["uimage2DRect"] = UIMAGE2DRECT; - (*KeywordMap)["imageCube"] = IMAGECUBE; - (*KeywordMap)["iimageCube"] = IIMAGECUBE; - (*KeywordMap)["uimageCube"] = UIMAGECUBE; - (*KeywordMap)["imageBuffer"] = IMAGEBUFFER; - (*KeywordMap)["iimageBuffer"] = IIMAGEBUFFER; - (*KeywordMap)["uimageBuffer"] = UIMAGEBUFFER; - (*KeywordMap)["image1DArray"] = IMAGE1DARRAY; - (*KeywordMap)["iimage1DArray"] = IIMAGE1DARRAY; - (*KeywordMap)["uimage1DArray"] = UIMAGE1DARRAY; - (*KeywordMap)["image2DArray"] = IMAGE2DARRAY; - (*KeywordMap)["iimage2DArray"] = IIMAGE2DARRAY; - (*KeywordMap)["uimage2DArray"] = UIMAGE2DARRAY; - (*KeywordMap)["imageCubeArray"] = IMAGECUBEARRAY; - (*KeywordMap)["iimageCubeArray"] = IIMAGECUBEARRAY; - (*KeywordMap)["uimageCubeArray"] = UIMAGECUBEARRAY; - (*KeywordMap)["image2DMS"] = IMAGE2DMS; - (*KeywordMap)["iimage2DMS"] = IIMAGE2DMS; - (*KeywordMap)["uimage2DMS"] = UIMAGE2DMS; - (*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY; - (*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY; - (*KeywordMap)["uimage2DMSArray"] = UIMAGE2DMSARRAY; - (*KeywordMap)["i64image1D"] = I64IMAGE1D; - (*KeywordMap)["u64image1D"] = U64IMAGE1D; - (*KeywordMap)["i64image2D"] = I64IMAGE2D; - (*KeywordMap)["u64image2D"] = U64IMAGE2D; - (*KeywordMap)["i64image3D"] = I64IMAGE3D; - (*KeywordMap)["u64image3D"] = U64IMAGE3D; - (*KeywordMap)["i64image2DRect"] = I64IMAGE2DRECT; - (*KeywordMap)["u64image2DRect"] = U64IMAGE2DRECT; - (*KeywordMap)["i64imageCube"] = I64IMAGECUBE; - (*KeywordMap)["u64imageCube"] = U64IMAGECUBE; - (*KeywordMap)["i64imageBuffer"] = I64IMAGEBUFFER; - (*KeywordMap)["u64imageBuffer"] = U64IMAGEBUFFER; - (*KeywordMap)["i64image1DArray"] = I64IMAGE1DARRAY; - (*KeywordMap)["u64image1DArray"] = U64IMAGE1DARRAY; - (*KeywordMap)["i64image2DArray"] = I64IMAGE2DARRAY; - (*KeywordMap)["u64image2DArray"] = U64IMAGE2DARRAY; - (*KeywordMap)["i64imageCubeArray"] = I64IMAGECUBEARRAY; - (*KeywordMap)["u64imageCubeArray"] = U64IMAGECUBEARRAY; - (*KeywordMap)["i64image2DMS"] = I64IMAGE2DMS; - (*KeywordMap)["u64image2DMS"] = U64IMAGE2DMS; - (*KeywordMap)["i64image2DMSArray"] = I64IMAGE2DMSARRAY; - (*KeywordMap)["u64image2DMSArray"] = U64IMAGE2DMSARRAY; - (*KeywordMap)["double"] = DOUBLE; - (*KeywordMap)["dvec2"] = DVEC2; - (*KeywordMap)["dvec3"] = DVEC3; - (*KeywordMap)["dvec4"] = DVEC4; - (*KeywordMap)["int64_t"] = INT64_T; - (*KeywordMap)["uint64_t"] = UINT64_T; - (*KeywordMap)["i64vec2"] = I64VEC2; - (*KeywordMap)["i64vec3"] = I64VEC3; - (*KeywordMap)["i64vec4"] = I64VEC4; - (*KeywordMap)["u64vec2"] = U64VEC2; - (*KeywordMap)["u64vec3"] = U64VEC3; - (*KeywordMap)["u64vec4"] = U64VEC4; - - // GL_EXT_shader_explicit_arithmetic_types - (*KeywordMap)["int8_t"] = INT8_T; - (*KeywordMap)["i8vec2"] = I8VEC2; - (*KeywordMap)["i8vec3"] = I8VEC3; - (*KeywordMap)["i8vec4"] = I8VEC4; - (*KeywordMap)["uint8_t"] = UINT8_T; - (*KeywordMap)["u8vec2"] = U8VEC2; - (*KeywordMap)["u8vec3"] = U8VEC3; - (*KeywordMap)["u8vec4"] = U8VEC4; - - (*KeywordMap)["int16_t"] = INT16_T; - (*KeywordMap)["i16vec2"] = I16VEC2; - (*KeywordMap)["i16vec3"] = I16VEC3; - (*KeywordMap)["i16vec4"] = I16VEC4; - (*KeywordMap)["uint16_t"] = UINT16_T; - (*KeywordMap)["u16vec2"] = U16VEC2; - (*KeywordMap)["u16vec3"] = U16VEC3; - (*KeywordMap)["u16vec4"] = U16VEC4; - - (*KeywordMap)["int32_t"] = INT32_T; - (*KeywordMap)["i32vec2"] = I32VEC2; - (*KeywordMap)["i32vec3"] = I32VEC3; - (*KeywordMap)["i32vec4"] = I32VEC4; - (*KeywordMap)["uint32_t"] = UINT32_T; - (*KeywordMap)["u32vec2"] = U32VEC2; - (*KeywordMap)["u32vec3"] = U32VEC3; - (*KeywordMap)["u32vec4"] = U32VEC4; - - (*KeywordMap)["float16_t"] = FLOAT16_T; - (*KeywordMap)["f16vec2"] = F16VEC2; - (*KeywordMap)["f16vec3"] = F16VEC3; - (*KeywordMap)["f16vec4"] = F16VEC4; - (*KeywordMap)["f16mat2"] = F16MAT2; - (*KeywordMap)["f16mat3"] = F16MAT3; - (*KeywordMap)["f16mat4"] = F16MAT4; - (*KeywordMap)["f16mat2x2"] = F16MAT2X2; - (*KeywordMap)["f16mat2x3"] = F16MAT2X3; - (*KeywordMap)["f16mat2x4"] = F16MAT2X4; - (*KeywordMap)["f16mat3x2"] = F16MAT3X2; - (*KeywordMap)["f16mat3x3"] = F16MAT3X3; - (*KeywordMap)["f16mat3x4"] = F16MAT3X4; - (*KeywordMap)["f16mat4x2"] = F16MAT4X2; - (*KeywordMap)["f16mat4x3"] = F16MAT4X3; - (*KeywordMap)["f16mat4x4"] = F16MAT4X4; - - (*KeywordMap)["float32_t"] = FLOAT32_T; - (*KeywordMap)["f32vec2"] = F32VEC2; - (*KeywordMap)["f32vec3"] = F32VEC3; - (*KeywordMap)["f32vec4"] = F32VEC4; - (*KeywordMap)["f32mat2"] = F32MAT2; - (*KeywordMap)["f32mat3"] = F32MAT3; - (*KeywordMap)["f32mat4"] = F32MAT4; - (*KeywordMap)["f32mat2x2"] = F32MAT2X2; - (*KeywordMap)["f32mat2x3"] = F32MAT2X3; - (*KeywordMap)["f32mat2x4"] = F32MAT2X4; - (*KeywordMap)["f32mat3x2"] = F32MAT3X2; - (*KeywordMap)["f32mat3x3"] = F32MAT3X3; - (*KeywordMap)["f32mat3x4"] = F32MAT3X4; - (*KeywordMap)["f32mat4x2"] = F32MAT4X2; - (*KeywordMap)["f32mat4x3"] = F32MAT4X3; - (*KeywordMap)["f32mat4x4"] = F32MAT4X4; - (*KeywordMap)["float64_t"] = FLOAT64_T; - (*KeywordMap)["f64vec2"] = F64VEC2; - (*KeywordMap)["f64vec3"] = F64VEC3; - (*KeywordMap)["f64vec4"] = F64VEC4; - (*KeywordMap)["f64mat2"] = F64MAT2; - (*KeywordMap)["f64mat3"] = F64MAT3; - (*KeywordMap)["f64mat4"] = F64MAT4; - (*KeywordMap)["f64mat2x2"] = F64MAT2X2; - (*KeywordMap)["f64mat2x3"] = F64MAT2X3; - (*KeywordMap)["f64mat2x4"] = F64MAT2X4; - (*KeywordMap)["f64mat3x2"] = F64MAT3X2; - (*KeywordMap)["f64mat3x3"] = F64MAT3X3; - (*KeywordMap)["f64mat3x4"] = F64MAT3X4; - (*KeywordMap)["f64mat4x2"] = F64MAT4X2; - (*KeywordMap)["f64mat4x3"] = F64MAT4X3; - (*KeywordMap)["f64mat4x4"] = F64MAT4X4; - - // GL_EXT_spirv_intrinsics - (*KeywordMap)["spirv_instruction"] = SPIRV_INSTRUCTION; - (*KeywordMap)["spirv_execution_mode"] = SPIRV_EXECUTION_MODE; - (*KeywordMap)["spirv_execution_mode_id"] = SPIRV_EXECUTION_MODE_ID; - (*KeywordMap)["spirv_decorate"] = SPIRV_DECORATE; - (*KeywordMap)["spirv_decorate_id"] = SPIRV_DECORATE_ID; - (*KeywordMap)["spirv_decorate_string"] = SPIRV_DECORATE_STRING; - (*KeywordMap)["spirv_type"] = SPIRV_TYPE; - (*KeywordMap)["spirv_storage_class"] = SPIRV_STORAGE_CLASS; - (*KeywordMap)["spirv_by_reference"] = SPIRV_BY_REFERENCE; - (*KeywordMap)["spirv_literal"] = SPIRV_LITERAL; - - (*KeywordMap)["sampler2D"] = SAMPLER2D; - (*KeywordMap)["samplerCube"] = SAMPLERCUBE; - (*KeywordMap)["samplerCubeShadow"] = SAMPLERCUBESHADOW; - (*KeywordMap)["sampler2DArray"] = SAMPLER2DARRAY; - (*KeywordMap)["sampler2DArrayShadow"] = SAMPLER2DARRAYSHADOW; - (*KeywordMap)["isampler2D"] = ISAMPLER2D; - (*KeywordMap)["isampler3D"] = ISAMPLER3D; - (*KeywordMap)["isamplerCube"] = ISAMPLERCUBE; - (*KeywordMap)["isampler2DArray"] = ISAMPLER2DARRAY; - (*KeywordMap)["usampler2D"] = USAMPLER2D; - (*KeywordMap)["usampler3D"] = USAMPLER3D; - (*KeywordMap)["usamplerCube"] = USAMPLERCUBE; - (*KeywordMap)["usampler2DArray"] = USAMPLER2DARRAY; - (*KeywordMap)["sampler3D"] = SAMPLER3D; - (*KeywordMap)["sampler2DShadow"] = SAMPLER2DSHADOW; - - (*KeywordMap)["texture2D"] = TEXTURE2D; - (*KeywordMap)["textureCube"] = TEXTURECUBE; - (*KeywordMap)["texture2DArray"] = TEXTURE2DARRAY; - (*KeywordMap)["itexture2D"] = ITEXTURE2D; - (*KeywordMap)["itexture3D"] = ITEXTURE3D; - (*KeywordMap)["itextureCube"] = ITEXTURECUBE; - (*KeywordMap)["itexture2DArray"] = ITEXTURE2DARRAY; - (*KeywordMap)["utexture2D"] = UTEXTURE2D; - (*KeywordMap)["utexture3D"] = UTEXTURE3D; - (*KeywordMap)["utextureCube"] = UTEXTURECUBE; - (*KeywordMap)["utexture2DArray"] = UTEXTURE2DARRAY; - (*KeywordMap)["texture3D"] = TEXTURE3D; - - (*KeywordMap)["sampler"] = SAMPLER; - (*KeywordMap)["samplerShadow"] = SAMPLERSHADOW; - - (*KeywordMap)["textureCubeArray"] = TEXTURECUBEARRAY; - (*KeywordMap)["itextureCubeArray"] = ITEXTURECUBEARRAY; - (*KeywordMap)["utextureCubeArray"] = UTEXTURECUBEARRAY; - (*KeywordMap)["samplerCubeArray"] = SAMPLERCUBEARRAY; - (*KeywordMap)["samplerCubeArrayShadow"] = SAMPLERCUBEARRAYSHADOW; - (*KeywordMap)["isamplerCubeArray"] = ISAMPLERCUBEARRAY; - (*KeywordMap)["usamplerCubeArray"] = USAMPLERCUBEARRAY; - (*KeywordMap)["sampler1DArrayShadow"] = SAMPLER1DARRAYSHADOW; - (*KeywordMap)["isampler1DArray"] = ISAMPLER1DARRAY; - (*KeywordMap)["usampler1D"] = USAMPLER1D; - (*KeywordMap)["isampler1D"] = ISAMPLER1D; - (*KeywordMap)["usampler1DArray"] = USAMPLER1DARRAY; - (*KeywordMap)["samplerBuffer"] = SAMPLERBUFFER; - (*KeywordMap)["isampler2DRect"] = ISAMPLER2DRECT; - (*KeywordMap)["usampler2DRect"] = USAMPLER2DRECT; - (*KeywordMap)["isamplerBuffer"] = ISAMPLERBUFFER; - (*KeywordMap)["usamplerBuffer"] = USAMPLERBUFFER; - (*KeywordMap)["sampler2DMS"] = SAMPLER2DMS; - (*KeywordMap)["isampler2DMS"] = ISAMPLER2DMS; - (*KeywordMap)["usampler2DMS"] = USAMPLER2DMS; - (*KeywordMap)["sampler2DMSArray"] = SAMPLER2DMSARRAY; - (*KeywordMap)["isampler2DMSArray"] = ISAMPLER2DMSARRAY; - (*KeywordMap)["usampler2DMSArray"] = USAMPLER2DMSARRAY; - (*KeywordMap)["sampler1D"] = SAMPLER1D; - (*KeywordMap)["sampler1DShadow"] = SAMPLER1DSHADOW; - (*KeywordMap)["sampler2DRect"] = SAMPLER2DRECT; - (*KeywordMap)["sampler2DRectShadow"] = SAMPLER2DRECTSHADOW; - (*KeywordMap)["sampler1DArray"] = SAMPLER1DARRAY; - - (*KeywordMap)["samplerExternalOES"] = SAMPLEREXTERNALOES; // GL_OES_EGL_image_external - - (*KeywordMap)["__samplerExternal2DY2YEXT"] = SAMPLEREXTERNAL2DY2YEXT; // GL_EXT_YUV_target - - (*KeywordMap)["itexture1DArray"] = ITEXTURE1DARRAY; - (*KeywordMap)["utexture1D"] = UTEXTURE1D; - (*KeywordMap)["itexture1D"] = ITEXTURE1D; - (*KeywordMap)["utexture1DArray"] = UTEXTURE1DARRAY; - (*KeywordMap)["textureBuffer"] = TEXTUREBUFFER; - (*KeywordMap)["itexture2DRect"] = ITEXTURE2DRECT; - (*KeywordMap)["utexture2DRect"] = UTEXTURE2DRECT; - (*KeywordMap)["itextureBuffer"] = ITEXTUREBUFFER; - (*KeywordMap)["utextureBuffer"] = UTEXTUREBUFFER; - (*KeywordMap)["texture2DMS"] = TEXTURE2DMS; - (*KeywordMap)["itexture2DMS"] = ITEXTURE2DMS; - (*KeywordMap)["utexture2DMS"] = UTEXTURE2DMS; - (*KeywordMap)["texture2DMSArray"] = TEXTURE2DMSARRAY; - (*KeywordMap)["itexture2DMSArray"] = ITEXTURE2DMSARRAY; - (*KeywordMap)["utexture2DMSArray"] = UTEXTURE2DMSARRAY; - (*KeywordMap)["texture1D"] = TEXTURE1D; - (*KeywordMap)["texture2DRect"] = TEXTURE2DRECT; - (*KeywordMap)["texture1DArray"] = TEXTURE1DARRAY; - - (*KeywordMap)["attachmentEXT"] = ATTACHMENTEXT; - (*KeywordMap)["iattachmentEXT"] = IATTACHMENTEXT; - (*KeywordMap)["uattachmentEXT"] = UATTACHMENTEXT; - - (*KeywordMap)["subpassInput"] = SUBPASSINPUT; - (*KeywordMap)["subpassInputMS"] = SUBPASSINPUTMS; - (*KeywordMap)["isubpassInput"] = ISUBPASSINPUT; - (*KeywordMap)["isubpassInputMS"] = ISUBPASSINPUTMS; - (*KeywordMap)["usubpassInput"] = USUBPASSINPUT; - (*KeywordMap)["usubpassInputMS"] = USUBPASSINPUTMS; - - (*KeywordMap)["f16sampler1D"] = F16SAMPLER1D; - (*KeywordMap)["f16sampler2D"] = F16SAMPLER2D; - (*KeywordMap)["f16sampler3D"] = F16SAMPLER3D; - (*KeywordMap)["f16sampler2DRect"] = F16SAMPLER2DRECT; - (*KeywordMap)["f16samplerCube"] = F16SAMPLERCUBE; - (*KeywordMap)["f16sampler1DArray"] = F16SAMPLER1DARRAY; - (*KeywordMap)["f16sampler2DArray"] = F16SAMPLER2DARRAY; - (*KeywordMap)["f16samplerCubeArray"] = F16SAMPLERCUBEARRAY; - (*KeywordMap)["f16samplerBuffer"] = F16SAMPLERBUFFER; - (*KeywordMap)["f16sampler2DMS"] = F16SAMPLER2DMS; - (*KeywordMap)["f16sampler2DMSArray"] = F16SAMPLER2DMSARRAY; - (*KeywordMap)["f16sampler1DShadow"] = F16SAMPLER1DSHADOW; - (*KeywordMap)["f16sampler2DShadow"] = F16SAMPLER2DSHADOW; - (*KeywordMap)["f16sampler2DRectShadow"] = F16SAMPLER2DRECTSHADOW; - (*KeywordMap)["f16samplerCubeShadow"] = F16SAMPLERCUBESHADOW; - (*KeywordMap)["f16sampler1DArrayShadow"] = F16SAMPLER1DARRAYSHADOW; - (*KeywordMap)["f16sampler2DArrayShadow"] = F16SAMPLER2DARRAYSHADOW; - (*KeywordMap)["f16samplerCubeArrayShadow"] = F16SAMPLERCUBEARRAYSHADOW; - - (*KeywordMap)["f16image1D"] = F16IMAGE1D; - (*KeywordMap)["f16image2D"] = F16IMAGE2D; - (*KeywordMap)["f16image3D"] = F16IMAGE3D; - (*KeywordMap)["f16image2DRect"] = F16IMAGE2DRECT; - (*KeywordMap)["f16imageCube"] = F16IMAGECUBE; - (*KeywordMap)["f16image1DArray"] = F16IMAGE1DARRAY; - (*KeywordMap)["f16image2DArray"] = F16IMAGE2DARRAY; - (*KeywordMap)["f16imageCubeArray"] = F16IMAGECUBEARRAY; - (*KeywordMap)["f16imageBuffer"] = F16IMAGEBUFFER; - (*KeywordMap)["f16image2DMS"] = F16IMAGE2DMS; - (*KeywordMap)["f16image2DMSArray"] = F16IMAGE2DMSARRAY; - - (*KeywordMap)["f16texture1D"] = F16TEXTURE1D; - (*KeywordMap)["f16texture2D"] = F16TEXTURE2D; - (*KeywordMap)["f16texture3D"] = F16TEXTURE3D; - (*KeywordMap)["f16texture2DRect"] = F16TEXTURE2DRECT; - (*KeywordMap)["f16textureCube"] = F16TEXTURECUBE; - (*KeywordMap)["f16texture1DArray"] = F16TEXTURE1DARRAY; - (*KeywordMap)["f16texture2DArray"] = F16TEXTURE2DARRAY; - (*KeywordMap)["f16textureCubeArray"] = F16TEXTURECUBEARRAY; - (*KeywordMap)["f16textureBuffer"] = F16TEXTUREBUFFER; - (*KeywordMap)["f16texture2DMS"] = F16TEXTURE2DMS; - (*KeywordMap)["f16texture2DMSArray"] = F16TEXTURE2DMSARRAY; - - (*KeywordMap)["f16subpassInput"] = F16SUBPASSINPUT; - (*KeywordMap)["f16subpassInputMS"] = F16SUBPASSINPUTMS; - (*KeywordMap)["__explicitInterpAMD"] = EXPLICITINTERPAMD; - (*KeywordMap)["pervertexNV"] = PERVERTEXNV; - (*KeywordMap)["pervertexEXT"] = PERVERTEXEXT; - (*KeywordMap)["precise"] = PRECISE; - - (*KeywordMap)["rayPayloadNV"] = PAYLOADNV; - (*KeywordMap)["rayPayloadEXT"] = PAYLOADEXT; - (*KeywordMap)["rayPayloadInNV"] = PAYLOADINNV; - (*KeywordMap)["rayPayloadInEXT"] = PAYLOADINEXT; - (*KeywordMap)["hitAttributeNV"] = HITATTRNV; - (*KeywordMap)["hitAttributeEXT"] = HITATTREXT; - (*KeywordMap)["callableDataNV"] = CALLDATANV; - (*KeywordMap)["callableDataEXT"] = CALLDATAEXT; - (*KeywordMap)["callableDataInNV"] = CALLDATAINNV; - (*KeywordMap)["callableDataInEXT"] = CALLDATAINEXT; - (*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV; - (*KeywordMap)["accelerationStructureEXT"] = ACCSTRUCTEXT; - (*KeywordMap)["rayQueryEXT"] = RAYQUERYEXT; - (*KeywordMap)["perprimitiveNV"] = PERPRIMITIVENV; - (*KeywordMap)["perviewNV"] = PERVIEWNV; - (*KeywordMap)["taskNV"] = PERTASKNV; - (*KeywordMap)["perprimitiveEXT"] = PERPRIMITIVEEXT; - (*KeywordMap)["taskPayloadSharedEXT"] = TASKPAYLOADWORKGROUPEXT; - - (*KeywordMap)["fcoopmatNV"] = FCOOPMATNV; - (*KeywordMap)["icoopmatNV"] = ICOOPMATNV; - (*KeywordMap)["ucoopmatNV"] = UCOOPMATNV; - - (*KeywordMap)["coopmat"] = COOPMAT; - - (*KeywordMap)["hitObjectNV"] = HITOBJECTNV; - (*KeywordMap)["hitObjectAttributeNV"] = HITOBJECTATTRNV; - - ReservedSet = new std::unordered_set; - - ReservedSet->insert("common"); - ReservedSet->insert("partition"); - ReservedSet->insert("active"); - ReservedSet->insert("asm"); - ReservedSet->insert("class"); - ReservedSet->insert("union"); - ReservedSet->insert("enum"); - ReservedSet->insert("typedef"); - ReservedSet->insert("template"); - ReservedSet->insert("this"); - ReservedSet->insert("goto"); - ReservedSet->insert("inline"); - ReservedSet->insert("noinline"); - ReservedSet->insert("public"); - ReservedSet->insert("static"); - ReservedSet->insert("extern"); - ReservedSet->insert("external"); - ReservedSet->insert("interface"); - ReservedSet->insert("long"); - ReservedSet->insert("short"); - ReservedSet->insert("half"); - ReservedSet->insert("fixed"); - ReservedSet->insert("unsigned"); - ReservedSet->insert("input"); - ReservedSet->insert("output"); - ReservedSet->insert("hvec2"); - ReservedSet->insert("hvec3"); - ReservedSet->insert("hvec4"); - ReservedSet->insert("fvec2"); - ReservedSet->insert("fvec3"); - ReservedSet->insert("fvec4"); - ReservedSet->insert("sampler3DRect"); - ReservedSet->insert("filter"); - ReservedSet->insert("sizeof"); - ReservedSet->insert("cast"); - ReservedSet->insert("namespace"); - ReservedSet->insert("using"); -} - -void TScanContext::deleteKeywordMap() -{ - delete KeywordMap; - KeywordMap = nullptr; - delete ReservedSet; - ReservedSet = nullptr; -} - -// Called by yylex to get the next token. -// Returning 0 implies end of input. -int TScanContext::tokenize(TPpContext* pp, TParserToken& token) -{ - do { - parserToken = &token; - TPpToken ppToken; - int token = pp->tokenize(ppToken); - if (token == EndOfInput) - return 0; - - tokenText = ppToken.name; - loc = ppToken.loc; - parserToken->sType.lex.loc = loc; - switch (token) { - case ';': afterType = false; afterBuffer = false; return SEMICOLON; - case ',': afterType = false; return COMMA; - case ':': return COLON; - case '=': afterType = false; return EQUAL; - case '(': afterType = false; return LEFT_PAREN; - case ')': afterType = false; return RIGHT_PAREN; - case '.': field = true; return DOT; - case '!': return BANG; - case '-': return DASH; - case '~': return TILDE; - case '+': return PLUS; - case '*': return STAR; - case '/': return SLASH; - case '%': return PERCENT; - case '<': return LEFT_ANGLE; - case '>': return RIGHT_ANGLE; - case '|': return VERTICAL_BAR; - case '^': return CARET; - case '&': return AMPERSAND; - case '?': return QUESTION; - case '[': return LEFT_BRACKET; - case ']': return RIGHT_BRACKET; - case '{': afterStruct = false; afterBuffer = false; return LEFT_BRACE; - case '}': return RIGHT_BRACE; - case '\\': - parseContext.error(loc, "illegal use of escape character", "\\", ""); - break; - - case PPAtomAddAssign: return ADD_ASSIGN; - case PPAtomSubAssign: return SUB_ASSIGN; - case PPAtomMulAssign: return MUL_ASSIGN; - case PPAtomDivAssign: return DIV_ASSIGN; - case PPAtomModAssign: return MOD_ASSIGN; - - case PpAtomRight: return RIGHT_OP; - case PpAtomLeft: return LEFT_OP; - - case PpAtomRightAssign: return RIGHT_ASSIGN; - case PpAtomLeftAssign: return LEFT_ASSIGN; - case PpAtomAndAssign: return AND_ASSIGN; - case PpAtomOrAssign: return OR_ASSIGN; - case PpAtomXorAssign: return XOR_ASSIGN; - - case PpAtomAnd: return AND_OP; - case PpAtomOr: return OR_OP; - case PpAtomXor: return XOR_OP; - - case PpAtomEQ: return EQ_OP; - case PpAtomGE: return GE_OP; - case PpAtomNE: return NE_OP; - case PpAtomLE: return LE_OP; - - case PpAtomDecrement: return DEC_OP; - case PpAtomIncrement: return INC_OP; - - case PpAtomColonColon: - parseContext.error(loc, "not supported", "::", ""); - break; - - case PpAtomConstString: parserToken->sType.lex.string = NewPoolTString(tokenText); return STRING_LITERAL; - case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT; - case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT; - case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT; - case PpAtomConstInt16: parserToken->sType.lex.i = ppToken.ival; return INT16CONSTANT; - case PpAtomConstUint16: parserToken->sType.lex.i = ppToken.ival; return UINT16CONSTANT; - case PpAtomConstInt64: parserToken->sType.lex.i64 = ppToken.i64val; return INT64CONSTANT; - case PpAtomConstUint64: parserToken->sType.lex.i64 = ppToken.i64val; return UINT64CONSTANT; - case PpAtomConstDouble: parserToken->sType.lex.d = ppToken.dval; return DOUBLECONSTANT; - case PpAtomConstFloat16: parserToken->sType.lex.d = ppToken.dval; return FLOAT16CONSTANT; - case PpAtomIdentifier: - { - int token = tokenizeIdentifier(); - field = false; - return token; - } - - case EndOfInput: return 0; - - default: - char buf[2]; - buf[0] = (char)token; - buf[1] = 0; - parseContext.error(loc, "unexpected token", buf, ""); - break; - } - } while (true); -} - -int TScanContext::tokenizeIdentifier() -{ - if (ReservedSet->find(tokenText) != ReservedSet->end()) - return reservedWord(); - - auto it = KeywordMap->find(tokenText); - if (it == KeywordMap->end()) { - // Should have an identifier of some sort - return identifierOrType(); - } - keyword = it->second; - - switch (keyword) { - case CONST: - case UNIFORM: - case TILEIMAGEEXT: - case IN: - case OUT: - case INOUT: - case BREAK: - case CONTINUE: - case DO: - case FOR: - case WHILE: - case IF: - case ELSE: - case DISCARD: - case RETURN: - case CASE: - return keyword; - - case TERMINATE_INVOCATION: - if (!parseContext.extensionTurnedOn(E_GL_EXT_terminate_invocation)) - return identifierOrType(); - return keyword; - - case TERMINATE_RAY: - case IGNORE_INTERSECTION: - if (!parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing)) - return identifierOrType(); - return keyword; - - case BUFFER: - afterBuffer = true; - if ((parseContext.isEsProfile() && parseContext.version < 310) || - (!parseContext.isEsProfile() && (parseContext.version < 430 && - !parseContext.extensionTurnedOn(E_GL_ARB_shader_storage_buffer_object)))) - return identifierOrType(); - return keyword; - - case STRUCT: - afterStruct = true; - return keyword; - - case SWITCH: - case DEFAULT: - if ((parseContext.isEsProfile() && parseContext.version < 300) || - (!parseContext.isEsProfile() && parseContext.version < 130)) - reservedWord(); - return keyword; - - case VOID: - case BOOL: - case FLOAT: - case INT: - case BVEC2: - case BVEC3: - case BVEC4: - case VEC2: - case VEC3: - case VEC4: - case IVEC2: - case IVEC3: - case IVEC4: - case MAT2: - case MAT3: - case MAT4: - case SAMPLER2D: - case SAMPLERCUBE: - afterType = true; - return keyword; - - case BOOLCONSTANT: - if (strcmp("true", tokenText) == 0) - parserToken->sType.lex.b = true; - else - parserToken->sType.lex.b = false; - return keyword; - - case SMOOTH: - if ((parseContext.isEsProfile() && parseContext.version < 300) || - (!parseContext.isEsProfile() && parseContext.version < 130)) - return identifierOrType(); - return keyword; - case FLAT: - if (parseContext.isEsProfile() && parseContext.version < 300) - reservedWord(); - else if (!parseContext.isEsProfile() && parseContext.version < 130) - return identifierOrType(); - return keyword; - case CENTROID: - if (parseContext.version < 120) - return identifierOrType(); - return keyword; - case INVARIANT: - if (!parseContext.isEsProfile() && parseContext.version < 120) - return identifierOrType(); - return keyword; - case PACKED: - if ((parseContext.isEsProfile() && parseContext.version < 300) || - (!parseContext.isEsProfile() && parseContext.version < 140)) - return reservedWord(); - return identifierOrType(); - - case RESOURCE: - { - bool reserved = (parseContext.isEsProfile() && parseContext.version >= 300) || - (!parseContext.isEsProfile() && parseContext.version >= 420); - return identifierOrReserved(reserved); - } - case SUPERP: - { - bool reserved = parseContext.isEsProfile() || parseContext.version >= 130; - return identifierOrReserved(reserved); - } - - case NOPERSPECTIVE: - if (parseContext.extensionTurnedOn(E_GL_NV_shader_noperspective_interpolation)) - return keyword; - return es30ReservedFromGLSL(130); - - case NONUNIFORM: - if (parseContext.extensionTurnedOn(E_GL_EXT_nonuniform_qualifier)) - return keyword; - else - return identifierOrType(); - case ATTRIBUTE: - case VARYING: - if (parseContext.isEsProfile() && parseContext.version >= 300) - reservedWord(); - return keyword; - case PAYLOADNV: - case PAYLOADINNV: - case HITATTRNV: - case CALLDATANV: - case CALLDATAINNV: - case ACCSTRUCTNV: - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_NV_ray_tracing)) - return keyword; - return identifierOrType(); - case ACCSTRUCTEXT: - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing) || - parseContext.extensionTurnedOn(E_GL_EXT_ray_query) || - parseContext.extensionTurnedOn(E_GL_NV_displacement_micromap)) - return keyword; - return identifierOrType(); - case PAYLOADEXT: - case PAYLOADINEXT: - case HITATTREXT: - case CALLDATAEXT: - case CALLDATAINEXT: - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_ray_tracing) || - parseContext.extensionTurnedOn(E_GL_EXT_ray_query)) - return keyword; - return identifierOrType(); - case RAYQUERYEXT: - if (parseContext.symbolTable.atBuiltInLevel() || - (!parseContext.isEsProfile() && parseContext.version >= 460 - && parseContext.extensionTurnedOn(E_GL_EXT_ray_query))) - return keyword; - return identifierOrType(); - case ATOMIC_UINT: - if ((parseContext.isEsProfile() && parseContext.version >= 310) || - parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters)) - return keyword; - return es30ReservedFromGLSL(420); - - case COHERENT: - case DEVICECOHERENT: - case QUEUEFAMILYCOHERENT: - case WORKGROUPCOHERENT: - case SUBGROUPCOHERENT: - case SHADERCALLCOHERENT: - case NONPRIVATE: - case RESTRICT: - case READONLY: - case WRITEONLY: - if (parseContext.isEsProfile() && parseContext.version >= 310) - return keyword; - return es30ReservedFromGLSL(parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store) ? 130 : 420); - case VOLATILE: - if (parseContext.isEsProfile() && parseContext.version >= 310) - return keyword; - if (! parseContext.symbolTable.atBuiltInLevel() && (parseContext.isEsProfile() || - (parseContext.version < 420 && ! parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store)))) - reservedWord(); - return keyword; - case PATCH: - if (parseContext.symbolTable.atBuiltInLevel() || - (parseContext.isEsProfile() && - (parseContext.version >= 320 || - parseContext.extensionsTurnedOn(Num_AEP_tessellation_shader, AEP_tessellation_shader))) || - (!parseContext.isEsProfile() && parseContext.extensionTurnedOn(E_GL_ARB_tessellation_shader))) - return keyword; - - return es30ReservedFromGLSL(400); - - case SAMPLE: - if ((parseContext.isEsProfile() && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(1, &E_GL_OES_shader_multisample_interpolation)) - return keyword; - return es30ReservedFromGLSL(400); - - case SUBROUTINE: - return es30ReservedFromGLSL(400); - - case SHARED: - if ((parseContext.isEsProfile() && parseContext.version < 300) || - (!parseContext.isEsProfile() && parseContext.version < 140)) - return identifierOrType(); - return keyword; - case LAYOUT: - { - const int numLayoutExts = 2; - const char* layoutExts[numLayoutExts] = { E_GL_ARB_shading_language_420pack, - E_GL_ARB_explicit_attrib_location }; - if ((parseContext.isEsProfile() && parseContext.version < 300) || - (!parseContext.isEsProfile() && parseContext.version < 140 && - ! parseContext.extensionsTurnedOn(numLayoutExts, layoutExts))) - return identifierOrType(); - return keyword; - } - - case HIGH_PRECISION: - case MEDIUM_PRECISION: - case LOW_PRECISION: - case PRECISION: - return precisionKeyword(); - - case MAT2X2: - case MAT2X3: - case MAT2X4: - case MAT3X2: - case MAT3X3: - case MAT3X4: - case MAT4X2: - case MAT4X3: - case MAT4X4: - return matNxM(); - - case DMAT2: - case DMAT3: - case DMAT4: - case DMAT2X2: - case DMAT2X3: - case DMAT2X4: - case DMAT3X2: - case DMAT3X3: - case DMAT3X4: - case DMAT4X2: - case DMAT4X3: - case DMAT4X4: - return dMat(); - - case IMAGE1D: - case IIMAGE1D: - case UIMAGE1D: - case IMAGE1DARRAY: - case IIMAGE1DARRAY: - case UIMAGE1DARRAY: - case IMAGE2DRECT: - case IIMAGE2DRECT: - case UIMAGE2DRECT: - afterType = true; - return firstGenerationImage(false); - - case I64IMAGE1D: - case U64IMAGE1D: - case I64IMAGE1DARRAY: - case U64IMAGE1DARRAY: - case I64IMAGE2DRECT: - case U64IMAGE2DRECT: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) { - return firstGenerationImage(false); - } - return identifierOrType(); - - case IMAGEBUFFER: - case IIMAGEBUFFER: - case UIMAGEBUFFER: - afterType = true; - if ((parseContext.isEsProfile() && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) - return keyword; - return firstGenerationImage(false); - - case I64IMAGEBUFFER: - case U64IMAGEBUFFER: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) { - if ((parseContext.isEsProfile() && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) - return keyword; - return firstGenerationImage(false); - } - return identifierOrType(); - - case IMAGE2D: - case IIMAGE2D: - case UIMAGE2D: - case IMAGE3D: - case IIMAGE3D: - case UIMAGE3D: - case IMAGECUBE: - case IIMAGECUBE: - case UIMAGECUBE: - case IMAGE2DARRAY: - case IIMAGE2DARRAY: - case UIMAGE2DARRAY: - afterType = true; - return firstGenerationImage(true); - - case I64IMAGE2D: - case U64IMAGE2D: - case I64IMAGE3D: - case U64IMAGE3D: - case I64IMAGECUBE: - case U64IMAGECUBE: - case I64IMAGE2DARRAY: - case U64IMAGE2DARRAY: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) - return firstGenerationImage(true); - return identifierOrType(); - - case IMAGECUBEARRAY: - case IIMAGECUBEARRAY: - case UIMAGECUBEARRAY: - afterType = true; - if ((parseContext.isEsProfile() && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) - return keyword; - return secondGenerationImage(); - - case I64IMAGECUBEARRAY: - case U64IMAGECUBEARRAY: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) { - if ((parseContext.isEsProfile() && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) - return keyword; - return secondGenerationImage(); - } - return identifierOrType(); - - case IMAGE2DMS: - case IIMAGE2DMS: - case UIMAGE2DMS: - case IMAGE2DMSARRAY: - case IIMAGE2DMSARRAY: - case UIMAGE2DMSARRAY: - afterType = true; - return secondGenerationImage(); - - case I64IMAGE2DMS: - case U64IMAGE2DMS: - case I64IMAGE2DMSARRAY: - case U64IMAGE2DMSARRAY: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_shader_image_int64)) { - return secondGenerationImage(); - } - return identifierOrType(); - - case DOUBLE: - case DVEC2: - case DVEC3: - case DVEC4: - afterType = true; - if (parseContext.isEsProfile() || parseContext.version < 150 || - (!parseContext.symbolTable.atBuiltInLevel() && - (parseContext.version < 400 && !parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) && - (parseContext.version < 410 && !parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit))))) - reservedWord(); - return keyword; - - case INT64_T: - case UINT64_T: - case I64VEC2: - case I64VEC3: - case I64VEC4: - case U64VEC2: - case U64VEC3: - case U64VEC4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64)) - return keyword; - return identifierOrType(); - - case INT8_T: - case UINT8_T: - case I8VEC2: - case I8VEC3: - case I8VEC4: - case U8VEC2: - case U8VEC3: - case U8VEC4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_8bit_storage) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8)) - return keyword; - return identifierOrType(); - - case INT16_T: - case UINT16_T: - case I16VEC2: - case I16VEC3: - case I16VEC4: - case U16VEC2: - case U16VEC3: - case U16VEC4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16)) - return keyword; - return identifierOrType(); - case INT32_T: - case UINT32_T: - case I32VEC2: - case I32VEC3: - case I32VEC4: - case U32VEC2: - case U32VEC3: - case U32VEC4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32)) - return keyword; - return identifierOrType(); - case FLOAT32_T: - case F32VEC2: - case F32VEC3: - case F32VEC4: - case F32MAT2: - case F32MAT3: - case F32MAT4: - case F32MAT2X2: - case F32MAT2X3: - case F32MAT2X4: - case F32MAT3X2: - case F32MAT3X3: - case F32MAT3X4: - case F32MAT4X2: - case F32MAT4X3: - case F32MAT4X4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32)) - return keyword; - return identifierOrType(); - - case FLOAT64_T: - case F64VEC2: - case F64VEC3: - case F64VEC4: - case F64MAT2: - case F64MAT3: - case F64MAT4: - case F64MAT2X2: - case F64MAT2X3: - case F64MAT2X4: - case F64MAT3X2: - case F64MAT3X3: - case F64MAT3X4: - case F64MAT4X2: - case F64MAT4X3: - case F64MAT4X4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64)) - return keyword; - return identifierOrType(); - - case FLOAT16_T: - case F16VEC2: - case F16VEC3: - case F16VEC4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16)) - return keyword; - - return identifierOrType(); - - case F16MAT2: - case F16MAT3: - case F16MAT4: - case F16MAT2X2: - case F16MAT2X3: - case F16MAT2X4: - case F16MAT3X2: - case F16MAT3X3: - case F16MAT3X4: - case F16MAT4X2: - case F16MAT4X3: - case F16MAT4X4: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) || - parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16)) - return keyword; - - return identifierOrType(); - - case SAMPLERCUBEARRAY: - case SAMPLERCUBEARRAYSHADOW: - case ISAMPLERCUBEARRAY: - case USAMPLERCUBEARRAY: - afterType = true; - if ((parseContext.isEsProfile() && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) - return keyword; - if (parseContext.isEsProfile() || (parseContext.version < 400 && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_cube_map_array))) - reservedWord(); - return keyword; - - case TEXTURECUBEARRAY: - case ITEXTURECUBEARRAY: - case UTEXTURECUBEARRAY: - if (parseContext.spvVersion.vulkan > 0) - return keyword; - else - return identifierOrType(); - - case UINT: - case UVEC2: - case UVEC3: - case UVEC4: - case SAMPLERCUBESHADOW: - case SAMPLER2DARRAY: - case SAMPLER2DARRAYSHADOW: - case ISAMPLER2D: - case ISAMPLER3D: - case ISAMPLERCUBE: - case ISAMPLER2DARRAY: - case USAMPLER2D: - case USAMPLER3D: - case USAMPLERCUBE: - case USAMPLER2DARRAY: - afterType = true; - if (keyword == SAMPLER2DARRAY || keyword == SAMPLER2DARRAYSHADOW) { - if (!parseContext.isEsProfile() && - (parseContext.extensionTurnedOn(E_GL_EXT_texture_array) || parseContext.symbolTable.atBuiltInLevel())) { - return keyword; - } - } - return nonreservedKeyword(300, 130); - - case SAMPLER3D: - afterType = true; - if (parseContext.isEsProfile() && parseContext.version < 300) { - if (!parseContext.extensionTurnedOn(E_GL_OES_texture_3D)) - reservedWord(); - } - return keyword; - - case SAMPLER2DSHADOW: - afterType = true; - if (parseContext.isEsProfile() && parseContext.version < 300) { - if (!parseContext.extensionTurnedOn(E_GL_EXT_shadow_samplers)) - reservedWord(); - } - return keyword; - - case TEXTURE2D: - case TEXTURECUBE: - case TEXTURE2DARRAY: - case ITEXTURE2D: - case ITEXTURE3D: - case ITEXTURECUBE: - case ITEXTURE2DARRAY: - case UTEXTURE2D: - case UTEXTURE3D: - case UTEXTURECUBE: - case UTEXTURE2DARRAY: - case TEXTURE3D: - case SAMPLER: - case SAMPLERSHADOW: - if (parseContext.spvVersion.vulkan > 0) - return keyword; - else - return identifierOrType(); - - case ISAMPLER1D: - case ISAMPLER1DARRAY: - case SAMPLER1DARRAYSHADOW: - case USAMPLER1D: - case USAMPLER1DARRAY: - afterType = true; - if (keyword == SAMPLER1DARRAYSHADOW) { - if (!parseContext.isEsProfile() && - (parseContext.extensionTurnedOn(E_GL_EXT_texture_array) || parseContext.symbolTable.atBuiltInLevel())) { - return keyword; - } - } - return es30ReservedFromGLSL(130); - case ISAMPLER2DRECT: - case USAMPLER2DRECT: - afterType = true; - return es30ReservedFromGLSL(140); - - case SAMPLERBUFFER: - afterType = true; - if ((parseContext.isEsProfile() && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) - return keyword; - return es30ReservedFromGLSL(130); - - case ISAMPLERBUFFER: - case USAMPLERBUFFER: - afterType = true; - if ((parseContext.isEsProfile() && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) - return keyword; - return es30ReservedFromGLSL(140); - - case SAMPLER2DMS: - case ISAMPLER2DMS: - case USAMPLER2DMS: - afterType = true; - if (parseContext.isEsProfile() && parseContext.version >= 310) - return keyword; - if (!parseContext.isEsProfile() && (parseContext.version > 140 || - (parseContext.version == 140 && parseContext.extensionsTurnedOn(1, &E_GL_ARB_texture_multisample)))) - return keyword; - return es30ReservedFromGLSL(150); - - case SAMPLER2DMSARRAY: - case ISAMPLER2DMSARRAY: - case USAMPLER2DMSARRAY: - afterType = true; - if ((parseContext.isEsProfile() && parseContext.version >= 320) || - parseContext.extensionsTurnedOn(1, &E_GL_OES_texture_storage_multisample_2d_array)) - return keyword; - if (!parseContext.isEsProfile() && (parseContext.version > 140 || - (parseContext.version == 140 && parseContext.extensionsTurnedOn(1, &E_GL_ARB_texture_multisample)))) - return keyword; - return es30ReservedFromGLSL(150); - - case SAMPLER1D: - case SAMPLER1DSHADOW: - afterType = true; - if (parseContext.isEsProfile()) - reservedWord(); - return keyword; - - case SAMPLER2DRECT: - case SAMPLER2DRECTSHADOW: - afterType = true; - if (parseContext.isEsProfile()) - reservedWord(); - else if (parseContext.version < 140 && ! parseContext.symbolTable.atBuiltInLevel() && ! parseContext.extensionTurnedOn(E_GL_ARB_texture_rectangle)) { - if (parseContext.relaxedErrors()) - parseContext.requireExtensions(loc, 1, &E_GL_ARB_texture_rectangle, "texture-rectangle sampler keyword"); - else - reservedWord(); - } - return keyword; - - case SAMPLER1DARRAY: - afterType = true; - if (parseContext.isEsProfile() && parseContext.version == 300) - reservedWord(); - else if ((parseContext.isEsProfile() && parseContext.version < 300) || - ((!parseContext.isEsProfile() && parseContext.version < 130) && - !parseContext.symbolTable.atBuiltInLevel() && - !parseContext.extensionTurnedOn(E_GL_EXT_texture_array))) - return identifierOrType(); - return keyword; - - case SAMPLEREXTERNALOES: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external) || - parseContext.extensionTurnedOn(E_GL_OES_EGL_image_external_essl3)) - return keyword; - return identifierOrType(); - - case SAMPLEREXTERNAL2DY2YEXT: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_YUV_target)) - return keyword; - return identifierOrType(); - - case ITEXTURE1DARRAY: - case UTEXTURE1D: - case ITEXTURE1D: - case UTEXTURE1DARRAY: - case TEXTUREBUFFER: - case ITEXTURE2DRECT: - case UTEXTURE2DRECT: - case ITEXTUREBUFFER: - case UTEXTUREBUFFER: - case TEXTURE2DMS: - case ITEXTURE2DMS: - case UTEXTURE2DMS: - case TEXTURE2DMSARRAY: - case ITEXTURE2DMSARRAY: - case UTEXTURE2DMSARRAY: - case TEXTURE1D: - case TEXTURE2DRECT: - case TEXTURE1DARRAY: - if (parseContext.spvVersion.vulkan > 0) - return keyword; - else - return identifierOrType(); - - case SUBPASSINPUT: - case SUBPASSINPUTMS: - case ISUBPASSINPUT: - case ISUBPASSINPUTMS: - case USUBPASSINPUT: - case USUBPASSINPUTMS: - case ATTACHMENTEXT: - case IATTACHMENTEXT: - case UATTACHMENTEXT: - if (parseContext.spvVersion.vulkan > 0) - return keyword; - else - return identifierOrType(); - - case F16SAMPLER1D: - case F16SAMPLER2D: - case F16SAMPLER3D: - case F16SAMPLER2DRECT: - case F16SAMPLERCUBE: - case F16SAMPLER1DARRAY: - case F16SAMPLER2DARRAY: - case F16SAMPLERCUBEARRAY: - case F16SAMPLERBUFFER: - case F16SAMPLER2DMS: - case F16SAMPLER2DMSARRAY: - case F16SAMPLER1DSHADOW: - case F16SAMPLER2DSHADOW: - case F16SAMPLER1DARRAYSHADOW: - case F16SAMPLER2DARRAYSHADOW: - case F16SAMPLER2DRECTSHADOW: - case F16SAMPLERCUBESHADOW: - case F16SAMPLERCUBEARRAYSHADOW: - - case F16IMAGE1D: - case F16IMAGE2D: - case F16IMAGE3D: - case F16IMAGE2DRECT: - case F16IMAGECUBE: - case F16IMAGE1DARRAY: - case F16IMAGE2DARRAY: - case F16IMAGECUBEARRAY: - case F16IMAGEBUFFER: - case F16IMAGE2DMS: - case F16IMAGE2DMSARRAY: - - case F16TEXTURE1D: - case F16TEXTURE2D: - case F16TEXTURE3D: - case F16TEXTURE2DRECT: - case F16TEXTURECUBE: - case F16TEXTURE1DARRAY: - case F16TEXTURE2DARRAY: - case F16TEXTURECUBEARRAY: - case F16TEXTUREBUFFER: - case F16TEXTURE2DMS: - case F16TEXTURE2DMSARRAY: - - case F16SUBPASSINPUT: - case F16SUBPASSINPUTMS: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float_fetch)) - return keyword; - return identifierOrType(); - - case EXPLICITINTERPAMD: - if (parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter)) - return keyword; - return identifierOrType(); - - case PERVERTEXNV: - if ((!parseContext.isEsProfile() && parseContext.version >= 450) || - parseContext.extensionTurnedOn(E_GL_NV_fragment_shader_barycentric)) - return keyword; - return identifierOrType(); - - case PERVERTEXEXT: - if ((!parseContext.isEsProfile() && parseContext.version >= 450) || - parseContext.extensionTurnedOn(E_GL_EXT_fragment_shader_barycentric)) - return keyword; - return identifierOrType(); - - case PRECISE: - if ((parseContext.isEsProfile() && - (parseContext.version >= 320 || parseContext.extensionsTurnedOn(Num_AEP_gpu_shader5, AEP_gpu_shader5))) || - (!parseContext.isEsProfile() && parseContext.version >= 400)) - return keyword; - if (parseContext.isEsProfile() && parseContext.version == 310) { - reservedWord(); - return keyword; - } - return identifierOrType(); - - case PERPRIMITIVENV: - case PERVIEWNV: - case PERTASKNV: - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_NV_mesh_shader)) - return keyword; - return identifierOrType(); - - case PERPRIMITIVEEXT: - case TASKPAYLOADWORKGROUPEXT: - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_mesh_shader)) - return keyword; - return identifierOrType(); - - case FCOOPMATNV: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_NV_cooperative_matrix)) - return keyword; - return identifierOrType(); - - case UCOOPMATNV: - case ICOOPMATNV: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_NV_integer_cooperative_matrix)) - return keyword; - return identifierOrType(); - - case COOPMAT: - afterType = true; - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_KHR_cooperative_matrix)) - return keyword; - return identifierOrType(); - - case DEMOTE: - if (parseContext.extensionTurnedOn(E_GL_EXT_demote_to_helper_invocation)) - return keyword; - else - return identifierOrType(); - - case SPIRV_INSTRUCTION: - case SPIRV_EXECUTION_MODE: - case SPIRV_EXECUTION_MODE_ID: - case SPIRV_DECORATE: - case SPIRV_DECORATE_ID: - case SPIRV_DECORATE_STRING: - case SPIRV_TYPE: - case SPIRV_STORAGE_CLASS: - case SPIRV_BY_REFERENCE: - case SPIRV_LITERAL: - if (parseContext.symbolTable.atBuiltInLevel() || - parseContext.extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) - return keyword; - return identifierOrType(); - - case HITOBJECTNV: - if (parseContext.symbolTable.atBuiltInLevel() || - (!parseContext.isEsProfile() && parseContext.version >= 460 - && parseContext.extensionTurnedOn(E_GL_NV_shader_invocation_reorder))) - return keyword; - return identifierOrType(); - - case HITOBJECTATTRNV: - if (parseContext.symbolTable.atBuiltInLevel() || - (!parseContext.isEsProfile() && parseContext.version >= 460 - && parseContext.extensionTurnedOn(E_GL_NV_shader_invocation_reorder))) - return keyword; - return identifierOrType(); - - default: - parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc); - return 0; - } -} - -int TScanContext::identifierOrType() -{ - parserToken->sType.lex.string = NewPoolTString(tokenText); - if (field) - return IDENTIFIER; - - parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string); - if ((afterType == false && afterStruct == false) && parserToken->sType.lex.symbol != nullptr) { - if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) { - if (variable->isUserType() && - // treat redeclaration of forward-declared buffer/uniform reference as an identifier - !(variable->getType().isReference() && afterBuffer)) { - afterType = true; - - return TYPE_NAME; - } - } - } - - return IDENTIFIER; -} - -// Give an error for use of a reserved symbol. -// However, allow built-in declarations to use reserved words, to allow -// extension support before the extension is enabled. -int TScanContext::reservedWord() -{ - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.error(loc, "Reserved word.", tokenText, "", ""); - - return 0; -} - -int TScanContext::identifierOrReserved(bool reserved) -{ - if (reserved) { - reservedWord(); - - return 0; - } - - if (parseContext.isForwardCompatible()) - parseContext.warn(loc, "using future reserved keyword", tokenText, ""); - - return identifierOrType(); -} - -// For keywords that suddenly showed up on non-ES (not previously reserved) -// but then got reserved by ES 3.0. -int TScanContext::es30ReservedFromGLSL(int version) -{ - if (parseContext.symbolTable.atBuiltInLevel()) - return keyword; - - if ((parseContext.isEsProfile() && parseContext.version < 300) || - (!parseContext.isEsProfile() && parseContext.version < version)) { - if (parseContext.isForwardCompatible()) - parseContext.warn(loc, "future reserved word in ES 300 and keyword in GLSL", tokenText, ""); - - return identifierOrType(); - } else if (parseContext.isEsProfile() && parseContext.version >= 300) - reservedWord(); - - return keyword; -} - -// For a keyword that was never reserved, until it suddenly -// showed up, both in an es version and a non-ES version. -int TScanContext::nonreservedKeyword(int esVersion, int nonEsVersion) -{ - if ((parseContext.isEsProfile() && parseContext.version < esVersion) || - (!parseContext.isEsProfile() && parseContext.version < nonEsVersion)) { - if (parseContext.isForwardCompatible()) - parseContext.warn(loc, "using future keyword", tokenText, ""); - - return identifierOrType(); - } - - return keyword; -} - -int TScanContext::precisionKeyword() -{ - if (parseContext.isEsProfile() || parseContext.version >= 130) - return keyword; - - if (parseContext.isForwardCompatible()) - parseContext.warn(loc, "using ES precision qualifier keyword", tokenText, ""); - - return identifierOrType(); -} - -int TScanContext::matNxM() -{ - afterType = true; - - if (parseContext.version > 110) - return keyword; - - if (parseContext.isForwardCompatible()) - parseContext.warn(loc, "using future non-square matrix type keyword", tokenText, ""); - - return identifierOrType(); -} - -int TScanContext::dMat() -{ - afterType = true; - - if (parseContext.isEsProfile() && parseContext.version >= 300) { - reservedWord(); - - return keyword; - } - - if (!parseContext.isEsProfile() && (parseContext.version >= 400 || - parseContext.symbolTable.atBuiltInLevel() || - (parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)) || - (parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit) - && parseContext.language == EShLangVertex))) - return keyword; - - if (parseContext.isForwardCompatible()) - parseContext.warn(loc, "using future type keyword", tokenText, ""); - - return identifierOrType(); -} - -int TScanContext::firstGenerationImage(bool inEs310) -{ - if (parseContext.symbolTable.atBuiltInLevel() || - (!parseContext.isEsProfile() && (parseContext.version >= 420 || - parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store))) || - (inEs310 && parseContext.isEsProfile() && parseContext.version >= 310)) - return keyword; - - if ((parseContext.isEsProfile() && parseContext.version >= 300) || - (!parseContext.isEsProfile() && parseContext.version >= 130)) { - reservedWord(); - - return keyword; - } - - if (parseContext.isForwardCompatible()) - parseContext.warn(loc, "using future type keyword", tokenText, ""); - - return identifierOrType(); -} - -int TScanContext::secondGenerationImage() -{ - if (parseContext.isEsProfile() && parseContext.version >= 310) { - reservedWord(); - return keyword; - } - - if (parseContext.symbolTable.atBuiltInLevel() || - (!parseContext.isEsProfile() && - (parseContext.version >= 420 || parseContext.extensionTurnedOn(E_GL_ARB_shader_image_load_store)))) - return keyword; - - if (parseContext.isForwardCompatible()) - parseContext.warn(loc, "using future type keyword", tokenText, ""); - - return identifierOrType(); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/Scan.h b/3rdparty/glslang/glslang/MachineIndependent/Scan.h deleted file mode 100644 index 24b75cf7..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/Scan.h +++ /dev/null @@ -1,276 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -#ifndef _GLSLANG_SCAN_INCLUDED_ -#define _GLSLANG_SCAN_INCLUDED_ - -#include "Versions.h" - -namespace glslang { - -// Use a global end-of-input character, so no translation is needed across -// layers of encapsulation. Characters are all 8 bit, and positive, so there is -// no aliasing of character 255 onto -1, for example. -const int EndOfInput = -1; - -// -// A character scanner that seamlessly, on read-only strings, reads across an -// array of strings without assuming null termination. -// -class TInputScanner { -public: - TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr, - int b = 0, int f = 0, bool single = false) : - numSources(n), - // up to this point, common usage is "char*", but now we need positive 8-bit characters - sources(reinterpret_cast(s)), - lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single), - endOfFileReached(false) - { - loc = new TSourceLoc[numSources]; - for (int i = 0; i < numSources; ++i) { - loc[i].init(i - stringBias); - } - if (names != nullptr) { - for (int i = 0; i < numSources; ++i) - loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr; - } - loc[currentSource].line = 1; - logicalSourceLoc.init(1); - logicalSourceLoc.name = loc[0].name; - } - - virtual ~TInputScanner() - { - delete [] loc; - } - - // retrieve the next character and advance one character - int get() - { - int ret = peek(); - if (ret == EndOfInput) - return ret; - ++loc[currentSource].column; - ++logicalSourceLoc.column; - if (ret == '\n') { - ++loc[currentSource].line; - ++logicalSourceLoc.line; - logicalSourceLoc.column = 0; - loc[currentSource].column = 0; - } - advance(); - - return ret; - } - - // retrieve the next character, no advance - int peek() - { - if (currentSource >= numSources) { - endOfFileReached = true; - return EndOfInput; - } - // Make sure we do not read off the end of a string. - // N.B. Sources can have a length of 0. - int sourceToRead = currentSource; - size_t charToRead = currentChar; - while(charToRead >= lengths[sourceToRead]) { - charToRead = 0; - sourceToRead += 1; - if (sourceToRead >= numSources) { - return EndOfInput; - } - } - - // Here, we care about making negative valued characters positive - return sources[sourceToRead][charToRead]; - } - - // go back one character - void unget() - { - // Do not roll back once we've reached the end of the file. - if (endOfFileReached) - return; - - if (currentChar > 0) { - --currentChar; - --loc[currentSource].column; - --logicalSourceLoc.column; - if (loc[currentSource].column < 0) { - // We've moved back past a new line. Find the - // previous newline (or start of the file) to compute - // the column count on the now current line. - size_t chIndex = currentChar; - while (chIndex > 0) { - if (sources[currentSource][chIndex] == '\n') { - break; - } - --chIndex; - } - logicalSourceLoc.column = (int)(currentChar - chIndex); - loc[currentSource].column = (int)(currentChar - chIndex); - } - } else { - do { - --currentSource; - } while (currentSource > 0 && lengths[currentSource] == 0); - if (lengths[currentSource] == 0) { - // set to 0 if we've backed up to the start of an empty string - currentChar = 0; - } else - currentChar = lengths[currentSource] - 1; - } - if (peek() == '\n') { - --loc[currentSource].line; - --logicalSourceLoc.line; - } - } - - // for #line override - void setLine(int newLine) - { - logicalSourceLoc.line = newLine; - loc[getLastValidSourceIndex()].line = newLine; - } - - // for #line override in filename based parsing - void setFile(const char* filename) - { - TString* fn_tstr = NewPoolTString(filename); - logicalSourceLoc.name = fn_tstr; - loc[getLastValidSourceIndex()].name = fn_tstr; - } - - void setFile(const char* filename, int i) - { - TString* fn_tstr = NewPoolTString(filename); - if (i == getLastValidSourceIndex()) { - logicalSourceLoc.name = fn_tstr; - } - loc[i].name = fn_tstr; - } - - void setString(int newString) - { - logicalSourceLoc.string = newString; - loc[getLastValidSourceIndex()].string = newString; - logicalSourceLoc.name = nullptr; - loc[getLastValidSourceIndex()].name = nullptr; - } - - // for #include content indentation - void setColumn(int col) - { - logicalSourceLoc.column = col; - loc[getLastValidSourceIndex()].column = col; - } - - void setEndOfInput() - { - endOfFileReached = true; - currentSource = numSources; - } - - bool atEndOfInput() const { return endOfFileReached; } - - const TSourceLoc& getSourceLoc() const - { - if (singleLogical) { - return logicalSourceLoc; - } else { - return loc[std::max(0, std::min(currentSource, numSources - finale - 1))]; - } - } - // Returns the index (starting from 0) of the most recent valid source string we are reading from. - int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); } - - void consumeWhiteSpace(bool& foundNonSpaceTab); - bool consumeComment(); - void consumeWhitespaceComment(bool& foundNonSpaceTab); - bool scanVersion(int& version, EProfile& profile, bool& notFirstToken); - -protected: - - // advance one character - void advance() - { - ++currentChar; - if (currentChar >= lengths[currentSource]) { - ++currentSource; - if (currentSource < numSources) { - loc[currentSource].string = loc[currentSource - 1].string + 1; - loc[currentSource].line = 1; - loc[currentSource].column = 0; - } - while (currentSource < numSources && lengths[currentSource] == 0) { - ++currentSource; - if (currentSource < numSources) { - loc[currentSource].string = loc[currentSource - 1].string + 1; - loc[currentSource].line = 1; - loc[currentSource].column = 0; - } - } - currentChar = 0; - } - } - - int numSources; // number of strings in source - const unsigned char* const *sources; // array of strings; must be converted to positive values on use, to avoid aliasing with -1 as EndOfInput - const size_t *lengths; // length of each string - int currentSource; - size_t currentChar; - - // This is for reporting what string/line an error occurred on, and can be overridden by #line. - // It remembers the last state of each source string as it is left for the next one, so unget() - // can restore that state. - TSourceLoc* loc; // an array - - int stringBias; // the first string that is the user's string number 0 - int finale; // number of internal strings after user's last string - - TSourceLoc logicalSourceLoc; - bool singleLogical; // treats the strings as a single logical string. - // locations will be reported from the first string. - - // Set to true once peek() returns EndOfFile, so that we won't roll back - // once we've reached EndOfFile. - bool endOfFileReached; -}; - -} // end namespace glslang - -#endif // _GLSLANG_SCAN_INCLUDED_ diff --git a/3rdparty/glslang/glslang/MachineIndependent/ScanContext.h b/3rdparty/glslang/glslang/MachineIndependent/ScanContext.h deleted file mode 100644 index 74b2b3c7..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/ScanContext.h +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright (C) 2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// This holds context specific to the GLSL scanner, which -// sits between the preprocessor scanner and parser. -// - -#pragma once - -#include "ParseHelper.h" - -namespace glslang { - -class TPpContext; -class TPpToken; -class TParserToken; - -class TScanContext { -public: - explicit TScanContext(TParseContextBase& pc) : - parseContext(pc), - afterType(false), afterStruct(false), - field(false), afterBuffer(false) { } - virtual ~TScanContext() { } - - static void fillInKeywordMap(); - static void deleteKeywordMap(); - - int tokenize(TPpContext*, TParserToken&); - -protected: - TScanContext(TScanContext&); - TScanContext& operator=(TScanContext&); - - int tokenizeIdentifier(); - int identifierOrType(); - int reservedWord(); - int identifierOrReserved(bool reserved); - int es30ReservedFromGLSL(int version); - int nonreservedKeyword(int esVersion, int nonEsVersion); - int precisionKeyword(); - int matNxM(); - int dMat(); - int firstGenerationImage(bool inEs310); - int secondGenerationImage(); - - TParseContextBase& parseContext; - bool afterType; // true if we've recognized a type, so can only be looking for an identifier - bool afterStruct; // true if we've recognized the STRUCT keyword, so can only be looking for an identifier - bool field; // true if we're on a field, right after a '.' - bool afterBuffer; // true if we've recognized the BUFFER keyword - TSourceLoc loc; - TParserToken* parserToken; - TPpToken* ppToken; - - const char* tokenText; - int keyword; -}; - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp b/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp deleted file mode 100644 index 6e50a9d4..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/ShaderLang.cpp +++ /dev/null @@ -1,2179 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013-2016 LunarG, Inc. -// Copyright (C) 2015-2020 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Implement the top-level of interface to the compiler/linker, -// as defined in ShaderLang.h -// This is the platform independent interface between an OGL driver -// and the shading language compiler/linker. -// -#include -#include -#include -#include -#include -#include "SymbolTable.h" -#include "ParseHelper.h" -#include "Scan.h" -#include "ScanContext.h" - -#ifdef ENABLE_HLSL -#include "../HLSL/hlslParseHelper.h" -#include "../HLSL/hlslParseables.h" -#include "../HLSL/hlslScanContext.h" -#endif - -#include "../Include/ShHandle.h" - -#include "preprocessor/PpContext.h" - -#define SH_EXPORTING -#include "../Public/ShaderLang.h" -#include "reflection.h" -#include "iomapper.h" -#include "Initialize.h" - -// TODO: this really shouldn't be here, it is only because of the trial addition -// of printing pre-processed tokens, which requires knowing the string literal -// token to print ", but none of that seems appropriate for this file. -#include "preprocessor/PpTokens.h" - -// Build-time generated includes -#include "glslang/build_info.h" - -namespace { // anonymous namespace for file-local functions and symbols - -// Total number of successful initializers of glslang: a refcount -// Shared global; access should be protected by a global mutex/critical section. -int NumberOfClients = 0; - -// global initialization lock -std::mutex init_lock; - -using namespace glslang; - -// Create a language specific version of parseables. -TBuiltInParseables* CreateBuiltInParseables(TInfoSink& infoSink, EShSource source) -{ - switch (source) { - case EShSourceGlsl: return new TBuiltIns(); // GLSL builtIns -#ifdef ENABLE_HLSL - case EShSourceHlsl: return new TBuiltInParseablesHlsl(); // HLSL intrinsics -#endif - - default: - infoSink.info.message(EPrefixInternalError, "Unable to determine source language"); - return nullptr; - } -} - -// Create a language specific version of a parse context. -TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& intermediate, - int version, EProfile profile, EShSource source, - EShLanguage language, TInfoSink& infoSink, - SpvVersion spvVersion, bool forwardCompatible, EShMessages messages, - bool parsingBuiltIns, std::string sourceEntryPointName = "") -{ - switch (source) { - case EShSourceGlsl: { - if (sourceEntryPointName.size() == 0) - intermediate.setEntryPointName("main"); - TString entryPoint = sourceEntryPointName.c_str(); - return new TParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion, - language, infoSink, forwardCompatible, messages, &entryPoint); - } -#ifdef ENABLE_HLSL - case EShSourceHlsl: - return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion, - language, infoSink, sourceEntryPointName.c_str(), forwardCompatible, messages); -#endif - default: - infoSink.info.message(EPrefixInternalError, "Unable to determine source language"); - return nullptr; - } -} - -// Local mapping functions for making arrays of symbol tables.... - -const int VersionCount = 17; // index range in MapVersionToIndex - -int MapVersionToIndex(int version) -{ - int index = 0; - - switch (version) { - case 100: index = 0; break; - case 110: index = 1; break; - case 120: index = 2; break; - case 130: index = 3; break; - case 140: index = 4; break; - case 150: index = 5; break; - case 300: index = 6; break; - case 330: index = 7; break; - case 400: index = 8; break; - case 410: index = 9; break; - case 420: index = 10; break; - case 430: index = 11; break; - case 440: index = 12; break; - case 310: index = 13; break; - case 450: index = 14; break; - case 500: index = 0; break; // HLSL - case 320: index = 15; break; - case 460: index = 16; break; - default: assert(0); break; - } - - assert(index < VersionCount); - - return index; -} - -const int SpvVersionCount = 4; // index range in MapSpvVersionToIndex - -int MapSpvVersionToIndex(const SpvVersion& spvVersion) -{ - int index = 0; - - if (spvVersion.openGl > 0) - index = 1; - else if (spvVersion.vulkan > 0) { - if (!spvVersion.vulkanRelaxed) - index = 2; - else - index = 3; - } - - assert(index < SpvVersionCount); - - return index; -} - -const int ProfileCount = 4; // index range in MapProfileToIndex - -int MapProfileToIndex(EProfile profile) -{ - int index = 0; - - switch (profile) { - case ENoProfile: index = 0; break; - case ECoreProfile: index = 1; break; - case ECompatibilityProfile: index = 2; break; - case EEsProfile: index = 3; break; - default: break; - } - - assert(index < ProfileCount); - - return index; -} - -const int SourceCount = 2; - -int MapSourceToIndex(EShSource source) -{ - int index = 0; - - switch (source) { - case EShSourceGlsl: index = 0; break; - case EShSourceHlsl: index = 1; break; - default: break; - } - - assert(index < SourceCount); - - return index; -} - -// only one of these needed for non-ES; ES needs 2 for different precision defaults of built-ins -enum EPrecisionClass { - EPcGeneral, - EPcFragment, - EPcCount -}; - -// A process-global symbol table per version per profile for built-ins common -// to multiple stages (languages), and a process-global symbol table per version -// per profile per stage for built-ins unique to each stage. They will be sparsely -// populated, so they will only be generated as needed. -// -// Each has a different set of built-ins, and we want to preserve that from -// compile to compile. -// -TSymbolTable* CommonSymbolTable[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EPcCount] = {}; -TSymbolTable* SharedSymbolTables[VersionCount][SpvVersionCount][ProfileCount][SourceCount][EShLangCount] = {}; - -TPoolAllocator* PerProcessGPA = nullptr; - -// -// Parse and add to the given symbol table the content of the given shader string. -// -bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, - EShSource source, TInfoSink& infoSink, TSymbolTable& symbolTable) -{ - TIntermediate intermediate(language, version, profile); - - intermediate.setSource(source); - - std::unique_ptr parseContext(CreateParseContext(symbolTable, intermediate, version, profile, source, - language, infoSink, spvVersion, true, EShMsgDefault, - true)); - - TShader::ForbidIncluder includer; - TPpContext ppContext(*parseContext, "", includer); - TScanContext scanContext(*parseContext); - parseContext->setScanContext(&scanContext); - parseContext->setPpContext(&ppContext); - - // - // Push the symbol table to give it an initial scope. This - // push should not have a corresponding pop, so that built-ins - // are preserved, and the test for an empty table fails. - // - - symbolTable.push(); - - const char* builtInShaders[2]; - size_t builtInLengths[2]; - builtInShaders[0] = builtIns.c_str(); - builtInLengths[0] = builtIns.size(); - - if (builtInLengths[0] == 0) - return true; - - TInputScanner input(1, builtInShaders, builtInLengths); - if (! parseContext->parseShaderStrings(ppContext, input) != 0) { - infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins"); - printf("Unable to parse built-ins\n%s\n", infoSink.info.c_str()); - printf("%s\n", builtInShaders[0]); - - return false; - } - - return true; -} - -int CommonIndex(EProfile profile, EShLanguage language) -{ - return (profile == EEsProfile && language == EShLangFragment) ? EPcFragment : EPcGeneral; -} - -// -// To initialize per-stage shared tables, with the common table already complete. -// -void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int version, EProfile profile, const SpvVersion& spvVersion, - EShLanguage language, EShSource source, TInfoSink& infoSink, TSymbolTable** commonTable, - TSymbolTable** symbolTables) -{ - (*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]); - InitializeSymbolTable(builtInParseables.getStageString(language), version, profile, spvVersion, language, source, - infoSink, *symbolTables[language]); - builtInParseables.identifyBuiltIns(version, profile, spvVersion, language, *symbolTables[language]); - if (profile == EEsProfile && version >= 300) - (*symbolTables[language]).setNoBuiltInRedeclarations(); - if (version == 110) - (*symbolTables[language]).setSeparateNameSpaces(); -} - -// -// Initialize the full set of shareable symbol tables; -// The common (cross-stage) and those shareable per-stage. -// -bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables, int version, EProfile profile, const SpvVersion& spvVersion, EShSource source) -{ - std::unique_ptr builtInParseables(CreateBuiltInParseables(infoSink, source)); - - if (builtInParseables == nullptr) - return false; - - builtInParseables->initialize(version, profile, spvVersion); - - // do the common tables - InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangVertex, source, - infoSink, *commonTable[EPcGeneral]); - if (profile == EEsProfile) - InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangFragment, source, - infoSink, *commonTable[EPcFragment]); - - // do the per-stage tables - - // always have vertex and fragment - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangVertex, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangFragment, source, - infoSink, commonTable, symbolTables); - - // check for tessellation - if ((profile != EEsProfile && version >= 150) || - (profile == EEsProfile && version >= 310)) { - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessControl, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessEvaluation, source, - infoSink, commonTable, symbolTables); - } - - // check for geometry - if ((profile != EEsProfile && version >= 150) || - (profile == EEsProfile && version >= 310)) - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source, - infoSink, commonTable, symbolTables); - - // check for compute - if ((profile != EEsProfile && version >= 420) || - (profile == EEsProfile && version >= 310)) - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source, - infoSink, commonTable, symbolTables); - - // check for ray tracing stages - if (profile != EEsProfile && version >= 450) { - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGen, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersect, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHit, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHit, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMiss, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallable, source, - infoSink, commonTable, symbolTables); - } - - // check for mesh - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 320)) - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMesh, source, - infoSink, commonTable, symbolTables); - - // check for task - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 320)) - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTask, source, - infoSink, commonTable, symbolTables); - - return true; -} - -bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable& symbolTable, int version, - EProfile profile, const SpvVersion& spvVersion, EShLanguage language, EShSource source) -{ - std::unique_ptr builtInParseables(CreateBuiltInParseables(infoSink, source)); - - if (builtInParseables == nullptr) - return false; - - builtInParseables->initialize(*resources, version, profile, spvVersion, language); - InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, language, source, infoSink, symbolTable); - builtInParseables->identifyBuiltIns(version, profile, spvVersion, language, symbolTable, *resources); - - return true; -} - -// -// To do this on the fly, we want to leave the current state of our thread's -// pool allocator intact, so: -// - Switch to a new pool for parsing the built-ins -// - Do the parsing, which builds the symbol table, using the new pool -// - Switch to the process-global pool to save a copy of the resulting symbol table -// - Free up the new pool used to parse the built-ins -// - Switch back to the original thread's pool -// -// This only gets done the first time any thread needs a particular symbol table -// (lazy evaluation). -// -void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& spvVersion, EShSource source) -{ - TInfoSink infoSink; - - // Make sure only one thread tries to do this at a time - const std::lock_guard lock(init_lock); - - // See if it's already been done for this version/profile combination - int versionIndex = MapVersionToIndex(version); - int spvVersionIndex = MapSpvVersionToIndex(spvVersion); - int profileIndex = MapProfileToIndex(profile); - int sourceIndex = MapSourceToIndex(source); - if (CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][EPcGeneral]) - return; - - // Switch to a new pool - TPoolAllocator& previousAllocator = GetThreadPoolAllocator(); - TPoolAllocator* builtInPoolAllocator = new TPoolAllocator; - SetThreadPoolAllocator(builtInPoolAllocator); - - // Dynamically allocate the local symbol tables so we can control when they are deallocated WRT when the pool is popped. - TSymbolTable* commonTable[EPcCount]; - TSymbolTable* stageTables[EShLangCount]; - for (int precClass = 0; precClass < EPcCount; ++precClass) - commonTable[precClass] = new TSymbolTable; - for (int stage = 0; stage < EShLangCount; ++stage) - stageTables[stage] = new TSymbolTable; - - // Generate the local symbol tables using the new pool - InitializeSymbolTables(infoSink, commonTable, stageTables, version, profile, spvVersion, source); - - // Switch to the process-global pool - SetThreadPoolAllocator(PerProcessGPA); - - // Copy the local symbol tables from the new pool to the global tables using the process-global pool - for (int precClass = 0; precClass < EPcCount; ++precClass) { - if (! commonTable[precClass]->isEmpty()) { - CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass] = new TSymbolTable; - CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->copyTable(*commonTable[precClass]); - CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->readOnly(); - } - } - for (int stage = 0; stage < EShLangCount; ++stage) { - if (! stageTables[stage]->isEmpty()) { - SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage] = new TSymbolTable; - SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->adoptLevels(*CommonSymbolTable - [versionIndex][spvVersionIndex][profileIndex][sourceIndex][CommonIndex(profile, (EShLanguage)stage)]); - SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->copyTable(*stageTables[stage]); - SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->readOnly(); - } - } - - // Clean up the local tables before deleting the pool they used. - for (int precClass = 0; precClass < EPcCount; ++precClass) - delete commonTable[precClass]; - for (int stage = 0; stage < EShLangCount; ++stage) - delete stageTables[stage]; - - delete builtInPoolAllocator; - SetThreadPoolAllocator(&previousAllocator); -} - -// Function to Print all builtins -void DumpBuiltinSymbolTable(TInfoSink& infoSink, const TSymbolTable& symbolTable) -{ - infoSink.debug << "BuiltinSymbolTable {\n"; - - symbolTable.dump(infoSink, true); - - infoSink.debug << "}\n"; -} - -// Return true if the shader was correctly specified for version/profile/stage. -bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNotFirst, int defaultVersion, - EShSource source, int& version, EProfile& profile, const SpvVersion& spvVersion) -{ - const int FirstProfileVersion = 150; - bool correct = true; - - if (source == EShSourceHlsl) { - version = 500; // shader model; currently a characteristic of glslang, not the input - profile = ECoreProfile; // allow doubles in prototype parsing - return correct; - } - - // Get a version... - if (version == 0) { - version = defaultVersion; - // infoSink.info.message(EPrefixWarning, "#version: statement missing; use #version on first line of shader"); - } - - // Get a good profile... - if (profile == ENoProfile) { - if (version == 300 || version == 310 || version == 320) { - correct = false; - infoSink.info.message(EPrefixError, "#version: versions 300, 310, and 320 require specifying the 'es' profile"); - profile = EEsProfile; - } else if (version == 100) - profile = EEsProfile; - else if (version >= FirstProfileVersion) - profile = ECoreProfile; - else - profile = ENoProfile; - } else { - // a profile was provided... - if (version < 150) { - correct = false; - infoSink.info.message(EPrefixError, "#version: versions before 150 do not allow a profile token"); - if (version == 100) - profile = EEsProfile; - else - profile = ENoProfile; - } else if (version == 300 || version == 310 || version == 320) { - if (profile != EEsProfile) { - correct = false; - infoSink.info.message(EPrefixError, "#version: versions 300, 310, and 320 support only the es profile"); - } - profile = EEsProfile; - } else { - if (profile == EEsProfile) { - correct = false; - infoSink.info.message(EPrefixError, "#version: only version 300, 310, and 320 support the es profile"); - if (version >= FirstProfileVersion) - profile = ECoreProfile; - else - profile = ENoProfile; - } - // else: typical desktop case... e.g., "#version 410 core" - } - } - - // Fix version... - switch (version) { - // ES versions - case 100: break; - case 300: break; - case 310: break; - case 320: break; - - // desktop versions - case 110: break; - case 120: break; - case 130: break; - case 140: break; - case 150: break; - case 330: break; - case 400: break; - case 410: break; - case 420: break; - case 430: break; - case 440: break; - case 450: break; - case 460: break; - - // unknown version - default: - correct = false; - infoSink.info.message(EPrefixError, "version not supported"); - if (profile == EEsProfile) - version = 310; - else { - version = 450; - profile = ECoreProfile; - } - break; - } - - // Correct for stage type... - switch (stage) { - case EShLangGeometry: - if ((profile == EEsProfile && version < 310) || - (profile != EEsProfile && version < 150)) { - correct = false; - infoSink.info.message(EPrefixError, "#version: geometry shaders require es profile with version 310 or non-es profile with version 150 or above"); - version = (profile == EEsProfile) ? 310 : 150; - if (profile == EEsProfile || profile == ENoProfile) - profile = ECoreProfile; - } - break; - case EShLangTessControl: - case EShLangTessEvaluation: - if ((profile == EEsProfile && version < 310) || - (profile != EEsProfile && version < 150)) { - correct = false; - infoSink.info.message(EPrefixError, "#version: tessellation shaders require es profile with version 310 or non-es profile with version 150 or above"); - version = (profile == EEsProfile) ? 310 : 400; // 150 supports the extension, correction is to 400 which does not - if (profile == EEsProfile || profile == ENoProfile) - profile = ECoreProfile; - } - break; - case EShLangCompute: - if ((profile == EEsProfile && version < 310) || - (profile != EEsProfile && version < 420)) { - correct = false; - infoSink.info.message(EPrefixError, "#version: compute shaders require es profile with version 310 or above, or non-es profile with version 420 or above"); - version = profile == EEsProfile ? 310 : 420; - } - break; - case EShLangRayGen: - case EShLangIntersect: - case EShLangAnyHit: - case EShLangClosestHit: - case EShLangMiss: - case EShLangCallable: - if (profile == EEsProfile || version < 460) { - correct = false; - infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above"); - version = 460; - } - break; - case EShLangMesh: - case EShLangTask: - if ((profile == EEsProfile && version < 320) || - (profile != EEsProfile && version < 450)) { - correct = false; - infoSink.info.message(EPrefixError, "#version: mesh/task shaders require es profile with version 320 or above, or non-es profile with version 450 or above"); - version = profile == EEsProfile ? 320 : 450; - } - default: - break; - } - - if (profile == EEsProfile && version >= 300 && versionNotFirst) { - correct = false; - infoSink.info.message(EPrefixError, "#version: statement must appear first in es-profile shader; before comments or newlines"); - } - - // Check for SPIR-V compatibility - if (spvVersion.spv != 0) { - switch (profile) { - case EEsProfile: - if (version < 310) { - correct = false; - infoSink.info.message(EPrefixError, "#version: ES shaders for SPIR-V require version 310 or higher"); - version = 310; - } - break; - case ECompatibilityProfile: - infoSink.info.message(EPrefixError, "#version: compilation for SPIR-V does not support the compatibility profile"); - break; - default: - if (spvVersion.vulkan > 0 && version < 140) { - correct = false; - infoSink.info.message(EPrefixError, "#version: Desktop shaders for Vulkan SPIR-V require version 140 or higher"); - version = 140; - } - if (spvVersion.openGl >= 100 && version < 330) { - correct = false; - infoSink.info.message(EPrefixError, "#version: Desktop shaders for OpenGL SPIR-V require version 330 or higher"); - version = 330; - } - break; - } - } - - return correct; -} - -// There are multiple paths in for setting environment stuff. -// TEnvironment takes precedence, for what it sets, so sort all this out. -// Ideally, the internal code could be made to use TEnvironment, but for -// now, translate it to the historically used parameters. -void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages, EShSource& source, - EShLanguage& stage, SpvVersion& spvVersion) -{ - // Set up environmental defaults, first ignoring 'environment'. - if (messages & EShMsgSpvRules) - spvVersion.spv = EShTargetSpv_1_0; - if (messages & EShMsgVulkanRules) { - spvVersion.vulkan = EShTargetVulkan_1_0; - spvVersion.vulkanGlsl = 100; - } else if (spvVersion.spv != 0) - spvVersion.openGl = 100; - - // Now, override, based on any content set in 'environment'. - // 'environment' must be cleared to ESh*None settings when items - // are not being set. - if (environment != nullptr) { - // input language - if (environment->input.languageFamily != EShSourceNone) { - stage = environment->input.stage; - switch (environment->input.dialect) { - case EShClientNone: - break; - case EShClientVulkan: - spvVersion.vulkanGlsl = environment->input.dialectVersion; - spvVersion.vulkanRelaxed = environment->input.vulkanRulesRelaxed; - break; - case EShClientOpenGL: - spvVersion.openGl = environment->input.dialectVersion; - break; - case EShClientCount: - assert(0); - break; - } - switch (environment->input.languageFamily) { - case EShSourceNone: - break; - case EShSourceGlsl: - source = EShSourceGlsl; - messages = static_cast(messages & ~EShMsgReadHlsl); - break; - case EShSourceHlsl: - source = EShSourceHlsl; - messages = static_cast(messages | EShMsgReadHlsl); - break; - case EShSourceCount: - assert(0); - break; - } - } - - // client - switch (environment->client.client) { - case EShClientVulkan: - spvVersion.vulkan = environment->client.version; - break; - default: - break; - } - - // generated code - switch (environment->target.language) { - case EshTargetSpv: - spvVersion.spv = environment->target.version; - break; - default: - break; - } - } -} - -// Most processes are recorded when set in the intermediate representation, -// These are the few that are not. -void RecordProcesses(TIntermediate& intermediate, EShMessages messages, const std::string& sourceEntryPointName) -{ - if ((messages & EShMsgRelaxedErrors) != 0) - intermediate.addProcess("relaxed-errors"); - if ((messages & EShMsgSuppressWarnings) != 0) - intermediate.addProcess("suppress-warnings"); - if ((messages & EShMsgKeepUncalled) != 0) - intermediate.addProcess("keep-uncalled"); - if (sourceEntryPointName.size() > 0) { - intermediate.addProcess("source-entrypoint"); - intermediate.addProcessArgument(sourceEntryPointName); - } -} - -// This is the common setup and cleanup code for PreprocessDeferred and -// CompileDeferred. -// It takes any callable with a signature of -// bool (TParseContextBase& parseContext, TPpContext& ppContext, -// TInputScanner& input, bool versionWillBeError, -// TSymbolTable& , TIntermediate& , -// EShOptimizationLevel , EShMessages ); -// Which returns false if a failure was detected and true otherwise. -// -template -bool ProcessDeferred( - TCompiler* compiler, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const char* const stringNames[], - const char* customPreamble, - const EShOptimizationLevel optLevel, - const TBuiltInResource* resources, - int defaultVersion, // use 100 for ES environment, 110 for desktop; this is the GLSL version, not SPIR-V or Vulkan - EProfile defaultProfile, - // set version/profile to defaultVersion/defaultProfile regardless of the #version - // directive in the source code - bool forceDefaultVersionAndProfile, - int overrideVersion, // overrides version specified by #verison or default version - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages, // warnings/errors/AST; things to print out - TIntermediate& intermediate, // returned tree, etc. - ProcessingContext& processingContext, - bool requireNonempty, - TShader::Includer& includer, - const std::string sourceEntryPointName = "", - const TEnvironment* environment = nullptr, // optional way of fully setting all versions, overriding the above - bool compileOnly = false) -{ - // This must be undone (.pop()) by the caller, after it finishes consuming the created tree. - GetThreadPoolAllocator().push(); - - if (numStrings == 0) - return true; - - // Move to length-based strings, rather than null-terminated strings. - // Also, add strings to include the preamble and to ensure the shader is not null, - // which lets the grammar accept what was a null (post preprocessing) shader. - // - // Shader will look like - // string 0: system preamble - // string 1: custom preamble - // string 2...numStrings+1: user's shader - // string numStrings+2: "int;" - const int numPre = 2; - const int numPost = requireNonempty? 1 : 0; - const int numTotal = numPre + numStrings + numPost; - std::unique_ptr lengths(new size_t[numTotal]); - std::unique_ptr strings(new const char*[numTotal]); - std::unique_ptr names(new const char*[numTotal]); - for (int s = 0; s < numStrings; ++s) { - strings[s + numPre] = shaderStrings[s]; - if (inputLengths == nullptr || inputLengths[s] < 0) - lengths[s + numPre] = strlen(shaderStrings[s]); - else - lengths[s + numPre] = inputLengths[s]; - } - if (stringNames != nullptr) { - for (int s = 0; s < numStrings; ++s) - names[s + numPre] = stringNames[s]; - } else { - for (int s = 0; s < numStrings; ++s) - names[s + numPre] = nullptr; - } - - // Get all the stages, languages, clients, and other environment - // stuff sorted out. - EShSource sourceGuess = (messages & EShMsgReadHlsl) != 0 ? EShSourceHlsl : EShSourceGlsl; - SpvVersion spvVersion; - EShLanguage stage = compiler->getLanguage(); - TranslateEnvironment(environment, messages, sourceGuess, stage, spvVersion); -#ifdef ENABLE_HLSL - EShSource source = sourceGuess; - if (environment != nullptr && environment->target.hlslFunctionality1) - intermediate.setHlslFunctionality1(); -#else - const EShSource source = EShSourceGlsl; -#endif - // First, without using the preprocessor or parser, find the #version, so we know what - // symbol tables, processing rules, etc. to set up. This does not need the extra strings - // outlined above, just the user shader, after the system and user preambles. - glslang::TInputScanner userInput(numStrings, &strings[numPre], &lengths[numPre]); - int version = 0; - EProfile profile = ENoProfile; - bool versionNotFirstToken = false; - bool versionNotFirst = (source == EShSourceHlsl) - ? true - : userInput.scanVersion(version, profile, versionNotFirstToken); - bool versionNotFound = version == 0; - if (forceDefaultVersionAndProfile && source == EShSourceGlsl) { - if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound && - (version != defaultVersion || profile != defaultProfile)) { - compiler->infoSink.info << "Warning, (version, profile) forced to be (" - << defaultVersion << ", " << ProfileName(defaultProfile) - << "), while in source code it is (" - << version << ", " << ProfileName(profile) << ")\n"; - } - - if (versionNotFound) { - versionNotFirstToken = false; - versionNotFirst = false; - versionNotFound = false; - } - version = defaultVersion; - profile = defaultProfile; - } - if (source == EShSourceGlsl && overrideVersion != 0) { - version = overrideVersion; - } - - bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage, - versionNotFirst, defaultVersion, source, version, profile, spvVersion); - bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst)); - bool warnVersionNotFirst = false; - if (! versionWillBeError && versionNotFirstToken) { - if (messages & EShMsgRelaxedErrors) - warnVersionNotFirst = true; - else - versionWillBeError = true; - } - - intermediate.setSource(source); - intermediate.setVersion(version); - intermediate.setProfile(profile); - intermediate.setSpv(spvVersion); - RecordProcesses(intermediate, messages, sourceEntryPointName); - if (spvVersion.vulkan > 0) - intermediate.setOriginUpperLeft(); -#ifdef ENABLE_HLSL - if ((messages & EShMsgHlslOffsets) || source == EShSourceHlsl) - intermediate.setHlslOffsets(); -#endif - if (messages & EShMsgDebugInfo) { - intermediate.setSourceFile(names[numPre]); - for (int s = 0; s < numStrings; ++s) { - // The string may not be null-terminated, so make sure we provide - // the length along with the string. - intermediate.addSourceText(strings[numPre + s], lengths[numPre + s]); - } - } - SetupBuiltinSymbolTable(version, profile, spvVersion, source); - - TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)] - [MapSpvVersionToIndex(spvVersion)] - [MapProfileToIndex(profile)] - [MapSourceToIndex(source)] - [stage]; - - // Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool. - std::unique_ptr symbolTable(new TSymbolTable); - if (cachedTable) - symbolTable->adoptLevels(*cachedTable); - - if (intermediate.getUniqueId() != 0) - symbolTable->overwriteUniqueId(intermediate.getUniqueId()); - - // Add built-in symbols that are potentially context dependent; - // they get popped again further down. - if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion, - stage, source)) { - return false; - } - - if (messages & EShMsgBuiltinSymbolTable) - DumpBuiltinSymbolTable(compiler->infoSink, *symbolTable); - - // - // Now we can process the full shader under proper symbols and rules. - // - - std::unique_ptr parseContext(CreateParseContext(*symbolTable, intermediate, version, profile, source, - stage, compiler->infoSink, - spvVersion, forwardCompatible, messages, false, sourceEntryPointName)); - parseContext->compileOnly = compileOnly; - TPpContext ppContext(*parseContext, names[numPre] ? names[numPre] : "", includer); - - // only GLSL (bison triggered, really) needs an externally set scan context - glslang::TScanContext scanContext(*parseContext); - if (source == EShSourceGlsl) - parseContext->setScanContext(&scanContext); - - parseContext->setPpContext(&ppContext); - parseContext->setLimits(*resources); - if (! goodVersion) - parseContext->addError(); - if (warnVersionNotFirst) { - TSourceLoc loc; - loc.init(); - parseContext->warn(loc, "Illegal to have non-comment, non-whitespace tokens before #version", "#version", ""); - } - - parseContext->initializeExtensionBehavior(); - - // Fill in the strings as outlined above. - std::string preamble; - parseContext->getPreamble(preamble); - strings[0] = preamble.c_str(); - lengths[0] = strlen(strings[0]); - names[0] = nullptr; - strings[1] = customPreamble; - lengths[1] = strlen(strings[1]); - names[1] = nullptr; - assert(2 == numPre); - if (requireNonempty) { - const int postIndex = numStrings + numPre; - strings[postIndex] = "\n int;"; - lengths[postIndex] = strlen(strings[numStrings + numPre]); - names[postIndex] = nullptr; - } - TInputScanner fullInput(numStrings + numPre + numPost, strings.get(), lengths.get(), names.get(), numPre, numPost); - - // Push a new symbol allocation scope that will get used for the shader's globals. - symbolTable->push(); - - bool success = processingContext(*parseContext, ppContext, fullInput, - versionWillBeError, *symbolTable, - intermediate, optLevel, messages); - intermediate.setUniqueId(symbolTable->getMaxSymbolId()); - return success; -} - -// Responsible for keeping track of the most recent source string and line in -// the preprocessor and outputting newlines appropriately if the source string -// or line changes. -class SourceLineSynchronizer { -public: - SourceLineSynchronizer(const std::function& lastSourceIndex, - std::string* output) - : getLastSourceIndex(lastSourceIndex), output(output), lastSource(-1), lastLine(0) {} -// SourceLineSynchronizer(const SourceLineSynchronizer&) = delete; -// SourceLineSynchronizer& operator=(const SourceLineSynchronizer&) = delete; - - // Sets the internally tracked source string index to that of the most - // recently read token. If we switched to a new source string, returns - // true and inserts a newline. Otherwise, returns false and outputs nothing. - bool syncToMostRecentString() { - if (getLastSourceIndex() != lastSource) { - // After switching to a new source string, we need to reset lastLine - // because line number resets every time a new source string is - // used. We also need to output a newline to separate the output - // from the previous source string (if there is one). - if (lastSource != -1 || lastLine != 0) - *output += '\n'; - lastSource = getLastSourceIndex(); - lastLine = -1; - return true; - } - return false; - } - - // Calls syncToMostRecentString() and then sets the internally tracked line - // number to tokenLine. If we switched to a new line, returns true and inserts - // newlines appropriately. Otherwise, returns false and outputs nothing. - bool syncToLine(int tokenLine) { - syncToMostRecentString(); - const bool newLineStarted = lastLine < tokenLine; - for (; lastLine < tokenLine; ++lastLine) { - if (lastLine > 0) *output += '\n'; - } - return newLineStarted; - } - - // Sets the internally tracked line number to newLineNum. - void setLineNum(int newLineNum) { lastLine = newLineNum; } - -private: - SourceLineSynchronizer& operator=(const SourceLineSynchronizer&); - - // A function for getting the index of the last valid source string we've - // read tokens from. - const std::function getLastSourceIndex; - // output string for newlines. - std::string* output; - // lastSource is the source string index (starting from 0) of the last token - // processed. It is tracked in order for newlines to be inserted when a new - // source string starts. -1 means we haven't started processing any source - // string. - int lastSource; - // lastLine is the line number (starting from 1) of the last token processed. - // It is tracked in order for newlines to be inserted when a token appears - // on a new line. 0 means we haven't started processing any line in the - // current source string. - int lastLine; -}; - -// DoPreprocessing is a valid ProcessingContext template argument, -// which only performs the preprocessing step of compilation. -// It places the result in the "string" argument to its constructor. -// -// This is not an officially supported or fully working path. -struct DoPreprocessing { - explicit DoPreprocessing(std::string* string): outputString(string) {} - bool operator()(TParseContextBase& parseContext, TPpContext& ppContext, - TInputScanner& input, bool versionWillBeError, - TSymbolTable&, TIntermediate&, - EShOptimizationLevel, EShMessages) - { - // This is a list of tokens that do not require a space before or after. - static const std::string noNeededSpaceBeforeTokens = ";)[].,"; - static const std::string noNeededSpaceAfterTokens = ".(["; - glslang::TPpToken ppToken; - - parseContext.setScanner(&input); - ppContext.setInput(input, versionWillBeError); - - std::string outputBuffer; - SourceLineSynchronizer lineSync( - std::bind(&TInputScanner::getLastValidSourceIndex, &input), &outputBuffer); - - parseContext.setExtensionCallback([&lineSync, &outputBuffer]( - int line, const char* extension, const char* behavior) { - lineSync.syncToLine(line); - outputBuffer += "#extension "; - outputBuffer += extension; - outputBuffer += " : "; - outputBuffer += behavior; - }); - - parseContext.setLineCallback([&lineSync, &outputBuffer, &parseContext]( - int curLineNum, int newLineNum, bool hasSource, int sourceNum, const char* sourceName) { - // SourceNum is the number of the source-string that is being parsed. - lineSync.syncToLine(curLineNum); - outputBuffer += "#line "; - outputBuffer += std::to_string(newLineNum); - if (hasSource) { - outputBuffer += ' '; - if (sourceName != nullptr) { - outputBuffer += '\"'; - outputBuffer += sourceName; - outputBuffer += '\"'; - } else { - outputBuffer += std::to_string(sourceNum); - } - } - if (parseContext.lineDirectiveShouldSetNextLine()) { - // newLineNum is the new line number for the line following the #line - // directive. So the new line number for the current line is - newLineNum -= 1; - } - outputBuffer += '\n'; - // And we are at the next line of the #line directive now. - lineSync.setLineNum(newLineNum + 1); - }); - - parseContext.setVersionCallback( - [&lineSync, &outputBuffer](int line, int version, const char* str) { - lineSync.syncToLine(line); - outputBuffer += "#version "; - outputBuffer += std::to_string(version); - if (str) { - outputBuffer += ' '; - outputBuffer += str; - } - }); - - parseContext.setPragmaCallback([&lineSync, &outputBuffer]( - int line, const glslang::TVector& ops) { - lineSync.syncToLine(line); - outputBuffer += "#pragma "; - for(size_t i = 0; i < ops.size(); ++i) { - outputBuffer += ops[i].c_str(); - } - }); - - parseContext.setErrorCallback([&lineSync, &outputBuffer]( - int line, const char* errorMessage) { - lineSync.syncToLine(line); - outputBuffer += "#error "; - outputBuffer += errorMessage; - }); - - int lastToken = EndOfInput; // lastToken records the last token processed. - std::string lastTokenName; - do { - int token = ppContext.tokenize(ppToken); - if (token == EndOfInput) - break; - - bool isNewString = lineSync.syncToMostRecentString(); - bool isNewLine = lineSync.syncToLine(ppToken.loc.line); - - if (isNewLine) { - // Don't emit whitespace onto empty lines. - // Copy any whitespace characters at the start of a line - // from the input to the output. - outputBuffer += std::string(ppToken.loc.column - 1, ' '); - } - - // Output a space in between tokens, but not at the start of a line, - // and also not around special tokens. This helps with readability - // and consistency. - if (!isNewString && !isNewLine && lastToken != EndOfInput) { - // left parenthesis need a leading space, except it is in a function-call-like context. - // examples: `for (xxx)`, `a * (b + c)`, `vec(2.0)`, `foo(x, y, z)` - if (token == '(') { - if (lastToken != PpAtomIdentifier || - lastTokenName == "if" || - lastTokenName == "for" || - lastTokenName == "while" || - lastTokenName == "switch") - outputBuffer += ' '; - } else if ((noNeededSpaceBeforeTokens.find((char)token) == std::string::npos) && - (noNeededSpaceAfterTokens.find((char)lastToken) == std::string::npos)) { - outputBuffer += ' '; - } - } - if (token == PpAtomIdentifier) - lastTokenName = ppToken.name; - lastToken = token; - if (token == PpAtomConstString) - outputBuffer += "\""; - outputBuffer += ppToken.name; - if (token == PpAtomConstString) - outputBuffer += "\""; - } while (true); - outputBuffer += '\n'; - *outputString = std::move(outputBuffer); - - bool success = true; - if (parseContext.getNumErrors() > 0) { - success = false; - parseContext.infoSink.info.prefix(EPrefixError); - parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n"; - } - return success; - } - std::string* outputString; -}; - -// DoFullParse is a valid ProcessingConext template argument for fully -// parsing the shader. It populates the "intermediate" with the AST. -struct DoFullParse{ - bool operator()(TParseContextBase& parseContext, TPpContext& ppContext, - TInputScanner& fullInput, bool versionWillBeError, - TSymbolTable&, TIntermediate& intermediate, - EShOptimizationLevel optLevel, EShMessages messages) - { - bool success = true; - // Parse the full shader. - if (! parseContext.parseShaderStrings(ppContext, fullInput, versionWillBeError)) - success = false; - - if (success && intermediate.getTreeRoot()) { - if (optLevel == EShOptNoGeneration) - parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested."); - else - success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.getLanguage()); - } else if (! success) { - parseContext.infoSink.info.prefix(EPrefixError); - parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n"; - } - - if (messages & EShMsgAST) - intermediate.output(parseContext.infoSink, true); - - return success; - } -}; - -// Take a single compilation unit, and run the preprocessor on it. -// Return: True if there were no issues found in preprocessing, -// False if during preprocessing any unknown version, pragmas or -// extensions were found. -// -// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string -// is not an officially supported or fully working path. -bool PreprocessDeferred( - TCompiler* compiler, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const char* const stringNames[], - const char* preamble, - const EShOptimizationLevel optLevel, - const TBuiltInResource* resources, - int defaultVersion, // use 100 for ES environment, 110 for desktop - EProfile defaultProfile, - bool forceDefaultVersionAndProfile, - int overrideVersion, // use 0 if not overriding GLSL version - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages, // warnings/errors/AST; things to print out - TShader::Includer& includer, - TIntermediate& intermediate, // returned tree, etc. - std::string* outputString, - TEnvironment* environment = nullptr) -{ - DoPreprocessing parser(outputString); - return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, - preamble, optLevel, resources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, overrideVersion, - forwardCompatible, messages, intermediate, parser, - false, includer, "", environment); -} - -// -// do a partial compile on the given strings for a single compilation unit -// for a potential deferred link into a single stage (and deferred full compile of that -// stage through machine-dependent compilation). -// -// all preprocessing, parsing, semantic checks, etc. for a single compilation unit -// are done here. -// -// return: the tree and other information is filled into the intermediate argument, -// and true is returned by the function for success. -// -bool CompileDeferred( - TCompiler* compiler, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const char* const stringNames[], - const char* preamble, - const EShOptimizationLevel optLevel, - const TBuiltInResource* resources, - int defaultVersion, // use 100 for ES environment, 110 for desktop - EProfile defaultProfile, - bool forceDefaultVersionAndProfile, - int overrideVersion, // use 0 if not overriding GLSL version - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages, // warnings/errors/AST; things to print out - TIntermediate& intermediate,// returned tree, etc. - TShader::Includer& includer, - const std::string sourceEntryPointName = "", - TEnvironment* environment = nullptr, - bool compileOnly = false) -{ - DoFullParse parser; - return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, - preamble, optLevel, resources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, overrideVersion, - forwardCompatible, messages, intermediate, parser, - true, includer, sourceEntryPointName, environment, compileOnly); -} - -} // end anonymous namespace for local functions - -// -// ShInitialize() should be called exactly once per process, not per thread. -// -int ShInitialize() -{ - const std::lock_guard lock(init_lock); - ++NumberOfClients; - - if (PerProcessGPA == nullptr) - PerProcessGPA = new TPoolAllocator(); - - glslang::TScanContext::fillInKeywordMap(); -#ifdef ENABLE_HLSL - glslang::HlslScanContext::fillInKeywordMap(); -#endif - - return 1; -} - -// -// Driver calls these to create and destroy compiler/linker -// objects. -// - -ShHandle ShConstructCompiler(const EShLanguage language, int /*debugOptions unused*/) -{ - TShHandleBase* base = static_cast(ConstructCompiler(language, 0)); - - return reinterpret_cast(base); -} - -ShHandle ShConstructLinker(const EShExecutable executable, int /*debugOptions unused*/) -{ - TShHandleBase* base = static_cast(ConstructLinker(executable, 0)); - - return reinterpret_cast(base); -} - -ShHandle ShConstructUniformMap() -{ - TShHandleBase* base = static_cast(ConstructUniformMap()); - - return reinterpret_cast(base); -} - -void ShDestruct(ShHandle handle) -{ - if (handle == nullptr) - return; - - TShHandleBase* base = static_cast(handle); - - if (base->getAsCompiler()) - DeleteCompiler(base->getAsCompiler()); - else if (base->getAsLinker()) - DeleteLinker(base->getAsLinker()); - else if (base->getAsUniformMap()) - DeleteUniformMap(base->getAsUniformMap()); -} - -// -// Cleanup symbol tables -// -int ShFinalize() -{ - const std::lock_guard lock(init_lock); - --NumberOfClients; - assert(NumberOfClients >= 0); - if (NumberOfClients > 0) - return 1; - - for (int version = 0; version < VersionCount; ++version) { - for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) { - for (int p = 0; p < ProfileCount; ++p) { - for (int source = 0; source < SourceCount; ++source) { - for (int stage = 0; stage < EShLangCount; ++stage) { - delete SharedSymbolTables[version][spvVersion][p][source][stage]; - SharedSymbolTables[version][spvVersion][p][source][stage] = nullptr; - } - } - } - } - } - - for (int version = 0; version < VersionCount; ++version) { - for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) { - for (int p = 0; p < ProfileCount; ++p) { - for (int source = 0; source < SourceCount; ++source) { - for (int pc = 0; pc < EPcCount; ++pc) { - delete CommonSymbolTable[version][spvVersion][p][source][pc]; - CommonSymbolTable[version][spvVersion][p][source][pc] = nullptr; - } - } - } - } - } - - if (PerProcessGPA != nullptr) { - delete PerProcessGPA; - PerProcessGPA = nullptr; - } - - glslang::TScanContext::deleteKeywordMap(); -#ifdef ENABLE_HLSL - glslang::HlslScanContext::deleteKeywordMap(); -#endif - - return 1; -} - -// -// Do a full compile on the given strings for a single compilation unit -// forming a complete stage. The result of the machine dependent compilation -// is left in the provided compile object. -// -// Return: The return value is really boolean, indicating -// success (1) or failure (0). -// -int ShCompile( - const ShHandle handle, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const EShOptimizationLevel optLevel, - const TBuiltInResource* resources, - int /*debugOptions*/, - int defaultVersion, // use 100 for ES environment, 110 for desktop - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages // warnings/errors/AST; things to print out - ) -{ - // Map the generic handle to the C++ object - if (handle == nullptr) - return 0; - - TShHandleBase* base = reinterpret_cast(handle); - TCompiler* compiler = base->getAsCompiler(); - if (compiler == nullptr) - return 0; - - SetThreadPoolAllocator(compiler->getPool()); - - compiler->infoSink.info.erase(); - compiler->infoSink.debug.erase(); - - TIntermediate intermediate(compiler->getLanguage()); - TShader::ForbidIncluder includer; - bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr, - "", optLevel, resources, defaultVersion, ENoProfile, false, 0, - forwardCompatible, messages, intermediate, includer); - - // - // Call the machine dependent compiler - // - if (success && intermediate.getTreeRoot() && optLevel != EShOptNoGeneration) - success = compiler->compile(intermediate.getTreeRoot(), intermediate.getVersion(), intermediate.getProfile()); - - intermediate.removeTree(); - - // Throw away all the temporary memory used by the compilation process. - // The push was done in the CompileDeferred() call above. - GetThreadPoolAllocator().pop(); - - return success ? 1 : 0; -} - -// -// Link the given compile objects. -// -// Return: The return value of is really boolean, indicating -// success or failure. -// -int ShLinkExt( - const ShHandle linkHandle, - const ShHandle compHandles[], - const int numHandles) -{ - if (linkHandle == nullptr || numHandles == 0) - return 0; - - THandleList cObjects; - - for (int i = 0; i < numHandles; ++i) { - if (compHandles[i] == nullptr) - return 0; - TShHandleBase* base = reinterpret_cast(compHandles[i]); - if (base->getAsLinker()) { - cObjects.push_back(base->getAsLinker()); - } - if (base->getAsCompiler()) - cObjects.push_back(base->getAsCompiler()); - - if (cObjects[i] == nullptr) - return 0; - } - - TShHandleBase* base = reinterpret_cast(linkHandle); - TLinker* linker = static_cast(base->getAsLinker()); - - if (linker == nullptr) - return 0; - - SetThreadPoolAllocator(linker->getPool()); - linker->infoSink.info.erase(); - - for (int i = 0; i < numHandles; ++i) { - if (cObjects[i]->getAsCompiler()) { - if (! cObjects[i]->getAsCompiler()->linkable()) { - linker->infoSink.info.message(EPrefixError, "Not all shaders have valid object code."); - return 0; - } - } - } - - bool ret = linker->link(cObjects); - - return ret ? 1 : 0; -} - -// -// ShSetEncrpytionMethod is a place-holder for specifying -// how source code is encrypted. -// -void ShSetEncryptionMethod(ShHandle handle) -{ - if (handle == nullptr) - return; -} - -// -// Return any compiler/linker/uniformmap log of messages for the application. -// -const char* ShGetInfoLog(const ShHandle handle) -{ - if (handle == nullptr) - return nullptr; - - TShHandleBase* base = static_cast(handle); - TInfoSink* infoSink; - - if (base->getAsCompiler()) - infoSink = &(base->getAsCompiler()->getInfoSink()); - else if (base->getAsLinker()) - infoSink = &(base->getAsLinker()->getInfoSink()); - else - return nullptr; - - infoSink->info << infoSink->debug.c_str(); - return infoSink->info.c_str(); -} - -// -// Return the resulting binary code from the link process. Structure -// is machine dependent. -// -const void* ShGetExecutable(const ShHandle handle) -{ - if (handle == nullptr) - return nullptr; - - TShHandleBase* base = reinterpret_cast(handle); - - TLinker* linker = static_cast(base->getAsLinker()); - if (linker == nullptr) - return nullptr; - - return linker->getObjectCode(); -} - -// -// Let the linker know where the application said it's attributes are bound. -// The linker does not use these values, they are remapped by the ICD or -// hardware. It just needs them to know what's aliased. -// -// Return: The return value of is really boolean, indicating -// success or failure. -// -int ShSetVirtualAttributeBindings(const ShHandle handle, const ShBindingTable* table) -{ - if (handle == nullptr) - return 0; - - TShHandleBase* base = reinterpret_cast(handle); - TLinker* linker = static_cast(base->getAsLinker()); - - if (linker == nullptr) - return 0; - - linker->setAppAttributeBindings(table); - - return 1; -} - -// -// Let the linker know where the predefined attributes have to live. -// -int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* table) -{ - if (handle == nullptr) - return 0; - - TShHandleBase* base = reinterpret_cast(handle); - TLinker* linker = static_cast(base->getAsLinker()); - - if (linker == nullptr) - return 0; - - linker->setFixedAttributeBindings(table); - return 1; -} - -// -// Some attribute locations are off-limits to the linker... -// -int ShExcludeAttributes(const ShHandle handle, int *attributes, int count) -{ - if (handle == nullptr) - return 0; - - TShHandleBase* base = reinterpret_cast(handle); - TLinker* linker = static_cast(base->getAsLinker()); - if (linker == nullptr) - return 0; - - linker->setExcludedAttributes(attributes, count); - - return 1; -} - -// -// Return the index for OpenGL to use for knowing where a uniform lives. -// -// Return: The return value of is really boolean, indicating -// success or failure. -// -int ShGetUniformLocation(const ShHandle handle, const char* name) -{ - if (handle == nullptr) - return -1; - - TShHandleBase* base = reinterpret_cast(handle); - TUniformMap* uniformMap= base->getAsUniformMap(); - if (uniformMap == nullptr) - return -1; - - return uniformMap->getLocation(name); -} - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// Deferred-Lowering C++ Interface -// ----------------------------------- -// -// Below is a new alternate C++ interface that might potentially replace the above -// opaque handle-based interface. -// -// See more detailed comment in ShaderLang.h -// - -namespace glslang { - -Version GetVersion() -{ - Version version; - version.major = GLSLANG_VERSION_MAJOR; - version.minor = GLSLANG_VERSION_MINOR; - version.patch = GLSLANG_VERSION_PATCH; - version.flavor = GLSLANG_VERSION_FLAVOR; - return version; -} - -#define QUOTE(s) #s -#define STR(n) QUOTE(n) - -const char* GetEsslVersionString() -{ - return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR( - GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR; -} - -const char* GetGlslVersionString() -{ - return "4.60 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR( - GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR; -} - -int GetKhronosToolId() -{ - return 8; -} - -bool InitializeProcess() -{ - return ShInitialize() != 0; -} - -void FinalizeProcess() -{ - ShFinalize(); -} - -class TDeferredCompiler : public TCompiler { -public: - TDeferredCompiler(EShLanguage s, TInfoSink& i) : TCompiler(s, i) { } - virtual bool compile(TIntermNode*, int = 0, EProfile = ENoProfile) { return true; } -}; - -TShader::TShader(EShLanguage s) - : stage(s), lengths(nullptr), stringNames(nullptr), preamble(""), overrideVersion(0) -{ - pool = new TPoolAllocator; - infoSink = new TInfoSink; - compiler = new TDeferredCompiler(stage, *infoSink); - intermediate = new TIntermediate(s); - - // clear environment (avoid constructors in them for use in a C interface) - environment.input.languageFamily = EShSourceNone; - environment.input.dialect = EShClientNone; - environment.input.vulkanRulesRelaxed = false; - environment.client.client = EShClientNone; - environment.target.language = EShTargetNone; - environment.target.hlslFunctionality1 = false; -} - -TShader::~TShader() -{ - delete infoSink; - delete compiler; - delete intermediate; - delete pool; -} - -void TShader::setStrings(const char* const* s, int n) -{ - strings = s; - numStrings = n; - lengths = nullptr; -} - -void TShader::setStringsWithLengths(const char* const* s, const int* l, int n) -{ - strings = s; - numStrings = n; - lengths = l; -} - -void TShader::setStringsWithLengthsAndNames( - const char* const* s, const int* l, const char* const* names, int n) -{ - strings = s; - numStrings = n; - lengths = l; - stringNames = names; -} - -void TShader::setEntryPoint(const char* entryPoint) -{ - intermediate->setEntryPointName(entryPoint); -} - -void TShader::setSourceEntryPoint(const char* name) -{ - sourceEntryPointName = name; -} - -// Log initial settings and transforms. -// See comment for class TProcesses. -void TShader::addProcesses(const std::vector& p) -{ - intermediate->addProcesses(p); -} - -void TShader::setUniqueId(unsigned long long id) -{ - intermediate->setUniqueId(id); -} - -void TShader::setOverrideVersion(int version) -{ - overrideVersion = version; -} - -void TShader::setDebugInfo(bool debugInfo) { intermediate->setDebugInfo(debugInfo); } -void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); } -void TShader::setDxPositionW(bool invert) { intermediate->setDxPositionW(invert); } -void TShader::setEnhancedMsgs() { intermediate->setEnhancedMsgs(); } -void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); } - -// Set binding base for given resource type -void TShader::setShiftBinding(TResourceType res, unsigned int base) { - intermediate->setShiftBinding(res, base); -} - -// Set binding base for given resource type for a given binding set. -void TShader::setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set) { - intermediate->setShiftBindingForSet(res, base, set); -} - -// Set binding base for sampler types -void TShader::setShiftSamplerBinding(unsigned int base) { setShiftBinding(EResSampler, base); } -// Set binding base for texture types (SRV) -void TShader::setShiftTextureBinding(unsigned int base) { setShiftBinding(EResTexture, base); } -// Set binding base for image types -void TShader::setShiftImageBinding(unsigned int base) { setShiftBinding(EResImage, base); } -// Set binding base for uniform buffer objects (CBV) -void TShader::setShiftUboBinding(unsigned int base) { setShiftBinding(EResUbo, base); } -// Synonym for setShiftUboBinding, to match HLSL language. -void TShader::setShiftCbufferBinding(unsigned int base) { setShiftBinding(EResUbo, base); } -// Set binding base for UAV (unordered access view) -void TShader::setShiftUavBinding(unsigned int base) { setShiftBinding(EResUav, base); } -// Set binding base for SSBOs -void TShader::setShiftSsboBinding(unsigned int base) { setShiftBinding(EResSsbo, base); } -// Enables binding automapping using TIoMapper -void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); } -// Enables position.Y output negation in vertex shader - -// Fragile: currently within one stage: simple auto-assignment of location -void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); } -void TShader::addUniformLocationOverride(const char* name, int loc) -{ - intermediate->addUniformLocationOverride(name, loc); -} -void TShader::setUniformLocationBase(int base) -{ - intermediate->setUniformLocationBase(base); -} -void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); } -void TShader::setResourceSetBinding(const std::vector& base) { intermediate->setResourceSetBinding(base); } -void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); } - -void TShader::addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing) { intermediate->addBlockStorageOverride(nameStr, backing); } - -void TShader::setGlobalUniformBlockName(const char* name) { intermediate->setGlobalUniformBlockName(name); } -void TShader::setGlobalUniformSet(unsigned int set) { intermediate->setGlobalUniformSet(set); } -void TShader::setGlobalUniformBinding(unsigned int binding) { intermediate->setGlobalUniformBinding(binding); } - -void TShader::setAtomicCounterBlockName(const char* name) { intermediate->setAtomicCounterBlockName(name); } -void TShader::setAtomicCounterBlockSet(unsigned int set) { intermediate->setAtomicCounterBlockSet(set); } - -#ifdef ENABLE_HLSL -// See comment above TDefaultHlslIoMapper in iomapper.cpp: -void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); } -void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); } -#endif - -// -// Turn the shader strings into a parse tree in the TIntermediate. -// -// Returns true for success. -// -bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages messages, Includer& includer) -{ - SetThreadPoolAllocator(pool); - - if (! preamble) - preamble = ""; - - return CompileDeferred(compiler, strings, numStrings, lengths, stringNames, - preamble, EShOptNone, builtInResources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, overrideVersion, - forwardCompatible, messages, *intermediate, includer, sourceEntryPointName, - &environment, compileOnly); -} - -// Fill in a string with the result of preprocessing ShaderStrings -// Returns true if all extensions, pragmas and version strings were valid. -// -// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string -// is not an officially supported or fully working path. -bool TShader::preprocess(const TBuiltInResource* builtInResources, - int defaultVersion, EProfile defaultProfile, - bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages message, - std::string* output_string, - Includer& includer) -{ - SetThreadPoolAllocator(pool); - - if (! preamble) - preamble = ""; - - return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble, - EShOptNone, builtInResources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, overrideVersion, - forwardCompatible, message, includer, *intermediate, output_string, - &environment); -} - -const char* TShader::getInfoLog() -{ - return infoSink->info.c_str(); -} - -const char* TShader::getInfoDebugLog() -{ - return infoSink->debug.c_str(); -} - -TProgram::TProgram() : reflection(nullptr), linked(false) -{ - pool = new TPoolAllocator; - infoSink = new TInfoSink; - for (int s = 0; s < EShLangCount; ++s) { - intermediate[s] = nullptr; - newedIntermediate[s] = false; - } -} - -TProgram::~TProgram() -{ - delete infoSink; - delete reflection; - - for (int s = 0; s < EShLangCount; ++s) - if (newedIntermediate[s]) - delete intermediate[s]; - - delete pool; -} - -// -// Merge the compilation units within each stage into a single TIntermediate. -// All starting compilation units need to be the result of calling TShader::parse(). -// -// Return true for success. -// -bool TProgram::link(EShMessages messages) -{ - if (linked) - return false; - linked = true; - - bool error = false; - - SetThreadPoolAllocator(pool); - - for (int s = 0; s < EShLangCount; ++s) { - if (! linkStage((EShLanguage)s, messages)) - error = true; - } - - if (!error) { - if (! crossStageCheck(messages)) - error = true; - } - - return ! error; -} - -// -// Merge the compilation units within the given stage into a single TIntermediate. -// -// Return true for success. -// -bool TProgram::linkStage(EShLanguage stage, EShMessages messages) -{ - if (stages[stage].size() == 0) - return true; - - int numEsShaders = 0, numNonEsShaders = 0; - for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) { - if ((*it)->intermediate->getProfile() == EEsProfile) { - numEsShaders++; - } else { - numNonEsShaders++; - } - } - - if (numEsShaders > 0 && numNonEsShaders > 0) { - infoSink->info.message(EPrefixError, "Cannot mix ES profile with non-ES profile shaders"); - return false; - } else if (numEsShaders > 1) { - infoSink->info.message(EPrefixError, "Cannot attach multiple ES shaders of the same type to a single program"); - return false; - } - - // - // Be efficient for the common single compilation unit per stage case, - // reusing it's TIntermediate instead of merging into a new one. - // - TIntermediate *firstIntermediate = stages[stage].front()->intermediate; - if (stages[stage].size() == 1) - intermediate[stage] = firstIntermediate; - else { - intermediate[stage] = new TIntermediate(stage, - firstIntermediate->getVersion(), - firstIntermediate->getProfile()); - intermediate[stage]->setLimits(firstIntermediate->getLimits()); - if (firstIntermediate->getEnhancedMsgs()) - intermediate[stage]->setEnhancedMsgs(); - - // The new TIntermediate must use the same origin as the original TIntermediates. - // Otherwise linking will fail due to different coordinate systems. - if (firstIntermediate->getOriginUpperLeft()) { - intermediate[stage]->setOriginUpperLeft(); - } - intermediate[stage]->setSpv(firstIntermediate->getSpv()); - - newedIntermediate[stage] = true; - } - - if (messages & EShMsgAST) - infoSink->info << "\nLinked " << StageName(stage) << " stage:\n\n"; - - if (stages[stage].size() > 1) { - std::list::const_iterator it; - for (it = stages[stage].begin(); it != stages[stage].end(); ++it) - intermediate[stage]->merge(*infoSink, *(*it)->intermediate); - } - intermediate[stage]->finalCheck(*infoSink, (messages & EShMsgKeepUncalled) != 0); - - if (messages & EShMsgAST) - intermediate[stage]->output(*infoSink, true); - - return intermediate[stage]->getNumErrors() == 0; -} - -// -// Check that there are no errors in linker objects accross stages -// -// Return true if no errors. -// -bool TProgram::crossStageCheck(EShMessages) { - - // make temporary intermediates to hold the linkage symbols for each linking interface - // while we do the checks - // Independent interfaces are: - // all uniform variables and blocks - // all buffer blocks - // all in/out on a stage boundary - - TVector activeStages; - for (int s = 0; s < EShLangCount; ++s) { - if (intermediate[s]) - activeStages.push_back(intermediate[s]); - } - - // no extra linking if there is only one stage - if (! (activeStages.size() > 1)) - return true; - - // setup temporary tree to hold unfirom objects from different stages - TIntermediate* firstIntermediate = activeStages.front(); - TIntermediate uniforms(EShLangCount, - firstIntermediate->getVersion(), - firstIntermediate->getProfile()); - uniforms.setSpv(firstIntermediate->getSpv()); - - TIntermAggregate uniformObjects(EOpLinkerObjects); - TIntermAggregate root(EOpSequence); - root.getSequence().push_back(&uniformObjects); - uniforms.setTreeRoot(&root); - - bool error = false; - - // merge uniforms from all stages into a single intermediate - for (unsigned int i = 0; i < activeStages.size(); ++i) { - uniforms.mergeUniformObjects(*infoSink, *activeStages[i]); - } - error |= uniforms.getNumErrors() != 0; - - // copy final definition of global block back into each stage - for (unsigned int i = 0; i < activeStages.size(); ++i) { - // We only want to merge into already existing global uniform blocks. - // A stage that doesn't already know about the global doesn't care about it's content. - // Otherwise we end up pointing to the same object between different stages - // and that will break binding/set remappings - bool mergeExistingOnly = true; - activeStages[i]->mergeGlobalUniformBlocks(*infoSink, uniforms, mergeExistingOnly); - } - - // compare cross stage symbols for each stage boundary - for (unsigned int i = 1; i < activeStages.size(); ++i) { - activeStages[i - 1]->checkStageIO(*infoSink, *activeStages[i]); - error |= (activeStages[i - 1]->getNumErrors() != 0); - } - - return !error; -} - -const char* TProgram::getInfoLog() -{ - return infoSink->info.c_str(); -} - -const char* TProgram::getInfoDebugLog() -{ - return infoSink->debug.c_str(); -} - -// -// Reflection implementation. -// - -bool TProgram::buildReflection(int opts) -{ - if (! linked || reflection != nullptr) - return false; - - int firstStage = EShLangVertex, lastStage = EShLangFragment; - - if (opts & EShReflectionIntermediateIO) { - // if we're reflecting intermediate I/O, determine the first and last stage linked and use those as the - // boundaries for which stages generate pipeline inputs/outputs - firstStage = EShLangCount; - lastStage = 0; - for (int s = 0; s < EShLangCount; ++s) { - if (intermediate[s]) { - firstStage = std::min(firstStage, s); - lastStage = std::max(lastStage, s); - } - } - } - - reflection = new TReflection((EShReflectionOptions)opts, (EShLanguage)firstStage, (EShLanguage)lastStage); - - for (int s = 0; s < EShLangCount; ++s) { - if (intermediate[s]) { - if (! reflection->addStage((EShLanguage)s, *intermediate[s])) - return false; - } - } - - return true; -} - -unsigned TProgram::getLocalSize(int dim) const { return reflection->getLocalSize(dim); } -int TProgram::getReflectionIndex(const char* name) const { return reflection->getIndex(name); } -int TProgram::getReflectionPipeIOIndex(const char* name, const bool inOrOut) const - { return reflection->getPipeIOIndex(name, inOrOut); } - -int TProgram::getNumUniformVariables() const { return reflection->getNumUniforms(); } -const TObjectReflection& TProgram::getUniform(int index) const { return reflection->getUniform(index); } -int TProgram::getNumUniformBlocks() const { return reflection->getNumUniformBlocks(); } -const TObjectReflection& TProgram::getUniformBlock(int index) const { return reflection->getUniformBlock(index); } -int TProgram::getNumPipeInputs() const { return reflection->getNumPipeInputs(); } -const TObjectReflection& TProgram::getPipeInput(int index) const { return reflection->getPipeInput(index); } -int TProgram::getNumPipeOutputs() const { return reflection->getNumPipeOutputs(); } -const TObjectReflection& TProgram::getPipeOutput(int index) const { return reflection->getPipeOutput(index); } -int TProgram::getNumBufferVariables() const { return reflection->getNumBufferVariables(); } -const TObjectReflection& TProgram::getBufferVariable(int index) const { return reflection->getBufferVariable(index); } -int TProgram::getNumBufferBlocks() const { return reflection->getNumStorageBuffers(); } -const TObjectReflection& TProgram::getBufferBlock(int index) const { return reflection->getStorageBufferBlock(index); } -int TProgram::getNumAtomicCounters() const { return reflection->getNumAtomicCounters(); } -const TObjectReflection& TProgram::getAtomicCounter(int index) const { return reflection->getAtomicCounter(index); } -void TProgram::dumpReflection() { if (reflection != nullptr) reflection->dump(); } - -// -// I/O mapping implementation. -// -bool TProgram::mapIO(TIoMapResolver* pResolver, TIoMapper* pIoMapper) -{ - if (! linked) - return false; - TIoMapper* ioMapper = nullptr; - TIoMapper defaultIOMapper; - if (pIoMapper == nullptr) - ioMapper = &defaultIOMapper; - else - ioMapper = pIoMapper; - for (int s = 0; s < EShLangCount; ++s) { - if (intermediate[s]) { - if (! ioMapper->addStage((EShLanguage)s, *intermediate[s], *infoSink, pResolver)) - return false; - } - } - - return ioMapper->doMap(pResolver, *infoSink); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp b/3rdparty/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp deleted file mode 100644 index 1d08797a..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/SpirvIntrinsics.cpp +++ /dev/null @@ -1,360 +0,0 @@ -// -// Copyright(C) 2021 Advanced Micro Devices, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// GL_EXT_spirv_intrinsics -// -#include "../Include/intermediate.h" -#include "../Include/SpirvIntrinsics.h" -#include "../Include/Types.h" -#include "ParseHelper.h" - -namespace glslang { - -bool TSpirvTypeParameter::operator==(const TSpirvTypeParameter& rhs) const -{ - if (getAsConstant() != nullptr) - return getAsConstant()->getConstArray() == rhs.getAsConstant()->getConstArray(); - - assert(getAsType() != nullptr); - return *getAsType() == *rhs.getAsType(); -} - -// -// Handle SPIR-V requirements -// -TSpirvRequirement* TParseContext::makeSpirvRequirement(const TSourceLoc& loc, const TString& name, - const TIntermAggregate* extensions, - const TIntermAggregate* capabilities) -{ - TSpirvRequirement* spirvReq = new TSpirvRequirement; - - if (name == "extensions") { - assert(extensions); - for (auto extension : extensions->getSequence()) { - assert(extension->getAsConstantUnion()); - spirvReq->extensions.insert(*extension->getAsConstantUnion()->getConstArray()[0].getSConst()); - } - } else if (name == "capabilities") { - assert(capabilities); - for (auto capability : capabilities->getSequence()) { - assert(capability->getAsConstantUnion()); - spirvReq->capabilities.insert(capability->getAsConstantUnion()->getConstArray()[0].getIConst()); - } - } else - error(loc, "unknown SPIR-V requirement", name.c_str(), ""); - - return spirvReq; -} - -TSpirvRequirement* TParseContext::mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1, - TSpirvRequirement* spirvReq2) -{ - // Merge the second SPIR-V requirement to the first one - if (!spirvReq2->extensions.empty()) { - if (spirvReq1->extensions.empty()) - spirvReq1->extensions = spirvReq2->extensions; - else - error(loc, "too many SPIR-V requirements", "extensions", ""); - } - - if (!spirvReq2->capabilities.empty()) { - if (spirvReq1->capabilities.empty()) - spirvReq1->capabilities = spirvReq2->capabilities; - else - error(loc, "too many SPIR-V requirements", "capabilities", ""); - } - - return spirvReq1; -} - -void TIntermediate::insertSpirvRequirement(const TSpirvRequirement* spirvReq) -{ - if (!spirvRequirement) - spirvRequirement = new TSpirvRequirement; - - for (auto extension : spirvReq->extensions) - spirvRequirement->extensions.insert(extension); - - for (auto capability : spirvReq->capabilities) - spirvRequirement->capabilities.insert(capability); -} - -// -// Handle SPIR-V execution modes -// -void TIntermediate::insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args) -{ - if (!spirvExecutionMode) - spirvExecutionMode = new TSpirvExecutionMode; - - TVector extraOperands; - if (args) { - for (auto arg : args->getSequence()) { - auto extraOperand = arg->getAsConstantUnion(); - assert(extraOperand != nullptr); - extraOperands.push_back(extraOperand); - } - } - spirvExecutionMode->modes[executionMode] = extraOperands; -} - -void TIntermediate::insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args) -{ - if (!spirvExecutionMode) - spirvExecutionMode = new TSpirvExecutionMode; - - assert(args); - TVector extraOperands; - - for (auto arg : args->getSequence()) { - auto extraOperand = arg->getAsTyped(); - assert(extraOperand != nullptr && extraOperand->getQualifier().isConstant()); - extraOperands.push_back(extraOperand); - } - spirvExecutionMode->modeIds[executionMode] = extraOperands; -} - -// -// Handle SPIR-V decorate qualifiers -// -void TQualifier::setSpirvDecorate(int decoration, const TIntermAggregate* args) -{ - if (!spirvDecorate) - spirvDecorate = new TSpirvDecorate; - - TVector extraOperands; - if (args) { - for (auto arg : args->getSequence()) { - auto extraOperand = arg->getAsConstantUnion(); - assert(extraOperand != nullptr); - extraOperands.push_back(extraOperand); - } - } - spirvDecorate->decorates[decoration] = extraOperands; -} - -void TQualifier::setSpirvDecorateId(int decoration, const TIntermAggregate* args) -{ - if (!spirvDecorate) - spirvDecorate = new TSpirvDecorate; - - assert(args); - TVector extraOperands; - for (auto arg : args->getSequence()) { - auto extraOperand = arg->getAsTyped(); - assert(extraOperand != nullptr); - extraOperands.push_back(extraOperand); - } - spirvDecorate->decorateIds[decoration] = extraOperands; -} - -void TQualifier::setSpirvDecorateString(int decoration, const TIntermAggregate* args) -{ - if (!spirvDecorate) - spirvDecorate = new TSpirvDecorate; - - assert(args); - TVector extraOperands; - for (auto arg : args->getSequence()) { - auto extraOperand = arg->getAsConstantUnion(); - assert(extraOperand != nullptr); - extraOperands.push_back(extraOperand); - } - spirvDecorate->decorateStrings[decoration] = extraOperands; -} - -TString TQualifier::getSpirvDecorateQualifierString() const -{ - assert(spirvDecorate); - - TString qualifierString; - - const auto appendFloat = [&](float f) { qualifierString.append(std::to_string(f).c_str()); }; - const auto appendInt = [&](int i) { qualifierString.append(std::to_string(i).c_str()); }; - const auto appendUint = [&](unsigned int u) { qualifierString.append(std::to_string(u).c_str()); }; - const auto appendBool = [&](bool b) { qualifierString.append(std::to_string(b).c_str()); }; - const auto appendStr = [&](const char* s) { qualifierString.append(s); }; - - const auto appendDecorate = [&](const TIntermTyped* constant) { - if (constant->getAsConstantUnion()) { - auto& constArray = constant->getAsConstantUnion()->getConstArray(); - if (constant->getBasicType() == EbtFloat) { - float value = static_cast(constArray[0].getDConst()); - appendFloat(value); - } else if (constant->getBasicType() == EbtInt) { - int value = constArray[0].getIConst(); - appendInt(value); - } else if (constant->getBasicType() == EbtUint) { - unsigned value = constArray[0].getUConst(); - appendUint(value); - } else if (constant->getBasicType() == EbtBool) { - bool value = constArray[0].getBConst(); - appendBool(value); - } else if (constant->getBasicType() == EbtString) { - const TString* value = constArray[0].getSConst(); - appendStr(value->c_str()); - } else - assert(0); - } else { - assert(constant->getAsSymbolNode()); - appendStr(constant->getAsSymbolNode()->getName().c_str()); - } - }; - - for (auto& decorate : spirvDecorate->decorates) { - appendStr("spirv_decorate("); - appendInt(decorate.first); - for (auto extraOperand : decorate.second) { - appendStr(", "); - appendDecorate(extraOperand); - } - appendStr(") "); - } - - for (auto& decorateId : spirvDecorate->decorateIds) { - appendStr("spirv_decorate_id("); - appendInt(decorateId.first); - for (auto extraOperand : decorateId.second) { - appendStr(", "); - appendDecorate(extraOperand); - } - appendStr(") "); - } - - for (auto& decorateString : spirvDecorate->decorateStrings) { - appendStr("spirv_decorate_string("); - appendInt(decorateString.first); - for (auto extraOperand : decorateString.second) { - appendStr(", "); - appendDecorate(extraOperand); - } - appendStr(") "); - } - - return qualifierString; -} - -// -// Handle SPIR-V type specifiers -// -void TPublicType::setSpirvType(const TSpirvInstruction& spirvInst, const TSpirvTypeParameters* typeParams) -{ - if (!spirvType) - spirvType = new TSpirvType; - - basicType = EbtSpirvType; - spirvType->spirvInst = spirvInst; - if (typeParams) - spirvType->typeParams = *typeParams; -} - -TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant) -{ - TSpirvTypeParameters* spirvTypeParams = new TSpirvTypeParameters; - if (constant->getBasicType() != EbtFloat && - constant->getBasicType() != EbtInt && - constant->getBasicType() != EbtUint && - constant->getBasicType() != EbtBool && - constant->getBasicType() != EbtString) - error(loc, "this type not allowed", constant->getType().getBasicString(), ""); - else - spirvTypeParams->push_back(TSpirvTypeParameter(constant)); - - return spirvTypeParams; -} - -TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TSourceLoc& /* loc */, - const TPublicType& type) -{ - TSpirvTypeParameters* spirvTypeParams = new TSpirvTypeParameters; - spirvTypeParams->push_back(TSpirvTypeParameter(new TType(type))); - return spirvTypeParams; -} - -TSpirvTypeParameters* TParseContext::mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, TSpirvTypeParameters* spirvTypeParams2) -{ - // Merge SPIR-V type parameters of the second one to the first one - for (const auto& spirvTypeParam : *spirvTypeParams2) - spirvTypeParams1->push_back(spirvTypeParam); - return spirvTypeParams1; -} - -// -// Handle SPIR-V instruction qualifiers -// -TSpirvInstruction* TParseContext::makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value) -{ - TSpirvInstruction* spirvInst = new TSpirvInstruction; - if (name == "set") - spirvInst->set = value; - else - error(loc, "unknown SPIR-V instruction qualifier", name.c_str(), ""); - - return spirvInst; -} - -TSpirvInstruction* TParseContext::makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value) -{ - TSpirvInstruction* spirvInstuction = new TSpirvInstruction; - if (name == "id") - spirvInstuction->id = value; - else - error(loc, "unknown SPIR-V instruction qualifier", name.c_str(), ""); - - return spirvInstuction; -} - -TSpirvInstruction* TParseContext::mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1, TSpirvInstruction* spirvInst2) -{ - // Merge qualifiers of the second SPIR-V instruction to those of the first one - if (!spirvInst2->set.empty()) { - if (spirvInst1->set.empty()) - spirvInst1->set = spirvInst2->set; - else - error(loc, "too many SPIR-V instruction qualifiers", "spirv_instruction", "(set)"); - } - - if (spirvInst2->id != -1) { - if (spirvInst1->id == -1) - spirvInst1->id = spirvInst2->id; - else - error(loc, "too many SPIR-V instruction qualifiers", "spirv_instruction", "(id)"); - } - - return spirvInst1; -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp b/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp deleted file mode 100644 index dae5a8b9..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.cpp +++ /dev/null @@ -1,476 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2018 Google, Inc. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Symbol table for parsing. Most functionality and main ideas -// are documented in the header file. -// - -#include "SymbolTable.h" - -namespace glslang { - -// -// TType helper function needs a place to live. -// - -// -// Recursively generate mangled names. -// -void TType::buildMangledName(TString& mangledName) const -{ - if (isMatrix()) - mangledName += 'm'; - else if (isVector()) - mangledName += 'v'; - - switch (basicType) { - case EbtFloat: mangledName += 'f'; break; - case EbtInt: mangledName += 'i'; break; - case EbtUint: mangledName += 'u'; break; - case EbtBool: mangledName += 'b'; break; - case EbtDouble: mangledName += 'd'; break; - case EbtFloat16: mangledName += "f16"; break; - case EbtInt8: mangledName += "i8"; break; - case EbtUint8: mangledName += "u8"; break; - case EbtInt16: mangledName += "i16"; break; - case EbtUint16: mangledName += "u16"; break; - case EbtInt64: mangledName += "i64"; break; - case EbtUint64: mangledName += "u64"; break; - case EbtAtomicUint: mangledName += "au"; break; - case EbtAccStruct: mangledName += "as"; break; - case EbtRayQuery: mangledName += "rq"; break; - case EbtSpirvType: mangledName += "spv-t"; break; - case EbtHitObjectNV: mangledName += "ho"; break; - case EbtSampler: - switch (sampler.type) { - case EbtFloat16: mangledName += "f16"; break; - case EbtInt: mangledName += "i"; break; - case EbtUint: mangledName += "u"; break; - case EbtInt64: mangledName += "i64"; break; - case EbtUint64: mangledName += "u64"; break; - default: break; // some compilers want this - } - if (sampler.isImageClass()) - mangledName += "I"; // a normal image or subpass - else if (sampler.isPureSampler()) - mangledName += "p"; // a "pure" sampler - else if (!sampler.isCombined()) - mangledName += "t"; // a "pure" texture - else - mangledName += "s"; // traditional combined sampler - if (sampler.isArrayed()) - mangledName += "A"; - if (sampler.isShadow()) - mangledName += "S"; - if (sampler.isExternal()) - mangledName += "E"; - if (sampler.isYuv()) - mangledName += "Y"; - switch (sampler.dim) { - case Esd2D: mangledName += "2"; break; - case Esd3D: mangledName += "3"; break; - case EsdCube: mangledName += "C"; break; - case Esd1D: mangledName += "1"; break; - case EsdRect: mangledName += "R2"; break; - case EsdBuffer: mangledName += "B"; break; - case EsdSubpass: mangledName += "P"; break; - default: break; // some compilers want this - } - -#ifdef ENABLE_HLSL - if (sampler.hasReturnStruct()) { - // Name mangle for sampler return struct uses struct table index. - mangledName += "-tx-struct"; - - char text[16]; // plenty enough space for the small integers. - snprintf(text, sizeof(text), "%u-", sampler.getStructReturnIndex()); - mangledName += text; - } else { - switch (sampler.getVectorSize()) { - case 1: mangledName += "1"; break; - case 2: mangledName += "2"; break; - case 3: mangledName += "3"; break; - case 4: break; // default to prior name mangle behavior - } - } -#endif - - if (sampler.isMultiSample()) - mangledName += "M"; - break; - case EbtStruct: - case EbtBlock: - if (basicType == EbtStruct) - mangledName += "struct-"; - else - mangledName += "block-"; - if (typeName) - mangledName += *typeName; - for (unsigned int i = 0; i < structure->size(); ++i) { - if ((*structure)[i].type->getBasicType() == EbtVoid) - continue; - mangledName += '-'; - (*structure)[i].type->buildMangledName(mangledName); - } - default: - break; - } - - if (getVectorSize() > 0) - mangledName += static_cast('0' + getVectorSize()); - else { - mangledName += static_cast('0' + getMatrixCols()); - mangledName += static_cast('0' + getMatrixRows()); - } - - if (arraySizes) { - const int maxSize = 11; - char buf[maxSize]; - for (int i = 0; i < arraySizes->getNumDims(); ++i) { - if (arraySizes->getDimNode(i)) { - if (arraySizes->getDimNode(i)->getAsSymbolNode()) - snprintf(buf, maxSize, "s%lld", arraySizes->getDimNode(i)->getAsSymbolNode()->getId()); - else - snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i)); - } else - snprintf(buf, maxSize, "%d", arraySizes->getDimSize(i)); - mangledName += '['; - mangledName += buf; - mangledName += ']'; - } - } -} - -// -// Dump functions. -// - -void TSymbol::dumpExtensions(TInfoSink& infoSink) const -{ - int numExtensions = getNumExtensions(); - if (numExtensions) { - infoSink.debug << " <"; - - for (int i = 0; i < numExtensions; i++) - infoSink.debug << getExtensions()[i] << ","; - - infoSink.debug << ">"; - } -} - -void TVariable::dump(TInfoSink& infoSink, bool complete) const -{ - if (complete) { - infoSink.debug << getName().c_str() << ": " << type.getCompleteString(); - dumpExtensions(infoSink); - } else { - infoSink.debug << getName().c_str() << ": " << type.getStorageQualifierString() << " " - << type.getBasicTypeString(); - - if (type.isArray()) - infoSink.debug << "[0]"; - } - - infoSink.debug << "\n"; -} - -void TFunction::dump(TInfoSink& infoSink, bool complete) const -{ - if (complete) { - infoSink.debug << getName().c_str() << ": " << returnType.getCompleteString() << " " << getName().c_str() - << "("; - - int numParams = getParamCount(); - for (int i = 0; i < numParams; i++) { - const TParameter ¶m = parameters[i]; - infoSink.debug << param.type->getCompleteString() << " " - << (param.type->isStruct() ? "of " + param.type->getTypeName() + " " : "") - << (param.name ? *param.name : "") << (i < numParams - 1 ? "," : ""); - } - - infoSink.debug << ")"; - dumpExtensions(infoSink); - } else { - infoSink.debug << getName().c_str() << ": " << returnType.getBasicTypeString() << " " - << getMangledName().c_str() << "n"; - } - - infoSink.debug << "\n"; -} - -void TAnonMember::dump(TInfoSink& TInfoSink, bool) const -{ - TInfoSink.debug << "anonymous member " << getMemberNumber() << " of " << getAnonContainer().getName().c_str() - << "\n"; -} - -void TSymbolTableLevel::dump(TInfoSink& infoSink, bool complete) const -{ - tLevel::const_iterator it; - for (it = level.begin(); it != level.end(); ++it) - (*it).second->dump(infoSink, complete); -} - -void TSymbolTable::dump(TInfoSink& infoSink, bool complete) const -{ - for (int level = currentLevel(); level >= 0; --level) { - infoSink.debug << "LEVEL " << level << "\n"; - table[level]->dump(infoSink, complete); - } -} - -// -// Functions have buried pointers to delete. -// -TFunction::~TFunction() -{ - for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) - delete (*i).type; -} - -// -// Symbol table levels are a map of pointers to symbols that have to be deleted. -// -TSymbolTableLevel::~TSymbolTableLevel() -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { - const TString& name = it->first; - auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(), - [&name](const std::pair& i) { return i.first == name; }); - if (retargetIter == retargetedSymbols.end()) - delete (*it).second; - } - - - delete [] defaultPrecision; -} - -// -// Change all function entries in the table with the non-mangled name -// to be related to the provided built-in operation. -// -void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) -{ - tLevel::const_iterator candidate = level.lower_bound(name); - while (candidate != level.end()) { - const TString& candidateName = (*candidate).first; - TString::size_type parenAt = candidateName.find_first_of('('); - if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) { - TFunction* function = (*candidate).second->getAsFunction(); - function->relateToOperator(op); - } else - break; - ++candidate; - } -} - -// Make all function overloads of the given name require an extension(s). -// Should only be used for a version/profile that actually needs the extension(s). -void TSymbolTableLevel::setFunctionExtensions(const char* name, int num, const char* const extensions[]) -{ - tLevel::const_iterator candidate = level.lower_bound(name); - while (candidate != level.end()) { - const TString& candidateName = (*candidate).first; - TString::size_type parenAt = candidateName.find_first_of('('); - if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) { - TSymbol* symbol = candidate->second; - symbol->setExtensions(num, extensions); - } else - break; - ++candidate; - } -} - -// Make a single function require an extension(s). i.e., this will only set the extensions for the symbol that matches 'name' exactly. -// This is different from setFunctionExtensions, which uses std::map::lower_bound to effectively set all symbols that start with 'name'. -// Should only be used for a version/profile that actually needs the extension(s). -void TSymbolTableLevel::setSingleFunctionExtensions(const char* name, int num, const char* const extensions[]) -{ - if (auto candidate = level.find(name); candidate != level.end()) { - candidate->second->setExtensions(num, extensions); - } -} - -// -// Make all symbols in this table level read only. -// -void TSymbolTableLevel::readOnly() -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) - (*it).second->makeReadOnly(); -} - -// -// Copy a symbol, but the copy is writable; call readOnly() afterward if that's not desired. -// -TSymbol::TSymbol(const TSymbol& copyOf) -{ - name = NewPoolTString(copyOf.name->c_str()); - uniqueId = copyOf.uniqueId; - writable = true; -} - -TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf) -{ - type.deepCopy(copyOf.type); - userType = copyOf.userType; - - // we don't support specialization-constant subtrees in cloned tables, only extensions - constSubtree = nullptr; - extensions = nullptr; - memberExtensions = nullptr; - if (copyOf.getNumExtensions() > 0) - setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions()); - if (copyOf.hasMemberExtensions()) { - for (int m = 0; m < (int)copyOf.type.getStruct()->size(); ++m) { - if (copyOf.getNumMemberExtensions(m) > 0) - setMemberExtensions(m, copyOf.getNumMemberExtensions(m), copyOf.getMemberExtensions(m)); - } - } - - if (! copyOf.constArray.empty()) { - assert(! copyOf.type.isStruct()); - TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size()); - constArray = newArray; - } -} - -TVariable* TVariable::clone() const -{ - TVariable *variable = new TVariable(*this); - - return variable; -} - -TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf) -{ - for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) { - TParameter param{}; - parameters.push_back(param); - (void)parameters.back().copyParam(copyOf.parameters[i]); - } - - extensions = nullptr; - if (copyOf.getNumExtensions() > 0) - setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions()); - returnType.deepCopy(copyOf.returnType); - mangledName = copyOf.mangledName; - op = copyOf.op; - defined = copyOf.defined; - prototyped = copyOf.prototyped; - implicitThis = copyOf.implicitThis; - illegalImplicitThis = copyOf.illegalImplicitThis; - defaultParamCount = copyOf.defaultParamCount; - spirvInst = copyOf.spirvInst; -} - -TFunction* TFunction::clone() const -{ - TFunction *function = new TFunction(*this); - - return function; -} - -TAnonMember* TAnonMember::clone() const -{ - // Anonymous members of a given block should be cloned at a higher level, - // where they can all be assured to still end up pointing to a single - // copy of the original container. - assert(0); - - return nullptr; -} - -TSymbolTableLevel* TSymbolTableLevel::clone() const -{ - TSymbolTableLevel *symTableLevel = new TSymbolTableLevel(); - symTableLevel->anonId = anonId; - symTableLevel->thisLevel = thisLevel; - symTableLevel->retargetedSymbols.clear(); - for (auto &s : retargetedSymbols) { - symTableLevel->retargetedSymbols.push_back({s.first, s.second}); - } - std::vector containerCopied(anonId, false); - tLevel::const_iterator iter; - for (iter = level.begin(); iter != level.end(); ++iter) { - const TAnonMember* anon = iter->second->getAsAnonMember(); - if (anon) { - // Insert all the anonymous members of this same container at once, - // avoid inserting the remaining members in the future, once this has been done, - // allowing them to all be part of the same new container. - if (! containerCopied[anon->getAnonId()]) { - TVariable* container = anon->getAnonContainer().clone(); - container->changeName(NewPoolTString("")); - // insert the container and all its members - symTableLevel->insert(*container, false); - containerCopied[anon->getAnonId()] = true; - } - } else { - const TString& name = iter->first; - auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(), - [&name](const std::pair& i) { return i.first == name; }); - if (retargetIter != retargetedSymbols.end()) - continue; - symTableLevel->insert(*iter->second->clone(), false); - } - } - // Now point retargeted symbols to the newly created versions of them - for (auto &s : retargetedSymbols) { - TSymbol* sym = symTableLevel->find(s.second); - if (!sym) - continue; - symTableLevel->insert(s.first, sym); - } - - return symTableLevel; -} - -void TSymbolTable::copyTable(const TSymbolTable& copyOf) -{ - assert(adoptedLevels == copyOf.adoptedLevels); - - uniqueId = copyOf.uniqueId; - noBuiltInRedeclarations = copyOf.noBuiltInRedeclarations; - separateNameSpaces = copyOf.separateNameSpaces; - for (unsigned int i = copyOf.adoptedLevels; i < copyOf.table.size(); ++i) - table.push_back(copyOf.table[i]->clone()); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h b/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h deleted file mode 100644 index 94c3929d..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/SymbolTable.h +++ /dev/null @@ -1,953 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _SYMBOL_TABLE_INCLUDED_ -#define _SYMBOL_TABLE_INCLUDED_ - -// -// Symbol table for parsing. Has these design characteristics: -// -// * Same symbol table can be used to compile many shaders, to preserve -// effort of creating and loading with the large numbers of built-in -// symbols. -// -// --> This requires a copy mechanism, so initial pools used to create -// the shared information can be popped. Done through "clone" -// methods. -// -// * Name mangling will be used to give each function a unique name -// so that symbol table lookups are never ambiguous. This allows -// a simpler symbol table structure. -// -// * Pushing and popping of scope, so symbol table will really be a stack -// of symbol tables. Searched from the top, with new inserts going into -// the top. -// -// * Constants: Compile time constant symbols will keep their values -// in the symbol table. The parser can substitute constants at parse -// time, including doing constant folding and constant propagation. -// -// * No temporaries: Temporaries made from operations (+, --, .xy, etc.) -// are tracked in the intermediate representation, not the symbol table. -// - -#include "../Include/Common.h" -#include "../Include/intermediate.h" -#include "../Include/InfoSink.h" - -namespace glslang { - -// -// Symbol base class. (Can build functions or variables out of these...) -// - -class TVariable; -class TFunction; -class TAnonMember; - -typedef TVector TExtensionList; - -class TSymbol { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - explicit TSymbol(const TString *n) : name(n), uniqueId(0), extensions(nullptr), writable(true) { } - virtual TSymbol* clone() const = 0; - virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool - - virtual const TString& getName() const { return *name; } - virtual void changeName(const TString* newName) { name = newName; } - virtual void addPrefix(const char* prefix) - { - TString newName(prefix); - newName.append(*name); - changeName(NewPoolTString(newName.c_str())); - } - virtual const TString& getMangledName() const { return getName(); } - virtual TFunction* getAsFunction() { return nullptr; } - virtual const TFunction* getAsFunction() const { return nullptr; } - virtual TVariable* getAsVariable() { return nullptr; } - virtual const TVariable* getAsVariable() const { return nullptr; } - virtual const TAnonMember* getAsAnonMember() const { return nullptr; } - virtual const TType& getType() const = 0; - virtual TType& getWritableType() = 0; - virtual void setUniqueId(long long id) { uniqueId = id; } - virtual long long getUniqueId() const { return uniqueId; } - virtual void setExtensions(int numExts, const char* const exts[]) - { - assert(extensions == nullptr); - assert(numExts > 0); - extensions = NewPoolObject(extensions); - for (int e = 0; e < numExts; ++e) - extensions->push_back(exts[e]); - } - virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); } - virtual const char** getExtensions() const { return extensions->data(); } - - virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0; - void dumpExtensions(TInfoSink& infoSink) const; - - virtual bool isReadOnly() const { return ! writable; } - virtual void makeReadOnly() { writable = false; } - -protected: - explicit TSymbol(const TSymbol&); - TSymbol& operator=(const TSymbol&); - - const TString *name; - unsigned long long uniqueId; // For cross-scope comparing during code generation - - // For tracking what extensions must be present - // (don't use if correct version/profile is present). - TExtensionList* extensions; // an array of pointers to existing constant char strings - - // - // N.B.: Non-const functions that will be generally used should assert on this, - // to avoid overwriting shared symbol-table information. - // - bool writable; -}; - -// -// Variable class, meaning a symbol that's not a function. -// -// There could be a separate class hierarchy for Constant variables; -// Only one of int, bool, or float, (or none) is correct for -// any particular use, but it's easy to do this way, and doesn't -// seem worth having separate classes, and "getConst" can't simply return -// different values for different types polymorphically, so this is -// just simple and pragmatic. -// -class TVariable : public TSymbol { -public: - TVariable(const TString *name, const TType& t, bool uT = false ) - : TSymbol(name), - userType(uT), - constSubtree(nullptr), - memberExtensions(nullptr), - anonId(-1) - { type.shallowCopy(t); } - virtual TVariable* clone() const; - virtual ~TVariable() { } - - virtual TVariable* getAsVariable() { return this; } - virtual const TVariable* getAsVariable() const { return this; } - virtual const TType& getType() const { return type; } - virtual TType& getWritableType() { assert(writable); return type; } - virtual bool isUserType() const { return userType; } - virtual const TConstUnionArray& getConstArray() const { return constArray; } - virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; } - virtual void setConstArray(const TConstUnionArray& array) { constArray = array; } - virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; } - virtual TIntermTyped* getConstSubtree() const { return constSubtree; } - virtual void setAnonId(int i) { anonId = i; } - virtual int getAnonId() const { return anonId; } - - virtual void setMemberExtensions(int member, int numExts, const char* const exts[]) - { - assert(type.isStruct()); - assert(numExts > 0); - if (memberExtensions == nullptr) { - memberExtensions = NewPoolObject(memberExtensions); - memberExtensions->resize(type.getStruct()->size()); - } - for (int e = 0; e < numExts; ++e) - (*memberExtensions)[member].push_back(exts[e]); - } - virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; } - virtual int getNumMemberExtensions(int member) const - { - return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size(); - } - virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); } - - virtual void dump(TInfoSink& infoSink, bool complete = false) const; - -protected: - explicit TVariable(const TVariable&); - TVariable& operator=(const TVariable&); - - TType type; - bool userType; - - // we are assuming that Pool Allocator will free the memory allocated to unionArray - // when this object is destroyed - - TConstUnionArray constArray; // for compile-time constant value - TIntermTyped* constSubtree; // for specialization constant computation - TVector* memberExtensions; // per-member extension list, allocated only when needed - int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose -}; - -// -// The function sub-class of symbols and the parser will need to -// share this definition of a function parameter. -// -struct TParameter { - TString *name; - TType* type; - TIntermTyped* defaultValue; - TParameter& copyParam(const TParameter& param) - { - if (param.name) - name = NewPoolTString(param.name->c_str()); - else - name = nullptr; - type = param.type->clone(); - defaultValue = param.defaultValue; - return *this; - } - TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; } -}; - -// -// The function sub-class of a symbol. -// -class TFunction : public TSymbol { -public: - explicit TFunction(TOperator o) : - TSymbol(nullptr), - op(o), - defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { } - TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) : - TSymbol(name), - mangledName(*name + '('), - op(tOp), - defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0), - linkType(ELinkNone) - { - returnType.shallowCopy(retType); - declaredBuiltIn = retType.getQualifier().builtIn; - } - virtual TFunction* clone() const override; - virtual ~TFunction(); - - virtual TFunction* getAsFunction() override { return this; } - virtual const TFunction* getAsFunction() const override { return this; } - - // Install 'p' as the (non-'this') last parameter. - // Non-'this' parameters are reflected in both the list of parameters and the - // mangled name. - virtual void addParameter(TParameter& p) - { - assert(writable); - parameters.push_back(p); - p.type->appendMangledName(mangledName); - - if (p.defaultValue != nullptr) - defaultParamCount++; - } - - // Install 'this' as the first parameter. - // 'this' is reflected in the list of parameters, but not the mangled name. - virtual void addThisParameter(TType& type, const char* name) - { - TParameter p = { NewPoolTString(name), new TType, nullptr }; - p.type->shallowCopy(type); - parameters.insert(parameters.begin(), p); - } - - virtual void addPrefix(const char* prefix) override - { - TSymbol::addPrefix(prefix); - mangledName.insert(0, prefix); - } - - virtual void removePrefix(const TString& prefix) - { - assert(mangledName.compare(0, prefix.size(), prefix) == 0); - mangledName.erase(0, prefix.size()); - } - - virtual const TString& getMangledName() const override { return mangledName; } - virtual const TType& getType() const override { return returnType; } - virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; } - virtual TType& getWritableType() override { return returnType; } - virtual void relateToOperator(TOperator o) { assert(writable); op = o; } - virtual TOperator getBuiltInOp() const { return op; } - virtual void setDefined() { assert(writable); defined = true; } - virtual bool isDefined() const { return defined; } - virtual void setPrototyped() { assert(writable); prototyped = true; } - virtual bool isPrototyped() const { return prototyped; } - virtual void setImplicitThis() { assert(writable); implicitThis = true; } - virtual bool hasImplicitThis() const { return implicitThis; } - virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; } - virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; } - - // Return total number of parameters - virtual int getParamCount() const { return static_cast(parameters.size()); } - // Return number of parameters with default values. - virtual int getDefaultParamCount() const { return defaultParamCount; } - // Return number of fixed parameters (without default values) - virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); } - - virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; } - virtual const TParameter& operator[](int i) const { return parameters[i]; } - const TQualifier& getQualifier() const { return returnType.getQualifier(); } - - virtual void setSpirvInstruction(const TSpirvInstruction& inst) - { - relateToOperator(EOpSpirvInst); - spirvInst = inst; - } - virtual const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; } - - virtual void dump(TInfoSink& infoSink, bool complete = false) const override; - - void setExport() { linkType = ELinkExport; } - TLinkType getLinkType() const { return linkType; } - -protected: - explicit TFunction(const TFunction&); - TFunction& operator=(const TFunction&); - - typedef TVector TParamList; - TParamList parameters; - TType returnType; - TBuiltInVariable declaredBuiltIn; - - TString mangledName; - TOperator op; - bool defined; - bool prototyped; - bool implicitThis; // True if this function is allowed to see all members of 'this' - bool illegalImplicitThis; // True if this function is not supposed to have access to dynamic members of 'this', - // even if it finds member variables in the symbol table. - // This is important for a static member function that has member variables in scope, - // but is not allowed to use them, or see hidden symbols instead. - int defaultParamCount; - - TSpirvInstruction spirvInst; // SPIR-V instruction qualifiers - TLinkType linkType; -}; - -// -// Members of anonymous blocks are a kind of TSymbol. They are not hidden in -// the symbol table behind a container; rather they are visible and point to -// their anonymous container. (The anonymous container is found through the -// member, not the other way around.) -// -class TAnonMember : public TSymbol { -public: - TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { } - virtual TAnonMember* clone() const override; - virtual ~TAnonMember() { } - - virtual const TAnonMember* getAsAnonMember() const override { return this; } - virtual const TVariable& getAnonContainer() const { return anonContainer; } - virtual unsigned int getMemberNumber() const { return memberNumber; } - - virtual const TType& getType() const override - { - const TTypeList& types = *anonContainer.getType().getStruct(); - return *types[memberNumber].type; - } - - virtual TType& getWritableType() override - { - assert(writable); - const TTypeList& types = *anonContainer.getType().getStruct(); - return *types[memberNumber].type; - } - - virtual void setExtensions(int numExts, const char* const exts[]) override - { - anonContainer.setMemberExtensions(memberNumber, numExts, exts); - } - virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); } - virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); } - - virtual int getAnonId() const { return anonId; } - virtual void dump(TInfoSink& infoSink, bool complete = false) const override; - -protected: - explicit TAnonMember(const TAnonMember&); - TAnonMember& operator=(const TAnonMember&); - - TVariable& anonContainer; - unsigned int memberNumber; - int anonId; -}; - -class TSymbolTableLevel { -public: - POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) - TSymbolTableLevel() : defaultPrecision(nullptr), anonId(0), thisLevel(false) { } - ~TSymbolTableLevel(); - - bool insert(const TString& name, TSymbol* symbol) { - return level.insert(tLevelPair(name, symbol)).second; - } - - bool insert(TSymbol& symbol, bool separateNameSpaces, const TString& forcedKeyName = TString()) - { - // - // returning true means symbol was added to the table with no semantic errors - // - const TString& name = symbol.getName(); - if (forcedKeyName.length()) { - return level.insert(tLevelPair(forcedKeyName, &symbol)).second; - } - else if (name == "") { - symbol.getAsVariable()->setAnonId(anonId++); - // An empty name means an anonymous container, exposing its members to the external scope. - // Give it a name and insert its members in the symbol table, pointing to the container. - char buf[20]; - snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId()); - symbol.changeName(NewPoolTString(buf)); - - return insertAnonymousMembers(symbol, 0); - } else { - // Check for redefinition errors: - // - STL itself will tell us if there is a direct name collision, with name mangling, at this level - // - additionally, check for function-redefining-variable name collisions - const TString& insertName = symbol.getMangledName(); - if (symbol.getAsFunction()) { - // make sure there isn't a variable of this name - if (! separateNameSpaces && level.find(name) != level.end()) - return false; - - // insert, and whatever happens is okay - level.insert(tLevelPair(insertName, &symbol)); - - return true; - } else - return level.insert(tLevelPair(insertName, &symbol)).second; - } - } - - // Add more members to an already inserted aggregate object - bool amend(TSymbol& symbol, int firstNewMember) - { - // See insert() for comments on basic explanation of insert. - // This operates similarly, but more simply. - // Only supporting amend of anonymous blocks so far. - if (IsAnonymous(symbol.getName())) - return insertAnonymousMembers(symbol, firstNewMember); - else - return false; - } - - bool insertAnonymousMembers(TSymbol& symbol, int firstMember) - { - const TTypeList& types = *symbol.getAsVariable()->getType().getStruct(); - for (unsigned int m = firstMember; m < types.size(); ++m) { - TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId()); - if (! level.insert(tLevelPair(member->getMangledName(), member)).second) - return false; - } - - return true; - } - - void retargetSymbol(const TString& from, const TString& to) { - tLevel::const_iterator fromIt = level.find(from); - tLevel::const_iterator toIt = level.find(to); - if (fromIt == level.end() || toIt == level.end()) - return; - delete fromIt->second; - level[from] = toIt->second; - retargetedSymbols.push_back({from, to}); - } - - TSymbol* find(const TString& name) const - { - tLevel::const_iterator it = level.find(name); - if (it == level.end()) - return nullptr; - else - return (*it).second; - } - - void findFunctionNameList(const TString& name, TVector& list) - { - size_t parenAt = name.find_first_of('('); - TString base(name, 0, parenAt + 1); - - tLevel::const_iterator begin = level.lower_bound(base); - base[parenAt] = ')'; // assume ')' is lexically after '(' - tLevel::const_iterator end = level.upper_bound(base); - for (tLevel::const_iterator it = begin; it != end; ++it) - list.push_back(it->second->getAsFunction()); - } - - // See if there is already a function in the table having the given non-function-style name. - bool hasFunctionName(const TString& name) const - { - tLevel::const_iterator candidate = level.lower_bound(name); - if (candidate != level.end()) { - const TString& candidateName = (*candidate).first; - TString::size_type parenAt = candidateName.find_first_of('('); - if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) - - return true; - } - - return false; - } - - // See if there is a variable at this level having the given non-function-style name. - // Return true if name is found, and set variable to true if the name was a variable. - bool findFunctionVariableName(const TString& name, bool& variable) const - { - tLevel::const_iterator candidate = level.lower_bound(name); - if (candidate != level.end()) { - const TString& candidateName = (*candidate).first; - TString::size_type parenAt = candidateName.find_first_of('('); - if (parenAt == candidateName.npos) { - // not a mangled name - if (candidateName == name) { - // found a variable name match - variable = true; - return true; - } - } else { - // a mangled name - if (candidateName.compare(0, parenAt, name) == 0) { - // found a function name match - variable = false; - return true; - } - } - } - - return false; - } - - // Use this to do a lazy 'push' of precision defaults the first time - // a precision statement is seen in a new scope. Leave it at 0 for - // when no push was needed. Thus, it is not the current defaults, - // it is what to restore the defaults to when popping a level. - void setPreviousDefaultPrecisions(const TPrecisionQualifier *p) - { - // can call multiple times at one scope, will only latch on first call, - // as we're tracking the previous scope's values, not the current values - if (defaultPrecision != nullptr) - return; - - defaultPrecision = new TPrecisionQualifier[EbtNumTypes]; - for (int t = 0; t < EbtNumTypes; ++t) - defaultPrecision[t] = p[t]; - } - - void getPreviousDefaultPrecisions(TPrecisionQualifier *p) - { - // can be called for table level pops that didn't set the - // defaults - if (defaultPrecision == nullptr || p == nullptr) - return; - - for (int t = 0; t < EbtNumTypes; ++t) - p[t] = defaultPrecision[t]; - } - - void relateToOperator(const char* name, TOperator op); - void setFunctionExtensions(const char* name, int num, const char* const extensions[]); - void setSingleFunctionExtensions(const char* name, int num, const char* const extensions[]); - void dump(TInfoSink& infoSink, bool complete = false) const; - TSymbolTableLevel* clone() const; - void readOnly(); - - void setThisLevel() { thisLevel = true; } - bool isThisLevel() const { return thisLevel; } - -protected: - explicit TSymbolTableLevel(TSymbolTableLevel&); - TSymbolTableLevel& operator=(TSymbolTableLevel&); - - typedef std::map, pool_allocator > > tLevel; - typedef const tLevel::value_type tLevelPair; - typedef std::pair tInsertResult; - - tLevel level; // named mappings - TPrecisionQualifier *defaultPrecision; - // pair - TVector> retargetedSymbols; - int anonId; - bool thisLevel; // True if this level of the symbol table is a structure scope containing member function - // that are supposed to see anonymous access to member variables. -}; - -class TSymbolTable { -public: - TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0) - { - // - // This symbol table cannot be used until push() is called. - // - } - ~TSymbolTable() - { - // this can be called explicitly; safest to code it so it can be called multiple times - - // don't deallocate levels passed in from elsewhere - while (table.size() > adoptedLevels) - pop(nullptr); - } - - void adoptLevels(TSymbolTable& symTable) - { - for (unsigned int level = 0; level < symTable.table.size(); ++level) { - table.push_back(symTable.table[level]); - ++adoptedLevels; - } - uniqueId = symTable.uniqueId; - noBuiltInRedeclarations = symTable.noBuiltInRedeclarations; - separateNameSpaces = symTable.separateNameSpaces; - } - - // - // While level adopting is generic, the methods below enact a the following - // convention for levels: - // 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables - // 1: per-stage built-ins, shared across all compiles, but a different copy per stage - // 2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins - // 3: user-shader globals - // -protected: - static const uint32_t LevelFlagBitOffset = 56; - static const int globalLevel = 3; - static bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels - static bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals - static bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals -public: - bool isEmpty() { return table.size() == 0; } - bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); } - bool atGlobalLevel() { return isGlobalLevel(currentLevel()); } - static bool isBuiltInSymbol(long long uniqueId) { - int level = static_cast(uniqueId >> LevelFlagBitOffset); - return isBuiltInLevel(level); - } - static constexpr uint64_t uniqueIdMask = (1LL << LevelFlagBitOffset) - 1; - static const uint32_t MaxLevelInUniqueID = 127; - void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; } - void setSeparateNameSpaces() { separateNameSpaces = true; } - - void push() - { - table.push_back(new TSymbolTableLevel); - updateUniqueIdLevelFlag(); - } - - // Make a new symbol-table level to represent the scope introduced by a structure - // containing member functions, such that the member functions can find anonymous - // references to member variables. - // - // 'thisSymbol' should have a name of "" to trigger anonymous structure-member - // symbol finds. - void pushThis(TSymbol& thisSymbol) - { - assert(thisSymbol.getName().size() == 0); - table.push_back(new TSymbolTableLevel); - updateUniqueIdLevelFlag(); - table.back()->setThisLevel(); - insert(thisSymbol); - } - - void pop(TPrecisionQualifier *p) - { - table[currentLevel()]->getPreviousDefaultPrecisions(p); - delete table.back(); - table.pop_back(); - updateUniqueIdLevelFlag(); - } - - // - // Insert a visible symbol into the symbol table so it can - // be found later by name. - // - // Returns false if the was a name collision. - // - bool insert(TSymbol& symbol) - { - symbol.setUniqueId(++uniqueId); - - // make sure there isn't a function of this variable name - if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName())) - return false; - - // check for not overloading or redefining a built-in function - if (noBuiltInRedeclarations) { - if (atGlobalLevel() && currentLevel() > 0) { - if (table[0]->hasFunctionName(symbol.getName())) - return false; - if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName())) - return false; - } - } - - return table[currentLevel()]->insert(symbol, separateNameSpaces); - } - - // Add more members to an already inserted aggregate object - bool amend(TSymbol& symbol, int firstNewMember) - { - // See insert() for comments on basic explanation of insert. - // This operates similarly, but more simply. - return table[currentLevel()]->amend(symbol, firstNewMember); - } - - // Update the level info in symbol's unique ID to current level - void amendSymbolIdLevel(TSymbol& symbol) - { - // clamp level to avoid overflow - uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel(); - uint64_t symbolId = symbol.getUniqueId(); - symbolId &= uniqueIdMask; - symbolId |= (level << LevelFlagBitOffset); - symbol.setUniqueId(symbolId); - } - // - // To allocate an internal temporary, which will need to be uniquely - // identified by the consumer of the AST, but never need to - // found by doing a symbol table search by name, hence allowed an - // arbitrary name in the symbol with no worry of collision. - // - void makeInternalVariable(TSymbol& symbol) - { - symbol.setUniqueId(++uniqueId); - } - - // - // Copy a variable or anonymous member's structure from a shared level so that - // it can be added (soon after return) to the symbol table where it can be - // modified without impacting other users of the shared table. - // - TSymbol* copyUpDeferredInsert(TSymbol* shared) - { - if (shared->getAsVariable()) { - TSymbol* copy = shared->clone(); - copy->setUniqueId(shared->getUniqueId()); - return copy; - } else { - const TAnonMember* anon = shared->getAsAnonMember(); - assert(anon); - TVariable* container = anon->getAnonContainer().clone(); - container->changeName(NewPoolTString("")); - container->setUniqueId(anon->getAnonContainer().getUniqueId()); - return container; - } - } - - TSymbol* copyUp(TSymbol* shared) - { - TSymbol* copy = copyUpDeferredInsert(shared); - table[globalLevel]->insert(*copy, separateNameSpaces); - if (shared->getAsVariable()) - return copy; - else { - // return the copy of the anonymous member - return table[globalLevel]->find(shared->getName()); - } - } - - // Normal find of a symbol, that can optionally say whether the symbol was found - // at a built-in level or the current top-scope level. - TSymbol* find(const TString& name, bool* builtIn = nullptr, bool* currentScope = nullptr, int* thisDepthP = nullptr) - { - int level = currentLevel(); - TSymbol* symbol; - int thisDepth = 0; - do { - if (table[level]->isThisLevel()) - ++thisDepth; - symbol = table[level]->find(name); - --level; - } while (symbol == nullptr && level >= 0); - level++; - if (builtIn) - *builtIn = isBuiltInLevel(level); - if (currentScope) - *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals - if (thisDepthP != nullptr) { - if (! table[level]->isThisLevel()) - thisDepth = 0; - *thisDepthP = thisDepth; - } - - return symbol; - } - - void retargetSymbol(const TString& from, const TString& to) { - int level = currentLevel(); - table[level]->retargetSymbol(from, to); - } - - - // Find of a symbol that returns how many layers deep of nested - // structures-with-member-functions ('this' scopes) deep the symbol was - // found in. - TSymbol* find(const TString& name, int& thisDepth) - { - int level = currentLevel(); - TSymbol* symbol; - thisDepth = 0; - do { - if (table[level]->isThisLevel()) - ++thisDepth; - symbol = table[level]->find(name); - --level; - } while (symbol == nullptr && level >= 0); - - if (! table[level + 1]->isThisLevel()) - thisDepth = 0; - - return symbol; - } - - bool isFunctionNameVariable(const TString& name) const - { - if (separateNameSpaces) - return false; - - int level = currentLevel(); - do { - bool variable; - bool found = table[level]->findFunctionVariableName(name, variable); - if (found) - return variable; - --level; - } while (level >= 0); - - return false; - } - - void findFunctionNameList(const TString& name, TVector& list, bool& builtIn) - { - // For user levels, return the set found in the first scope with a match - builtIn = false; - int level = currentLevel(); - do { - table[level]->findFunctionNameList(name, list); - --level; - } while (list.empty() && level >= globalLevel); - - if (! list.empty()) - return; - - // Gather across all built-in levels; they don't hide each other - builtIn = true; - do { - table[level]->findFunctionNameList(name, list); - --level; - } while (level >= 0); - } - - void relateToOperator(const char* name, TOperator op) - { - for (unsigned int level = 0; level < table.size(); ++level) - table[level]->relateToOperator(name, op); - } - - void setFunctionExtensions(const char* name, int num, const char* const extensions[]) - { - for (unsigned int level = 0; level < table.size(); ++level) - table[level]->setFunctionExtensions(name, num, extensions); - } - - void setSingleFunctionExtensions(const char* name, int num, const char* const extensions[]) - { - for (unsigned int level = 0; level < table.size(); ++level) - table[level]->setSingleFunctionExtensions(name, num, extensions); - } - - void setVariableExtensions(const char* name, int numExts, const char* const extensions[]) - { - TSymbol* symbol = find(TString(name)); - if (symbol == nullptr) - return; - - symbol->setExtensions(numExts, extensions); - } - - void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[]) - { - TSymbol* symbol = find(TString(blockName)); - if (symbol == nullptr) - return; - TVariable* variable = symbol->getAsVariable(); - assert(variable != nullptr); - - const TTypeList& structure = *variable->getAsVariable()->getType().getStruct(); - for (int member = 0; member < (int)structure.size(); ++member) { - if (structure[member].type->getFieldName().compare(name) == 0) { - variable->setMemberExtensions(member, numExts, extensions); - return; - } - } - } - - long long getMaxSymbolId() { return uniqueId; } - void dump(TInfoSink& infoSink, bool complete = false) const; - void copyTable(const TSymbolTable& copyOf); - - void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); } - - void readOnly() - { - for (unsigned int level = 0; level < table.size(); ++level) - table[level]->readOnly(); - } - - // Add current level in the high-bits of unique id - void updateUniqueIdLevelFlag() { - // clamp level to avoid overflow - uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel(); - uniqueId &= uniqueIdMask; - uniqueId |= (level << LevelFlagBitOffset); - } - - void overwriteUniqueId(long long id) - { - uniqueId = id; - updateUniqueIdLevelFlag(); - } - -protected: - TSymbolTable(TSymbolTable&); - TSymbolTable& operator=(TSymbolTableLevel&); - - int currentLevel() const { return static_cast(table.size()) - 1; } - std::vector table; - long long uniqueId; // for unique identification in code generation - bool noBuiltInRedeclarations; - bool separateNameSpaces; - unsigned int adoptedLevels; -}; - -} // end namespace glslang - -#endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/3rdparty/glslang/glslang/MachineIndependent/Versions.cpp b/3rdparty/glslang/glslang/MachineIndependent/Versions.cpp deleted file mode 100644 index 694246cb..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/Versions.cpp +++ /dev/null @@ -1,1393 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2020 Google, Inc. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Help manage multiple profiles, versions, extensions etc. -// -// These don't return error codes, as the presumption is parsing will -// always continue as if the tested feature were enabled, and thus there -// is no error recovery needed. -// - -// -// HOW TO add a feature enabled by an extension. -// -// To add a new hypothetical "Feature F" to the front end, where an extension -// "XXX_extension_X" can be used to enable the feature, do the following. -// -// OVERVIEW: Specific features are what are error-checked for, not -// extensions: A specific Feature F might be enabled by an extension, or a -// particular version in a particular profile, or a stage, or combinations, etc. -// -// The basic mechanism is to use the following to "declare" all the things that -// enable/disable Feature F, in a code path that implements Feature F: -// -// requireProfile() -// profileRequires() -// requireStage() -// checkDeprecated() -// requireNotRemoved() -// requireExtensions() -// extensionRequires() -// -// Typically, only the first two calls are needed. They go into a code path that -// implements Feature F, and will log the proper error/warning messages. Parsing -// will then always continue as if the tested feature was enabled. -// -// There is typically no if-testing or conditional parsing, just insertion of the calls above. -// However, if symbols specific to the extension are added (step 5), they will -// only be added under tests that the minimum version and profile are present. -// -// 1) Add a symbol name for the extension string at the bottom of Versions.h: -// -// const char* const XXX_extension_X = "XXX_extension_X"; -// -// 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(), -// the first function below and optionally a entry to extensionData for additional -// error checks: -// -// extensionBehavior[XXX_extension_X] = EBhDisable; -// (Optional) exts[] = {XXX_extension_X, EShTargetSpv_1_4} -// -// 3) Add any preprocessor directives etc. in the next function, TParseVersions::getPreamble(): -// -// "#define XXX_extension_X 1\n" -// -// The new-line is important, as that ends preprocess tokens. -// -// 4) Insert a profile check in the feature's path (unless all profiles support the feature, -// for some version level). That is, call requireProfile() to constrain the profiles, e.g.: -// -// // ... in a path specific to Feature F... -// requireProfile(loc, -// ECoreProfile | ECompatibilityProfile, -// "Feature F"); -// -// 5) For each profile that supports the feature, insert version/extension checks: -// -// The mostly likely scenario is that Feature F can only be used with a -// particular profile if XXX_extension_X is present or the version is -// high enough that the core specification already incorporated it. -// -// // following the requireProfile() call... -// profileRequires(loc, -// ECoreProfile | ECompatibilityProfile, -// 420, // 0 if no version incorporated the feature into the core spec. -// XXX_extension_X, // can be a list of extensions that all add the feature -// "Feature F Description"); -// -// This allows the feature if either A) one of the extensions is enabled or -// B) the version is high enough. If no version yet incorporates the feature -// into core, pass in 0. -// -// This can be called multiple times, if different profiles support the -// feature starting at different version numbers or with different -// extensions. -// -// This must be called for each profile allowed by the initial call to requireProfile(). -// -// Profiles are all masks, which can be "or"-ed together. -// -// ENoProfile -// ECoreProfile -// ECompatibilityProfile -// EEsProfile -// -// The ENoProfile profile is only for desktop, before profiles showed up in version 150; -// All other #version with no profile default to either es or core, and so have profiles. -// -// You can select all but a particular profile using ~. The following basically means "desktop": -// -// ~EEsProfile -// -// 6) If built-in symbols are added by the extension, add them in Initialize.cpp: Their use -// will be automatically error checked against the extensions enabled at that moment. -// see the comment at the top of Initialize.cpp for where to put them. Establish them at -// the earliest release that supports the extension. Then, tag them with the -// set of extensions that both enable them and are necessary, given the version of the symbol -// table. (There is a different symbol table for each version.) -// -// 7) If the extension has additional requirements like minimum SPIR-V version required, add them -// to extensionRequires() - -#include "parseVersions.h" -#include "localintermediate.h" - -namespace glslang { - -// -// Initialize all extensions, almost always to 'disable', as once their features -// are incorporated into a core version, their features are supported through allowing that -// core version, not through a pseudo-enablement of the extension. -// -void TParseVersions::initializeExtensionBehavior() -{ - typedef struct { - const char *const extensionName; - EShTargetLanguageVersion minSpvVersion; - } extensionData; - - const extensionData exts[] = { {E_GL_EXT_ray_tracing, EShTargetSpv_1_4}, - {E_GL_NV_ray_tracing_motion_blur, EShTargetSpv_1_4}, - {E_GL_EXT_mesh_shader, EShTargetSpv_1_4} - }; - - for (size_t ii = 0; ii < sizeof(exts) / sizeof(exts[0]); ii++) { - // Add only extensions which require > spv1.0 to save space in map - if (exts[ii].minSpvVersion > EShTargetSpv_1_0) { - extensionMinSpv[exts[ii].extensionName] = exts[ii].minSpvVersion; - } - } - - extensionBehavior[E_GL_OES_texture_3D] = EBhDisable; - extensionBehavior[E_GL_OES_standard_derivatives] = EBhDisable; - extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable; - extensionBehavior[E_GL_OES_EGL_image_external] = EBhDisable; - extensionBehavior[E_GL_OES_EGL_image_external_essl3] = EBhDisable; - extensionBehavior[E_GL_EXT_YUV_target] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_texture_lod] = EBhDisable; - extensionBehavior[E_GL_EXT_shadow_samplers] = EBhDisable; - extensionBehavior[E_GL_ARB_texture_rectangle] = EBhDisable; - extensionBehavior[E_GL_3DL_array_objects] = EBhDisable; - extensionBehavior[E_GL_ARB_shading_language_420pack] = EBhDisable; - extensionBehavior[E_GL_ARB_texture_gather] = EBhDisable; - extensionBehavior[E_GL_ARB_gpu_shader5] = EBhDisablePartial; - extensionBehavior[E_GL_ARB_separate_shader_objects] = EBhDisable; - extensionBehavior[E_GL_ARB_compute_shader] = EBhDisable; - extensionBehavior[E_GL_ARB_tessellation_shader] = EBhDisable; - extensionBehavior[E_GL_ARB_enhanced_layouts] = EBhDisable; - extensionBehavior[E_GL_ARB_texture_cube_map_array] = EBhDisable; - extensionBehavior[E_GL_ARB_texture_multisample] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_texture_lod] = EBhDisable; - extensionBehavior[E_GL_ARB_explicit_attrib_location] = EBhDisable; - extensionBehavior[E_GL_ARB_explicit_uniform_location] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_image_load_store] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_atomic_counters] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_atomic_counter_ops] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_draw_parameters] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_group_vote] = EBhDisable; - extensionBehavior[E_GL_ARB_derivative_control] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_texture_image_samples] = EBhDisable; - extensionBehavior[E_GL_ARB_viewport_array] = EBhDisable; - extensionBehavior[E_GL_ARB_gpu_shader_int64] = EBhDisable; - extensionBehavior[E_GL_ARB_gpu_shader_fp64] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_ballot] = EBhDisable; - extensionBehavior[E_GL_ARB_sparse_texture2] = EBhDisable; - extensionBehavior[E_GL_ARB_sparse_texture_clamp] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_stencil_export] = EBhDisable; -// extensionBehavior[E_GL_ARB_cull_distance] = EBhDisable; // present for 4.5, but need extension control over block members - extensionBehavior[E_GL_ARB_post_depth_coverage] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_viewport_layer_array] = EBhDisable; - extensionBehavior[E_GL_ARB_fragment_shader_interlock] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_clock] = EBhDisable; - extensionBehavior[E_GL_ARB_uniform_buffer_object] = EBhDisable; - extensionBehavior[E_GL_ARB_sample_shading] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_bit_encoding] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_image_size] = EBhDisable; - extensionBehavior[E_GL_ARB_shader_storage_buffer_object] = EBhDisable; - extensionBehavior[E_GL_ARB_shading_language_packing] = EBhDisable; - extensionBehavior[E_GL_ARB_texture_query_lod] = EBhDisable; - extensionBehavior[E_GL_ARB_vertex_attrib_64bit] = EBhDisable; - extensionBehavior[E_GL_ARB_draw_instanced] = EBhDisable; - extensionBehavior[E_GL_ARB_bindless_texture] = EBhDisable; - extensionBehavior[E_GL_ARB_fragment_coord_conventions] = EBhDisable; - - - extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_arithmetic] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_ballot] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_shuffle] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_shuffle_relative] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_clustered] = EBhDisable; - extensionBehavior[E_GL_KHR_shader_subgroup_quad] = EBhDisable; - extensionBehavior[E_GL_KHR_memory_scope_semantics] = EBhDisable; - - extensionBehavior[E_GL_EXT_shader_atomic_int64] = EBhDisable; - - extensionBehavior[E_GL_EXT_shader_non_constant_global_initializers] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_image_load_formatted] = EBhDisable; - extensionBehavior[E_GL_EXT_post_depth_coverage] = EBhDisable; - extensionBehavior[E_GL_EXT_control_flow_attributes] = EBhDisable; - extensionBehavior[E_GL_EXT_nonuniform_qualifier] = EBhDisable; - extensionBehavior[E_GL_EXT_samplerless_texture_functions] = EBhDisable; - extensionBehavior[E_GL_EXT_scalar_block_layout] = EBhDisable; - extensionBehavior[E_GL_EXT_fragment_invocation_density] = EBhDisable; - extensionBehavior[E_GL_EXT_buffer_reference] = EBhDisable; - extensionBehavior[E_GL_EXT_buffer_reference2] = EBhDisable; - extensionBehavior[E_GL_EXT_buffer_reference_uvec2] = EBhDisable; - extensionBehavior[E_GL_EXT_demote_to_helper_invocation] = EBhDisable; - extensionBehavior[E_GL_EXT_debug_printf] = EBhDisable; - - extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable; - extensionBehavior[E_GL_EXT_subgroup_uniform_control_flow] = EBhDisable; - - extensionBehavior[E_GL_EXT_fragment_shader_barycentric] = EBhDisable; - - extensionBehavior[E_GL_KHR_cooperative_matrix] = EBhDisable; - - // #line and #include - extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable; - extensionBehavior[E_GL_GOOGLE_include_directive] = EBhDisable; - - extensionBehavior[E_GL_AMD_shader_ballot] = EBhDisable; - extensionBehavior[E_GL_AMD_shader_trinary_minmax] = EBhDisable; - extensionBehavior[E_GL_AMD_shader_explicit_vertex_parameter] = EBhDisable; - extensionBehavior[E_GL_AMD_gcn_shader] = EBhDisable; - extensionBehavior[E_GL_AMD_gpu_shader_half_float] = EBhDisable; - extensionBehavior[E_GL_AMD_texture_gather_bias_lod] = EBhDisable; - extensionBehavior[E_GL_AMD_gpu_shader_int16] = EBhDisable; - extensionBehavior[E_GL_AMD_shader_image_load_store_lod] = EBhDisable; - extensionBehavior[E_GL_AMD_shader_fragment_mask] = EBhDisable; - extensionBehavior[E_GL_AMD_gpu_shader_half_float_fetch] = EBhDisable; - extensionBehavior[E_GL_AMD_shader_early_and_late_fragment_tests] = EBhDisable; - - extensionBehavior[E_GL_INTEL_shader_integer_functions2] = EBhDisable; - - extensionBehavior[E_GL_NV_sample_mask_override_coverage] = EBhDisable; - extensionBehavior[E_SPV_NV_geometry_shader_passthrough] = EBhDisable; - extensionBehavior[E_GL_NV_viewport_array2] = EBhDisable; - extensionBehavior[E_GL_NV_stereo_view_rendering] = EBhDisable; - extensionBehavior[E_GL_NVX_multiview_per_view_attributes] = EBhDisable; - extensionBehavior[E_GL_NV_shader_atomic_int64] = EBhDisable; - extensionBehavior[E_GL_NV_conservative_raster_underestimation] = EBhDisable; - extensionBehavior[E_GL_NV_shader_noperspective_interpolation] = EBhDisable; - extensionBehavior[E_GL_NV_shader_subgroup_partitioned] = EBhDisable; - extensionBehavior[E_GL_NV_shading_rate_image] = EBhDisable; - extensionBehavior[E_GL_NV_ray_tracing] = EBhDisable; - extensionBehavior[E_GL_NV_ray_tracing_motion_blur] = EBhDisable; - extensionBehavior[E_GL_NV_fragment_shader_barycentric] = EBhDisable; - extensionBehavior[E_GL_NV_compute_shader_derivatives] = EBhDisable; - extensionBehavior[E_GL_NV_shader_texture_footprint] = EBhDisable; - extensionBehavior[E_GL_NV_mesh_shader] = EBhDisable; - extensionBehavior[E_GL_NV_cooperative_matrix] = EBhDisable; - extensionBehavior[E_GL_NV_shader_sm_builtins] = EBhDisable; - extensionBehavior[E_GL_NV_integer_cooperative_matrix] = EBhDisable; - extensionBehavior[E_GL_NV_shader_invocation_reorder] = EBhDisable; - extensionBehavior[E_GL_NV_displacement_micromap] = EBhDisable; - - // ARM - extensionBehavior[E_GL_ARM_shader_core_builtins] = EBhDisable; - - // QCOM - extensionBehavior[E_GL_QCOM_image_processing] = EBhDisable; - - // AEP - extensionBehavior[E_GL_ANDROID_extension_pack_es31a] = EBhDisable; - extensionBehavior[E_GL_KHR_blend_equation_advanced] = EBhDisable; - extensionBehavior[E_GL_OES_sample_variables] = EBhDisable; - extensionBehavior[E_GL_OES_shader_image_atomic] = EBhDisable; - extensionBehavior[E_GL_OES_shader_multisample_interpolation] = EBhDisable; - extensionBehavior[E_GL_OES_texture_storage_multisample_2d_array] = EBhDisable; - extensionBehavior[E_GL_EXT_geometry_shader] = EBhDisable; - extensionBehavior[E_GL_EXT_geometry_point_size] = EBhDisable; - extensionBehavior[E_GL_EXT_gpu_shader5] = EBhDisable; - extensionBehavior[E_GL_EXT_primitive_bounding_box] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_io_blocks] = EBhDisable; - extensionBehavior[E_GL_EXT_tessellation_shader] = EBhDisable; - extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable; - extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisable; - extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisable; - extensionBehavior[E_GL_EXT_null_initializer] = EBhDisable; - - // OES matching AEP - extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable; - extensionBehavior[E_GL_OES_geometry_point_size] = EBhDisable; - extensionBehavior[E_GL_OES_gpu_shader5] = EBhDisable; - extensionBehavior[E_GL_OES_primitive_bounding_box] = EBhDisable; - extensionBehavior[E_GL_OES_shader_io_blocks] = EBhDisable; - extensionBehavior[E_GL_OES_tessellation_shader] = EBhDisable; - extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable; - extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable; - extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_integer_mix] = EBhDisable; - - // EXT extensions - extensionBehavior[E_GL_EXT_device_group] = EBhDisable; - extensionBehavior[E_GL_EXT_multiview] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_realtime_clock] = EBhDisable; - extensionBehavior[E_GL_EXT_ray_tracing] = EBhDisable; - extensionBehavior[E_GL_EXT_ray_query] = EBhDisable; - extensionBehavior[E_GL_EXT_ray_flags_primitive_culling] = EBhDisable; - extensionBehavior[E_GL_EXT_ray_cull_mask] = EBhDisable; - extensionBehavior[E_GL_EXT_blend_func_extended] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_implicit_conversions] = EBhDisable; - extensionBehavior[E_GL_EXT_fragment_shading_rate] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_image_int64] = EBhDisable; - extensionBehavior[E_GL_EXT_terminate_invocation] = EBhDisable; - extensionBehavior[E_GL_EXT_shared_memory_block] = EBhDisable; - extensionBehavior[E_GL_EXT_spirv_intrinsics] = EBhDisable; - extensionBehavior[E_GL_EXT_mesh_shader] = EBhDisable; - extensionBehavior[E_GL_EXT_opacity_micromap] = EBhDisable; - extensionBehavior[E_GL_EXT_ray_tracing_position_fetch] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_tile_image] = EBhDisable; - extensionBehavior[E_GL_EXT_texture_shadow_lod] = EBhDisable; - extensionBehavior[E_GL_EXT_draw_instanced] = EBhDisable; - extensionBehavior[E_GL_EXT_texture_array] = EBhDisable; - - // OVR extensions - extensionBehavior[E_GL_OVR_multiview] = EBhDisable; - extensionBehavior[E_GL_OVR_multiview2] = EBhDisable; - - // explicit types - extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int8] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int16] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int32] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int64] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float16] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float32] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float64] = EBhDisable; - - // subgroup extended types - extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int8] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int16] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int64] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_float16] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_atomic_float] = EBhDisable; - extensionBehavior[E_GL_EXT_shader_atomic_float2] = EBhDisable; - - // Record extensions not for spv. - spvUnsupportedExt.push_back(E_GL_ARB_bindless_texture); -} - -// Get code that is not part of a shared symbol table, is specific to this shader, -// or needed by the preprocessor (which does not use a shared symbol table). -void TParseVersions::getPreamble(std::string& preamble) -{ - if (isEsProfile()) { - preamble = - "#define GL_ES 1\n" - "#define GL_FRAGMENT_PRECISION_HIGH 1\n" - "#define GL_OES_texture_3D 1\n" - "#define GL_OES_standard_derivatives 1\n" - "#define GL_EXT_frag_depth 1\n" - "#define GL_OES_EGL_image_external 1\n" - "#define GL_OES_EGL_image_external_essl3 1\n" - "#define GL_EXT_YUV_target 1\n" - "#define GL_EXT_shader_texture_lod 1\n" - "#define GL_EXT_shadow_samplers 1\n" - "#define GL_EXT_fragment_shading_rate 1\n" - - // AEP - "#define GL_ANDROID_extension_pack_es31a 1\n" - "#define GL_OES_sample_variables 1\n" - "#define GL_OES_shader_image_atomic 1\n" - "#define GL_OES_shader_multisample_interpolation 1\n" - "#define GL_OES_texture_storage_multisample_2d_array 1\n" - "#define GL_EXT_geometry_shader 1\n" - "#define GL_EXT_geometry_point_size 1\n" - "#define GL_EXT_gpu_shader5 1\n" - "#define GL_EXT_primitive_bounding_box 1\n" - "#define GL_EXT_shader_io_blocks 1\n" - "#define GL_EXT_tessellation_shader 1\n" - "#define GL_EXT_tessellation_point_size 1\n" - "#define GL_EXT_texture_buffer 1\n" - "#define GL_EXT_texture_cube_map_array 1\n" - "#define GL_EXT_shader_implicit_conversions 1\n" - "#define GL_EXT_shader_integer_mix 1\n" - "#define GL_EXT_blend_func_extended 1\n" - - // OES matching AEP - "#define GL_OES_geometry_shader 1\n" - "#define GL_OES_geometry_point_size 1\n" - "#define GL_OES_gpu_shader5 1\n" - "#define GL_OES_primitive_bounding_box 1\n" - "#define GL_OES_shader_io_blocks 1\n" - "#define GL_OES_tessellation_shader 1\n" - "#define GL_OES_tessellation_point_size 1\n" - "#define GL_OES_texture_buffer 1\n" - "#define GL_OES_texture_cube_map_array 1\n" - "#define GL_EXT_shader_non_constant_global_initializers 1\n" - - "#define GL_QCOM_image_processing 1\n" - ; - - if (version >= 300) { - preamble += "#define GL_NV_shader_noperspective_interpolation 1\n"; - } - if (version >= 310) { - preamble += "#define GL_EXT_null_initializer 1\n"; - preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n"; - } - - } else { // !isEsProfile() - preamble = - "#define GL_ARB_texture_rectangle 1\n" - "#define GL_ARB_shading_language_420pack 1\n" - "#define GL_ARB_texture_gather 1\n" - "#define GL_ARB_gpu_shader5 1\n" - "#define GL_ARB_separate_shader_objects 1\n" - "#define GL_ARB_compute_shader 1\n" - "#define GL_ARB_tessellation_shader 1\n" - "#define GL_ARB_enhanced_layouts 1\n" - "#define GL_ARB_texture_cube_map_array 1\n" - "#define GL_ARB_texture_multisample 1\n" - "#define GL_ARB_shader_texture_lod 1\n" - "#define GL_ARB_explicit_attrib_location 1\n" - "#define GL_ARB_explicit_uniform_location 1\n" - "#define GL_ARB_shader_image_load_store 1\n" - "#define GL_ARB_shader_atomic_counters 1\n" - "#define GL_ARB_shader_draw_parameters 1\n" - "#define GL_ARB_shader_group_vote 1\n" - "#define GL_ARB_derivative_control 1\n" - "#define GL_ARB_shader_texture_image_samples 1\n" - "#define GL_ARB_viewport_array 1\n" - "#define GL_ARB_gpu_shader_int64 1\n" - "#define GL_ARB_gpu_shader_fp64 1\n" - "#define GL_ARB_shader_ballot 1\n" - "#define GL_ARB_sparse_texture2 1\n" - "#define GL_ARB_sparse_texture_clamp 1\n" - "#define GL_ARB_shader_stencil_export 1\n" - "#define GL_ARB_sample_shading 1\n" - "#define GL_ARB_shader_image_size 1\n" - "#define GL_ARB_shading_language_packing 1\n" -// "#define GL_ARB_cull_distance 1\n" // present for 4.5, but need extension control over block members - "#define GL_ARB_post_depth_coverage 1\n" - "#define GL_ARB_fragment_shader_interlock 1\n" - "#define GL_ARB_uniform_buffer_object 1\n" - "#define GL_ARB_shader_bit_encoding 1\n" - "#define GL_ARB_shader_storage_buffer_object 1\n" - "#define GL_ARB_texture_query_lod 1\n" - "#define GL_ARB_vertex_attrib_64bit 1\n" - "#define GL_ARB_draw_instanced 1\n" - "#define GL_ARB_fragment_coord_conventions 1\n" - - "#define GL_EXT_shader_non_constant_global_initializers 1\n" - "#define GL_EXT_shader_image_load_formatted 1\n" - "#define GL_EXT_post_depth_coverage 1\n" - "#define GL_EXT_control_flow_attributes 1\n" - "#define GL_EXT_nonuniform_qualifier 1\n" - "#define GL_EXT_shader_16bit_storage 1\n" - "#define GL_EXT_shader_8bit_storage 1\n" - "#define GL_EXT_samplerless_texture_functions 1\n" - "#define GL_EXT_scalar_block_layout 1\n" - "#define GL_EXT_fragment_invocation_density 1\n" - "#define GL_EXT_buffer_reference 1\n" - "#define GL_EXT_buffer_reference2 1\n" - "#define GL_EXT_buffer_reference_uvec2 1\n" - "#define GL_EXT_demote_to_helper_invocation 1\n" - "#define GL_EXT_debug_printf 1\n" - "#define GL_EXT_fragment_shading_rate 1\n" - "#define GL_EXT_shared_memory_block 1\n" - "#define GL_EXT_shader_integer_mix 1\n" - - // GL_KHR_shader_subgroup - "#define GL_KHR_shader_subgroup_basic 1\n" - "#define GL_KHR_shader_subgroup_vote 1\n" - "#define GL_KHR_shader_subgroup_arithmetic 1\n" - "#define GL_KHR_shader_subgroup_ballot 1\n" - "#define GL_KHR_shader_subgroup_shuffle 1\n" - "#define GL_KHR_shader_subgroup_shuffle_relative 1\n" - "#define GL_KHR_shader_subgroup_clustered 1\n" - "#define GL_KHR_shader_subgroup_quad 1\n" - - "#define GL_KHR_cooperative_matrix 1\n" - - "#define GL_EXT_shader_image_int64 1\n" - "#define GL_EXT_shader_atomic_int64 1\n" - "#define GL_EXT_shader_realtime_clock 1\n" - "#define GL_EXT_ray_tracing 1\n" - "#define GL_EXT_ray_query 1\n" - "#define GL_EXT_ray_flags_primitive_culling 1\n" - "#define GL_EXT_ray_cull_mask 1\n" - "#define GL_EXT_ray_tracing_position_fetch 1\n" - "#define GL_EXT_spirv_intrinsics 1\n" - "#define GL_EXT_mesh_shader 1\n" - - "#define GL_AMD_shader_ballot 1\n" - "#define GL_AMD_shader_trinary_minmax 1\n" - "#define GL_AMD_shader_explicit_vertex_parameter 1\n" - "#define GL_AMD_gcn_shader 1\n" - "#define GL_AMD_gpu_shader_half_float 1\n" - "#define GL_AMD_texture_gather_bias_lod 1\n" - "#define GL_AMD_gpu_shader_int16 1\n" - "#define GL_AMD_shader_image_load_store_lod 1\n" - "#define GL_AMD_shader_fragment_mask 1\n" - "#define GL_AMD_gpu_shader_half_float_fetch 1\n" - - "#define GL_INTEL_shader_integer_functions2 1\n" - - "#define GL_NV_sample_mask_override_coverage 1\n" - "#define GL_NV_geometry_shader_passthrough 1\n" - "#define GL_NV_viewport_array2 1\n" - "#define GL_NV_shader_atomic_int64 1\n" - "#define GL_NV_conservative_raster_underestimation 1\n" - "#define GL_NV_shader_subgroup_partitioned 1\n" - "#define GL_NV_shading_rate_image 1\n" - "#define GL_NV_ray_tracing 1\n" - "#define GL_NV_ray_tracing_motion_blur 1\n" - "#define GL_NV_fragment_shader_barycentric 1\n" - "#define GL_NV_compute_shader_derivatives 1\n" - "#define GL_NV_shader_texture_footprint 1\n" - "#define GL_NV_mesh_shader 1\n" - "#define GL_NV_cooperative_matrix 1\n" - "#define GL_NV_integer_cooperative_matrix 1\n" - "#define GL_NV_shader_invocation_reorder 1\n" - - "#define GL_QCOM_image_processing 1\n" - - "#define GL_EXT_shader_explicit_arithmetic_types 1\n" - "#define GL_EXT_shader_explicit_arithmetic_types_int8 1\n" - "#define GL_EXT_shader_explicit_arithmetic_types_int16 1\n" - "#define GL_EXT_shader_explicit_arithmetic_types_int32 1\n" - "#define GL_EXT_shader_explicit_arithmetic_types_int64 1\n" - "#define GL_EXT_shader_explicit_arithmetic_types_float16 1\n" - "#define GL_EXT_shader_explicit_arithmetic_types_float32 1\n" - "#define GL_EXT_shader_explicit_arithmetic_types_float64 1\n" - - "#define GL_EXT_shader_subgroup_extended_types_int8 1\n" - "#define GL_EXT_shader_subgroup_extended_types_int16 1\n" - "#define GL_EXT_shader_subgroup_extended_types_int64 1\n" - "#define GL_EXT_shader_subgroup_extended_types_float16 1\n" - - "#define GL_EXT_shader_atomic_float 1\n" - "#define GL_EXT_shader_atomic_float2 1\n" - - "#define GL_EXT_fragment_shader_barycentric 1\n" - "#define GL_EXT_texture_array 1\n" - ; - - if (spvVersion.spv == 0) { - preamble += "#define GL_ARB_bindless_texture 1\n"; - } - - if (version >= 150) { - // define GL_core_profile and GL_compatibility_profile - preamble += "#define GL_core_profile 1\n"; - - if (profile == ECompatibilityProfile) - preamble += "#define GL_compatibility_profile 1\n"; - } - if (version >= 140) { - preamble += "#define GL_EXT_null_initializer 1\n"; - preamble += "#define GL_EXT_subgroup_uniform_control_flow 1\n"; - } - if (version >= 130) { - preamble +="#define GL_FRAGMENT_PRECISION_HIGH 1\n"; - } - } - - if ((!isEsProfile() && version >= 140) || - (isEsProfile() && version >= 310)) { - preamble += - "#define GL_EXT_device_group 1\n" - "#define GL_EXT_multiview 1\n" - "#define GL_NV_shader_sm_builtins 1\n" - ; - } - - if (version >= 300 /* both ES and non-ES */) { - preamble += - "#define GL_OVR_multiview 1\n" - "#define GL_OVR_multiview2 1\n" - ; - } - - // #line and #include - preamble += - "#define GL_GOOGLE_cpp_style_line_directive 1\n" - "#define GL_GOOGLE_include_directive 1\n" - "#define GL_KHR_blend_equation_advanced 1\n" - ; - - // other general extensions - preamble += - "#define GL_EXT_terminate_invocation 1\n" - ; - - // #define VULKAN XXXX - const int numberBufSize = 12; - char numberBuf[numberBufSize]; - if (spvVersion.vulkanGlsl > 0) { - preamble += "#define VULKAN "; - snprintf(numberBuf, numberBufSize, "%d", spvVersion.vulkanGlsl); - preamble += numberBuf; - preamble += "\n"; - } - - // #define GL_SPIRV XXXX - if (spvVersion.openGl > 0) { - preamble += "#define GL_SPIRV "; - snprintf(numberBuf, numberBufSize, "%d", spvVersion.openGl); - preamble += numberBuf; - preamble += "\n"; - } - - // GL_EXT_spirv_intrinsics - if (!isEsProfile()) { - switch (language) { - case EShLangVertex: preamble += "#define GL_VERTEX_SHADER 1 \n"; break; - case EShLangTessControl: preamble += "#define GL_TESSELLATION_CONTROL_SHADER 1 \n"; break; - case EShLangTessEvaluation: preamble += "#define GL_TESSELLATION_EVALUATION_SHADER 1 \n"; break; - case EShLangGeometry: preamble += "#define GL_GEOMETRY_SHADER 1 \n"; break; - case EShLangFragment: preamble += "#define GL_FRAGMENT_SHADER 1 \n"; break; - case EShLangCompute: preamble += "#define GL_COMPUTE_SHADER 1 \n"; break; - case EShLangRayGen: preamble += "#define GL_RAY_GENERATION_SHADER_EXT 1 \n"; break; - case EShLangIntersect: preamble += "#define GL_INTERSECTION_SHADER_EXT 1 \n"; break; - case EShLangAnyHit: preamble += "#define GL_ANY_HIT_SHADER_EXT 1 \n"; break; - case EShLangClosestHit: preamble += "#define GL_CLOSEST_HIT_SHADER_EXT 1 \n"; break; - case EShLangMiss: preamble += "#define GL_MISS_SHADER_EXT 1 \n"; break; - case EShLangCallable: preamble += "#define GL_CALLABLE_SHADER_EXT 1 \n"; break; - case EShLangTask: preamble += "#define GL_TASK_SHADER_NV 1 \n"; break; - case EShLangMesh: preamble += "#define GL_MESH_SHADER_NV 1 \n"; break; - default: break; - } - } -} - -// -// Map from stage enum to externally readable text name. -// -const char* StageName(EShLanguage stage) -{ - switch(stage) { - case EShLangVertex: return "vertex"; - case EShLangFragment: return "fragment"; - case EShLangCompute: return "compute"; - case EShLangTessControl: return "tessellation control"; - case EShLangTessEvaluation: return "tessellation evaluation"; - case EShLangGeometry: return "geometry"; - case EShLangRayGen: return "ray-generation"; - case EShLangIntersect: return "intersection"; - case EShLangAnyHit: return "any-hit"; - case EShLangClosestHit: return "closest-hit"; - case EShLangMiss: return "miss"; - case EShLangCallable: return "callable"; - case EShLangMesh: return "mesh"; - case EShLangTask: return "task"; - default: return "unknown stage"; - } -} - -// -// When to use requireStage() -// -// If only some stages support a feature. -// -// Operation: If the current stage is not present, give an error message. -// -void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguageMask languageMask, const char* featureDesc) -{ - if (((1 << language) & languageMask) == 0) - error(loc, "not supported in this stage:", featureDesc, StageName(language)); -} - -// If only one stage supports a feature, this can be called. But, all supporting stages -// must be specified with one call. -void TParseVersions::requireStage(const TSourceLoc& loc, EShLanguage stage, const char* featureDesc) -{ - requireStage(loc, static_cast(1 << stage), featureDesc); -} - -// -// When to use requireProfile(): -// -// Use if only some profiles support a feature. However, if within a profile the feature -// is version or extension specific, follow this call with calls to profileRequires(). -// -// Operation: If the current profile is not one of the profileMask, -// give an error message. -// -void TParseVersions::requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc) -{ - if (! (profile & profileMask)) - error(loc, "not supported with this profile:", featureDesc, ProfileName(profile)); -} - -// -// When to use profileRequires(): -// -// If a set of profiles have the same requirements for what version or extensions -// are needed to support a feature. -// -// It must be called for each profile that needs protection. Use requireProfile() first -// to reduce that set of profiles. -// -// Operation: Will issue warnings/errors based on the current profile, version, and extension -// behaviors. It only checks extensions when the current profile is one of the profileMask. -// -// A minVersion of 0 means no version of the profileMask support this in core, -// the extension must be present. -// - -// entry point that takes multiple extensions -void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, - const char* const extensions[], const char* featureDesc) -{ - if (profile & profileMask) { - bool okay = minVersion > 0 && version >= minVersion; - for (int i = 0; i < numExtensions; ++i) { - switch (getExtensionBehavior(extensions[i])) { - case EBhWarn: - infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc); - // fall through - case EBhRequire: - case EBhEnable: - okay = true; - break; - default: break; // some compilers want this - } - } - if (! okay) - error(loc, "not supported for this version or the enabled extensions", featureDesc, ""); - } -} - -// entry point for the above that takes a single extension -void TParseVersions::profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, - const char* featureDesc) -{ - profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc); -} - -void TParseVersions::unimplemented(const TSourceLoc& loc, const char* featureDesc) -{ - error(loc, "feature not yet implemented", featureDesc, ""); -} - -// -// Within a set of profiles, see if a feature is deprecated and give an error or warning based on whether -// a future compatibility context is being use. -// -void TParseVersions::checkDeprecated(const TSourceLoc& loc, int profileMask, int depVersion, const char* featureDesc) -{ - if (profile & profileMask) { - if (version >= depVersion) { - if (forwardCompatible) - error(loc, "deprecated, may be removed in future release", featureDesc, ""); - else if (! suppressWarnings()) - infoSink.info.message(EPrefixWarning, (TString(featureDesc) + " deprecated in version " + - String(depVersion) + "; may be removed in future release").c_str(), loc); - } - } -} - -// -// Within a set of profiles, see if a feature has now been removed and if so, give an error. -// The version argument is the first version no longer having the feature. -// -void TParseVersions::requireNotRemoved(const TSourceLoc& loc, int profileMask, int removedVersion, const char* featureDesc) -{ - if (profile & profileMask) { - if (version >= removedVersion) { - const int maxSize = 60; - char buf[maxSize]; - snprintf(buf, maxSize, "%s profile; removed in version %d", ProfileName(profile), removedVersion); - error(loc, "no longer supported in", featureDesc, buf); - } - } -} - -// Returns true if at least one of the extensions in the extensions parameter is requested. Otherwise, returns false. -// Warns appropriately if the requested behavior of an extension is "warn". -bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc) -{ - // First, see if any of the extensions are enabled - for (int i = 0; i < numExtensions; ++i) { - TExtensionBehavior behavior = getExtensionBehavior(extensions[i]); - if (behavior == EBhEnable || behavior == EBhRequire) - return true; - } - - // See if any extensions want to give a warning on use; give warnings for all such extensions - bool warned = false; - for (int i = 0; i < numExtensions; ++i) { - TExtensionBehavior behavior = getExtensionBehavior(extensions[i]); - if (behavior == EBhDisable && relaxedErrors()) { - infoSink.info.message(EPrefixWarning, "The following extension must be enabled to use this feature:", loc); - behavior = EBhWarn; - } - if (behavior == EBhWarn) { - infoSink.info.message(EPrefixWarning, ("extension " + TString(extensions[i]) + " is being used for " + featureDesc).c_str(), loc); - warned = true; - } - } - if (warned) - return true; - return false; -} - -// -// Use when there are no profile/version to check, it's just an error if one of the -// extensions is not present. -// -void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], - const char* featureDesc) -{ - if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) - return; - - // If we get this far, give errors explaining what extensions are needed - if (numExtensions == 1) - error(loc, "required extension not requested:", featureDesc, extensions[0]); - else { - error(loc, "required extension not requested:", featureDesc, "Possible extensions include:"); - for (int i = 0; i < numExtensions; ++i) - infoSink.info.message(EPrefixNone, extensions[i]); - } -} - -// -// Use by preprocessor when there are no profile/version to check, it's just an error if one of the -// extensions is not present. -// -void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], - const char* featureDesc) -{ - if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) - return; - - // If we get this far, give errors explaining what extensions are needed - if (numExtensions == 1) - ppError(loc, "required extension not requested:", featureDesc, extensions[0]); - else { - ppError(loc, "required extension not requested:", featureDesc, "Possible extensions include:"); - for (int i = 0; i < numExtensions; ++i) - infoSink.info.message(EPrefixNone, extensions[i]); - } -} - -TExtensionBehavior TParseVersions::getExtensionBehavior(const char* extension) -{ - auto iter = extensionBehavior.find(TString(extension)); - if (iter == extensionBehavior.end()) - return EBhMissing; - else - return iter->second; -} - -// Returns true if the given extension is set to enable, require, or warn. -bool TParseVersions::extensionTurnedOn(const char* const extension) -{ - switch (getExtensionBehavior(extension)) { - case EBhEnable: - case EBhRequire: - case EBhWarn: - return true; - default: - break; - } - return false; -} -// See if any of the extensions are set to enable, require, or warn. -bool TParseVersions::extensionsTurnedOn(int numExtensions, const char* const extensions[]) -{ - for (int i = 0; i < numExtensions; ++i) { - if (extensionTurnedOn(extensions[i])) - return true; - } - return false; -} - -// -// Change the current state of an extension's behavior. -// -void TParseVersions::updateExtensionBehavior(int line, const char* extension, const char* behaviorString) -{ - // Translate from text string of extension's behavior to an enum. - TExtensionBehavior behavior = EBhDisable; - if (! strcmp("require", behaviorString)) - behavior = EBhRequire; - else if (! strcmp("enable", behaviorString)) - behavior = EBhEnable; - else if (! strcmp("disable", behaviorString)) - behavior = EBhDisable; - else if (! strcmp("warn", behaviorString)) - behavior = EBhWarn; - else { - error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString); - return; - } - bool on = behavior != EBhDisable; - - // check if extension is used with correct shader stage - checkExtensionStage(getCurrentLoc(), extension); - - // check if extension has additional requirements - extensionRequires(getCurrentLoc(), extension, behaviorString); - - // update the requested extension - updateExtensionBehavior(extension, behavior); - - // see if need to propagate to implicitly modified things - if (strcmp(extension, "GL_ANDROID_extension_pack_es31a") == 0) { - // to everything in AEP - updateExtensionBehavior(line, "GL_KHR_blend_equation_advanced", behaviorString); - updateExtensionBehavior(line, "GL_OES_sample_variables", behaviorString); - updateExtensionBehavior(line, "GL_OES_shader_image_atomic", behaviorString); - updateExtensionBehavior(line, "GL_OES_shader_multisample_interpolation", behaviorString); - updateExtensionBehavior(line, "GL_OES_texture_storage_multisample_2d_array", behaviorString); - updateExtensionBehavior(line, "GL_EXT_geometry_shader", behaviorString); - updateExtensionBehavior(line, "GL_EXT_gpu_shader5", behaviorString); - updateExtensionBehavior(line, "GL_EXT_primitive_bounding_box", behaviorString); - updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString); - updateExtensionBehavior(line, "GL_EXT_tessellation_shader", behaviorString); - updateExtensionBehavior(line, "GL_EXT_texture_buffer", behaviorString); - updateExtensionBehavior(line, "GL_EXT_texture_cube_map_array", behaviorString); - } - // geometry to io_blocks - else if (strcmp(extension, "GL_EXT_geometry_shader") == 0) - updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString); - else if (strcmp(extension, "GL_OES_geometry_shader") == 0) - updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString); - // tessellation to io_blocks - else if (strcmp(extension, "GL_EXT_tessellation_shader") == 0) - updateExtensionBehavior(line, "GL_EXT_shader_io_blocks", behaviorString); - else if (strcmp(extension, "GL_OES_tessellation_shader") == 0) - updateExtensionBehavior(line, "GL_OES_shader_io_blocks", behaviorString); - else if (strcmp(extension, "GL_GOOGLE_include_directive") == 0) - updateExtensionBehavior(line, "GL_GOOGLE_cpp_style_line_directive", behaviorString); - // subgroup_* to subgroup_basic - else if (strcmp(extension, "GL_KHR_shader_subgroup_vote") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_arithmetic") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_ballot") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_shuffle") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_shuffle_relative") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_clustered") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_KHR_shader_subgroup_quad") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_NV_shader_subgroup_partitioned") == 0) - updateExtensionBehavior(line, "GL_KHR_shader_subgroup_basic", behaviorString); - else if (strcmp(extension, "GL_EXT_buffer_reference2") == 0 || - strcmp(extension, "GL_EXT_buffer_reference_uvec2") == 0) - updateExtensionBehavior(line, "GL_EXT_buffer_reference", behaviorString); - else if (strcmp(extension, "GL_NV_integer_cooperative_matrix") == 0) - updateExtensionBehavior(line, "GL_NV_cooperative_matrix", behaviorString); - // subgroup extended types to explicit types - else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_int8") == 0) - updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int8", behaviorString); - else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_int16") == 0) - updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int16", behaviorString); - else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_int64") == 0) - updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int64", behaviorString); - else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_float16") == 0) - updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_float16", behaviorString); - - // see if we need to update the numeric features - else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types") == 0) - intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types, on); - else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int8") == 0) - intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int8, on); - else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int16") == 0) - intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int16, on); - else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int32") == 0) - intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int32, on); - else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_int64") == 0) - intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_int64, on); - else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float16") == 0) - intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float16, on); - else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float32") == 0) - intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float32, on); - else if (strcmp(extension, "GL_EXT_shader_explicit_arithmetic_types_float64") == 0) - intermediate.updateNumericFeature(TNumericFeatures::shader_explicit_arithmetic_types_float64, on); - else if (strcmp(extension, "GL_EXT_shader_implicit_conversions") == 0) - intermediate.updateNumericFeature(TNumericFeatures::shader_implicit_conversions, on); - else if (strcmp(extension, "GL_ARB_gpu_shader_fp64") == 0) - intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_fp64, on); - else if (strcmp(extension, "GL_AMD_gpu_shader_int16") == 0) - intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_int16, on); - else if (strcmp(extension, "GL_AMD_gpu_shader_half_float") == 0) - intermediate.updateNumericFeature(TNumericFeatures::gpu_shader_half_float, on); -} - -void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior) -{ - // Update the current behavior - if (strcmp(extension, "all") == 0) { - // special case for the 'all' extension; apply it to every extension present - if (behavior == EBhRequire || behavior == EBhEnable) { - error(getCurrentLoc(), "extension 'all' cannot have 'require' or 'enable' behavior", "#extension", ""); - return; - } else { - for (auto iter = extensionBehavior.begin(); iter != extensionBehavior.end(); ++iter) - iter->second = behavior; - } - } else { - // Do the update for this single extension - auto iter = extensionBehavior.find(TString(extension)); - if (iter == extensionBehavior.end()) { - switch (behavior) { - case EBhRequire: - error(getCurrentLoc(), "extension not supported:", "#extension", extension); - break; - case EBhEnable: - case EBhWarn: - case EBhDisable: - warn(getCurrentLoc(), "extension not supported:", "#extension", extension); - break; - default: - assert(0 && "unexpected behavior"); - } - - return; - } else { - if (iter->second == EBhDisablePartial) - warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension); - if (behavior != EBhDisable) - intermediate.addRequestedExtension(extension); - iter->second = behavior; - } - } -} - -// Check if extension is used with correct shader stage. -void TParseVersions::checkExtensionStage(const TSourceLoc& loc, const char * const extension) -{ - // GL_NV_mesh_shader extension is only allowed in task/mesh shaders - if (strcmp(extension, "GL_NV_mesh_shader") == 0) { - requireStage(loc, (EShLanguageMask)(EShLangTaskMask | EShLangMeshMask | EShLangFragmentMask), - "#extension GL_NV_mesh_shader"); - profileRequires(loc, ECoreProfile, 450, nullptr, "#extension GL_NV_mesh_shader"); - profileRequires(loc, EEsProfile, 320, nullptr, "#extension GL_NV_mesh_shader"); - if (extensionTurnedOn(E_GL_EXT_mesh_shader)) { - error(loc, "GL_EXT_mesh_shader is already turned on, and not allowed with", "#extension", extension); - } - } - else if (strcmp(extension, "GL_EXT_mesh_shader") == 0) { - requireStage(loc, (EShLanguageMask)(EShLangTaskMask | EShLangMeshMask | EShLangFragmentMask), - "#extension GL_EXT_mesh_shader"); - profileRequires(loc, ECoreProfile, 450, nullptr, "#extension GL_EXT_mesh_shader"); - profileRequires(loc, EEsProfile, 320, nullptr, "#extension GL_EXT_mesh_shader"); - if (extensionTurnedOn(E_GL_NV_mesh_shader)) { - error(loc, "GL_NV_mesh_shader is already turned on, and not allowed with", "#extension", extension); - } - } -} - -// Check if extension has additional requirements -void TParseVersions::extensionRequires(const TSourceLoc &loc, const char * const extension, const char *behaviorString) -{ - bool isEnabled = false; - if (!strcmp("require", behaviorString)) - isEnabled = true; - else if (!strcmp("enable", behaviorString)) - isEnabled = true; - - if (isEnabled) { - unsigned int minSpvVersion = 0; - auto iter = extensionMinSpv.find(TString(extension)); - if (iter != extensionMinSpv.end()) - minSpvVersion = iter->second; - requireSpv(loc, extension, minSpvVersion); - } - - if (spvVersion.spv != 0){ - for (auto ext : spvUnsupportedExt){ - if (strcmp(extension, ext.c_str()) == 0) - error(loc, "not allowed when using generating SPIR-V codes", extension, ""); - } - } -} - -// Call for any operation needing full GLSL integer data-type support. -void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op) -{ - profileRequires(loc, ENoProfile, 130, nullptr, op); - profileRequires(loc, EEsProfile, 300, nullptr, op); -} - -// Call for any operation needing GLSL double data-type support. -void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op) -{ - - //requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - if (language == EShLangVertex) { - const char* const f64_Extensions[] = {E_GL_ARB_gpu_shader_fp64, E_GL_ARB_vertex_attrib_64bit}; - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, 2, f64_Extensions, op); - } else - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader_fp64, op); -} - -// Call for any operation needing GLSL float16 data-type support. -void TParseVersions::float16Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (!builtIn) { - const char* const extensions[] = { - E_GL_AMD_gpu_shader_half_float, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_float16}; - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); - } -} - -bool TParseVersions::float16Arithmetic() -{ - const char* const extensions[] = { - E_GL_AMD_gpu_shader_half_float, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_float16}; - return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions); -} - -bool TParseVersions::int16Arithmetic() -{ - const char* const extensions[] = { - E_GL_AMD_gpu_shader_int16, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int16}; - return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions); -} - -bool TParseVersions::int8Arithmetic() -{ - const char* const extensions[] = { - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int8}; - return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions); -} - -void TParseVersions::requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) -{ - TString combined; - combined = op; - combined += ": "; - combined += featureDesc; - - const char* const extensions[] = { - E_GL_AMD_gpu_shader_half_float, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_float16}; - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str()); -} - -void TParseVersions::requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) -{ - TString combined; - combined = op; - combined += ": "; - combined += featureDesc; - - const char* const extensions[] = { - E_GL_AMD_gpu_shader_int16, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int16}; - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str()); -} - -void TParseVersions::requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) -{ - TString combined; - combined = op; - combined += ": "; - combined += featureDesc; - - const char* const extensions[] = { - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int8}; - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str()); -} - -void TParseVersions::float16ScalarVectorCheck(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (!builtIn) { - const char* const extensions[] = { - E_GL_AMD_gpu_shader_half_float, - E_GL_EXT_shader_16bit_storage, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_float16}; - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); - } -} - -// Call for any operation needing GLSL float32 data-type support. -void TParseVersions::explicitFloat32Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (!builtIn) { - const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_float32}; - requireExtensions(loc, 2, extensions, op); - } -} - -// Call for any operation needing GLSL float64 data-type support. -void TParseVersions::explicitFloat64Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (!builtIn) { - const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_float64}; - requireExtensions(loc, 2, extensions, op); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op); - } -} - -// Call for any operation needing GLSL explicit int8 data-type support. -void TParseVersions::explicitInt8Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { - const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int8}; - requireExtensions(loc, 2, extensions, op); - } -} - -// Call for any operation needing GLSL float16 opaque-type support -void TParseVersions::float16OpaqueCheck(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { - requireExtensions(loc, 1, &E_GL_AMD_gpu_shader_half_float_fetch, op); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op); - } -} - -// Call for any operation needing GLSL explicit int16 data-type support. -void TParseVersions::explicitInt16Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { - const char* const extensions[] = { - E_GL_AMD_gpu_shader_int16, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int16}; - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); - } -} - -void TParseVersions::int16ScalarVectorCheck(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { - const char* const extensions[] = { - E_GL_AMD_gpu_shader_int16, - E_GL_EXT_shader_16bit_storage, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int16}; - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); - } -} - -void TParseVersions::int8ScalarVectorCheck(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { - const char* const extensions[] = { - E_GL_EXT_shader_8bit_storage, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int8}; - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); - } -} - -// Call for any operation needing GLSL explicit int32 data-type support. -void TParseVersions::explicitInt32Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { - const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int32}; - requireExtensions(loc, 2, extensions, op); - } -} - -// Call for any operation needing GLSL 64-bit integer data-type support. -void TParseVersions::int64Check(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (! builtIn) { - const char* const extensions[3] = {E_GL_ARB_gpu_shader_int64, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int64}; - requireExtensions(loc, 3, extensions, op); - requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); - profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op); - } -} - -void TParseVersions::fcoopmatCheckNV(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (!builtIn) { - const char* const extensions[] = {E_GL_NV_cooperative_matrix}; - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); - } -} - -void TParseVersions::intcoopmatCheckNV(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (!builtIn) { - const char* const extensions[] = {E_GL_NV_integer_cooperative_matrix}; - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); - } -} - -void TParseVersions::coopmatCheck(const TSourceLoc& loc, const char* op, bool builtIn) -{ - if (!builtIn) { - const char* const extensions[] = {E_GL_KHR_cooperative_matrix}; - requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); - } -} - -// Call for any operation removed because SPIR-V is in use. -void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op) -{ - if (spvVersion.spv != 0) - error(loc, "not allowed when generating SPIR-V", op, ""); -} - -// Call for any operation removed because Vulkan SPIR-V is being generated. -void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op) -{ - if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed) - error(loc, "not allowed when using GLSL for Vulkan", op, ""); -} - -// Call for any operation that requires Vulkan. -void TParseVersions::requireVulkan(const TSourceLoc& loc, const char* op) -{ - if (spvVersion.vulkan == 0) - error(loc, "only allowed when using GLSL for Vulkan", op, ""); -} - -// Call for any operation that requires SPIR-V. -void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op) -{ - if (spvVersion.spv == 0) - error(loc, "only allowed when generating SPIR-V", op, ""); -} -void TParseVersions::requireSpv(const TSourceLoc& loc, const char *op, unsigned int version) -{ - if (spvVersion.spv < version) - error(loc, "not supported for current targeted SPIR-V version", op, ""); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/Versions.h b/3rdparty/glslang/glslang/MachineIndependent/Versions.h deleted file mode 100644 index 475cb893..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/Versions.h +++ /dev/null @@ -1,375 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2018 Google, Inc. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _VERSIONS_INCLUDED_ -#define _VERSIONS_INCLUDED_ - -#define LAST_ELEMENT_MARKER(x) x - -// -// Help manage multiple profiles, versions, extensions etc. -// - -// -// Profiles are set up for masking operations, so queries can be done on multiple -// profiles at the same time. -// -// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible -// defects from mixing the two different forms. -// -typedef enum : unsigned { - EBadProfile = 0, - ENoProfile = (1 << 0), // only for desktop, before profiles showed up - ECoreProfile = (1 << 1), - ECompatibilityProfile = (1 << 2), - EEsProfile = (1 << 3), - LAST_ELEMENT_MARKER(EProfileCount), -} EProfile; - -namespace glslang { - -// -// Map from profile enum to externally readable text name. -// -inline const char* ProfileName(EProfile profile) -{ - switch (profile) { - case ENoProfile: return "none"; - case ECoreProfile: return "core"; - case ECompatibilityProfile: return "compatibility"; - case EEsProfile: return "es"; - default: return "unknown profile"; - } -} - -// -// What source rules, validation rules, target language, etc. are needed or -// desired for SPIR-V? -// -// 0 means a target or rule set is not enabled (ignore rules from that entity). -// Non-0 means to apply semantic rules arising from that version of its rule set. -// The union of all requested rule sets will be applied. -// -struct SpvVersion { - SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0), vulkanRelaxed(false) {} - unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header - int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX" - int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use - int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX" - bool vulkanRelaxed; // relax changes to GLSL for Vulkan, allowing some GL-specific to be compiled to Vulkan SPIR-V target -}; - -// -// The behaviors from the GLSL "#extension extension_name : behavior" -// -typedef enum { - EBhMissing = 0, - EBhRequire, - EBhEnable, - EBhWarn, - EBhDisable, - EBhDisablePartial // use as initial state of an extension that is only partially implemented -} TExtensionBehavior; - -// -// Symbolic names for extensions. Strings may be directly used when calling the -// functions, but better to have the compiler do spelling checks. -// -const char* const E_GL_OES_texture_3D = "GL_OES_texture_3D"; -const char* const E_GL_OES_standard_derivatives = "GL_OES_standard_derivatives"; -const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth"; -const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external"; -const char* const E_GL_OES_EGL_image_external_essl3 = "GL_OES_EGL_image_external_essl3"; -const char* const E_GL_EXT_YUV_target = "GL_EXT_YUV_target"; -const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod"; -const char* const E_GL_EXT_shadow_samplers = "GL_EXT_shadow_samplers"; - -const char* const E_GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle"; -const char* const E_GL_3DL_array_objects = "GL_3DL_array_objects"; -const char* const E_GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack"; -const char* const E_GL_ARB_texture_gather = "GL_ARB_texture_gather"; -const char* const E_GL_ARB_gpu_shader5 = "GL_ARB_gpu_shader5"; -const char* const E_GL_ARB_separate_shader_objects = "GL_ARB_separate_shader_objects"; -const char* const E_GL_ARB_compute_shader = "GL_ARB_compute_shader"; -const char* const E_GL_ARB_tessellation_shader = "GL_ARB_tessellation_shader"; -const char* const E_GL_ARB_enhanced_layouts = "GL_ARB_enhanced_layouts"; -const char* const E_GL_ARB_texture_cube_map_array = "GL_ARB_texture_cube_map_array"; -const char* const E_GL_ARB_texture_multisample = "GL_ARB_texture_multisample"; -const char* const E_GL_ARB_shader_texture_lod = "GL_ARB_shader_texture_lod"; -const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attrib_location"; -const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location"; -const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store"; -const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters"; -const char* const E_GL_ARB_shader_atomic_counter_ops = "GL_ARB_shader_atomic_counter_ops"; -const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters"; -const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote"; -const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control"; -const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples"; -const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array"; -const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64"; -const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; -const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot"; -const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2"; -const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp"; -const char* const E_GL_ARB_shader_stencil_export = "GL_ARB_shader_stencil_export"; -// const char* const E_GL_ARB_cull_distance = "GL_ARB_cull_distance"; // present for 4.5, but need extension control over block members -const char* const E_GL_ARB_post_depth_coverage = "GL_ARB_post_depth_coverage"; -const char* const E_GL_ARB_shader_viewport_layer_array = "GL_ARB_shader_viewport_layer_array"; -const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shader_interlock"; -const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock"; -const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object"; -const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading"; -const char* const E_GL_ARB_shader_bit_encoding = "GL_ARB_shader_bit_encoding"; -const char* const E_GL_ARB_shader_image_size = "GL_ARB_shader_image_size"; -const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object"; -const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing"; -const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod"; -const char* const E_GL_ARB_vertex_attrib_64bit = "GL_ARB_vertex_attrib_64bit"; -const char* const E_GL_ARB_draw_instanced = "GL_ARB_draw_instanced"; -const char* const E_GL_ARB_fragment_coord_conventions = "GL_ARB_fragment_coord_conventions"; -const char* const E_GL_ARB_bindless_texture = "GL_ARB_bindless_texture"; - -const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic"; -const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote"; -const char* const E_GL_KHR_shader_subgroup_arithmetic = "GL_KHR_shader_subgroup_arithmetic"; -const char* const E_GL_KHR_shader_subgroup_ballot = "GL_KHR_shader_subgroup_ballot"; -const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_subgroup_shuffle"; -const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative"; -const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered"; -const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad"; -const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics"; -const char* const E_GL_KHR_cooperative_matrix = "GL_KHR_cooperative_matrix"; - -const char* const E_GL_EXT_shader_atomic_int64 = "GL_EXT_shader_atomic_int64"; - -const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers"; -const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted"; - -const char* const E_GL_EXT_shader_16bit_storage = "GL_EXT_shader_16bit_storage"; -const char* const E_GL_EXT_shader_8bit_storage = "GL_EXT_shader_8bit_storage"; - - -// EXT extensions -const char* const E_GL_EXT_device_group = "GL_EXT_device_group"; -const char* const E_GL_EXT_multiview = "GL_EXT_multiview"; -const char* const E_GL_EXT_post_depth_coverage = "GL_EXT_post_depth_coverage"; -const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes"; -const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier"; -const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions"; -const char* const E_GL_EXT_scalar_block_layout = "GL_EXT_scalar_block_layout"; -const char* const E_GL_EXT_fragment_invocation_density = "GL_EXT_fragment_invocation_density"; -const char* const E_GL_EXT_buffer_reference = "GL_EXT_buffer_reference"; -const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_reference2"; -const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2"; -const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation"; -const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock"; -const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf"; -const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing"; -const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query"; -const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling"; -const char* const E_GL_EXT_ray_cull_mask = "GL_EXT_ray_cull_mask"; -const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func_extended"; -const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions"; -const char* const E_GL_EXT_fragment_shading_rate = "GL_EXT_fragment_shading_rate"; -const char* const E_GL_EXT_shader_image_int64 = "GL_EXT_shader_image_int64"; -const char* const E_GL_EXT_null_initializer = "GL_EXT_null_initializer"; -const char* const E_GL_EXT_shared_memory_block = "GL_EXT_shared_memory_block"; -const char* const E_GL_EXT_subgroup_uniform_control_flow = "GL_EXT_subgroup_uniform_control_flow"; -const char* const E_GL_EXT_spirv_intrinsics = "GL_EXT_spirv_intrinsics"; -const char* const E_GL_EXT_fragment_shader_barycentric = "GL_EXT_fragment_shader_barycentric"; -const char* const E_GL_EXT_mesh_shader = "GL_EXT_mesh_shader"; -const char* const E_GL_EXT_opacity_micromap = "GL_EXT_opacity_micromap"; -const char* const E_GL_EXT_draw_instanced = "GL_EXT_draw_instanced"; -const char* const E_GL_EXT_texture_array = "GL_EXT_texture_array"; - -// Arrays of extensions for the above viewportEXTs duplications - -const char* const post_depth_coverageEXTs[] = { E_GL_ARB_post_depth_coverage, E_GL_EXT_post_depth_coverage }; -const int Num_post_depth_coverageEXTs = sizeof(post_depth_coverageEXTs) / sizeof(post_depth_coverageEXTs[0]); - -// Array of extensions to cover both extensions providing ray tracing capabilities. -const char* const ray_tracing_EXTs[] = { E_GL_EXT_ray_query, E_GL_EXT_ray_tracing }; -const int Num_ray_tracing_EXTs = sizeof(ray_tracing_EXTs) / sizeof(ray_tracing_EXTs[0]); - -// OVR extensions -const char* const E_GL_OVR_multiview = "GL_OVR_multiview"; -const char* const E_GL_OVR_multiview2 = "GL_OVR_multiview2"; - -const char* const OVR_multiview_EXTs[] = { E_GL_OVR_multiview, E_GL_OVR_multiview2 }; -const int Num_OVR_multiview_EXTs = sizeof(OVR_multiview_EXTs) / sizeof(OVR_multiview_EXTs[0]); - -// #line and #include -const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive"; -const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive"; - -const char* const E_GL_AMD_shader_ballot = "GL_AMD_shader_ballot"; -const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader_trinary_minmax"; -const char* const E_GL_AMD_shader_explicit_vertex_parameter = "GL_AMD_shader_explicit_vertex_parameter"; -const char* const E_GL_AMD_gcn_shader = "GL_AMD_gcn_shader"; -const char* const E_GL_AMD_gpu_shader_half_float = "GL_AMD_gpu_shader_half_float"; -const char* const E_GL_AMD_texture_gather_bias_lod = "GL_AMD_texture_gather_bias_lod"; -const char* const E_GL_AMD_gpu_shader_int16 = "GL_AMD_gpu_shader_int16"; -const char* const E_GL_AMD_shader_image_load_store_lod = "GL_AMD_shader_image_load_store_lod"; -const char* const E_GL_AMD_shader_fragment_mask = "GL_AMD_shader_fragment_mask"; -const char* const E_GL_AMD_gpu_shader_half_float_fetch = "GL_AMD_gpu_shader_half_float_fetch"; -const char* const E_GL_AMD_shader_early_and_late_fragment_tests = "GL_AMD_shader_early_and_late_fragment_tests"; - -const char* const E_GL_INTEL_shader_integer_functions2 = "GL_INTEL_shader_integer_functions2"; - -const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage"; -const char* const E_SPV_NV_geometry_shader_passthrough = "GL_NV_geometry_shader_passthrough"; -const char* const E_GL_NV_viewport_array2 = "GL_NV_viewport_array2"; -const char* const E_GL_NV_stereo_view_rendering = "GL_NV_stereo_view_rendering"; -const char* const E_GL_NVX_multiview_per_view_attributes = "GL_NVX_multiview_per_view_attributes"; -const char* const E_GL_NV_shader_atomic_int64 = "GL_NV_shader_atomic_int64"; -const char* const E_GL_NV_conservative_raster_underestimation = "GL_NV_conservative_raster_underestimation"; -const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_noperspective_interpolation"; -const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned"; -const char* const E_GL_NV_shading_rate_image = "GL_NV_shading_rate_image"; -const char* const E_GL_NV_ray_tracing = "GL_NV_ray_tracing"; -const char* const E_GL_NV_ray_tracing_motion_blur = "GL_NV_ray_tracing_motion_blur"; -const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragment_shader_barycentric"; -const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives"; -const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint"; -const char* const E_GL_NV_mesh_shader = "GL_NV_mesh_shader"; -const char* const E_GL_NV_cooperative_matrix = "GL_NV_cooperative_matrix"; -const char* const E_GL_NV_shader_sm_builtins = "GL_NV_shader_sm_builtins"; -const char* const E_GL_NV_integer_cooperative_matrix = "GL_NV_integer_cooperative_matrix"; -const char* const E_GL_NV_shader_invocation_reorder = "GL_NV_shader_invocation_reorder"; -const char* const E_GL_EXT_ray_tracing_position_fetch = "GL_EXT_ray_tracing_position_fetch"; -const char* const E_GL_NV_displacement_micromap = "GL_NV_displacement_micromap"; - -// ARM -const char* const E_GL_ARM_shader_core_builtins = "GL_ARM_shader_core_builtins"; - -// Arrays of extensions for the above viewportEXTs duplications - -const char* const viewportEXTs[] = { E_GL_ARB_shader_viewport_layer_array, E_GL_NV_viewport_array2 }; -const int Num_viewportEXTs = sizeof(viewportEXTs) / sizeof(viewportEXTs[0]); - - -const char* const E_GL_QCOM_image_processing = "GL_QCOM_image_processing"; - -// AEP -const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a"; -const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced"; -const char* const E_GL_OES_sample_variables = "GL_OES_sample_variables"; -const char* const E_GL_OES_shader_image_atomic = "GL_OES_shader_image_atomic"; -const char* const E_GL_OES_shader_multisample_interpolation = "GL_OES_shader_multisample_interpolation"; -const char* const E_GL_OES_texture_storage_multisample_2d_array = "GL_OES_texture_storage_multisample_2d_array"; -const char* const E_GL_EXT_geometry_shader = "GL_EXT_geometry_shader"; -const char* const E_GL_EXT_geometry_point_size = "GL_EXT_geometry_point_size"; -const char* const E_GL_EXT_gpu_shader5 = "GL_EXT_gpu_shader5"; -const char* const E_GL_EXT_primitive_bounding_box = "GL_EXT_primitive_bounding_box"; -const char* const E_GL_EXT_shader_io_blocks = "GL_EXT_shader_io_blocks"; -const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessellation_shader"; -const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size"; -const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer"; -const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array"; -const char* const E_GL_EXT_shader_integer_mix = "GL_EXT_shader_integer_mix"; - -// OES matching AEP -const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader"; -const char* const E_GL_OES_geometry_point_size = "GL_OES_geometry_point_size"; -const char* const E_GL_OES_gpu_shader5 = "GL_OES_gpu_shader5"; -const char* const E_GL_OES_primitive_bounding_box = "GL_OES_primitive_bounding_box"; -const char* const E_GL_OES_shader_io_blocks = "GL_OES_shader_io_blocks"; -const char* const E_GL_OES_tessellation_shader = "GL_OES_tessellation_shader"; -const char* const E_GL_OES_tessellation_point_size = "GL_OES_tessellation_point_size"; -const char* const E_GL_OES_texture_buffer = "GL_OES_texture_buffer"; -const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array"; - -// EXT -const char* const E_GL_EXT_shader_explicit_arithmetic_types = "GL_EXT_shader_explicit_arithmetic_types"; -const char* const E_GL_EXT_shader_explicit_arithmetic_types_int8 = "GL_EXT_shader_explicit_arithmetic_types_int8"; -const char* const E_GL_EXT_shader_explicit_arithmetic_types_int16 = "GL_EXT_shader_explicit_arithmetic_types_int16"; -const char* const E_GL_EXT_shader_explicit_arithmetic_types_int32 = "GL_EXT_shader_explicit_arithmetic_types_int32"; -const char* const E_GL_EXT_shader_explicit_arithmetic_types_int64 = "GL_EXT_shader_explicit_arithmetic_types_int64"; -const char* const E_GL_EXT_shader_explicit_arithmetic_types_float16 = "GL_EXT_shader_explicit_arithmetic_types_float16"; -const char* const E_GL_EXT_shader_explicit_arithmetic_types_float32 = "GL_EXT_shader_explicit_arithmetic_types_float32"; -const char* const E_GL_EXT_shader_explicit_arithmetic_types_float64 = "GL_EXT_shader_explicit_arithmetic_types_float64"; - -const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shader_subgroup_extended_types_int8"; -const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16"; -const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64"; -const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16"; -const char* const E_GL_EXT_terminate_invocation = "GL_EXT_terminate_invocation"; - -const char* const E_GL_EXT_shader_atomic_float = "GL_EXT_shader_atomic_float"; -const char* const E_GL_EXT_shader_atomic_float2 = "GL_EXT_shader_atomic_float2"; - -const char* const E_GL_EXT_shader_tile_image = "GL_EXT_shader_tile_image"; - -const char* const E_GL_EXT_texture_shadow_lod = "GL_EXT_texture_shadow_lod"; - -// Arrays of extensions for the above AEP duplications - -const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader }; -const int Num_AEP_geometry_shader = sizeof(AEP_geometry_shader)/sizeof(AEP_geometry_shader[0]); - -const char* const AEP_geometry_point_size[] = { E_GL_EXT_geometry_point_size, E_GL_OES_geometry_point_size }; -const int Num_AEP_geometry_point_size = sizeof(AEP_geometry_point_size)/sizeof(AEP_geometry_point_size[0]); - -const char* const AEP_gpu_shader5[] = { E_GL_EXT_gpu_shader5, E_GL_OES_gpu_shader5 }; -const int Num_AEP_gpu_shader5 = sizeof(AEP_gpu_shader5)/sizeof(AEP_gpu_shader5[0]); - -const char* const AEP_primitive_bounding_box[] = { E_GL_EXT_primitive_bounding_box, E_GL_OES_primitive_bounding_box }; -const int Num_AEP_primitive_bounding_box = sizeof(AEP_primitive_bounding_box)/sizeof(AEP_primitive_bounding_box[0]); - -const char* const AEP_shader_io_blocks[] = { E_GL_EXT_shader_io_blocks, E_GL_OES_shader_io_blocks }; -const int Num_AEP_shader_io_blocks = sizeof(AEP_shader_io_blocks)/sizeof(AEP_shader_io_blocks[0]); - -const char* const AEP_tessellation_shader[] = { E_GL_EXT_tessellation_shader, E_GL_OES_tessellation_shader }; -const int Num_AEP_tessellation_shader = sizeof(AEP_tessellation_shader)/sizeof(AEP_tessellation_shader[0]); - -const char* const AEP_tessellation_point_size[] = { E_GL_EXT_tessellation_point_size, E_GL_OES_tessellation_point_size }; -const int Num_AEP_tessellation_point_size = sizeof(AEP_tessellation_point_size)/sizeof(AEP_tessellation_point_size[0]); - -const char* const AEP_texture_buffer[] = { E_GL_EXT_texture_buffer, E_GL_OES_texture_buffer }; -const int Num_AEP_texture_buffer = sizeof(AEP_texture_buffer)/sizeof(AEP_texture_buffer[0]); - -const char* const AEP_texture_cube_map_array[] = { E_GL_EXT_texture_cube_map_array, E_GL_OES_texture_cube_map_array }; -const int Num_AEP_texture_cube_map_array = sizeof(AEP_texture_cube_map_array)/sizeof(AEP_texture_cube_map_array[0]); - -const char* const AEP_mesh_shader[] = { E_GL_NV_mesh_shader, E_GL_EXT_mesh_shader }; -const int Num_AEP_mesh_shader = sizeof(AEP_mesh_shader)/sizeof(AEP_mesh_shader[0]); - -} // end namespace glslang - -#endif // _VERSIONS_INCLUDED_ diff --git a/3rdparty/glslang/glslang/MachineIndependent/attribute.cpp b/3rdparty/glslang/glslang/MachineIndependent/attribute.cpp deleted file mode 100644 index a167c494..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/attribute.cpp +++ /dev/null @@ -1,370 +0,0 @@ -// -// Copyright (C) 2017 LunarG, Inc. -// Copyright (C) 2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google, Inc., nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "attribute.h" -#include "../Include/intermediate.h" -#include "ParseHelper.h" - -namespace glslang { - -// extract integers out of attribute arguments stored in attribute aggregate -bool TAttributeArgs::getInt(int& value, int argNum) const -{ - const TConstUnion* intConst = getConstUnion(EbtInt, argNum); - - if (intConst == nullptr) - return false; - - value = intConst->getIConst(); - return true; -} - - -// extract strings out of attribute arguments stored in attribute aggregate. -// convert to lower case if converToLower is true (for case-insensitive compare convenience) -bool TAttributeArgs::getString(TString& value, int argNum, bool convertToLower) const -{ - const TConstUnion* stringConst = getConstUnion(EbtString, argNum); - - if (stringConst == nullptr) - return false; - - value = *stringConst->getSConst(); - - // Convenience. - if (convertToLower) - std::transform(value.begin(), value.end(), value.begin(), ::tolower); - - return true; -} - -// How many arguments were supplied? -int TAttributeArgs::size() const -{ - return args == nullptr ? 0 : (int)args->getSequence().size(); -} - -// Helper to get attribute const union. Returns nullptr on failure. -const TConstUnion* TAttributeArgs::getConstUnion(TBasicType basicType, int argNum) const -{ - if (args == nullptr) - return nullptr; - - if (argNum >= (int)args->getSequence().size()) - return nullptr; - - if (args->getSequence()[argNum]->getAsConstantUnion() == nullptr) - return nullptr; - - const TConstUnion* constVal = &args->getSequence()[argNum]->getAsConstantUnion()->getConstArray()[0]; - if (constVal == nullptr || constVal->getType() != basicType) - return nullptr; - - return constVal; -} - -// Implementation of TParseContext parts of attributes -TAttributeType TParseContext::attributeFromName(const TString& name) const -{ - if (name == "branch" || name == "dont_flatten") - return EatBranch; - else if (name == "flatten") - return EatFlatten; - else if (name == "unroll") - return EatUnroll; - else if (name == "loop" || name == "dont_unroll") - return EatLoop; - else if (name == "dependency_infinite") - return EatDependencyInfinite; - else if (name == "dependency_length") - return EatDependencyLength; - else if (name == "min_iterations") - return EatMinIterations; - else if (name == "max_iterations") - return EatMaxIterations; - else if (name == "iteration_multiple") - return EatIterationMultiple; - else if (name == "peel_count") - return EatPeelCount; - else if (name == "partial_count") - return EatPartialCount; - else if (name == "subgroup_uniform_control_flow") - return EatSubgroupUniformControlFlow; - else if (name == "export") - return EatExport; - else - return EatNone; -} - -// Make an initial leaf for the grammar from a no-argument attribute -TAttributes* TParseContext::makeAttributes(const TString& identifier) const -{ - TAttributes *attributes = nullptr; - attributes = NewPoolObject(attributes); - TAttributeArgs args = { attributeFromName(identifier), nullptr }; - attributes->push_back(args); - return attributes; -} - -// Make an initial leaf for the grammar from a one-argument attribute -TAttributes* TParseContext::makeAttributes(const TString& identifier, TIntermNode* node) const -{ - TAttributes *attributes = nullptr; - attributes = NewPoolObject(attributes); - - // for now, node is always a simple single expression, but other code expects - // a list, so make it so - TIntermAggregate* agg = intermediate.makeAggregate(node); - TAttributeArgs args = { attributeFromName(identifier), agg }; - attributes->push_back(args); - return attributes; -} - -// Merge two sets of attributes into a single set. -// The second argument is destructively consumed. -TAttributes* TParseContext::mergeAttributes(TAttributes* attr1, TAttributes* attr2) const -{ - attr1->splice(attr1->end(), *attr2); - return attr1; -} - -// -// Selection attributes -// -void TParseContext::handleSelectionAttributes(const TAttributes& attributes, TIntermNode* node) -{ - TIntermSelection* selection = node->getAsSelectionNode(); - if (selection == nullptr) - return; - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - if (it->size() > 0) { - warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", ""); - continue; - } - - switch (it->name) { - case EatFlatten: - selection->setFlatten(); - break; - case EatBranch: - selection->setDontFlatten(); - break; - default: - warn(node->getLoc(), "attribute does not apply to a selection", "", ""); - break; - } - } -} - -// -// Switch attributes -// -void TParseContext::handleSwitchAttributes(const TAttributes& attributes, TIntermNode* node) -{ - TIntermSwitch* selection = node->getAsSwitchNode(); - if (selection == nullptr) - return; - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - if (it->size() > 0) { - warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", ""); - continue; - } - - switch (it->name) { - case EatFlatten: - selection->setFlatten(); - break; - case EatBranch: - selection->setDontFlatten(); - break; - default: - warn(node->getLoc(), "attribute does not apply to a switch", "", ""); - break; - } - } -} - -// -// Loop attributes -// -void TParseContext::handleLoopAttributes(const TAttributes& attributes, TIntermNode* node) -{ - TIntermLoop* loop = node->getAsLoopNode(); - if (loop == nullptr) { - // the actual loop might be part of a sequence - TIntermAggregate* agg = node->getAsAggregate(); - if (agg == nullptr) - return; - for (auto it = agg->getSequence().begin(); it != agg->getSequence().end(); ++it) { - loop = (*it)->getAsLoopNode(); - if (loop != nullptr) - break; - } - if (loop == nullptr) - return; - } - - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - - const auto noArgument = [&](const char* feature) { - if (it->size() > 0) { - warn(node->getLoc(), "expected no arguments", feature, ""); - return false; - } - return true; - }; - - const auto positiveSignedArgument = [&](const char* feature, int& value) { - if (it->size() == 1 && it->getInt(value)) { - if (value <= 0) { - error(node->getLoc(), "must be positive", feature, ""); - return false; - } - } else { - warn(node->getLoc(), "expected a single integer argument", feature, ""); - return false; - } - return true; - }; - - const auto unsignedArgument = [&](const char* feature, unsigned int& uiValue) { - int value; - if (!(it->size() == 1 && it->getInt(value))) { - warn(node->getLoc(), "expected a single integer argument", feature, ""); - return false; - } - uiValue = (unsigned int)value; - return true; - }; - - const auto positiveUnsignedArgument = [&](const char* feature, unsigned int& uiValue) { - int value; - if (it->size() == 1 && it->getInt(value)) { - if (value == 0) { - error(node->getLoc(), "must be greater than or equal to 1", feature, ""); - return false; - } - } else { - warn(node->getLoc(), "expected a single integer argument", feature, ""); - return false; - } - uiValue = (unsigned int)value; - return true; - }; - - const auto spirv14 = [&](const char* feature) { - if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4) - warn(node->getLoc(), "attribute requires a SPIR-V 1.4 target-env", feature, ""); - }; - - int value = 0; - unsigned uiValue = 0; - switch (it->name) { - case EatUnroll: - if (noArgument("unroll")) - loop->setUnroll(); - break; - case EatLoop: - if (noArgument("dont_unroll")) - loop->setDontUnroll(); - break; - case EatDependencyInfinite: - if (noArgument("dependency_infinite")) - loop->setLoopDependency(TIntermLoop::dependencyInfinite); - break; - case EatDependencyLength: - if (positiveSignedArgument("dependency_length", value)) - loop->setLoopDependency(value); - break; - case EatMinIterations: - spirv14("min_iterations"); - if (unsignedArgument("min_iterations", uiValue)) - loop->setMinIterations(uiValue); - break; - case EatMaxIterations: - spirv14("max_iterations"); - if (unsignedArgument("max_iterations", uiValue)) - loop->setMaxIterations(uiValue); - break; - case EatIterationMultiple: - spirv14("iteration_multiple"); - if (positiveUnsignedArgument("iteration_multiple", uiValue)) - loop->setIterationMultiple(uiValue); - break; - case EatPeelCount: - spirv14("peel_count"); - if (unsignedArgument("peel_count", uiValue)) - loop->setPeelCount(uiValue); - break; - case EatPartialCount: - spirv14("partial_count"); - if (unsignedArgument("partial_count", uiValue)) - loop->setPartialCount(uiValue); - break; - default: - warn(node->getLoc(), "attribute does not apply to a loop", "", ""); - break; - } - } -} - - -// -// Function attributes -// -void TParseContext::handleFunctionAttributes(const TSourceLoc& loc, const TAttributes& attributes) -{ - for (auto it = attributes.begin(); it != attributes.end(); ++it) { - if (it->size() > 0) { - warn(loc, "attribute with arguments not recognized, skipping", "", ""); - continue; - } - - switch (it->name) { - case EatSubgroupUniformControlFlow: - requireExtensions(loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute"); - intermediate.setSubgroupUniformControlFlow(); - break; - default: - warn(loc, "attribute does not apply to a function", "", ""); - break; - } - } -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/attribute.h b/3rdparty/glslang/glslang/MachineIndependent/attribute.h deleted file mode 100644 index a0c4c43d..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/attribute.h +++ /dev/null @@ -1,151 +0,0 @@ -// -// Copyright (C) 2017 LunarG, Inc. -// Copyright (C) 2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _ATTRIBUTE_INCLUDED_ -#define _ATTRIBUTE_INCLUDED_ - -#include "../Include/Common.h" -#include "../Include/ConstantUnion.h" - -namespace glslang { - - enum TAttributeType { - EatNone, - EatAllow_uav_condition, - EatBranch, - EatCall, - EatDomain, - EatEarlyDepthStencil, - EatFastOpt, - EatFlatten, - EatForceCase, - EatInstance, - EatMaxTessFactor, - EatNumThreads, - EatMaxVertexCount, - EatOutputControlPoints, - EatOutputTopology, - EatPartitioning, - EatPatchConstantFunc, - EatPatchSize, - EatUnroll, - EatLoop, - EatBinding, - EatGlobalBinding, - EatLocation, - EatInputAttachment, - EatBuiltIn, - EatPushConstant, - EatConstantId, - EatDependencyInfinite, - EatDependencyLength, - EatMinIterations, - EatMaxIterations, - EatIterationMultiple, - EatPeelCount, - EatPartialCount, - EatFormatRgba32f, - EatFormatRgba16f, - EatFormatR32f, - EatFormatRgba8, - EatFormatRgba8Snorm, - EatFormatRg32f, - EatFormatRg16f, - EatFormatR11fG11fB10f, - EatFormatR16f, - EatFormatRgba16, - EatFormatRgb10A2, - EatFormatRg16, - EatFormatRg8, - EatFormatR16, - EatFormatR8, - EatFormatRgba16Snorm, - EatFormatRg16Snorm, - EatFormatRg8Snorm, - EatFormatR16Snorm, - EatFormatR8Snorm, - EatFormatRgba32i, - EatFormatRgba16i, - EatFormatRgba8i, - EatFormatR32i, - EatFormatRg32i, - EatFormatRg16i, - EatFormatRg8i, - EatFormatR16i, - EatFormatR8i, - EatFormatRgba32ui, - EatFormatRgba16ui, - EatFormatRgba8ui, - EatFormatR32ui, - EatFormatRgb10a2ui, - EatFormatRg32ui, - EatFormatRg16ui, - EatFormatRg8ui, - EatFormatR16ui, - EatFormatR8ui, - EatFormatUnknown, - EatNonWritable, - EatNonReadable, - EatSubgroupUniformControlFlow, - EatExport, - }; - - class TIntermAggregate; - - struct TAttributeArgs { - TAttributeType name; - const TIntermAggregate* args; - - // Obtain attribute as integer - // Return false if it cannot be obtained - bool getInt(int& value, int argNum = 0) const; - - // Obtain attribute as string, with optional to-lower transform - // Return false if it cannot be obtained - bool getString(TString& value, int argNum = 0, bool convertToLower = true) const; - - // How many arguments were provided to the attribute? - int size() const; - - protected: - const TConstUnion* getConstUnion(TBasicType basicType, int argNum) const; - }; - - typedef TList TAttributes; - -} // end namespace glslang - -#endif // _ATTRIBUTE_INCLUDED_ diff --git a/3rdparty/glslang/glslang/MachineIndependent/gl_types.h b/3rdparty/glslang/glslang/MachineIndependent/gl_types.h deleted file mode 100644 index d6c93937..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/gl_types.h +++ /dev/null @@ -1,218 +0,0 @@ -/* -** Copyright (c) 2013 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. -** -** 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. -*/ - -#pragma once - -#define GL_FLOAT 0x1406 -#define GL_FLOAT_VEC2 0x8B50 -#define GL_FLOAT_VEC3 0x8B51 -#define GL_FLOAT_VEC4 0x8B52 - -#define GL_DOUBLE 0x140A -#define GL_DOUBLE_VEC2 0x8FFC -#define GL_DOUBLE_VEC3 0x8FFD -#define GL_DOUBLE_VEC4 0x8FFE - -#define GL_INT 0x1404 -#define GL_INT_VEC2 0x8B53 -#define GL_INT_VEC3 0x8B54 -#define GL_INT_VEC4 0x8B55 - -#define GL_UNSIGNED_INT 0x1405 -#define GL_UNSIGNED_INT_VEC2 0x8DC6 -#define GL_UNSIGNED_INT_VEC3 0x8DC7 -#define GL_UNSIGNED_INT_VEC4 0x8DC8 - -#define GL_INT64_ARB 0x140E -#define GL_INT64_VEC2_ARB 0x8FE9 -#define GL_INT64_VEC3_ARB 0x8FEA -#define GL_INT64_VEC4_ARB 0x8FEB - -#define GL_UNSIGNED_INT64_ARB 0x140F -#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5 -#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6 -#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7 -#define GL_UNSIGNED_INT16_VEC2_NV 0x8FF1 -#define GL_UNSIGNED_INT16_VEC3_NV 0x8FF2 -#define GL_UNSIGNED_INT16_VEC4_NV 0x8FF3 - -#define GL_INT16_NV 0x8FE4 -#define GL_INT16_VEC2_NV 0x8FE5 -#define GL_INT16_VEC3_NV 0x8FE6 -#define GL_INT16_VEC4_NV 0x8FE7 - -#define GL_BOOL 0x8B56 -#define GL_BOOL_VEC2 0x8B57 -#define GL_BOOL_VEC3 0x8B58 -#define GL_BOOL_VEC4 0x8B59 - -#define GL_FLOAT_MAT2 0x8B5A -#define GL_FLOAT_MAT3 0x8B5B -#define GL_FLOAT_MAT4 0x8B5C -#define GL_FLOAT_MAT2x3 0x8B65 -#define GL_FLOAT_MAT2x4 0x8B66 -#define GL_FLOAT_MAT3x2 0x8B67 -#define GL_FLOAT_MAT3x4 0x8B68 -#define GL_FLOAT_MAT4x2 0x8B69 -#define GL_FLOAT_MAT4x3 0x8B6A - -#define GL_DOUBLE_MAT2 0x8F46 -#define GL_DOUBLE_MAT3 0x8F47 -#define GL_DOUBLE_MAT4 0x8F48 -#define GL_DOUBLE_MAT2x3 0x8F49 -#define GL_DOUBLE_MAT2x4 0x8F4A -#define GL_DOUBLE_MAT3x2 0x8F4B -#define GL_DOUBLE_MAT3x4 0x8F4C -#define GL_DOUBLE_MAT4x2 0x8F4D -#define GL_DOUBLE_MAT4x3 0x8F4E - -// Those constants are borrowed from extension NV_gpu_shader5 -#define GL_FLOAT16_NV 0x8FF8 -#define GL_FLOAT16_VEC2_NV 0x8FF9 -#define GL_FLOAT16_VEC3_NV 0x8FFA -#define GL_FLOAT16_VEC4_NV 0x8FFB - -#define GL_FLOAT16_MAT2_AMD 0x91C5 -#define GL_FLOAT16_MAT3_AMD 0x91C6 -#define GL_FLOAT16_MAT4_AMD 0x91C7 -#define GL_FLOAT16_MAT2x3_AMD 0x91C8 -#define GL_FLOAT16_MAT2x4_AMD 0x91C9 -#define GL_FLOAT16_MAT3x2_AMD 0x91CA -#define GL_FLOAT16_MAT3x4_AMD 0x91CB -#define GL_FLOAT16_MAT4x2_AMD 0x91CC -#define GL_FLOAT16_MAT4x3_AMD 0x91CD - -#define GL_SAMPLER_1D 0x8B5D -#define GL_SAMPLER_2D 0x8B5E -#define GL_SAMPLER_3D 0x8B5F -#define GL_SAMPLER_CUBE 0x8B60 -#define GL_SAMPLER_BUFFER 0x8DC2 -#define GL_SAMPLER_1D_ARRAY 0x8DC0 -#define GL_SAMPLER_2D_ARRAY 0x8DC1 -#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 -#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 -#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 -#define GL_SAMPLER_1D_SHADOW 0x8B61 -#define GL_SAMPLER_2D_SHADOW 0x8B62 -#define GL_SAMPLER_2D_RECT 0x8B63 -#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 -#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 -#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B -#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C -#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D -#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C -#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D - -#define GL_FLOAT16_SAMPLER_1D_AMD 0x91CE -#define GL_FLOAT16_SAMPLER_2D_AMD 0x91CF -#define GL_FLOAT16_SAMPLER_3D_AMD 0x91D0 -#define GL_FLOAT16_SAMPLER_CUBE_AMD 0x91D1 -#define GL_FLOAT16_SAMPLER_2D_RECT_AMD 0x91D2 -#define GL_FLOAT16_SAMPLER_1D_ARRAY_AMD 0x91D3 -#define GL_FLOAT16_SAMPLER_2D_ARRAY_AMD 0x91D4 -#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD 0x91D5 -#define GL_FLOAT16_SAMPLER_BUFFER_AMD 0x91D6 -#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD 0x91D7 -#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD 0x91D8 - -#define GL_FLOAT16_SAMPLER_1D_SHADOW_AMD 0x91D9 -#define GL_FLOAT16_SAMPLER_2D_SHADOW_AMD 0x91DA -#define GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD 0x91DB -#define GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD 0x91DC -#define GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD 0x91DD -#define GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD 0x91DE -#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD 0x91DF - -#define GL_FLOAT16_IMAGE_1D_AMD 0x91E0 -#define GL_FLOAT16_IMAGE_2D_AMD 0x91E1 -#define GL_FLOAT16_IMAGE_3D_AMD 0x91E2 -#define GL_FLOAT16_IMAGE_2D_RECT_AMD 0x91E3 -#define GL_FLOAT16_IMAGE_CUBE_AMD 0x91E4 -#define GL_FLOAT16_IMAGE_1D_ARRAY_AMD 0x91E5 -#define GL_FLOAT16_IMAGE_2D_ARRAY_AMD 0x91E6 -#define GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD 0x91E7 -#define GL_FLOAT16_IMAGE_BUFFER_AMD 0x91E8 -#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD 0x91E9 -#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD 0x91EA - -#define GL_INT_SAMPLER_1D 0x8DC9 -#define GL_INT_SAMPLER_2D 0x8DCA -#define GL_INT_SAMPLER_3D 0x8DCB -#define GL_INT_SAMPLER_CUBE 0x8DCC -#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE -#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF -#define GL_INT_SAMPLER_2D_RECT 0x8DCD -#define GL_INT_SAMPLER_BUFFER 0x8DD0 -#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 -#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C -#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E -#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E - -#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 -#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 -#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 -#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 -#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 -#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 -#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 -#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 -#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D -#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F -#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F -#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A - -#define GL_IMAGE_1D 0x904C -#define GL_IMAGE_2D 0x904D -#define GL_IMAGE_3D 0x904E -#define GL_IMAGE_2D_RECT 0x904F -#define GL_IMAGE_CUBE 0x9050 -#define GL_IMAGE_BUFFER 0x9051 -#define GL_IMAGE_1D_ARRAY 0x9052 -#define GL_IMAGE_2D_ARRAY 0x9053 -#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 -#define GL_IMAGE_2D_MULTISAMPLE 0x9055 -#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 -#define GL_INT_IMAGE_1D 0x9057 -#define GL_INT_IMAGE_2D 0x9058 -#define GL_INT_IMAGE_3D 0x9059 -#define GL_INT_IMAGE_2D_RECT 0x905A -#define GL_INT_IMAGE_CUBE 0x905B -#define GL_INT_IMAGE_BUFFER 0x905C -#define GL_INT_IMAGE_1D_ARRAY 0x905D -#define GL_INT_IMAGE_2D_ARRAY 0x905E -#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F -#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 -#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 -#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 -#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 -#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 -#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 -#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 -#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 -#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 -#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 -#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A -#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B -#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C - -#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB diff --git a/3rdparty/glslang/glslang/MachineIndependent/glslang.y b/3rdparty/glslang/glslang/MachineIndependent/glslang.y deleted file mode 100644 index 167cdca0..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/glslang.y +++ /dev/null @@ -1,4443 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2013 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2019 Google, Inc. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -/** - * This is bison grammar and productions for parsing all versions of the - * GLSL shading languages. - */ -%{ - -/* Based on: -ANSI C Yacc grammar - -In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a -matching Lex specification) for the April 30, 1985 draft version of the -ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that -original, as mentioned in the answer to question 17.25 of the comp.lang.c -FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z. - -I intend to keep this version as close to the current C Standard grammar as -possible; please let me know if you discover discrepancies. - -Jutta Degener, 1995 -*/ - -#include "SymbolTable.h" -#include "ParseHelper.h" -#include "../Public/ShaderLang.h" -#include "attribute.h" - -using namespace glslang; - -%} - -%define parse.error verbose - -%union { - struct { - glslang::TSourceLoc loc; - union { - glslang::TString *string; - int i; - unsigned int u; - long long i64; - unsigned long long u64; - bool b; - double d; - }; - glslang::TSymbol* symbol; - } lex; - struct { - glslang::TSourceLoc loc; - glslang::TOperator op; - union { - TIntermNode* intermNode; - glslang::TIntermNodePair nodePair; - glslang::TIntermTyped* intermTypedNode; - glslang::TAttributes* attributes; - glslang::TSpirvRequirement* spirvReq; - glslang::TSpirvInstruction* spirvInst; - glslang::TSpirvTypeParameters* spirvTypeParams; - }; - union { - glslang::TPublicType type; - glslang::TFunction* function; - glslang::TParameter param; - glslang::TTypeLoc typeLine; - glslang::TTypeList* typeList; - glslang::TArraySizes* arraySizes; - glslang::TIdentifierList* identifierList; - }; - glslang::TTypeParameters* typeParameters; - } interm; -} - -%{ - -#define parseContext (*pParseContext) -#define yyerror(context, msg) context->parserError(msg) - -extern int yylex(YYSTYPE*, TParseContext&); - -%} - -%parse-param {glslang::TParseContext* pParseContext} -%lex-param {parseContext} -%pure-parser // enable thread safety -%expect 1 // One shift reduce conflict because of if | else - -%token CONST BOOL INT UINT FLOAT -%token BVEC2 BVEC3 BVEC4 -%token IVEC2 IVEC3 IVEC4 -%token UVEC2 UVEC3 UVEC4 -%token VEC2 VEC3 VEC4 -%token MAT2 MAT3 MAT4 -%token MAT2X2 MAT2X3 MAT2X4 -%token MAT3X2 MAT3X3 MAT3X4 -%token MAT4X2 MAT4X3 MAT4X4 - -// combined image/sampler -%token SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER2DSHADOW -%token SAMPLERCUBESHADOW SAMPLER2DARRAY -%token SAMPLER2DARRAYSHADOW ISAMPLER2D ISAMPLER3D ISAMPLERCUBE -%token ISAMPLER2DARRAY USAMPLER2D USAMPLER3D -%token USAMPLERCUBE USAMPLER2DARRAY - -// separate image/sampler -%token SAMPLER SAMPLERSHADOW -%token TEXTURE2D TEXTURE3D TEXTURECUBE TEXTURE2DARRAY -%token ITEXTURE2D ITEXTURE3D ITEXTURECUBE ITEXTURE2DARRAY -%token UTEXTURE2D UTEXTURE3D UTEXTURECUBE UTEXTURE2DARRAY - -%token ATTRIBUTE VARYING -%token FLOAT16_T FLOAT32_T DOUBLE FLOAT64_T -%token INT64_T UINT64_T INT32_T UINT32_T INT16_T UINT16_T INT8_T UINT8_T -%token I64VEC2 I64VEC3 I64VEC4 -%token U64VEC2 U64VEC3 U64VEC4 -%token I32VEC2 I32VEC3 I32VEC4 -%token U32VEC2 U32VEC3 U32VEC4 -%token I16VEC2 I16VEC3 I16VEC4 -%token U16VEC2 U16VEC3 U16VEC4 -%token I8VEC2 I8VEC3 I8VEC4 -%token U8VEC2 U8VEC3 U8VEC4 -%token DVEC2 DVEC3 DVEC4 DMAT2 DMAT3 DMAT4 -%token F16VEC2 F16VEC3 F16VEC4 F16MAT2 F16MAT3 F16MAT4 -%token F32VEC2 F32VEC3 F32VEC4 F32MAT2 F32MAT3 F32MAT4 -%token F64VEC2 F64VEC3 F64VEC4 F64MAT2 F64MAT3 F64MAT4 -%token DMAT2X2 DMAT2X3 DMAT2X4 -%token DMAT3X2 DMAT3X3 DMAT3X4 -%token DMAT4X2 DMAT4X3 DMAT4X4 -%token F16MAT2X2 F16MAT2X3 F16MAT2X4 -%token F16MAT3X2 F16MAT3X3 F16MAT3X4 -%token F16MAT4X2 F16MAT4X3 F16MAT4X4 -%token F32MAT2X2 F32MAT2X3 F32MAT2X4 -%token F32MAT3X2 F32MAT3X3 F32MAT3X4 -%token F32MAT4X2 F32MAT4X3 F32MAT4X4 -%token F64MAT2X2 F64MAT2X3 F64MAT2X4 -%token F64MAT3X2 F64MAT3X3 F64MAT3X4 -%token F64MAT4X2 F64MAT4X3 F64MAT4X4 -%token ATOMIC_UINT -%token ACCSTRUCTNV -%token ACCSTRUCTEXT -%token RAYQUERYEXT -%token FCOOPMATNV ICOOPMATNV UCOOPMATNV -%token COOPMAT -%token HITOBJECTNV HITOBJECTATTRNV - -// combined image/sampler -%token SAMPLERCUBEARRAY SAMPLERCUBEARRAYSHADOW -%token ISAMPLERCUBEARRAY USAMPLERCUBEARRAY -%token SAMPLER1D SAMPLER1DARRAY SAMPLER1DARRAYSHADOW ISAMPLER1D SAMPLER1DSHADOW -%token SAMPLER2DRECT SAMPLER2DRECTSHADOW ISAMPLER2DRECT USAMPLER2DRECT -%token SAMPLERBUFFER ISAMPLERBUFFER USAMPLERBUFFER -%token SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS -%token SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY -%token SAMPLEREXTERNALOES -%token SAMPLEREXTERNAL2DY2YEXT -%token ISAMPLER1DARRAY USAMPLER1D USAMPLER1DARRAY -%token F16SAMPLER1D F16SAMPLER2D F16SAMPLER3D F16SAMPLER2DRECT F16SAMPLERCUBE -%token F16SAMPLER1DARRAY F16SAMPLER2DARRAY F16SAMPLERCUBEARRAY -%token F16SAMPLERBUFFER F16SAMPLER2DMS F16SAMPLER2DMSARRAY -%token F16SAMPLER1DSHADOW F16SAMPLER2DSHADOW F16SAMPLER1DARRAYSHADOW F16SAMPLER2DARRAYSHADOW -%token F16SAMPLER2DRECTSHADOW F16SAMPLERCUBESHADOW F16SAMPLERCUBEARRAYSHADOW - -// images -%token IMAGE1D IIMAGE1D UIMAGE1D IMAGE2D IIMAGE2D -%token UIMAGE2D IMAGE3D IIMAGE3D UIMAGE3D -%token IMAGE2DRECT IIMAGE2DRECT UIMAGE2DRECT -%token IMAGECUBE IIMAGECUBE UIMAGECUBE -%token IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER -%token IMAGE1DARRAY IIMAGE1DARRAY UIMAGE1DARRAY -%token IMAGE2DARRAY IIMAGE2DARRAY UIMAGE2DARRAY -%token IMAGECUBEARRAY IIMAGECUBEARRAY UIMAGECUBEARRAY -%token IMAGE2DMS IIMAGE2DMS UIMAGE2DMS -%token IMAGE2DMSARRAY IIMAGE2DMSARRAY UIMAGE2DMSARRAY - -%token F16IMAGE1D F16IMAGE2D F16IMAGE3D F16IMAGE2DRECT -%token F16IMAGECUBE F16IMAGE1DARRAY F16IMAGE2DARRAY F16IMAGECUBEARRAY -%token F16IMAGEBUFFER F16IMAGE2DMS F16IMAGE2DMSARRAY - -%token I64IMAGE1D U64IMAGE1D -%token I64IMAGE2D U64IMAGE2D -%token I64IMAGE3D U64IMAGE3D -%token I64IMAGE2DRECT U64IMAGE2DRECT -%token I64IMAGECUBE U64IMAGECUBE -%token I64IMAGEBUFFER U64IMAGEBUFFER -%token I64IMAGE1DARRAY U64IMAGE1DARRAY -%token I64IMAGE2DARRAY U64IMAGE2DARRAY -%token I64IMAGECUBEARRAY U64IMAGECUBEARRAY -%token I64IMAGE2DMS U64IMAGE2DMS -%token I64IMAGE2DMSARRAY U64IMAGE2DMSARRAY - -// texture without sampler -%token TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY -%token TEXTURE1D ITEXTURE1D UTEXTURE1D -%token TEXTURE1DARRAY ITEXTURE1DARRAY UTEXTURE1DARRAY -%token TEXTURE2DRECT ITEXTURE2DRECT UTEXTURE2DRECT -%token TEXTUREBUFFER ITEXTUREBUFFER UTEXTUREBUFFER -%token TEXTURE2DMS ITEXTURE2DMS UTEXTURE2DMS -%token TEXTURE2DMSARRAY ITEXTURE2DMSARRAY UTEXTURE2DMSARRAY - -%token F16TEXTURE1D F16TEXTURE2D F16TEXTURE3D F16TEXTURE2DRECT F16TEXTURECUBE -%token F16TEXTURE1DARRAY F16TEXTURE2DARRAY F16TEXTURECUBEARRAY -%token F16TEXTUREBUFFER F16TEXTURE2DMS F16TEXTURE2DMSARRAY - -// input attachments -%token SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS -%token F16SUBPASSINPUT F16SUBPASSINPUTMS - -// spirv intrinsics -%token SPIRV_INSTRUCTION SPIRV_EXECUTION_MODE SPIRV_EXECUTION_MODE_ID -%token SPIRV_DECORATE SPIRV_DECORATE_ID SPIRV_DECORATE_STRING -%token SPIRV_TYPE SPIRV_STORAGE_CLASS SPIRV_BY_REFERENCE SPIRV_LITERAL -%token ATTACHMENTEXT IATTACHMENTEXT UATTACHMENTEXT - -%token LEFT_OP RIGHT_OP -%token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP -%token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN -%token MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN -%token SUB_ASSIGN -%token STRING_LITERAL - -%token LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT -%token COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT -%token LEFT_ANGLE RIGHT_ANGLE VERTICAL_BAR CARET AMPERSAND QUESTION - -%token INVARIANT -%token HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION -%token PACKED RESOURCE SUPERP - -%token FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT -%token IDENTIFIER TYPE_NAME -%token CENTROID IN OUT INOUT -%token STRUCT VOID WHILE -%token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT -%token TERMINATE_INVOCATION -%token TERMINATE_RAY IGNORE_INTERSECTION -%token UNIFORM SHARED BUFFER TILEIMAGEEXT -%token FLAT SMOOTH LAYOUT - -%token DOUBLECONSTANT INT16CONSTANT UINT16CONSTANT FLOAT16CONSTANT INT32CONSTANT UINT32CONSTANT -%token INT64CONSTANT UINT64CONSTANT -%token SUBROUTINE DEMOTE -%token PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV -%token PAYLOADEXT PAYLOADINEXT HITATTREXT CALLDATAEXT CALLDATAINEXT -%token PATCH SAMPLE NONUNIFORM -%token COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT -%token SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT -%token NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXEXT PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV PERPRIMITIVEEXT TASKPAYLOADWORKGROUPEXT -%token PRECISE - -%type assignment_operator unary_operator -%type variable_identifier primary_expression postfix_expression -%type expression integer_expression assignment_expression -%type unary_expression multiplicative_expression additive_expression -%type relational_expression equality_expression -%type conditional_expression constant_expression -%type logical_or_expression logical_xor_expression logical_and_expression -%type shift_expression and_expression exclusive_or_expression inclusive_or_expression -%type function_call initializer condition conditionopt - -%type translation_unit function_definition -%type statement simple_statement -%type statement_list switch_statement_list compound_statement -%type declaration_statement selection_statement selection_statement_nonattributed expression_statement -%type switch_statement switch_statement_nonattributed case_label -%type declaration external_declaration -%type for_init_statement compound_statement_no_new_scope -%type selection_rest_statement for_rest_statement -%type iteration_statement iteration_statement_nonattributed jump_statement statement_no_new_scope statement_scoped -%type single_declaration init_declarator_list - -%type parameter_declaration parameter_declarator parameter_type_specifier - -%type array_specifier -%type invariant_qualifier interpolation_qualifier storage_qualifier precision_qualifier -%type layout_qualifier layout_qualifier_id_list layout_qualifier_id - -%type type_parameter_specifier -%type type_parameter_specifier_opt -%type type_parameter_specifier_list - -%type type_qualifier fully_specified_type type_specifier -%type single_type_qualifier -%type type_specifier_nonarray -%type struct_specifier -%type struct_declarator -%type struct_declarator_list struct_declaration struct_declaration_list -%type block_structure -%type function_header function_declarator -%type function_header_with_parameters -%type function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype -%type function_call_or_method function_identifier function_call_header - -%type identifier_list - -%type precise_qualifier non_uniform_qualifier -%type type_name_list -%type attribute attribute_list single_attribute -%type demote_statement -%type initializer_list -%type spirv_requirements_list spirv_requirements_parameter -%type spirv_extension_list spirv_capability_list -%type spirv_execution_mode_qualifier -%type spirv_execution_mode_parameter_list spirv_execution_mode_parameter spirv_execution_mode_id_parameter_list -%type spirv_storage_class_qualifier -%type spirv_decorate_qualifier -%type spirv_decorate_parameter_list spirv_decorate_parameter -%type spirv_decorate_id_parameter_list spirv_decorate_id_parameter -%type spirv_decorate_string_parameter_list -%type spirv_type_specifier -%type spirv_type_parameter_list spirv_type_parameter -%type spirv_instruction_qualifier -%type spirv_instruction_qualifier_list spirv_instruction_qualifier_id - -%start translation_unit -%% - -variable_identifier - : IDENTIFIER { - $$ = parseContext.handleVariable($1.loc, $1.symbol, $1.string); - } - ; - -primary_expression - : variable_identifier { - $$ = $1; - } - | LEFT_PAREN expression RIGHT_PAREN { - $$ = $2; - if ($$->getAsConstantUnion()) - $$->getAsConstantUnion()->setExpression(); - } - | FLOATCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true); - } - | INTCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); - } - | UINTCONSTANT { - parseContext.fullIntegerCheck($1.loc, "unsigned literal"); - $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true); - } - | BOOLCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); - } - | STRING_LITERAL { - $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true); - } - | INT32CONSTANT { - parseContext.explicitInt32Check($1.loc, "32-bit signed literal"); - $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); - } - | UINT32CONSTANT { - parseContext.explicitInt32Check($1.loc, "32-bit signed literal"); - $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true); - } - | INT64CONSTANT { - parseContext.int64Check($1.loc, "64-bit integer literal"); - $$ = parseContext.intermediate.addConstantUnion($1.i64, $1.loc, true); - } - | UINT64CONSTANT { - parseContext.int64Check($1.loc, "64-bit unsigned integer literal"); - $$ = parseContext.intermediate.addConstantUnion($1.u64, $1.loc, true); - } - | INT16CONSTANT { - parseContext.explicitInt16Check($1.loc, "16-bit integer literal"); - $$ = parseContext.intermediate.addConstantUnion((short)$1.i, $1.loc, true); - } - | UINT16CONSTANT { - parseContext.explicitInt16Check($1.loc, "16-bit unsigned integer literal"); - $$ = parseContext.intermediate.addConstantUnion((unsigned short)$1.u, $1.loc, true); - } - | DOUBLECONSTANT { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double literal"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double literal"); - $$ = parseContext.intermediate.addConstantUnion($1.d, EbtDouble, $1.loc, true); - } - | FLOAT16CONSTANT { - parseContext.float16Check($1.loc, "half float literal"); - $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat16, $1.loc, true); - } - ; - -postfix_expression - : primary_expression { - $$ = $1; - } - | postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET { - $$ = parseContext.handleBracketDereference($2.loc, $1, $3); - } - | function_call { - $$ = $1; - } - | postfix_expression DOT IDENTIFIER { - $$ = parseContext.handleDotDereference($3.loc, $1, *$3.string); - } - | postfix_expression INC_OP { - parseContext.variableCheck($1); - parseContext.lValueErrorCheck($2.loc, "++", $1); - $$ = parseContext.handleUnaryMath($2.loc, "++", EOpPostIncrement, $1); - } - | postfix_expression DEC_OP { - parseContext.variableCheck($1); - parseContext.lValueErrorCheck($2.loc, "--", $1); - $$ = parseContext.handleUnaryMath($2.loc, "--", EOpPostDecrement, $1); - } - ; - -integer_expression - : expression { - parseContext.integerCheck($1, "[]"); - $$ = $1; - } - ; - -function_call - : function_call_or_method { - $$ = parseContext.handleFunctionCall($1.loc, $1.function, $1.intermNode); - delete $1.function; - } - ; - -function_call_or_method - : function_call_generic { - $$ = $1; - } - ; - -function_call_generic - : function_call_header_with_parameters RIGHT_PAREN { - $$ = $1; - $$.loc = $2.loc; - } - | function_call_header_no_parameters RIGHT_PAREN { - $$ = $1; - $$.loc = $2.loc; - } - ; - -function_call_header_no_parameters - : function_call_header VOID { - $$ = $1; - } - | function_call_header { - $$ = $1; - } - ; - -function_call_header_with_parameters - : function_call_header assignment_expression { - if (parseContext.spvVersion.vulkan > 0 - && parseContext.spvVersion.vulkanRelaxed - && $2->getType().containsOpaque()) - { - $$.intermNode = parseContext.vkRelaxedRemapFunctionArgument($$.loc, $1.function, $2); - $$.function = $1.function; - } - else - { - TParameter param = { 0, new TType }; - param.type->shallowCopy($2->getType()); - - $1.function->addParameter(param); - $$.function = $1.function; - $$.intermNode = $2; - } - } - | function_call_header_with_parameters COMMA assignment_expression { - if (parseContext.spvVersion.vulkan > 0 - && parseContext.spvVersion.vulkanRelaxed - && $3->getType().containsOpaque()) - { - TIntermNode* remappedNode = parseContext.vkRelaxedRemapFunctionArgument($2.loc, $1.function, $3); - $$.intermNode = parseContext.intermediate.mergeAggregate($1.intermNode, remappedNode, $2.loc); - $$.function = $1.function; - } - else - { - TParameter param = { 0, new TType }; - param.type->shallowCopy($3->getType()); - - $1.function->addParameter(param); - $$.function = $1.function; - $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, $3, $2.loc); - } - } - ; - -function_call_header - : function_identifier LEFT_PAREN { - $$ = $1; - } - ; - -// Grammar Note: Constructors look like functions, but are recognized as types. - -function_identifier - : type_specifier { - // Constructor - $$.intermNode = 0; - $$.function = parseContext.handleConstructorCall($1.loc, $1); - } - | postfix_expression { - // - // Should be a method or subroutine call, but we haven't recognized the arguments yet. - // - $$.function = 0; - $$.intermNode = 0; - - TIntermMethod* method = $1->getAsMethodNode(); - if (method) { - $$.function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength); - $$.intermNode = method->getObject(); - } else { - TIntermSymbol* symbol = $1->getAsSymbolNode(); - if (symbol) { - parseContext.reservedErrorCheck(symbol->getLoc(), symbol->getName()); - TFunction *function = new TFunction(&symbol->getName(), TType(EbtVoid)); - $$.function = function; - } else - parseContext.error($1->getLoc(), "function call, method, or subroutine call expected", "", ""); - } - - if ($$.function == 0) { - // error recover - TString* empty = NewPoolTString(""); - $$.function = new TFunction(empty, TType(EbtVoid), EOpNull); - } - } - | non_uniform_qualifier { - // Constructor - $$.intermNode = 0; - $$.function = parseContext.handleConstructorCall($1.loc, $1); - } - ; - -unary_expression - : postfix_expression { - parseContext.variableCheck($1); - $$ = $1; - if (TIntermMethod* method = $1->getAsMethodNode()) - parseContext.error($1->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), ""); - } - | INC_OP unary_expression { - parseContext.lValueErrorCheck($1.loc, "++", $2); - $$ = parseContext.handleUnaryMath($1.loc, "++", EOpPreIncrement, $2); - } - | DEC_OP unary_expression { - parseContext.lValueErrorCheck($1.loc, "--", $2); - $$ = parseContext.handleUnaryMath($1.loc, "--", EOpPreDecrement, $2); - } - | unary_operator unary_expression { - if ($1.op != EOpNull) { - char errorOp[2] = {0, 0}; - switch($1.op) { - case EOpNegative: errorOp[0] = '-'; break; - case EOpLogicalNot: errorOp[0] = '!'; break; - case EOpBitwiseNot: errorOp[0] = '~'; break; - default: break; // some compilers want this - } - $$ = parseContext.handleUnaryMath($1.loc, errorOp, $1.op, $2); - } else { - $$ = $2; - if ($$->getAsConstantUnion()) - $$->getAsConstantUnion()->setExpression(); - } - } - ; -// Grammar Note: No traditional style type casts. - -unary_operator - : PLUS { $$.loc = $1.loc; $$.op = EOpNull; } - | DASH { $$.loc = $1.loc; $$.op = EOpNegative; } - | BANG { $$.loc = $1.loc; $$.op = EOpLogicalNot; } - | TILDE { $$.loc = $1.loc; $$.op = EOpBitwiseNot; - parseContext.fullIntegerCheck($1.loc, "bitwise not"); } - ; -// Grammar Note: No '*' or '&' unary ops. Pointers are not supported. - -multiplicative_expression - : unary_expression { $$ = $1; } - | multiplicative_expression STAR unary_expression { - $$ = parseContext.handleBinaryMath($2.loc, "*", EOpMul, $1, $3); - if ($$ == 0) - $$ = $1; - } - | multiplicative_expression SLASH unary_expression { - $$ = parseContext.handleBinaryMath($2.loc, "/", EOpDiv, $1, $3); - if ($$ == 0) - $$ = $1; - } - | multiplicative_expression PERCENT unary_expression { - parseContext.fullIntegerCheck($2.loc, "%"); - $$ = parseContext.handleBinaryMath($2.loc, "%", EOpMod, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -additive_expression - : multiplicative_expression { $$ = $1; } - | additive_expression PLUS multiplicative_expression { - $$ = parseContext.handleBinaryMath($2.loc, "+", EOpAdd, $1, $3); - if ($$ == 0) - $$ = $1; - } - | additive_expression DASH multiplicative_expression { - $$ = parseContext.handleBinaryMath($2.loc, "-", EOpSub, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -shift_expression - : additive_expression { $$ = $1; } - | shift_expression LEFT_OP additive_expression { - parseContext.fullIntegerCheck($2.loc, "bit shift left"); - $$ = parseContext.handleBinaryMath($2.loc, "<<", EOpLeftShift, $1, $3); - if ($$ == 0) - $$ = $1; - } - | shift_expression RIGHT_OP additive_expression { - parseContext.fullIntegerCheck($2.loc, "bit shift right"); - $$ = parseContext.handleBinaryMath($2.loc, ">>", EOpRightShift, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -relational_expression - : shift_expression { $$ = $1; } - | relational_expression LEFT_ANGLE shift_expression { - $$ = parseContext.handleBinaryMath($2.loc, "<", EOpLessThan, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - | relational_expression RIGHT_ANGLE shift_expression { - $$ = parseContext.handleBinaryMath($2.loc, ">", EOpGreaterThan, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - | relational_expression LE_OP shift_expression { - $$ = parseContext.handleBinaryMath($2.loc, "<=", EOpLessThanEqual, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - | relational_expression GE_OP shift_expression { - $$ = parseContext.handleBinaryMath($2.loc, ">=", EOpGreaterThanEqual, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - ; - -equality_expression - : relational_expression { $$ = $1; } - | equality_expression EQ_OP relational_expression { - parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison"); - parseContext.opaqueCheck($2.loc, $1->getType(), "=="); - parseContext.specializationCheck($2.loc, $1->getType(), "=="); - parseContext.referenceCheck($2.loc, $1->getType(), "=="); - $$ = parseContext.handleBinaryMath($2.loc, "==", EOpEqual, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - | equality_expression NE_OP relational_expression { - parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison"); - parseContext.opaqueCheck($2.loc, $1->getType(), "!="); - parseContext.specializationCheck($2.loc, $1->getType(), "!="); - parseContext.referenceCheck($2.loc, $1->getType(), "!="); - $$ = parseContext.handleBinaryMath($2.loc, "!=", EOpNotEqual, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - ; - -and_expression - : equality_expression { $$ = $1; } - | and_expression AMPERSAND equality_expression { - parseContext.fullIntegerCheck($2.loc, "bitwise and"); - $$ = parseContext.handleBinaryMath($2.loc, "&", EOpAnd, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -exclusive_or_expression - : and_expression { $$ = $1; } - | exclusive_or_expression CARET and_expression { - parseContext.fullIntegerCheck($2.loc, "bitwise exclusive or"); - $$ = parseContext.handleBinaryMath($2.loc, "^", EOpExclusiveOr, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -inclusive_or_expression - : exclusive_or_expression { $$ = $1; } - | inclusive_or_expression VERTICAL_BAR exclusive_or_expression { - parseContext.fullIntegerCheck($2.loc, "bitwise inclusive or"); - $$ = parseContext.handleBinaryMath($2.loc, "|", EOpInclusiveOr, $1, $3); - if ($$ == 0) - $$ = $1; - } - ; - -logical_and_expression - : inclusive_or_expression { $$ = $1; } - | logical_and_expression AND_OP inclusive_or_expression { - $$ = parseContext.handleBinaryMath($2.loc, "&&", EOpLogicalAnd, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - ; - -logical_xor_expression - : logical_and_expression { $$ = $1; } - | logical_xor_expression XOR_OP logical_and_expression { - $$ = parseContext.handleBinaryMath($2.loc, "^^", EOpLogicalXor, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - ; - -logical_or_expression - : logical_xor_expression { $$ = $1; } - | logical_or_expression OR_OP logical_xor_expression { - $$ = parseContext.handleBinaryMath($2.loc, "||", EOpLogicalOr, $1, $3); - if ($$ == 0) - $$ = parseContext.intermediate.addConstantUnion(false, $2.loc); - } - ; - -conditional_expression - : logical_or_expression { $$ = $1; } - | logical_or_expression QUESTION { - ++parseContext.controlFlowNestingLevel; - } - expression COLON assignment_expression { - --parseContext.controlFlowNestingLevel; - parseContext.boolCheck($2.loc, $1); - parseContext.rValueErrorCheck($2.loc, "?", $1); - parseContext.rValueErrorCheck($5.loc, ":", $4); - parseContext.rValueErrorCheck($5.loc, ":", $6); - $$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc); - if ($$ == 0) { - parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $6->getCompleteString(parseContext.intermediate.getEnhancedMsgs())); - $$ = $6; - } - } - ; - -assignment_expression - : conditional_expression { $$ = $1; } - | unary_expression assignment_operator assignment_expression { - parseContext.arrayObjectCheck($2.loc, $1->getType(), "array assignment"); - parseContext.opaqueCheck($2.loc, $1->getType(), "="); - parseContext.storage16BitAssignmentCheck($2.loc, $1->getType(), "="); - parseContext.specializationCheck($2.loc, $1->getType(), "="); - parseContext.lValueErrorCheck($2.loc, "assign", $1); - parseContext.rValueErrorCheck($2.loc, "assign", $3); - $$ = parseContext.addAssign($2.loc, $2.op, $1, $3); - if ($$ == 0) { - parseContext.assignError($2.loc, "assign", $1->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $3->getCompleteString(parseContext.intermediate.getEnhancedMsgs())); - $$ = $1; - } - } - ; - -assignment_operator - : EQUAL { - $$.loc = $1.loc; - $$.op = EOpAssign; - } - | MUL_ASSIGN { - $$.loc = $1.loc; - $$.op = EOpMulAssign; - } - | DIV_ASSIGN { - $$.loc = $1.loc; - $$.op = EOpDivAssign; - } - | MOD_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "%="); - $$.loc = $1.loc; - $$.op = EOpModAssign; - } - | ADD_ASSIGN { - $$.loc = $1.loc; - $$.op = EOpAddAssign; - } - | SUB_ASSIGN { - $$.loc = $1.loc; - $$.op = EOpSubAssign; - } - | LEFT_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "bit-shift left assign"); - $$.loc = $1.loc; $$.op = EOpLeftShiftAssign; - } - | RIGHT_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "bit-shift right assign"); - $$.loc = $1.loc; $$.op = EOpRightShiftAssign; - } - | AND_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "bitwise-and assign"); - $$.loc = $1.loc; $$.op = EOpAndAssign; - } - | XOR_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "bitwise-xor assign"); - $$.loc = $1.loc; $$.op = EOpExclusiveOrAssign; - } - | OR_ASSIGN { - parseContext.fullIntegerCheck($1.loc, "bitwise-or assign"); - $$.loc = $1.loc; $$.op = EOpInclusiveOrAssign; - } - ; - -expression - : assignment_expression { - $$ = $1; - } - | expression COMMA assignment_expression { - parseContext.samplerConstructorLocationCheck($2.loc, ",", $3); - $$ = parseContext.intermediate.addComma($1, $3, $2.loc); - if ($$ == 0) { - parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $3->getCompleteString(parseContext.intermediate.getEnhancedMsgs())); - $$ = $3; - } - } - ; - -constant_expression - : conditional_expression { - parseContext.constantValueCheck($1, ""); - $$ = $1; - } - ; - -declaration - : function_prototype SEMICOLON { - parseContext.handleFunctionDeclarator($1.loc, *$1.function, true /* prototype */); - $$ = 0; - // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature - } - | spirv_instruction_qualifier function_prototype SEMICOLON { - parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V instruction qualifier"); - $2.function->setSpirvInstruction(*$1); // Attach SPIR-V intruction qualifier - parseContext.handleFunctionDeclarator($2.loc, *$2.function, true /* prototype */); - $$ = 0; - // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature - } - | spirv_execution_mode_qualifier SEMICOLON { - parseContext.globalCheck($2.loc, "SPIR-V execution mode qualifier"); - parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V execution mode qualifier"); - $$ = 0; - } - | init_declarator_list SEMICOLON { - if ($1.intermNode && $1.intermNode->getAsAggregate()) - $1.intermNode->getAsAggregate()->setOperator(EOpSequence); - $$ = $1.intermNode; - } - | PRECISION precision_qualifier type_specifier SEMICOLON { - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "precision statement"); - // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope - parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]); - parseContext.setDefaultPrecision($1.loc, $3, $2.qualifier.precision); - $$ = 0; - } - | block_structure SEMICOLON { - parseContext.declareBlock($1.loc, *$1.typeList); - $$ = 0; - } - | block_structure IDENTIFIER SEMICOLON { - parseContext.declareBlock($1.loc, *$1.typeList, $2.string); - $$ = 0; - } - | block_structure IDENTIFIER array_specifier SEMICOLON { - parseContext.declareBlock($1.loc, *$1.typeList, $2.string, $3.arraySizes); - $$ = 0; - } - | type_qualifier SEMICOLON { - parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); - parseContext.updateStandaloneQualifierDefaults($1.loc, $1); - $$ = 0; - } - | type_qualifier IDENTIFIER SEMICOLON { - parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); - parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$2.string); - $$ = 0; - } - | type_qualifier IDENTIFIER identifier_list SEMICOLON { - parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); - $3->push_back($2.string); - parseContext.addQualifierToExisting($1.loc, $1.qualifier, *$3); - $$ = 0; - } - ; - -block_structure - : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE { - --parseContext.blockNestingLevel; - parseContext.blockName = $2.string; - parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); - parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); - parseContext.currentBlockQualifier = $1.qualifier; - $$.loc = $1.loc; - $$.typeList = $5; - } - -identifier_list - : COMMA IDENTIFIER { - $$ = new TIdentifierList; - $$->push_back($2.string); - } - | identifier_list COMMA IDENTIFIER { - $$ = $1; - $$->push_back($3.string); - } - ; - -function_prototype - : function_declarator RIGHT_PAREN { - $$.function = $1; - if (parseContext.compileOnly) $$.function->setExport(); - $$.loc = $2.loc; - } - | function_declarator RIGHT_PAREN attribute { - $$.function = $1; - if (parseContext.compileOnly) $$.function->setExport(); - $$.loc = $2.loc; - parseContext.handleFunctionAttributes($2.loc, *$3); - } - | attribute function_declarator RIGHT_PAREN { - $$.function = $2; - if (parseContext.compileOnly) $$.function->setExport(); - $$.loc = $3.loc; - parseContext.handleFunctionAttributes($3.loc, *$1); - } - | attribute function_declarator RIGHT_PAREN attribute { - $$.function = $2; - if (parseContext.compileOnly) $$.function->setExport(); - $$.loc = $3.loc; - parseContext.handleFunctionAttributes($3.loc, *$1); - parseContext.handleFunctionAttributes($3.loc, *$4); - } - ; - -function_declarator - : function_header { - $$ = $1; - } - | function_header_with_parameters { - $$ = $1; - } - ; - - -function_header_with_parameters - : function_header parameter_declaration { - // Add the parameter - $$ = $1; - if ($2.param.type->getBasicType() != EbtVoid) - { - if (!(parseContext.spvVersion.vulkan > 0 && parseContext.spvVersion.vulkanRelaxed)) - $1->addParameter($2.param); - else - parseContext.vkRelaxedRemapFunctionParameter($1, $2.param); - } - else - delete $2.param.type; - } - | function_header_with_parameters COMMA parameter_declaration { - // - // Only first parameter of one-parameter functions can be void - // The check for named parameters not being void is done in parameter_declarator - // - if ($3.param.type->getBasicType() == EbtVoid) { - // - // This parameter > first is void - // - parseContext.error($2.loc, "cannot be an argument type except for '(void)'", "void", ""); - delete $3.param.type; - } else { - // Add the parameter - $$ = $1; - if (!(parseContext.spvVersion.vulkan > 0 && parseContext.spvVersion.vulkanRelaxed)) - $1->addParameter($3.param); - else - parseContext.vkRelaxedRemapFunctionParameter($1, $3.param); - } - } - ; - -function_header - : fully_specified_type IDENTIFIER LEFT_PAREN { - if ($1.qualifier.storage != EvqGlobal && $1.qualifier.storage != EvqTemporary) { - parseContext.error($2.loc, "no qualifiers allowed for function return", - GetStorageQualifierString($1.qualifier.storage), ""); - } - if ($1.arraySizes) - parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes); - - // Add the function as a prototype after parsing it (we do not support recursion) - TFunction *function; - TType type($1); - - // Potentially rename shader entry point function. No-op most of the time. - parseContext.renameShaderFunction($2.string); - - // Make the function - function = new TFunction($2.string, type); - $$ = function; - } - ; - -parameter_declarator - // Type + name - : type_specifier IDENTIFIER { - if ($1.arraySizes) { - parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type"); - parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes); - } - if ($1.basicType == EbtVoid) { - parseContext.error($2.loc, "illegal use of type 'void'", $2.string->c_str(), ""); - } - parseContext.reservedErrorCheck($2.loc, *$2.string); - - TParameter param = {$2.string, new TType($1)}; - $$.loc = $2.loc; - $$.param = param; - } - | type_specifier IDENTIFIER array_specifier { - if ($1.arraySizes) { - parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type"); - parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes); - } - TType* type = new TType($1); - type->transferArraySizes($3.arraySizes); - type->copyArrayInnerSizes($1.arraySizes); - - parseContext.arrayOfArrayVersionCheck($2.loc, type->getArraySizes()); - parseContext.arraySizeRequiredCheck($3.loc, *$3.arraySizes); - parseContext.reservedErrorCheck($2.loc, *$2.string); - - TParameter param = { $2.string, type }; - - $$.loc = $2.loc; - $$.param = param; - } - ; - -parameter_declaration - // - // With name - // - : type_qualifier parameter_declarator { - $$ = $2; - if ($1.qualifier.precision != EpqNone) - $$.param.type->getQualifier().precision = $1.qualifier.precision; - parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier(), $$.param.type->isCoopMat()); - - parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); - parseContext.parameterTypeCheck($2.loc, $1.qualifier.storage, *$$.param.type); - parseContext.paramCheckFix($1.loc, $1.qualifier, *$$.param.type); - - } - | parameter_declarator { - $$ = $1; - - parseContext.parameterTypeCheck($1.loc, EvqIn, *$1.param.type); - parseContext.paramCheckFixStorage($1.loc, EvqTemporary, *$$.param.type); - parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier(), $$.param.type->isCoopMat()); - } - // - // Without name - // - | type_qualifier parameter_type_specifier { - $$ = $2; - if ($1.qualifier.precision != EpqNone) - $$.param.type->getQualifier().precision = $1.qualifier.precision; - parseContext.precisionQualifierCheck($1.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier(), $$.param.type->isCoopMat()); - - parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); - parseContext.parameterTypeCheck($2.loc, $1.qualifier.storage, *$$.param.type); - parseContext.paramCheckFix($1.loc, $1.qualifier, *$$.param.type); - } - | parameter_type_specifier { - $$ = $1; - - parseContext.parameterTypeCheck($1.loc, EvqIn, *$1.param.type); - parseContext.paramCheckFixStorage($1.loc, EvqTemporary, *$$.param.type); - parseContext.precisionQualifierCheck($$.loc, $$.param.type->getBasicType(), $$.param.type->getQualifier(), $$.param.type->isCoopMat()); - } - ; - -parameter_type_specifier - : type_specifier { - TParameter param = { 0, new TType($1) }; - $$.param = param; - if ($1.arraySizes) - parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes); - } - ; - -init_declarator_list - : single_declaration { - $$ = $1; - } - | init_declarator_list COMMA IDENTIFIER { - $$ = $1; - parseContext.declareVariable($3.loc, *$3.string, $1.type); - } - | init_declarator_list COMMA IDENTIFIER array_specifier { - $$ = $1; - parseContext.declareVariable($3.loc, *$3.string, $1.type, $4.arraySizes); - } - | init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer { - $$.type = $1.type; - TIntermNode* initNode = parseContext.declareVariable($3.loc, *$3.string, $1.type, $4.arraySizes, $6); - $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, initNode, $5.loc); - } - | init_declarator_list COMMA IDENTIFIER EQUAL initializer { - $$.type = $1.type; - TIntermNode* initNode = parseContext.declareVariable($3.loc, *$3.string, $1.type, 0, $5); - $$.intermNode = parseContext.intermediate.growAggregate($1.intermNode, initNode, $4.loc); - } - ; - -single_declaration - : fully_specified_type { - $$.type = $1; - $$.intermNode = 0; - parseContext.declareTypeDefaults($$.loc, $$.type); - } - | fully_specified_type IDENTIFIER { - $$.type = $1; - $$.intermNode = 0; - parseContext.declareVariable($2.loc, *$2.string, $1); - } - | fully_specified_type IDENTIFIER array_specifier { - $$.type = $1; - $$.intermNode = 0; - parseContext.declareVariable($2.loc, *$2.string, $1, $3.arraySizes); - } - | fully_specified_type IDENTIFIER array_specifier EQUAL initializer { - $$.type = $1; - TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, $3.arraySizes, $5); - $$.intermNode = parseContext.intermediate.growAggregate(0, initNode, $4.loc); - } - | fully_specified_type IDENTIFIER EQUAL initializer { - $$.type = $1; - TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, 0, $4); - $$.intermNode = parseContext.intermediate.growAggregate(0, initNode, $3.loc); - } - -// Grammar Note: No 'enum', or 'typedef'. - -fully_specified_type - : type_specifier { - $$ = $1; - - parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $$); - if ($1.arraySizes) { - parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type"); - } - parseContext.precisionQualifierCheck($$.loc, $$.basicType, $$.qualifier, $$.isCoopmat()); - } - | type_qualifier type_specifier { - parseContext.globalQualifierFixCheck($1.loc, $1.qualifier, false, &$2); - parseContext.globalQualifierTypeCheck($1.loc, $1.qualifier, $2); - - if ($2.arraySizes) { - parseContext.profileRequires($2.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type"); - } - - if ($2.arraySizes && parseContext.arrayQualifierError($2.loc, $1.qualifier)) - $2.arraySizes = nullptr; - - parseContext.checkNoShaderLayouts($2.loc, $1.shaderQualifiers); - $2.shaderQualifiers.merge($1.shaderQualifiers); - parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true); - parseContext.precisionQualifierCheck($2.loc, $2.basicType, $2.qualifier, $2.isCoopmat()); - - $$ = $2; - - if (! $$.qualifier.isInterpolation() && - ((parseContext.language == EShLangVertex && $$.qualifier.storage == EvqVaryingOut) || - (parseContext.language == EShLangFragment && $$.qualifier.storage == EvqVaryingIn))) - $$.qualifier.smooth = true; - } - ; - -invariant_qualifier - : INVARIANT { - parseContext.globalCheck($1.loc, "invariant"); - parseContext.profileRequires($$.loc, ENoProfile, 120, 0, "invariant"); - $$.init($1.loc); - $$.qualifier.invariant = true; - } - ; - -interpolation_qualifier - : SMOOTH { - parseContext.globalCheck($1.loc, "smooth"); - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "smooth"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "smooth"); - $$.init($1.loc); - $$.qualifier.smooth = true; - } - | FLAT { - parseContext.globalCheck($1.loc, "flat"); - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "flat"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "flat"); - $$.init($1.loc); - $$.qualifier.flat = true; - } - | NOPERSPECTIVE { - parseContext.globalCheck($1.loc, "noperspective"); - parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_NV_shader_noperspective_interpolation, "noperspective"); - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "noperspective"); - $$.init($1.loc); - $$.qualifier.nopersp = true; - } - | EXPLICITINTERPAMD { - parseContext.globalCheck($1.loc, "__explicitInterpAMD"); - parseContext.profileRequires($1.loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); - parseContext.profileRequires($1.loc, ECompatibilityProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); - $$.init($1.loc); - $$.qualifier.explicitInterp = true; - } - | PERVERTEXNV { - parseContext.globalCheck($1.loc, "pervertexNV"); - parseContext.profileRequires($1.loc, ECoreProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); - parseContext.profileRequires($1.loc, ECompatibilityProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); - parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); - $$.init($1.loc); - $$.qualifier.pervertexNV = true; - } - | PERVERTEXEXT { - parseContext.globalCheck($1.loc, "pervertexEXT"); - parseContext.profileRequires($1.loc, ECoreProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric"); - parseContext.profileRequires($1.loc, ECompatibilityProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric"); - parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric"); - $$.init($1.loc); - $$.qualifier.pervertexEXT = true; - } - | PERPRIMITIVENV { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck($1.loc, "perprimitiveNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangFragmentMask | EShLangMeshMask), "perprimitiveNV"); - // Fragment shader stage doesn't check for extension. So we explicitly add below extension check. - if (parseContext.language == EShLangFragment) - parseContext.requireExtensions($1.loc, 1, &E_GL_NV_mesh_shader, "perprimitiveNV"); - $$.init($1.loc); - $$.qualifier.perPrimitiveNV = true; - } - | PERPRIMITIVEEXT { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck($1.loc, "perprimitiveEXT"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangFragmentMask | EShLangMeshMask), "perprimitiveEXT"); - // Fragment shader stage doesn't check for extension. So we explicitly add below extension check. - if (parseContext.language == EShLangFragment) - parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_mesh_shader, "perprimitiveEXT"); - $$.init($1.loc); - $$.qualifier.perPrimitiveNV = true; - } - | PERVIEWNV { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck($1.loc, "perviewNV"); - parseContext.requireStage($1.loc, EShLangMesh, "perviewNV"); - $$.init($1.loc); - $$.qualifier.perViewNV = true; - } - | PERTASKNV { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck($1.loc, "taskNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangTaskMask | EShLangMeshMask), "taskNV"); - $$.init($1.loc); - $$.qualifier.perTaskNV = true; - } - ; - -layout_qualifier - : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN { - $$ = $3; - } - ; - -layout_qualifier_id_list - : layout_qualifier_id { - $$ = $1; - } - | layout_qualifier_id_list COMMA layout_qualifier_id { - $$ = $1; - $$.shaderQualifiers.merge($3.shaderQualifiers); - parseContext.mergeObjectLayoutQualifiers($$.qualifier, $3.qualifier, false); - } - -layout_qualifier_id - : IDENTIFIER { - $$.init($1.loc); - parseContext.setLayoutQualifier($1.loc, $$, *$1.string); - } - | IDENTIFIER EQUAL constant_expression { - $$.init($1.loc); - parseContext.setLayoutQualifier($1.loc, $$, *$1.string, $3); - } - | SHARED { // because "shared" is both an identifier and a keyword - $$.init($1.loc); - TString strShared("shared"); - parseContext.setLayoutQualifier($1.loc, $$, strShared); - } - ; - -precise_qualifier - : PRECISE { - parseContext.profileRequires($$.loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise"); - parseContext.profileRequires($1.loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise"); - $$.init($1.loc); - $$.qualifier.noContraction = true; - } - ; - -type_qualifier - : single_type_qualifier { - $$ = $1; - } - | type_qualifier single_type_qualifier { - $$ = $1; - if ($$.basicType == EbtVoid) - $$.basicType = $2.basicType; - - $$.shaderQualifiers.merge($2.shaderQualifiers); - parseContext.mergeQualifiers($$.loc, $$.qualifier, $2.qualifier, false); - } - ; - -single_type_qualifier - : storage_qualifier { - $$ = $1; - } - | layout_qualifier { - $$ = $1; - } - | precision_qualifier { - parseContext.checkPrecisionQualifier($1.loc, $1.qualifier.precision); - $$ = $1; - } - | interpolation_qualifier { - // allow inheritance of storage qualifier from block declaration - $$ = $1; - } - | invariant_qualifier { - // allow inheritance of storage qualifier from block declaration - $$ = $1; - } - | precise_qualifier { - // allow inheritance of storage qualifier from block declaration - $$ = $1; - } - | non_uniform_qualifier { - $$ = $1; - } - | spirv_storage_class_qualifier { - parseContext.globalCheck($1.loc, "spirv_storage_class"); - parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V storage class qualifier"); - $$ = $1; - } - | spirv_decorate_qualifier { - parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V decorate qualifier"); - $$ = $1; - } - | SPIRV_BY_REFERENCE { - parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_reference"); - $$.init($1.loc); - $$.qualifier.setSpirvByReference(); - } - | SPIRV_LITERAL { - parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_literal"); - $$.init($1.loc); - $$.qualifier.setSpirvLiteral(); - } - ; - -storage_qualifier - : CONST { - $$.init($1.loc); - $$.qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant - } - | INOUT { - parseContext.globalCheck($1.loc, "inout"); - $$.init($1.loc); - $$.qualifier.storage = EvqInOut; - } - | IN { - parseContext.globalCheck($1.loc, "in"); - $$.init($1.loc); - // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later - $$.qualifier.storage = EvqIn; - } - | OUT { - parseContext.globalCheck($1.loc, "out"); - $$.init($1.loc); - // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later - $$.qualifier.storage = EvqOut; - } - | CENTROID { - parseContext.profileRequires($1.loc, ENoProfile, 120, 0, "centroid"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "centroid"); - parseContext.globalCheck($1.loc, "centroid"); - $$.init($1.loc); - $$.qualifier.centroid = true; - } - | UNIFORM { - parseContext.globalCheck($1.loc, "uniform"); - $$.init($1.loc); - $$.qualifier.storage = EvqUniform; - } - | TILEIMAGEEXT { - parseContext.globalCheck($1.loc, "tileImageEXT"); - $$.init($1.loc); - $$.qualifier.storage = EvqTileImageEXT; - } - | SHARED { - parseContext.globalCheck($1.loc, "shared"); - parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared"); - parseContext.profileRequires($1.loc, EEsProfile, 310, 0, "shared"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangComputeMask | EShLangMeshMask | EShLangTaskMask), "shared"); - $$.init($1.loc); - $$.qualifier.storage = EvqShared; - } - | BUFFER { - parseContext.globalCheck($1.loc, "buffer"); - $$.init($1.loc); - $$.qualifier.storage = EvqBuffer; - } - | ATTRIBUTE { - parseContext.requireStage($1.loc, EShLangVertex, "attribute"); - parseContext.checkDeprecated($1.loc, ECoreProfile, 130, "attribute"); - parseContext.checkDeprecated($1.loc, ENoProfile, 130, "attribute"); - parseContext.requireNotRemoved($1.loc, ECoreProfile, 420, "attribute"); - parseContext.requireNotRemoved($1.loc, EEsProfile, 300, "attribute"); - - parseContext.globalCheck($1.loc, "attribute"); - - $$.init($1.loc); - $$.qualifier.storage = EvqVaryingIn; - } - | VARYING { - parseContext.checkDeprecated($1.loc, ENoProfile, 130, "varying"); - parseContext.checkDeprecated($1.loc, ECoreProfile, 130, "varying"); - parseContext.requireNotRemoved($1.loc, ECoreProfile, 420, "varying"); - parseContext.requireNotRemoved($1.loc, EEsProfile, 300, "varying"); - - parseContext.globalCheck($1.loc, "varying"); - - $$.init($1.loc); - if (parseContext.language == EShLangVertex) - $$.qualifier.storage = EvqVaryingOut; - else - $$.qualifier.storage = EvqVaryingIn; - } - | PATCH { - parseContext.globalCheck($1.loc, "patch"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch"); - $$.init($1.loc); - $$.qualifier.patch = true; - } - | SAMPLE { - parseContext.globalCheck($1.loc, "sample"); - $$.init($1.loc); - $$.qualifier.sample = true; - } - | HITATTRNV { - parseContext.globalCheck($1.loc, "hitAttributeNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask - | EShLangAnyHitMask), "hitAttributeNV"); - parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV"); - $$.init($1.loc); - $$.qualifier.storage = EvqHitAttr; - } - | HITOBJECTATTRNV { - parseContext.globalCheck($1.loc, "hitAttributeNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask - | EShLangMissMask), "hitObjectAttributeNV"); - parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_shader_invocation_reorder, "hitObjectAttributeNV"); - $$.init($1.loc); - $$.qualifier.storage = EvqHitObjectAttrNV; - } - | HITATTREXT { - parseContext.globalCheck($1.loc, "hitAttributeEXT"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask - | EShLangAnyHitMask), "hitAttributeEXT"); - parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "hitAttributeNV"); - $$.init($1.loc); - $$.qualifier.storage = EvqHitAttr; - } - | PAYLOADNV { - parseContext.globalCheck($1.loc, "rayPayloadNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | - EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV"); - parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV"); - $$.init($1.loc); - $$.qualifier.storage = EvqPayload; - } - | PAYLOADEXT { - parseContext.globalCheck($1.loc, "rayPayloadEXT"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | - EShLangAnyHitMask | EShLangMissMask), "rayPayloadEXT"); - parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadEXT"); - $$.init($1.loc); - $$.qualifier.storage = EvqPayload; - } - | PAYLOADINNV { - parseContext.globalCheck($1.loc, "rayPayloadInNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask | - EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV"); - parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV"); - $$.init($1.loc); - $$.qualifier.storage = EvqPayloadIn; - } - | PAYLOADINEXT { - parseContext.globalCheck($1.loc, "rayPayloadInEXT"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask | - EShLangAnyHitMask | EShLangMissMask), "rayPayloadInEXT"); - parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadInEXT"); - $$.init($1.loc); - $$.qualifier.storage = EvqPayloadIn; - } - | CALLDATANV { - parseContext.globalCheck($1.loc, "callableDataNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | - EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV"); - parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV"); - $$.init($1.loc); - $$.qualifier.storage = EvqCallableData; - } - | CALLDATAEXT { - parseContext.globalCheck($1.loc, "callableDataEXT"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | - EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataEXT"); - parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataEXT"); - $$.init($1.loc); - $$.qualifier.storage = EvqCallableData; - } - | CALLDATAINNV { - parseContext.globalCheck($1.loc, "callableDataInNV"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV"); - parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV"); - $$.init($1.loc); - $$.qualifier.storage = EvqCallableDataIn; - } - | CALLDATAINEXT { - parseContext.globalCheck($1.loc, "callableDataInEXT"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT"); - parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataInEXT"); - $$.init($1.loc); - $$.qualifier.storage = EvqCallableDataIn; - } - | COHERENT { - $$.init($1.loc); - $$.qualifier.coherent = true; - } - | DEVICECOHERENT { - $$.init($1.loc); - parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "devicecoherent"); - $$.qualifier.devicecoherent = true; - } - | QUEUEFAMILYCOHERENT { - $$.init($1.loc); - parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "queuefamilycoherent"); - $$.qualifier.queuefamilycoherent = true; - } - | WORKGROUPCOHERENT { - $$.init($1.loc); - parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "workgroupcoherent"); - $$.qualifier.workgroupcoherent = true; - } - | SUBGROUPCOHERENT { - $$.init($1.loc); - parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "subgroupcoherent"); - $$.qualifier.subgroupcoherent = true; - } - | NONPRIVATE { - $$.init($1.loc); - parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); - $$.qualifier.nonprivate = true; - } - | SHADERCALLCOHERENT { - $$.init($1.loc); - parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent"); - $$.qualifier.shadercallcoherent = true; - } - | VOLATILE { - $$.init($1.loc); - $$.qualifier.volatil = true; - } - | RESTRICT { - $$.init($1.loc); - $$.qualifier.restrict = true; - } - | READONLY { - $$.init($1.loc); - $$.qualifier.readonly = true; - } - | WRITEONLY { - $$.init($1.loc); - $$.qualifier.writeonly = true; - } - | SUBROUTINE { - parseContext.spvRemoved($1.loc, "subroutine"); - parseContext.globalCheck($1.loc, "subroutine"); - parseContext.unimplemented($1.loc, "subroutine"); - $$.init($1.loc); - } - | SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN { - parseContext.spvRemoved($1.loc, "subroutine"); - parseContext.globalCheck($1.loc, "subroutine"); - parseContext.unimplemented($1.loc, "subroutine"); - $$.init($1.loc); - } - | TASKPAYLOADWORKGROUPEXT { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck($1.loc, "taskPayloadSharedEXT"); - parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangTaskMask | EShLangMeshMask), "taskPayloadSharedEXT "); - $$.init($1.loc); - $$.qualifier.storage = EvqtaskPayloadSharedEXT; - } - ; - -non_uniform_qualifier - : NONUNIFORM { - $$.init($1.loc); - $$.qualifier.nonUniform = true; - } - ; - -type_name_list - : IDENTIFIER { - // TODO - } - | type_name_list COMMA IDENTIFIER { - // TODO: 4.0 semantics: subroutines - // 1) make sure each identifier is a type declared earlier with SUBROUTINE - // 2) save all of the identifiers for future comparison with the declared function - } - ; - -type_specifier - : type_specifier_nonarray type_parameter_specifier_opt { - $$ = $1; - $$.qualifier.precision = parseContext.getDefaultPrecision($$); - $$.typeParameters = $2; - parseContext.coopMatTypeParametersCheck($1.loc, $$); - - } - | type_specifier_nonarray type_parameter_specifier_opt array_specifier { - parseContext.arrayOfArrayVersionCheck($3.loc, $3.arraySizes); - $$ = $1; - $$.qualifier.precision = parseContext.getDefaultPrecision($$); - $$.typeParameters = $2; - $$.arraySizes = $3.arraySizes; - parseContext.coopMatTypeParametersCheck($1.loc, $$); - } - ; - -array_specifier - : LEFT_BRACKET RIGHT_BRACKET { - $$.loc = $1.loc; - $$.arraySizes = new TArraySizes; - $$.arraySizes->addInnerSize(); - } - | LEFT_BRACKET conditional_expression RIGHT_BRACKET { - $$.loc = $1.loc; - $$.arraySizes = new TArraySizes; - - TArraySize size; - parseContext.arraySizeCheck($2->getLoc(), $2, size, "array size"); - $$.arraySizes->addInnerSize(size); - } - | array_specifier LEFT_BRACKET RIGHT_BRACKET { - $$ = $1; - $$.arraySizes->addInnerSize(); - } - | array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET { - $$ = $1; - - TArraySize size; - parseContext.arraySizeCheck($3->getLoc(), $3, size, "array size"); - $$.arraySizes->addInnerSize(size); - } - ; - -type_parameter_specifier_opt - : type_parameter_specifier { - $$ = $1; - } - | /* May be null */ { - $$ = 0; - } - ; - -type_parameter_specifier - : LEFT_ANGLE type_parameter_specifier_list RIGHT_ANGLE { - $$ = $2; - } - ; - -type_parameter_specifier_list - : type_specifier { - $$ = new TTypeParameters; - $$->arraySizes = new TArraySizes; - $$->basicType = $1.basicType; - } - | unary_expression { - $$ = new TTypeParameters; - $$->arraySizes = new TArraySizes; - - TArraySize size; - parseContext.arraySizeCheck($1->getLoc(), $1, size, "type parameter", true); - $$->arraySizes->addInnerSize(size); - } - | type_parameter_specifier_list COMMA unary_expression { - $$ = $1; - - TArraySize size; - parseContext.arraySizeCheck($3->getLoc(), $3, size, "type parameter", true); - $$->arraySizes->addInnerSize(size); - } - ; - -type_specifier_nonarray - : VOID { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtVoid; - } - | FLOAT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - } - | INT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - } - | UINT { - parseContext.fullIntegerCheck($1.loc, "unsigned integer"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - } - | BOOL { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtBool; - } - | VEC2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(2); - } - | VEC3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(3); - } - | VEC4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(4); - } - | BVEC2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtBool; - $$.setVector(2); - } - | BVEC3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtBool; - $$.setVector(3); - } - | BVEC4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtBool; - $$.setVector(4); - } - | IVEC2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(2); - } - | IVEC3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(3); - } - | IVEC4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(4); - } - | UVEC2 { - parseContext.fullIntegerCheck($1.loc, "unsigned integer vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(2); - } - | UVEC3 { - parseContext.fullIntegerCheck($1.loc, "unsigned integer vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(3); - } - | UVEC4 { - parseContext.fullIntegerCheck($1.loc, "unsigned integer vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(4); - } - | MAT2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 2); - } - | MAT3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 3); - } - | MAT4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 4); - } - | MAT2X2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 2); - } - | MAT2X3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 3); - } - | MAT2X4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 4); - } - | MAT3X2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 2); - } - | MAT3X3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 3); - } - | MAT3X4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 4); - } - | MAT4X2 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 2); - } - | MAT4X3 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 3); - } - | MAT4X4 { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 4); - } - | DOUBLE { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - } - | FLOAT16_T { - parseContext.float16ScalarVectorCheck($1.loc, "float16_t", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - } - | FLOAT32_T { - parseContext.explicitFloat32Check($1.loc, "float32_t", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - } - | FLOAT64_T { - parseContext.explicitFloat64Check($1.loc, "float64_t", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - } - | INT8_T { - parseContext.int8ScalarVectorCheck($1.loc, "8-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt8; - } - | UINT8_T { - parseContext.int8ScalarVectorCheck($1.loc, "8-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint8; - } - | INT16_T { - parseContext.int16ScalarVectorCheck($1.loc, "16-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt16; - } - | UINT16_T { - parseContext.int16ScalarVectorCheck($1.loc, "16-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint16; - } - | INT32_T { - parseContext.explicitInt32Check($1.loc, "32-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - } - | UINT32_T { - parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - } - | INT64_T { - parseContext.int64Check($1.loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt64; - } - | UINT64_T { - parseContext.int64Check($1.loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint64; - } - | DVEC2 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(2); - } - | DVEC3 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(3); - } - | DVEC4 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double vector"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double vector"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(4); - } - | F16VEC2 { - parseContext.float16ScalarVectorCheck($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setVector(2); - } - | F16VEC3 { - parseContext.float16ScalarVectorCheck($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setVector(3); - } - | F16VEC4 { - parseContext.float16ScalarVectorCheck($1.loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setVector(4); - } - | F32VEC2 { - parseContext.explicitFloat32Check($1.loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(2); - } - | F32VEC3 { - parseContext.explicitFloat32Check($1.loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(3); - } - | F32VEC4 { - parseContext.explicitFloat32Check($1.loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setVector(4); - } - | F64VEC2 { - parseContext.explicitFloat64Check($1.loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(2); - } - | F64VEC3 { - parseContext.explicitFloat64Check($1.loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(3); - } - | F64VEC4 { - parseContext.explicitFloat64Check($1.loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setVector(4); - } - | I8VEC2 { - parseContext.int8ScalarVectorCheck($1.loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt8; - $$.setVector(2); - } - | I8VEC3 { - parseContext.int8ScalarVectorCheck($1.loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt8; - $$.setVector(3); - } - | I8VEC4 { - parseContext.int8ScalarVectorCheck($1.loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt8; - $$.setVector(4); - } - | I16VEC2 { - parseContext.int16ScalarVectorCheck($1.loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt16; - $$.setVector(2); - } - | I16VEC3 { - parseContext.int16ScalarVectorCheck($1.loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt16; - $$.setVector(3); - } - | I16VEC4 { - parseContext.int16ScalarVectorCheck($1.loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt16; - $$.setVector(4); - } - | I32VEC2 { - parseContext.explicitInt32Check($1.loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(2); - } - | I32VEC3 { - parseContext.explicitInt32Check($1.loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(3); - } - | I32VEC4 { - parseContext.explicitInt32Check($1.loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.setVector(4); - } - | I64VEC2 { - parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt64; - $$.setVector(2); - } - | I64VEC3 { - parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt64; - $$.setVector(3); - } - | I64VEC4 { - parseContext.int64Check($1.loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt64; - $$.setVector(4); - } - | U8VEC2 { - parseContext.int8ScalarVectorCheck($1.loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint8; - $$.setVector(2); - } - | U8VEC3 { - parseContext.int8ScalarVectorCheck($1.loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint8; - $$.setVector(3); - } - | U8VEC4 { - parseContext.int8ScalarVectorCheck($1.loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint8; - $$.setVector(4); - } - | U16VEC2 { - parseContext.int16ScalarVectorCheck($1.loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint16; - $$.setVector(2); - } - | U16VEC3 { - parseContext.int16ScalarVectorCheck($1.loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint16; - $$.setVector(3); - } - | U16VEC4 { - parseContext.int16ScalarVectorCheck($1.loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint16; - $$.setVector(4); - } - | U32VEC2 { - parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(2); - } - | U32VEC3 { - parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(3); - } - | U32VEC4 { - parseContext.explicitInt32Check($1.loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.setVector(4); - } - | U64VEC2 { - parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint64; - $$.setVector(2); - } - | U64VEC3 { - parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint64; - $$.setVector(3); - } - | U64VEC4 { - parseContext.int64Check($1.loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint64; - $$.setVector(4); - } - | DMAT2 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 2); - } - | DMAT3 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 3); - } - | DMAT4 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 4); - } - | DMAT2X2 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 2); - } - | DMAT2X3 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 3); - } - | DMAT2X4 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 4); - } - | DMAT3X2 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 2); - } - | DMAT3X3 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 3); - } - | DMAT3X4 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 4); - } - | DMAT4X2 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 2); - } - | DMAT4X3 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 3); - } - | DMAT4X4 { - parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck($1.loc, "double matrix"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 4); - } - | F16MAT2 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(2, 2); - } - | F16MAT3 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(3, 3); - } - | F16MAT4 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(4, 4); - } - | F16MAT2X2 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(2, 2); - } - | F16MAT2X3 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(2, 3); - } - | F16MAT2X4 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(2, 4); - } - | F16MAT3X2 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(3, 2); - } - | F16MAT3X3 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(3, 3); - } - | F16MAT3X4 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(3, 4); - } - | F16MAT4X2 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(4, 2); - } - | F16MAT4X3 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(4, 3); - } - | F16MAT4X4 { - parseContext.float16Check($1.loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat16; - $$.setMatrix(4, 4); - } - | F32MAT2 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 2); - } - | F32MAT3 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 3); - } - | F32MAT4 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 4); - } - | F32MAT2X2 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 2); - } - | F32MAT2X3 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 3); - } - | F32MAT2X4 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(2, 4); - } - | F32MAT3X2 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 2); - } - | F32MAT3X3 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 3); - } - | F32MAT3X4 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(3, 4); - } - | F32MAT4X2 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 2); - } - | F32MAT4X3 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 3); - } - | F32MAT4X4 { - parseContext.explicitFloat32Check($1.loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.setMatrix(4, 4); - } - | F64MAT2 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 2); - } - | F64MAT3 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 3); - } - | F64MAT4 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 4); - } - | F64MAT2X2 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 2); - } - | F64MAT2X3 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 3); - } - | F64MAT2X4 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(2, 4); - } - | F64MAT3X2 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 2); - } - | F64MAT3X3 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 3); - } - | F64MAT3X4 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(3, 4); - } - | F64MAT4X2 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 2); - } - | F64MAT4X3 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 3); - } - | F64MAT4X4 { - parseContext.explicitFloat64Check($1.loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtDouble; - $$.setMatrix(4, 4); - } - | ACCSTRUCTNV { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtAccStruct; - } - | ACCSTRUCTEXT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtAccStruct; - } - | RAYQUERYEXT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtRayQuery; - } - | ATOMIC_UINT { - parseContext.vulkanRemoved($1.loc, "atomic counter types"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtAtomicUint; - } - | SAMPLER1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd1D); - } - | SAMPLER2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D); - } - | SAMPLER3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd3D); - } - | SAMPLERCUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdCube); - } - | SAMPLER2DSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D, false, true); - } - | SAMPLERCUBESHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdCube, false, true); - } - | SAMPLER2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D, true); - } - | SAMPLER2DARRAYSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D, true, true); - } - | SAMPLER1DSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd1D, false, true); - } - | SAMPLER1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd1D, true); - } - | SAMPLER1DARRAYSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd1D, true, true); - } - | SAMPLERCUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdCube, true); - } - | SAMPLERCUBEARRAYSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdCube, true, true); - } - | F16SAMPLER1D { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd1D); - } - | F16SAMPLER2D { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D); - } - | F16SAMPLER3D { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd3D); - } - | F16SAMPLERCUBE { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdCube); - } - | F16SAMPLER1DSHADOW { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd1D, false, true); - } - | F16SAMPLER2DSHADOW { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D, false, true); - } - | F16SAMPLERCUBESHADOW { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdCube, false, true); - } - | F16SAMPLER1DARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd1D, true); - } - | F16SAMPLER2DARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D, true); - } - | F16SAMPLER1DARRAYSHADOW { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd1D, true, true); - } - | F16SAMPLER2DARRAYSHADOW { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D, true, true); - } - | F16SAMPLERCUBEARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdCube, true); - } - | F16SAMPLERCUBEARRAYSHADOW { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdCube, true, true); - } - | ISAMPLER1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd1D); - } - | ISAMPLER2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd2D); - } - | ISAMPLER3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd3D); - } - | ISAMPLERCUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, EsdCube); - } - | ISAMPLER2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd2D, true); - } - | USAMPLER2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd2D); - } - | USAMPLER3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd3D); - } - | USAMPLERCUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, EsdCube); - } - | ISAMPLER1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd1D, true); - } - | ISAMPLERCUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, EsdCube, true); - } - | USAMPLER1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd1D); - } - | USAMPLER1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd1D, true); - } - | USAMPLERCUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, EsdCube, true); - } - | TEXTURECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, EsdCube, true); - } - | ITEXTURECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, EsdCube, true); - } - | UTEXTURECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, EsdCube, true); - } - | USAMPLER2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd2D, true); - } - | TEXTURE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd2D); - } - | TEXTURE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd3D); - } - | TEXTURE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd2D, true); - } - | TEXTURECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, EsdCube); - } - | ITEXTURE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd2D); - } - | ITEXTURE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd3D); - } - | ITEXTURECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, EsdCube); - } - | ITEXTURE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd2D, true); - } - | UTEXTURE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd2D); - } - | UTEXTURE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd3D); - } - | UTEXTURECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, EsdCube); - } - | UTEXTURE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd2D, true); - } - | SAMPLER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setPureSampler(false); - } - | SAMPLERSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setPureSampler(true); - } - | SAMPLER2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdRect); - } - | SAMPLER2DRECTSHADOW { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdRect, false, true); - } - | F16SAMPLER2DRECT { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdRect); - } - | F16SAMPLER2DRECTSHADOW { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdRect, false, true); - } - | ISAMPLER2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, EsdRect); - } - | USAMPLER2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, EsdRect); - } - | SAMPLERBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, EsdBuffer); - } - | F16SAMPLERBUFFER { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, EsdBuffer); - } - | ISAMPLERBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, EsdBuffer); - } - | USAMPLERBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, EsdBuffer); - } - | SAMPLER2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D, false, false, true); - } - | F16SAMPLER2DMS { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D, false, false, true); - } - | ISAMPLER2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd2D, false, false, true); - } - | USAMPLER2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd2D, false, false, true); - } - | SAMPLER2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D, true, false, true); - } - | F16SAMPLER2DMSARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat16, Esd2D, true, false, true); - } - | ISAMPLER2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtInt, Esd2D, true, false, true); - } - | USAMPLER2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtUint, Esd2D, true, false, true); - } - | TEXTURE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd1D); - } - | F16TEXTURE1D { - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd1D); - } - | F16TEXTURE2D { - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd2D); - } - | F16TEXTURE3D { - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd3D); - } - | F16TEXTURECUBE { - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, EsdCube); - } - | TEXTURE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd1D, true); - } - | F16TEXTURE1DARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd1D, true); - } - | F16TEXTURE2DARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd2D, true); - } - | F16TEXTURECUBEARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, EsdCube, true); - } - | ITEXTURE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd1D); - } - | ITEXTURE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd1D, true); - } - | UTEXTURE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd1D); - } - | UTEXTURE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd1D, true); - } - | TEXTURE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, EsdRect); - } - | F16TEXTURE2DRECT { - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, EsdRect); - } - | ITEXTURE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, EsdRect); - } - | UTEXTURE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, EsdRect); - } - | TEXTUREBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, EsdBuffer); - } - | F16TEXTUREBUFFER { - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, EsdBuffer); - } - | ITEXTUREBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, EsdBuffer); - } - | UTEXTUREBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, EsdBuffer); - } - | TEXTURE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd2D, false, false, true); - } - | F16TEXTURE2DMS { - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd2D, false, false, true); - } - | ITEXTURE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd2D, false, false, true); - } - | UTEXTURE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd2D, false, false, true); - } - | TEXTURE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat, Esd2D, true, false, true); - } - | F16TEXTURE2DMSARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtFloat16, Esd2D, true, false, true); - } - | ITEXTURE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtInt, Esd2D, true, false, true); - } - | UTEXTURE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setTexture(EbtUint, Esd2D, true, false, true); - } - | IMAGE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd1D); - } - | F16IMAGE1D { - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd1D); - } - | IIMAGE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd1D); - } - | UIMAGE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd1D); - } - | IMAGE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd2D); - } - | F16IMAGE2D { - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd2D); - } - | IIMAGE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd2D); - } - | UIMAGE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd2D); - } - | IMAGE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd3D); - } - | F16IMAGE3D { - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd3D); - } - | IIMAGE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd3D); - } - | UIMAGE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd3D); - } - | IMAGE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, EsdRect); - } - | F16IMAGE2DRECT { - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, EsdRect); - } - | IIMAGE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, EsdRect); - } - | UIMAGE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, EsdRect); - } - | IMAGECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, EsdCube); - } - | F16IMAGECUBE { - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, EsdCube); - } - | IIMAGECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, EsdCube); - } - | UIMAGECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, EsdCube); - } - | IMAGEBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, EsdBuffer); - } - | F16IMAGEBUFFER { - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, EsdBuffer); - } - | IIMAGEBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, EsdBuffer); - } - | UIMAGEBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, EsdBuffer); - } - | IMAGE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd1D, true); - } - | F16IMAGE1DARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd1D, true); - } - | IIMAGE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd1D, true); - } - | UIMAGE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd1D, true); - } - | IMAGE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd2D, true); - } - | F16IMAGE2DARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd2D, true); - } - | IIMAGE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd2D, true); - } - | UIMAGE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd2D, true); - } - | IMAGECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, EsdCube, true); - } - | F16IMAGECUBEARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, EsdCube, true); - } - | IIMAGECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, EsdCube, true); - } - | UIMAGECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, EsdCube, true); - } - | IMAGE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd2D, false, false, true); - } - | F16IMAGE2DMS { - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd2D, false, false, true); - } - | IIMAGE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd2D, false, false, true); - } - | UIMAGE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd2D, false, false, true); - } - | IMAGE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat, Esd2D, true, false, true); - } - | F16IMAGE2DMSARRAY { - parseContext.float16OpaqueCheck($1.loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtFloat16, Esd2D, true, false, true); - } - | IIMAGE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt, Esd2D, true, false, true); - } - | UIMAGE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint, Esd2D, true, false, true); - } - | I64IMAGE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt64, Esd1D); - } - | U64IMAGE1D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint64, Esd1D); - } - | I64IMAGE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt64, Esd2D); - } - | U64IMAGE2D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint64, Esd2D); - } - | I64IMAGE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt64, Esd3D); - } - | U64IMAGE3D { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint64, Esd3D); - } - | I64IMAGE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt64, EsdRect); - } - | U64IMAGE2DRECT { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint64, EsdRect); - } - | I64IMAGECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt64, EsdCube); - } - | U64IMAGECUBE { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint64, EsdCube); - } - | I64IMAGEBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt64, EsdBuffer); - } - | U64IMAGEBUFFER { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint64, EsdBuffer); - } - | I64IMAGE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt64, Esd1D, true); - } - | U64IMAGE1DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint64, Esd1D, true); - } - | I64IMAGE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt64, Esd2D, true); - } - | U64IMAGE2DARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint64, Esd2D, true); - } - | I64IMAGECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt64, EsdCube, true); - } - | U64IMAGECUBEARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint64, EsdCube, true); - } - | I64IMAGE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt64, Esd2D, false, false, true); - } - | U64IMAGE2DMS { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint64, Esd2D, false, false, true); - } - | I64IMAGE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtInt64, Esd2D, true, false, true); - } - | U64IMAGE2DMSARRAY { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setImage(EbtUint64, Esd2D, true, false, true); - } - | SAMPLEREXTERNALOES { // GL_OES_EGL_image_external - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D); - $$.sampler.external = true; - } - | SAMPLEREXTERNAL2DY2YEXT { // GL_EXT_YUV_target - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.set(EbtFloat, Esd2D); - $$.sampler.yuv = true; - } - | ATTACHMENTEXT { - parseContext.requireStage($1.loc, EShLangFragment, "attachmentEXT input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setAttachmentEXT(EbtFloat); - } - | IATTACHMENTEXT { - parseContext.requireStage($1.loc, EShLangFragment, "attachmentEXT input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setAttachmentEXT(EbtInt); - } - | UATTACHMENTEXT { - parseContext.requireStage($1.loc, EShLangFragment, "attachmentEXT input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setAttachmentEXT(EbtUint); - } - | SUBPASSINPUT { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtFloat); - } - | SUBPASSINPUTMS { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtFloat, true); - } - | F16SUBPASSINPUT { - parseContext.float16OpaqueCheck($1.loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtFloat16); - } - | F16SUBPASSINPUTMS { - parseContext.float16OpaqueCheck($1.loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtFloat16, true); - } - | ISUBPASSINPUT { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtInt); - } - | ISUBPASSINPUTMS { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtInt, true); - } - | USUBPASSINPUT { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtUint); - } - | USUBPASSINPUTMS { - parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtSampler; - $$.sampler.setSubpass(EbtUint, true); - } - | FCOOPMATNV { - parseContext.fcoopmatCheckNV($1.loc, "fcoopmatNV", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtFloat; - $$.coopmatNV = true; - $$.coopmatKHR = false; - } - | ICOOPMATNV { - parseContext.intcoopmatCheckNV($1.loc, "icoopmatNV", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtInt; - $$.coopmatNV = true; - $$.coopmatKHR = false; - } - | UCOOPMATNV { - parseContext.intcoopmatCheckNV($1.loc, "ucoopmatNV", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtUint; - $$.coopmatNV = true; - $$.coopmatKHR = false; - } - | COOPMAT { - parseContext.coopmatCheck($1.loc, "coopmat", parseContext.symbolTable.atBuiltInLevel()); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtCoopmat; - $$.coopmatNV = false; - $$.coopmatKHR = true; - } - | spirv_type_specifier { - parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier"); - $$ = $1; - } - | HITOBJECTNV { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtHitObjectNV; - } - | struct_specifier { - $$ = $1; - $$.qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - parseContext.structTypeCheck($$.loc, $$); - } - | TYPE_NAME { - // - // This is for user defined type names. The lexical phase looked up the - // type. - // - if (const TVariable* variable = ($1.symbol)->getAsVariable()) { - const TType& structure = variable->getType(); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.basicType = EbtStruct; - $$.userDef = &structure; - } else - parseContext.error($1.loc, "expected type name", $1.string->c_str(), ""); - } - ; - -precision_qualifier - : HIGH_PRECISION { - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "highp precision qualifier"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqHigh); - } - | MEDIUM_PRECISION { - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "mediump precision qualifier"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqMedium); - } - | LOW_PRECISION { - parseContext.profileRequires($1.loc, ENoProfile, 130, 0, "lowp precision qualifier"); - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier($1.loc, $$.qualifier, EpqLow); - } - ; - -struct_specifier - : STRUCT IDENTIFIER LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE { - - TType* structure = new TType($5, *$2.string); - parseContext.structArrayCheck($2.loc, *structure); - - TVariable* userTypeDef = new TVariable($2.string, *structure, true); - if (! parseContext.symbolTable.insert(*userTypeDef)) - parseContext.error($2.loc, "redefinition", $2.string->c_str(), "struct"); - else if (parseContext.spvVersion.vulkanRelaxed - && structure->containsOpaque()) - parseContext.relaxedSymbols.push_back(structure->getTypeName()); - - $$.init($1.loc); - $$.basicType = EbtStruct; - $$.userDef = structure; - --parseContext.structNestingLevel; - } - | STRUCT LEFT_BRACE { parseContext.nestedStructCheck($1.loc); } struct_declaration_list RIGHT_BRACE { - TType* structure = new TType($4, TString("")); - $$.init($1.loc); - $$.basicType = EbtStruct; - $$.userDef = structure; - --parseContext.structNestingLevel; - } - ; - -struct_declaration_list - : struct_declaration { - $$ = $1; - } - | struct_declaration_list struct_declaration { - $$ = $1; - for (unsigned int i = 0; i < $2->size(); ++i) { - for (unsigned int j = 0; j < $$->size(); ++j) { - if ((*$$)[j].type->getFieldName() == (*$2)[i].type->getFieldName()) - parseContext.error((*$2)[i].loc, "duplicate member name:", "", (*$2)[i].type->getFieldName().c_str()); - } - $$->push_back((*$2)[i]); - } - } - ; - -struct_declaration - : type_specifier struct_declarator_list SEMICOLON { - if ($1.arraySizes) { - parseContext.profileRequires($1.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type"); - if (parseContext.isEsProfile()) - parseContext.arraySizeRequiredCheck($1.loc, *$1.arraySizes); - } - - $$ = $2; - - parseContext.voidErrorCheck($1.loc, (*$2)[0].type->getFieldName(), $1.basicType); - parseContext.precisionQualifierCheck($1.loc, $1.basicType, $1.qualifier, $1.isCoopmat()); - - for (unsigned int i = 0; i < $$->size(); ++i) { - TType type($1); - type.setFieldName((*$$)[i].type->getFieldName()); - type.transferArraySizes((*$$)[i].type->getArraySizes()); - type.copyArrayInnerSizes($1.arraySizes); - parseContext.arrayOfArrayVersionCheck((*$$)[i].loc, type.getArraySizes()); - (*$$)[i].type->shallowCopy(type); - } - } - | type_qualifier type_specifier struct_declarator_list SEMICOLON { - if ($2.arraySizes) { - parseContext.profileRequires($2.loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type"); - if (parseContext.isEsProfile()) - parseContext.arraySizeRequiredCheck($2.loc, *$2.arraySizes); - } - - $$ = $3; - - parseContext.memberQualifierCheck($1); - parseContext.voidErrorCheck($2.loc, (*$3)[0].type->getFieldName(), $2.basicType); - parseContext.mergeQualifiers($2.loc, $2.qualifier, $1.qualifier, true); - parseContext.precisionQualifierCheck($2.loc, $2.basicType, $2.qualifier, $2.isCoopmat()); - - for (unsigned int i = 0; i < $$->size(); ++i) { - TType type($2); - type.setFieldName((*$$)[i].type->getFieldName()); - type.transferArraySizes((*$$)[i].type->getArraySizes()); - type.copyArrayInnerSizes($2.arraySizes); - parseContext.arrayOfArrayVersionCheck((*$$)[i].loc, type.getArraySizes()); - (*$$)[i].type->shallowCopy(type); - } - } - ; - -struct_declarator_list - : struct_declarator { - $$ = new TTypeList; - $$->push_back($1); - } - | struct_declarator_list COMMA struct_declarator { - $$->push_back($3); - } - ; - -struct_declarator - : IDENTIFIER { - $$.type = new TType(EbtVoid); - $$.loc = $1.loc; - $$.type->setFieldName(*$1.string); - } - | IDENTIFIER array_specifier { - parseContext.arrayOfArrayVersionCheck($1.loc, $2.arraySizes); - - $$.type = new TType(EbtVoid); - $$.loc = $1.loc; - $$.type->setFieldName(*$1.string); - $$.type->transferArraySizes($2.arraySizes); - } - ; - -initializer - : assignment_expression { - $$ = $1; - } - | LEFT_BRACE initializer_list RIGHT_BRACE { - const char* initFeature = "{ } style initializers"; - parseContext.requireProfile($1.loc, ~EEsProfile, initFeature); - parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - $$ = $2; - } - | LEFT_BRACE initializer_list COMMA RIGHT_BRACE { - const char* initFeature = "{ } style initializers"; - parseContext.requireProfile($1.loc, ~EEsProfile, initFeature); - parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - $$ = $2; - } - | LEFT_BRACE RIGHT_BRACE { - const char* initFeature = "empty { } initializer"; - parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); - parseContext.profileRequires($1.loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); - $$ = parseContext.intermediate.makeAggregate($1.loc); - } - ; - -initializer_list - : initializer { - $$ = parseContext.intermediate.growAggregate(0, $1, $1->getLoc()); - } - | initializer_list COMMA initializer { - $$ = parseContext.intermediate.growAggregate($1, $3); - } - ; - -declaration_statement - : declaration { $$ = $1; } - ; - -statement - : compound_statement { $$ = $1; } - | simple_statement { $$ = $1; } - ; - -// Grammar Note: labeled statements for switch statements only; 'goto' is not supported. - -simple_statement - : declaration_statement { $$ = $1; } - | expression_statement { $$ = $1; } - | selection_statement { $$ = $1; } - | switch_statement { $$ = $1; } - | case_label { $$ = $1; } - | iteration_statement { $$ = $1; } - | jump_statement { $$ = $1; } - | demote_statement { $$ = $1; } - ; - -demote_statement - : DEMOTE SEMICOLON { - parseContext.requireStage($1.loc, EShLangFragment, "demote"); - parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_demote_to_helper_invocation, "demote"); - $$ = parseContext.intermediate.addBranch(EOpDemote, $1.loc); - } - ; - -compound_statement - : LEFT_BRACE RIGHT_BRACE { $$ = 0; } - | LEFT_BRACE { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - } - statement_list { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - } - RIGHT_BRACE { - if ($3 && $3->getAsAggregate()) - $3->getAsAggregate()->setOperator(parseContext.intermediate.getDebugInfo() ? EOpScope : EOpSequence); - $$ = $3; - } - ; - -statement_no_new_scope - : compound_statement_no_new_scope { $$ = $1; } - | simple_statement { $$ = $1; } - ; - -statement_scoped - : { - ++parseContext.controlFlowNestingLevel; - } - compound_statement { - --parseContext.controlFlowNestingLevel; - $$ = $2; - } - | { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } - simple_statement { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - $$ = $2; - } - -compound_statement_no_new_scope - // Statement that doesn't create a new scope, for selection_statement, iteration_statement - : LEFT_BRACE RIGHT_BRACE { - $$ = 0; - } - | LEFT_BRACE statement_list RIGHT_BRACE { - if ($2 && $2->getAsAggregate()) - $2->getAsAggregate()->setOperator(EOpSequence); - $$ = $2; - } - ; - -statement_list - : statement { - $$ = parseContext.intermediate.makeAggregate($1); - if ($1 && $1->getAsBranchNode() && ($1->getAsBranchNode()->getFlowOp() == EOpCase || - $1->getAsBranchNode()->getFlowOp() == EOpDefault)) { - parseContext.wrapupSwitchSubsequence(0, $1); - $$ = 0; // start a fresh subsequence for what's after this case - } - } - | statement_list statement { - if ($2 && $2->getAsBranchNode() && ($2->getAsBranchNode()->getFlowOp() == EOpCase || - $2->getAsBranchNode()->getFlowOp() == EOpDefault)) { - parseContext.wrapupSwitchSubsequence($1 ? $1->getAsAggregate() : 0, $2); - $$ = 0; // start a fresh subsequence for what's after this case - } else - $$ = parseContext.intermediate.growAggregate($1, $2); - } - ; - -expression_statement - : SEMICOLON { $$ = 0; } - | expression SEMICOLON { $$ = static_cast($1); } - ; - -selection_statement - : selection_statement_nonattributed { - $$ = $1; - } - | attribute selection_statement_nonattributed { - parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); - parseContext.handleSelectionAttributes(*$1, $2); - $$ = $2; - } - -selection_statement_nonattributed - : IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement { - parseContext.boolCheck($1.loc, $3); - $$ = parseContext.intermediate.addSelection($3, $5, $1.loc); - } - ; - -selection_rest_statement - : statement_scoped ELSE statement_scoped { - $$.node1 = $1; - $$.node2 = $3; - } - | statement_scoped { - $$.node1 = $1; - $$.node2 = 0; - } - ; - -condition - // In 1996 c++ draft, conditions can include single declarations - : expression { - $$ = $1; - parseContext.boolCheck($1->getLoc(), $1); - } - | fully_specified_type IDENTIFIER EQUAL initializer { - parseContext.boolCheck($2.loc, $1); - - TType type($1); - TIntermNode* initNode = parseContext.declareVariable($2.loc, *$2.string, $1, 0, $4); - if (initNode) - $$ = initNode->getAsTyped(); - else - $$ = 0; - } - ; - -switch_statement - : switch_statement_nonattributed { - $$ = $1; - } - | attribute switch_statement_nonattributed { - parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); - parseContext.handleSwitchAttributes(*$1, $2); - $$ = $2; - } - -switch_statement_nonattributed - : SWITCH LEFT_PAREN expression RIGHT_PAREN { - // start new switch sequence on the switch stack - ++parseContext.controlFlowNestingLevel; - ++parseContext.statementNestingLevel; - parseContext.switchSequenceStack.push_back(new TIntermSequence); - parseContext.switchLevel.push_back(parseContext.statementNestingLevel); - parseContext.symbolTable.push(); - } - LEFT_BRACE switch_statement_list RIGHT_BRACE { - $$ = parseContext.addSwitch($1.loc, $3, $7 ? $7->getAsAggregate() : 0); - delete parseContext.switchSequenceStack.back(); - parseContext.switchSequenceStack.pop_back(); - parseContext.switchLevel.pop_back(); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } - ; - -switch_statement_list - : /* nothing */ { - $$ = 0; - } - | statement_list { - $$ = $1; - } - ; - -case_label - : CASE expression COLON { - $$ = 0; - if (parseContext.switchLevel.size() == 0) - parseContext.error($1.loc, "cannot appear outside switch statement", "case", ""); - else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) - parseContext.error($1.loc, "cannot be nested inside control flow", "case", ""); - else { - parseContext.constantValueCheck($2, "case"); - parseContext.integerCheck($2, "case"); - $$ = parseContext.intermediate.addBranch(EOpCase, $2, $1.loc); - } - } - | DEFAULT COLON { - $$ = 0; - if (parseContext.switchLevel.size() == 0) - parseContext.error($1.loc, "cannot appear outside switch statement", "default", ""); - else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) - parseContext.error($1.loc, "cannot be nested inside control flow", "default", ""); - else - $$ = parseContext.intermediate.addBranch(EOpDefault, $1.loc); - } - ; - -iteration_statement - : iteration_statement_nonattributed { - $$ = $1; - } - | attribute iteration_statement_nonattributed { - parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); - parseContext.handleLoopAttributes(*$1, $2); - $$ = $2; - } - -iteration_statement_nonattributed - : WHILE LEFT_PAREN { - if (! parseContext.limits.whileLoops) - parseContext.error($1.loc, "while loops not available", "limitation", ""); - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } - condition RIGHT_PAREN statement_no_new_scope { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - $$ = parseContext.intermediate.addLoop($6, $4, 0, true, $1.loc); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } - | DO { - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } - statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON { - if (! parseContext.limits.whileLoops) - parseContext.error($1.loc, "do-while loops not available", "limitation", ""); - - parseContext.boolCheck($8.loc, $6); - - $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } - | FOR LEFT_PAREN { - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } - for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - $$ = parseContext.intermediate.makeAggregate($4, $2.loc); - TIntermLoop* forLoop = parseContext.intermediate.addLoop($7, reinterpret_cast($5.node1), reinterpret_cast($5.node2), true, $1.loc); - if (! parseContext.limits.nonInductiveForLoops) - parseContext.inductiveLoopCheck($1.loc, $4, forLoop); - $$ = parseContext.intermediate.growAggregate($$, forLoop, $1.loc); - $$->getAsAggregate()->setOperator(EOpSequence); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } - ; - -for_init_statement - : expression_statement { - $$ = $1; - } - | declaration_statement { - $$ = $1; - } - ; - -conditionopt - : condition { - $$ = $1; - } - | /* May be null */ { - $$ = 0; - } - ; - -for_rest_statement - : conditionopt SEMICOLON { - $$.node1 = $1; - $$.node2 = 0; - } - | conditionopt SEMICOLON expression { - $$.node1 = $1; - $$.node2 = $3; - } - ; - -jump_statement - : CONTINUE SEMICOLON { - if (parseContext.loopNestingLevel <= 0) - parseContext.error($1.loc, "continue statement only allowed in loops", "", ""); - $$ = parseContext.intermediate.addBranch(EOpContinue, $1.loc); - } - | BREAK SEMICOLON { - if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0) - parseContext.error($1.loc, "break statement only allowed in switch and loops", "", ""); - $$ = parseContext.intermediate.addBranch(EOpBreak, $1.loc); - } - | RETURN SEMICOLON { - $$ = parseContext.intermediate.addBranch(EOpReturn, $1.loc); - if (parseContext.currentFunctionType->getBasicType() != EbtVoid) - parseContext.error($1.loc, "non-void function must return a value", "return", ""); - if (parseContext.inMain) - parseContext.postEntryPointReturn = true; - } - | RETURN expression SEMICOLON { - $$ = parseContext.handleReturnValue($1.loc, $2); - } - | DISCARD SEMICOLON { - parseContext.requireStage($1.loc, EShLangFragment, "discard"); - $$ = parseContext.intermediate.addBranch(EOpKill, $1.loc); - } - | TERMINATE_INVOCATION SEMICOLON { - parseContext.requireStage($1.loc, EShLangFragment, "terminateInvocation"); - $$ = parseContext.intermediate.addBranch(EOpTerminateInvocation, $1.loc); - } - | TERMINATE_RAY SEMICOLON { - parseContext.requireStage($1.loc, EShLangAnyHit, "terminateRayEXT"); - $$ = parseContext.intermediate.addBranch(EOpTerminateRayKHR, $1.loc); - } - | IGNORE_INTERSECTION SEMICOLON { - parseContext.requireStage($1.loc, EShLangAnyHit, "ignoreIntersectionEXT"); - $$ = parseContext.intermediate.addBranch(EOpIgnoreIntersectionKHR, $1.loc); - } - ; - -// Grammar Note: No 'goto'. Gotos are not supported. - -translation_unit - : external_declaration { - $$ = $1; - parseContext.intermediate.setTreeRoot($$); - } - | translation_unit external_declaration { - if ($2 != nullptr) { - $$ = parseContext.intermediate.growAggregate($1, $2); - parseContext.intermediate.setTreeRoot($$); - } - } - ; - -external_declaration - : function_definition { - $$ = $1; - } - | declaration { - $$ = $1; - } - | SEMICOLON { - parseContext.requireProfile($1.loc, ~EEsProfile, "extraneous semicolon"); - parseContext.profileRequires($1.loc, ~EEsProfile, 460, nullptr, "extraneous semicolon"); - $$ = nullptr; - } - ; - -function_definition - : function_prototype { - $1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */); - $1.intermNode = parseContext.handleFunctionDefinition($1.loc, *$1.function); - - // For ES 100 only, according to ES shading language 100 spec: A function - // body has a scope nested inside the function's definition. - if (parseContext.profile == EEsProfile && parseContext.version == 100) - { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - } - } - compound_statement_no_new_scope { - // May be best done as post process phase on intermediate code - if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) - parseContext.error($1.loc, "function does not return a value:", "", $1.function->getName().c_str()); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - $$ = parseContext.intermediate.growAggregate($1.intermNode, $3); - $$->getAsAggregate()->setLinkType($1.function->getLinkType()); - parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.function->getType(), $1.loc); - $$->getAsAggregate()->setName($1.function->getMangledName().c_str()); - - // store the pragma information for debug and optimize and other vendor specific - // information. This information can be queried from the parse tree - $$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); - $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug); - $$->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable); - - // Set currentFunctionType to empty pointer when goes outside of the function - parseContext.currentFunctionType = nullptr; - - // For ES 100 only, according to ES shading language 100 spec: A function - // body has a scope nested inside the function's definition. - if (parseContext.profile == EEsProfile && parseContext.version == 100) - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - } - } - ; - -attribute - : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET { - $$ = $3; - } - -attribute_list - : single_attribute { - $$ = $1; - } - | attribute_list COMMA single_attribute { - $$ = parseContext.mergeAttributes($1, $3); - } - -single_attribute - : IDENTIFIER { - $$ = parseContext.makeAttributes(*$1.string); - } - | IDENTIFIER LEFT_PAREN constant_expression RIGHT_PAREN { - $$ = parseContext.makeAttributes(*$1.string, $3); - } - -spirv_requirements_list - : spirv_requirements_parameter { - $$ = $1; - } - | spirv_requirements_list COMMA spirv_requirements_parameter { - $$ = parseContext.mergeSpirvRequirements($2.loc, $1, $3); - } - -spirv_requirements_parameter - : IDENTIFIER EQUAL LEFT_BRACKET spirv_extension_list RIGHT_BRACKET { - $$ = parseContext.makeSpirvRequirement($2.loc, *$1.string, $4->getAsAggregate(), nullptr); - } - | IDENTIFIER EQUAL LEFT_BRACKET spirv_capability_list RIGHT_BRACKET { - $$ = parseContext.makeSpirvRequirement($2.loc, *$1.string, nullptr, $4->getAsAggregate()); - } - -spirv_extension_list - : STRING_LITERAL { - $$ = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion($1.string, $1.loc, true)); - } - | spirv_extension_list COMMA STRING_LITERAL { - $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.string, $3.loc, true)); - } - -spirv_capability_list - : INTCONSTANT { - $$ = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion($1.i, $1.loc, true)); - } - | spirv_capability_list COMMA INTCONSTANT { - $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.i, $3.loc, true)); - } - -spirv_execution_mode_qualifier - : SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT RIGHT_PAREN { - parseContext.intermediate.insertSpirvExecutionMode($3.i); - $$ = 0; - } - | SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN { - parseContext.intermediate.insertSpirvRequirement($3); - parseContext.intermediate.insertSpirvExecutionMode($5.i); - $$ = 0; - } - | SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN { - parseContext.intermediate.insertSpirvExecutionMode($3.i, $5->getAsAggregate()); - $$ = 0; - } - | SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN { - parseContext.intermediate.insertSpirvRequirement($3); - parseContext.intermediate.insertSpirvExecutionMode($5.i, $7->getAsAggregate()); - $$ = 0; - } - | SPIRV_EXECUTION_MODE_ID LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN { - parseContext.intermediate.insertSpirvExecutionModeId($3.i, $5->getAsAggregate()); - $$ = 0; - } - | SPIRV_EXECUTION_MODE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN { - parseContext.intermediate.insertSpirvRequirement($3); - parseContext.intermediate.insertSpirvExecutionModeId($5.i, $7->getAsAggregate()); - $$ = 0; - } - -spirv_execution_mode_parameter_list - : spirv_execution_mode_parameter { - $$ = parseContext.intermediate.makeAggregate($1); - } - | spirv_execution_mode_parameter_list COMMA spirv_execution_mode_parameter { - $$ = parseContext.intermediate.growAggregate($1, $3); - } - -spirv_execution_mode_parameter - : FLOATCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true); - } - | INTCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); - } - | UINTCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true); - } - | BOOLCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); - } - | STRING_LITERAL { - $$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true); - } - -spirv_execution_mode_id_parameter_list - : constant_expression { - if ($1->getBasicType() != EbtFloat && - $1->getBasicType() != EbtInt && - $1->getBasicType() != EbtUint && - $1->getBasicType() != EbtBool && - $1->getBasicType() != EbtString) - parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), ""); - $$ = parseContext.intermediate.makeAggregate($1); - } - | spirv_execution_mode_id_parameter_list COMMA constant_expression { - if ($3->getBasicType() != EbtFloat && - $3->getBasicType() != EbtInt && - $3->getBasicType() != EbtUint && - $3->getBasicType() != EbtBool && - $3->getBasicType() != EbtString) - parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), ""); - $$ = parseContext.intermediate.growAggregate($1, $3); - } - -spirv_storage_class_qualifier - : SPIRV_STORAGE_CLASS LEFT_PAREN INTCONSTANT RIGHT_PAREN { - $$.init($1.loc); - $$.qualifier.storage = EvqSpirvStorageClass; - $$.qualifier.spirvStorageClass = $3.i; - } - | SPIRV_STORAGE_CLASS LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN { - $$.init($1.loc); - parseContext.intermediate.insertSpirvRequirement($3); - $$.qualifier.storage = EvqSpirvStorageClass; - $$.qualifier.spirvStorageClass = $5.i; - } - -spirv_decorate_qualifier - : SPIRV_DECORATE LEFT_PAREN INTCONSTANT RIGHT_PAREN{ - $$.init($1.loc); - $$.qualifier.setSpirvDecorate($3.i); - } - | SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN{ - $$.init($1.loc); - parseContext.intermediate.insertSpirvRequirement($3); - $$.qualifier.setSpirvDecorate($5.i); - } - | SPIRV_DECORATE LEFT_PAREN INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN { - $$.init($1.loc); - $$.qualifier.setSpirvDecorate($3.i, $5->getAsAggregate()); - } - | SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN { - $$.init($1.loc); - parseContext.intermediate.insertSpirvRequirement($3); - $$.qualifier.setSpirvDecorate($5.i, $7->getAsAggregate()); - } - | SPIRV_DECORATE_ID LEFT_PAREN INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN { - $$.init($1.loc); - $$.qualifier.setSpirvDecorateId($3.i, $5->getAsAggregate()); - } - | SPIRV_DECORATE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN { - $$.init($1.loc); - parseContext.intermediate.insertSpirvRequirement($3); - $$.qualifier.setSpirvDecorateId($5.i, $7->getAsAggregate()); - } - | SPIRV_DECORATE_STRING LEFT_PAREN INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN { - $$.init($1.loc); - $$.qualifier.setSpirvDecorateString($3.i, $5->getAsAggregate()); - } - | SPIRV_DECORATE_STRING LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN { - $$.init($1.loc); - parseContext.intermediate.insertSpirvRequirement($3); - $$.qualifier.setSpirvDecorateString($5.i, $7->getAsAggregate()); - } - -spirv_decorate_parameter_list - : spirv_decorate_parameter { - $$ = parseContext.intermediate.makeAggregate($1); - } - | spirv_decorate_parameter_list COMMA spirv_decorate_parameter { - $$ = parseContext.intermediate.growAggregate($1, $3); - } - -spirv_decorate_parameter - : FLOATCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true); - } - | INTCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); - } - | UINTCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true); - } - | BOOLCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); - } - -spirv_decorate_id_parameter_list - : spirv_decorate_id_parameter { - $$ = parseContext.intermediate.makeAggregate($1); - } - | spirv_decorate_id_parameter_list COMMA spirv_decorate_id_parameter { - $$ = parseContext.intermediate.growAggregate($1, $3); - } - -spirv_decorate_id_parameter - : variable_identifier { - if ($1->getAsConstantUnion() || $1->getAsSymbolNode()) - $$ = $1; - else - parseContext.error($1->getLoc(), "only allow constants or variables which are not elements of a composite", "", ""); - } - | FLOATCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.d, EbtFloat, $1.loc, true); - } - | INTCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); - } - | UINTCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.u, $1.loc, true); - } - | BOOLCONSTANT { - $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); - } - -spirv_decorate_string_parameter_list - : STRING_LITERAL { - $$ = parseContext.intermediate.makeAggregate( - parseContext.intermediate.addConstantUnion($1.string, $1.loc, true)); - } - | spirv_decorate_string_parameter_list COMMA STRING_LITERAL { - $$ = parseContext.intermediate.growAggregate($1, parseContext.intermediate.addConstantUnion($3.string, $3.loc, true)); - } - -spirv_type_specifier - : SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.setSpirvType(*$3, $5); - } - | SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.intermediate.insertSpirvRequirement($3); - $$.setSpirvType(*$5, $7); - } - | SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - $$.setSpirvType(*$3); - } - | SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN { - $$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.intermediate.insertSpirvRequirement($3); - $$.setSpirvType(*$5); - } - -spirv_type_parameter_list - : spirv_type_parameter { - $$ = $1; - } - | spirv_type_parameter_list COMMA spirv_type_parameter { - $$ = parseContext.mergeSpirvTypeParameters($1, $3); - } - -spirv_type_parameter - : constant_expression { - $$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion()); - } - | type_specifier_nonarray { - $$ = parseContext.makeSpirvTypeParameters($1.loc, $1); - } - -spirv_instruction_qualifier - : SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN { - $$ = $3; - } - | SPIRV_INSTRUCTION LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN { - parseContext.intermediate.insertSpirvRequirement($3); - $$ = $5; - } - -spirv_instruction_qualifier_list - : spirv_instruction_qualifier_id { - $$ = $1; - } - | spirv_instruction_qualifier_list COMMA spirv_instruction_qualifier_id { - $$ = parseContext.mergeSpirvInstruction($2.loc, $1, $3); - } - -spirv_instruction_qualifier_id - : IDENTIFIER EQUAL STRING_LITERAL { - $$ = parseContext.makeSpirvInstruction($2.loc, *$1.string, *$3.string); - } - | IDENTIFIER EQUAL INTCONSTANT { - $$ = parseContext.makeSpirvInstruction($2.loc, *$1.string, $3.i); - } - -%% diff --git a/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp b/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp deleted file mode 100644 index 5038bebe..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp +++ /dev/null @@ -1,12675 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.8.2. */ - -/* Bison implementation for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, - Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* C LALR(1) parser skeleton written by Richard Stallman, by - simplifying the original so-called "semantic" parser. */ - -/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, - especially those whose name start with YY_ or yy_. They are - private implementation details that can be changed or removed. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output, and Bison version. */ -#define YYBISON 30802 - -/* Bison version string. */ -#define YYBISON_VERSION "3.8.2" - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 1 - -/* Push parsers. */ -#define YYPUSH 0 - -/* Pull parsers. */ -#define YYPULL 1 - - - - -/* First part of user prologue. */ -#line 44 "MachineIndependent/glslang.y" - - -/* Based on: -ANSI C Yacc grammar - -In 1985, Jeff Lee published his Yacc grammar (which is accompanied by a -matching Lex specification) for the April 30, 1985 draft version of the -ANSI C standard. Tom Stockfisch reposted it to net.sources in 1987; that -original, as mentioned in the answer to question 17.25 of the comp.lang.c -FAQ, can be ftp'ed from ftp.uu.net, file usenet/net.sources/ansi.c.grammar.Z. - -I intend to keep this version as close to the current C Standard grammar as -possible; please let me know if you discover discrepancies. - -Jutta Degener, 1995 -*/ - -#include "SymbolTable.h" -#include "ParseHelper.h" -#include "../Public/ShaderLang.h" -#include "attribute.h" - -using namespace glslang; - - -#line 97 "MachineIndependent/glslang_tab.cpp" - -# ifndef YY_CAST -# ifdef __cplusplus -# define YY_CAST(Type, Val) static_cast (Val) -# define YY_REINTERPRET_CAST(Type, Val) reinterpret_cast (Val) -# else -# define YY_CAST(Type, Val) ((Type) (Val)) -# define YY_REINTERPRET_CAST(Type, Val) ((Type) (Val)) -# endif -# endif -# ifndef YY_NULLPTR -# if defined __cplusplus -# if 201103L <= __cplusplus -# define YY_NULLPTR nullptr -# else -# define YY_NULLPTR 0 -# endif -# else -# define YY_NULLPTR ((void*)0) -# endif -# endif - -#include "glslang_tab.cpp.h" -/* Symbol kind. */ -enum yysymbol_kind_t -{ - YYSYMBOL_YYEMPTY = -2, - YYSYMBOL_YYEOF = 0, /* "end of file" */ - YYSYMBOL_YYerror = 1, /* error */ - YYSYMBOL_YYUNDEF = 2, /* "invalid token" */ - YYSYMBOL_CONST = 3, /* CONST */ - YYSYMBOL_BOOL = 4, /* BOOL */ - YYSYMBOL_INT = 5, /* INT */ - YYSYMBOL_UINT = 6, /* UINT */ - YYSYMBOL_FLOAT = 7, /* FLOAT */ - YYSYMBOL_BVEC2 = 8, /* BVEC2 */ - YYSYMBOL_BVEC3 = 9, /* BVEC3 */ - YYSYMBOL_BVEC4 = 10, /* BVEC4 */ - YYSYMBOL_IVEC2 = 11, /* IVEC2 */ - YYSYMBOL_IVEC3 = 12, /* IVEC3 */ - YYSYMBOL_IVEC4 = 13, /* IVEC4 */ - YYSYMBOL_UVEC2 = 14, /* UVEC2 */ - YYSYMBOL_UVEC3 = 15, /* UVEC3 */ - YYSYMBOL_UVEC4 = 16, /* UVEC4 */ - YYSYMBOL_VEC2 = 17, /* VEC2 */ - YYSYMBOL_VEC3 = 18, /* VEC3 */ - YYSYMBOL_VEC4 = 19, /* VEC4 */ - YYSYMBOL_MAT2 = 20, /* MAT2 */ - YYSYMBOL_MAT3 = 21, /* MAT3 */ - YYSYMBOL_MAT4 = 22, /* MAT4 */ - YYSYMBOL_MAT2X2 = 23, /* MAT2X2 */ - YYSYMBOL_MAT2X3 = 24, /* MAT2X3 */ - YYSYMBOL_MAT2X4 = 25, /* MAT2X4 */ - YYSYMBOL_MAT3X2 = 26, /* MAT3X2 */ - YYSYMBOL_MAT3X3 = 27, /* MAT3X3 */ - YYSYMBOL_MAT3X4 = 28, /* MAT3X4 */ - YYSYMBOL_MAT4X2 = 29, /* MAT4X2 */ - YYSYMBOL_MAT4X3 = 30, /* MAT4X3 */ - YYSYMBOL_MAT4X4 = 31, /* MAT4X4 */ - YYSYMBOL_SAMPLER2D = 32, /* SAMPLER2D */ - YYSYMBOL_SAMPLER3D = 33, /* SAMPLER3D */ - YYSYMBOL_SAMPLERCUBE = 34, /* SAMPLERCUBE */ - YYSYMBOL_SAMPLER2DSHADOW = 35, /* SAMPLER2DSHADOW */ - YYSYMBOL_SAMPLERCUBESHADOW = 36, /* SAMPLERCUBESHADOW */ - YYSYMBOL_SAMPLER2DARRAY = 37, /* SAMPLER2DARRAY */ - YYSYMBOL_SAMPLER2DARRAYSHADOW = 38, /* SAMPLER2DARRAYSHADOW */ - YYSYMBOL_ISAMPLER2D = 39, /* ISAMPLER2D */ - YYSYMBOL_ISAMPLER3D = 40, /* ISAMPLER3D */ - YYSYMBOL_ISAMPLERCUBE = 41, /* ISAMPLERCUBE */ - YYSYMBOL_ISAMPLER2DARRAY = 42, /* ISAMPLER2DARRAY */ - YYSYMBOL_USAMPLER2D = 43, /* USAMPLER2D */ - YYSYMBOL_USAMPLER3D = 44, /* USAMPLER3D */ - YYSYMBOL_USAMPLERCUBE = 45, /* USAMPLERCUBE */ - YYSYMBOL_USAMPLER2DARRAY = 46, /* USAMPLER2DARRAY */ - YYSYMBOL_SAMPLER = 47, /* SAMPLER */ - YYSYMBOL_SAMPLERSHADOW = 48, /* SAMPLERSHADOW */ - YYSYMBOL_TEXTURE2D = 49, /* TEXTURE2D */ - YYSYMBOL_TEXTURE3D = 50, /* TEXTURE3D */ - YYSYMBOL_TEXTURECUBE = 51, /* TEXTURECUBE */ - YYSYMBOL_TEXTURE2DARRAY = 52, /* TEXTURE2DARRAY */ - YYSYMBOL_ITEXTURE2D = 53, /* ITEXTURE2D */ - YYSYMBOL_ITEXTURE3D = 54, /* ITEXTURE3D */ - YYSYMBOL_ITEXTURECUBE = 55, /* ITEXTURECUBE */ - YYSYMBOL_ITEXTURE2DARRAY = 56, /* ITEXTURE2DARRAY */ - YYSYMBOL_UTEXTURE2D = 57, /* UTEXTURE2D */ - YYSYMBOL_UTEXTURE3D = 58, /* UTEXTURE3D */ - YYSYMBOL_UTEXTURECUBE = 59, /* UTEXTURECUBE */ - YYSYMBOL_UTEXTURE2DARRAY = 60, /* UTEXTURE2DARRAY */ - YYSYMBOL_ATTRIBUTE = 61, /* ATTRIBUTE */ - YYSYMBOL_VARYING = 62, /* VARYING */ - YYSYMBOL_FLOAT16_T = 63, /* FLOAT16_T */ - YYSYMBOL_FLOAT32_T = 64, /* FLOAT32_T */ - YYSYMBOL_DOUBLE = 65, /* DOUBLE */ - YYSYMBOL_FLOAT64_T = 66, /* FLOAT64_T */ - YYSYMBOL_INT64_T = 67, /* INT64_T */ - YYSYMBOL_UINT64_T = 68, /* UINT64_T */ - YYSYMBOL_INT32_T = 69, /* INT32_T */ - YYSYMBOL_UINT32_T = 70, /* UINT32_T */ - YYSYMBOL_INT16_T = 71, /* INT16_T */ - YYSYMBOL_UINT16_T = 72, /* UINT16_T */ - YYSYMBOL_INT8_T = 73, /* INT8_T */ - YYSYMBOL_UINT8_T = 74, /* UINT8_T */ - YYSYMBOL_I64VEC2 = 75, /* I64VEC2 */ - YYSYMBOL_I64VEC3 = 76, /* I64VEC3 */ - YYSYMBOL_I64VEC4 = 77, /* I64VEC4 */ - YYSYMBOL_U64VEC2 = 78, /* U64VEC2 */ - YYSYMBOL_U64VEC3 = 79, /* U64VEC3 */ - YYSYMBOL_U64VEC4 = 80, /* U64VEC4 */ - YYSYMBOL_I32VEC2 = 81, /* I32VEC2 */ - YYSYMBOL_I32VEC3 = 82, /* I32VEC3 */ - YYSYMBOL_I32VEC4 = 83, /* I32VEC4 */ - YYSYMBOL_U32VEC2 = 84, /* U32VEC2 */ - YYSYMBOL_U32VEC3 = 85, /* U32VEC3 */ - YYSYMBOL_U32VEC4 = 86, /* U32VEC4 */ - YYSYMBOL_I16VEC2 = 87, /* I16VEC2 */ - YYSYMBOL_I16VEC3 = 88, /* I16VEC3 */ - YYSYMBOL_I16VEC4 = 89, /* I16VEC4 */ - YYSYMBOL_U16VEC2 = 90, /* U16VEC2 */ - YYSYMBOL_U16VEC3 = 91, /* U16VEC3 */ - YYSYMBOL_U16VEC4 = 92, /* U16VEC4 */ - YYSYMBOL_I8VEC2 = 93, /* I8VEC2 */ - YYSYMBOL_I8VEC3 = 94, /* I8VEC3 */ - YYSYMBOL_I8VEC4 = 95, /* I8VEC4 */ - YYSYMBOL_U8VEC2 = 96, /* U8VEC2 */ - YYSYMBOL_U8VEC3 = 97, /* U8VEC3 */ - YYSYMBOL_U8VEC4 = 98, /* U8VEC4 */ - YYSYMBOL_DVEC2 = 99, /* DVEC2 */ - YYSYMBOL_DVEC3 = 100, /* DVEC3 */ - YYSYMBOL_DVEC4 = 101, /* DVEC4 */ - YYSYMBOL_DMAT2 = 102, /* DMAT2 */ - YYSYMBOL_DMAT3 = 103, /* DMAT3 */ - YYSYMBOL_DMAT4 = 104, /* DMAT4 */ - YYSYMBOL_F16VEC2 = 105, /* F16VEC2 */ - YYSYMBOL_F16VEC3 = 106, /* F16VEC3 */ - YYSYMBOL_F16VEC4 = 107, /* F16VEC4 */ - YYSYMBOL_F16MAT2 = 108, /* F16MAT2 */ - YYSYMBOL_F16MAT3 = 109, /* F16MAT3 */ - YYSYMBOL_F16MAT4 = 110, /* F16MAT4 */ - YYSYMBOL_F32VEC2 = 111, /* F32VEC2 */ - YYSYMBOL_F32VEC3 = 112, /* F32VEC3 */ - YYSYMBOL_F32VEC4 = 113, /* F32VEC4 */ - YYSYMBOL_F32MAT2 = 114, /* F32MAT2 */ - YYSYMBOL_F32MAT3 = 115, /* F32MAT3 */ - YYSYMBOL_F32MAT4 = 116, /* F32MAT4 */ - YYSYMBOL_F64VEC2 = 117, /* F64VEC2 */ - YYSYMBOL_F64VEC3 = 118, /* F64VEC3 */ - YYSYMBOL_F64VEC4 = 119, /* F64VEC4 */ - YYSYMBOL_F64MAT2 = 120, /* F64MAT2 */ - YYSYMBOL_F64MAT3 = 121, /* F64MAT3 */ - YYSYMBOL_F64MAT4 = 122, /* F64MAT4 */ - YYSYMBOL_DMAT2X2 = 123, /* DMAT2X2 */ - YYSYMBOL_DMAT2X3 = 124, /* DMAT2X3 */ - YYSYMBOL_DMAT2X4 = 125, /* DMAT2X4 */ - YYSYMBOL_DMAT3X2 = 126, /* DMAT3X2 */ - YYSYMBOL_DMAT3X3 = 127, /* DMAT3X3 */ - YYSYMBOL_DMAT3X4 = 128, /* DMAT3X4 */ - YYSYMBOL_DMAT4X2 = 129, /* DMAT4X2 */ - YYSYMBOL_DMAT4X3 = 130, /* DMAT4X3 */ - YYSYMBOL_DMAT4X4 = 131, /* DMAT4X4 */ - YYSYMBOL_F16MAT2X2 = 132, /* F16MAT2X2 */ - YYSYMBOL_F16MAT2X3 = 133, /* F16MAT2X3 */ - YYSYMBOL_F16MAT2X4 = 134, /* F16MAT2X4 */ - YYSYMBOL_F16MAT3X2 = 135, /* F16MAT3X2 */ - YYSYMBOL_F16MAT3X3 = 136, /* F16MAT3X3 */ - YYSYMBOL_F16MAT3X4 = 137, /* F16MAT3X4 */ - YYSYMBOL_F16MAT4X2 = 138, /* F16MAT4X2 */ - YYSYMBOL_F16MAT4X3 = 139, /* F16MAT4X3 */ - YYSYMBOL_F16MAT4X4 = 140, /* F16MAT4X4 */ - YYSYMBOL_F32MAT2X2 = 141, /* F32MAT2X2 */ - YYSYMBOL_F32MAT2X3 = 142, /* F32MAT2X3 */ - YYSYMBOL_F32MAT2X4 = 143, /* F32MAT2X4 */ - YYSYMBOL_F32MAT3X2 = 144, /* F32MAT3X2 */ - YYSYMBOL_F32MAT3X3 = 145, /* F32MAT3X3 */ - YYSYMBOL_F32MAT3X4 = 146, /* F32MAT3X4 */ - YYSYMBOL_F32MAT4X2 = 147, /* F32MAT4X2 */ - YYSYMBOL_F32MAT4X3 = 148, /* F32MAT4X3 */ - YYSYMBOL_F32MAT4X4 = 149, /* F32MAT4X4 */ - YYSYMBOL_F64MAT2X2 = 150, /* F64MAT2X2 */ - YYSYMBOL_F64MAT2X3 = 151, /* F64MAT2X3 */ - YYSYMBOL_F64MAT2X4 = 152, /* F64MAT2X4 */ - YYSYMBOL_F64MAT3X2 = 153, /* F64MAT3X2 */ - YYSYMBOL_F64MAT3X3 = 154, /* F64MAT3X3 */ - YYSYMBOL_F64MAT3X4 = 155, /* F64MAT3X4 */ - YYSYMBOL_F64MAT4X2 = 156, /* F64MAT4X2 */ - YYSYMBOL_F64MAT4X3 = 157, /* F64MAT4X3 */ - YYSYMBOL_F64MAT4X4 = 158, /* F64MAT4X4 */ - YYSYMBOL_ATOMIC_UINT = 159, /* ATOMIC_UINT */ - YYSYMBOL_ACCSTRUCTNV = 160, /* ACCSTRUCTNV */ - YYSYMBOL_ACCSTRUCTEXT = 161, /* ACCSTRUCTEXT */ - YYSYMBOL_RAYQUERYEXT = 162, /* RAYQUERYEXT */ - YYSYMBOL_FCOOPMATNV = 163, /* FCOOPMATNV */ - YYSYMBOL_ICOOPMATNV = 164, /* ICOOPMATNV */ - YYSYMBOL_UCOOPMATNV = 165, /* UCOOPMATNV */ - YYSYMBOL_COOPMAT = 166, /* COOPMAT */ - YYSYMBOL_HITOBJECTNV = 167, /* HITOBJECTNV */ - YYSYMBOL_HITOBJECTATTRNV = 168, /* HITOBJECTATTRNV */ - YYSYMBOL_SAMPLERCUBEARRAY = 169, /* SAMPLERCUBEARRAY */ - YYSYMBOL_SAMPLERCUBEARRAYSHADOW = 170, /* SAMPLERCUBEARRAYSHADOW */ - YYSYMBOL_ISAMPLERCUBEARRAY = 171, /* ISAMPLERCUBEARRAY */ - YYSYMBOL_USAMPLERCUBEARRAY = 172, /* USAMPLERCUBEARRAY */ - YYSYMBOL_SAMPLER1D = 173, /* SAMPLER1D */ - YYSYMBOL_SAMPLER1DARRAY = 174, /* SAMPLER1DARRAY */ - YYSYMBOL_SAMPLER1DARRAYSHADOW = 175, /* SAMPLER1DARRAYSHADOW */ - YYSYMBOL_ISAMPLER1D = 176, /* ISAMPLER1D */ - YYSYMBOL_SAMPLER1DSHADOW = 177, /* SAMPLER1DSHADOW */ - YYSYMBOL_SAMPLER2DRECT = 178, /* SAMPLER2DRECT */ - YYSYMBOL_SAMPLER2DRECTSHADOW = 179, /* SAMPLER2DRECTSHADOW */ - YYSYMBOL_ISAMPLER2DRECT = 180, /* ISAMPLER2DRECT */ - YYSYMBOL_USAMPLER2DRECT = 181, /* USAMPLER2DRECT */ - YYSYMBOL_SAMPLERBUFFER = 182, /* SAMPLERBUFFER */ - YYSYMBOL_ISAMPLERBUFFER = 183, /* ISAMPLERBUFFER */ - YYSYMBOL_USAMPLERBUFFER = 184, /* USAMPLERBUFFER */ - YYSYMBOL_SAMPLER2DMS = 185, /* SAMPLER2DMS */ - YYSYMBOL_ISAMPLER2DMS = 186, /* ISAMPLER2DMS */ - YYSYMBOL_USAMPLER2DMS = 187, /* USAMPLER2DMS */ - YYSYMBOL_SAMPLER2DMSARRAY = 188, /* SAMPLER2DMSARRAY */ - YYSYMBOL_ISAMPLER2DMSARRAY = 189, /* ISAMPLER2DMSARRAY */ - YYSYMBOL_USAMPLER2DMSARRAY = 190, /* USAMPLER2DMSARRAY */ - YYSYMBOL_SAMPLEREXTERNALOES = 191, /* SAMPLEREXTERNALOES */ - YYSYMBOL_SAMPLEREXTERNAL2DY2YEXT = 192, /* SAMPLEREXTERNAL2DY2YEXT */ - YYSYMBOL_ISAMPLER1DARRAY = 193, /* ISAMPLER1DARRAY */ - YYSYMBOL_USAMPLER1D = 194, /* USAMPLER1D */ - YYSYMBOL_USAMPLER1DARRAY = 195, /* USAMPLER1DARRAY */ - YYSYMBOL_F16SAMPLER1D = 196, /* F16SAMPLER1D */ - YYSYMBOL_F16SAMPLER2D = 197, /* F16SAMPLER2D */ - YYSYMBOL_F16SAMPLER3D = 198, /* F16SAMPLER3D */ - YYSYMBOL_F16SAMPLER2DRECT = 199, /* F16SAMPLER2DRECT */ - YYSYMBOL_F16SAMPLERCUBE = 200, /* F16SAMPLERCUBE */ - YYSYMBOL_F16SAMPLER1DARRAY = 201, /* F16SAMPLER1DARRAY */ - YYSYMBOL_F16SAMPLER2DARRAY = 202, /* F16SAMPLER2DARRAY */ - YYSYMBOL_F16SAMPLERCUBEARRAY = 203, /* F16SAMPLERCUBEARRAY */ - YYSYMBOL_F16SAMPLERBUFFER = 204, /* F16SAMPLERBUFFER */ - YYSYMBOL_F16SAMPLER2DMS = 205, /* F16SAMPLER2DMS */ - YYSYMBOL_F16SAMPLER2DMSARRAY = 206, /* F16SAMPLER2DMSARRAY */ - YYSYMBOL_F16SAMPLER1DSHADOW = 207, /* F16SAMPLER1DSHADOW */ - YYSYMBOL_F16SAMPLER2DSHADOW = 208, /* F16SAMPLER2DSHADOW */ - YYSYMBOL_F16SAMPLER1DARRAYSHADOW = 209, /* F16SAMPLER1DARRAYSHADOW */ - YYSYMBOL_F16SAMPLER2DARRAYSHADOW = 210, /* F16SAMPLER2DARRAYSHADOW */ - YYSYMBOL_F16SAMPLER2DRECTSHADOW = 211, /* F16SAMPLER2DRECTSHADOW */ - YYSYMBOL_F16SAMPLERCUBESHADOW = 212, /* F16SAMPLERCUBESHADOW */ - YYSYMBOL_F16SAMPLERCUBEARRAYSHADOW = 213, /* F16SAMPLERCUBEARRAYSHADOW */ - YYSYMBOL_IMAGE1D = 214, /* IMAGE1D */ - YYSYMBOL_IIMAGE1D = 215, /* IIMAGE1D */ - YYSYMBOL_UIMAGE1D = 216, /* UIMAGE1D */ - YYSYMBOL_IMAGE2D = 217, /* IMAGE2D */ - YYSYMBOL_IIMAGE2D = 218, /* IIMAGE2D */ - YYSYMBOL_UIMAGE2D = 219, /* UIMAGE2D */ - YYSYMBOL_IMAGE3D = 220, /* IMAGE3D */ - YYSYMBOL_IIMAGE3D = 221, /* IIMAGE3D */ - YYSYMBOL_UIMAGE3D = 222, /* UIMAGE3D */ - YYSYMBOL_IMAGE2DRECT = 223, /* IMAGE2DRECT */ - YYSYMBOL_IIMAGE2DRECT = 224, /* IIMAGE2DRECT */ - YYSYMBOL_UIMAGE2DRECT = 225, /* UIMAGE2DRECT */ - YYSYMBOL_IMAGECUBE = 226, /* IMAGECUBE */ - YYSYMBOL_IIMAGECUBE = 227, /* IIMAGECUBE */ - YYSYMBOL_UIMAGECUBE = 228, /* UIMAGECUBE */ - YYSYMBOL_IMAGEBUFFER = 229, /* IMAGEBUFFER */ - YYSYMBOL_IIMAGEBUFFER = 230, /* IIMAGEBUFFER */ - YYSYMBOL_UIMAGEBUFFER = 231, /* UIMAGEBUFFER */ - YYSYMBOL_IMAGE1DARRAY = 232, /* IMAGE1DARRAY */ - YYSYMBOL_IIMAGE1DARRAY = 233, /* IIMAGE1DARRAY */ - YYSYMBOL_UIMAGE1DARRAY = 234, /* UIMAGE1DARRAY */ - YYSYMBOL_IMAGE2DARRAY = 235, /* IMAGE2DARRAY */ - YYSYMBOL_IIMAGE2DARRAY = 236, /* IIMAGE2DARRAY */ - YYSYMBOL_UIMAGE2DARRAY = 237, /* UIMAGE2DARRAY */ - YYSYMBOL_IMAGECUBEARRAY = 238, /* IMAGECUBEARRAY */ - YYSYMBOL_IIMAGECUBEARRAY = 239, /* IIMAGECUBEARRAY */ - YYSYMBOL_UIMAGECUBEARRAY = 240, /* UIMAGECUBEARRAY */ - YYSYMBOL_IMAGE2DMS = 241, /* IMAGE2DMS */ - YYSYMBOL_IIMAGE2DMS = 242, /* IIMAGE2DMS */ - YYSYMBOL_UIMAGE2DMS = 243, /* UIMAGE2DMS */ - YYSYMBOL_IMAGE2DMSARRAY = 244, /* IMAGE2DMSARRAY */ - YYSYMBOL_IIMAGE2DMSARRAY = 245, /* IIMAGE2DMSARRAY */ - YYSYMBOL_UIMAGE2DMSARRAY = 246, /* UIMAGE2DMSARRAY */ - YYSYMBOL_F16IMAGE1D = 247, /* F16IMAGE1D */ - YYSYMBOL_F16IMAGE2D = 248, /* F16IMAGE2D */ - YYSYMBOL_F16IMAGE3D = 249, /* F16IMAGE3D */ - YYSYMBOL_F16IMAGE2DRECT = 250, /* F16IMAGE2DRECT */ - YYSYMBOL_F16IMAGECUBE = 251, /* F16IMAGECUBE */ - YYSYMBOL_F16IMAGE1DARRAY = 252, /* F16IMAGE1DARRAY */ - YYSYMBOL_F16IMAGE2DARRAY = 253, /* F16IMAGE2DARRAY */ - YYSYMBOL_F16IMAGECUBEARRAY = 254, /* F16IMAGECUBEARRAY */ - YYSYMBOL_F16IMAGEBUFFER = 255, /* F16IMAGEBUFFER */ - YYSYMBOL_F16IMAGE2DMS = 256, /* F16IMAGE2DMS */ - YYSYMBOL_F16IMAGE2DMSARRAY = 257, /* F16IMAGE2DMSARRAY */ - YYSYMBOL_I64IMAGE1D = 258, /* I64IMAGE1D */ - YYSYMBOL_U64IMAGE1D = 259, /* U64IMAGE1D */ - YYSYMBOL_I64IMAGE2D = 260, /* I64IMAGE2D */ - YYSYMBOL_U64IMAGE2D = 261, /* U64IMAGE2D */ - YYSYMBOL_I64IMAGE3D = 262, /* I64IMAGE3D */ - YYSYMBOL_U64IMAGE3D = 263, /* U64IMAGE3D */ - YYSYMBOL_I64IMAGE2DRECT = 264, /* I64IMAGE2DRECT */ - YYSYMBOL_U64IMAGE2DRECT = 265, /* U64IMAGE2DRECT */ - YYSYMBOL_I64IMAGECUBE = 266, /* I64IMAGECUBE */ - YYSYMBOL_U64IMAGECUBE = 267, /* U64IMAGECUBE */ - YYSYMBOL_I64IMAGEBUFFER = 268, /* I64IMAGEBUFFER */ - YYSYMBOL_U64IMAGEBUFFER = 269, /* U64IMAGEBUFFER */ - YYSYMBOL_I64IMAGE1DARRAY = 270, /* I64IMAGE1DARRAY */ - YYSYMBOL_U64IMAGE1DARRAY = 271, /* U64IMAGE1DARRAY */ - YYSYMBOL_I64IMAGE2DARRAY = 272, /* I64IMAGE2DARRAY */ - YYSYMBOL_U64IMAGE2DARRAY = 273, /* U64IMAGE2DARRAY */ - YYSYMBOL_I64IMAGECUBEARRAY = 274, /* I64IMAGECUBEARRAY */ - YYSYMBOL_U64IMAGECUBEARRAY = 275, /* U64IMAGECUBEARRAY */ - YYSYMBOL_I64IMAGE2DMS = 276, /* I64IMAGE2DMS */ - YYSYMBOL_U64IMAGE2DMS = 277, /* U64IMAGE2DMS */ - YYSYMBOL_I64IMAGE2DMSARRAY = 278, /* I64IMAGE2DMSARRAY */ - YYSYMBOL_U64IMAGE2DMSARRAY = 279, /* U64IMAGE2DMSARRAY */ - YYSYMBOL_TEXTURECUBEARRAY = 280, /* TEXTURECUBEARRAY */ - YYSYMBOL_ITEXTURECUBEARRAY = 281, /* ITEXTURECUBEARRAY */ - YYSYMBOL_UTEXTURECUBEARRAY = 282, /* UTEXTURECUBEARRAY */ - YYSYMBOL_TEXTURE1D = 283, /* TEXTURE1D */ - YYSYMBOL_ITEXTURE1D = 284, /* ITEXTURE1D */ - YYSYMBOL_UTEXTURE1D = 285, /* UTEXTURE1D */ - YYSYMBOL_TEXTURE1DARRAY = 286, /* TEXTURE1DARRAY */ - YYSYMBOL_ITEXTURE1DARRAY = 287, /* ITEXTURE1DARRAY */ - YYSYMBOL_UTEXTURE1DARRAY = 288, /* UTEXTURE1DARRAY */ - YYSYMBOL_TEXTURE2DRECT = 289, /* TEXTURE2DRECT */ - YYSYMBOL_ITEXTURE2DRECT = 290, /* ITEXTURE2DRECT */ - YYSYMBOL_UTEXTURE2DRECT = 291, /* UTEXTURE2DRECT */ - YYSYMBOL_TEXTUREBUFFER = 292, /* TEXTUREBUFFER */ - YYSYMBOL_ITEXTUREBUFFER = 293, /* ITEXTUREBUFFER */ - YYSYMBOL_UTEXTUREBUFFER = 294, /* UTEXTUREBUFFER */ - YYSYMBOL_TEXTURE2DMS = 295, /* TEXTURE2DMS */ - YYSYMBOL_ITEXTURE2DMS = 296, /* ITEXTURE2DMS */ - YYSYMBOL_UTEXTURE2DMS = 297, /* UTEXTURE2DMS */ - YYSYMBOL_TEXTURE2DMSARRAY = 298, /* TEXTURE2DMSARRAY */ - YYSYMBOL_ITEXTURE2DMSARRAY = 299, /* ITEXTURE2DMSARRAY */ - YYSYMBOL_UTEXTURE2DMSARRAY = 300, /* UTEXTURE2DMSARRAY */ - YYSYMBOL_F16TEXTURE1D = 301, /* F16TEXTURE1D */ - YYSYMBOL_F16TEXTURE2D = 302, /* F16TEXTURE2D */ - YYSYMBOL_F16TEXTURE3D = 303, /* F16TEXTURE3D */ - YYSYMBOL_F16TEXTURE2DRECT = 304, /* F16TEXTURE2DRECT */ - YYSYMBOL_F16TEXTURECUBE = 305, /* F16TEXTURECUBE */ - YYSYMBOL_F16TEXTURE1DARRAY = 306, /* F16TEXTURE1DARRAY */ - YYSYMBOL_F16TEXTURE2DARRAY = 307, /* F16TEXTURE2DARRAY */ - YYSYMBOL_F16TEXTURECUBEARRAY = 308, /* F16TEXTURECUBEARRAY */ - YYSYMBOL_F16TEXTUREBUFFER = 309, /* F16TEXTUREBUFFER */ - YYSYMBOL_F16TEXTURE2DMS = 310, /* F16TEXTURE2DMS */ - YYSYMBOL_F16TEXTURE2DMSARRAY = 311, /* F16TEXTURE2DMSARRAY */ - YYSYMBOL_SUBPASSINPUT = 312, /* SUBPASSINPUT */ - YYSYMBOL_SUBPASSINPUTMS = 313, /* SUBPASSINPUTMS */ - YYSYMBOL_ISUBPASSINPUT = 314, /* ISUBPASSINPUT */ - YYSYMBOL_ISUBPASSINPUTMS = 315, /* ISUBPASSINPUTMS */ - YYSYMBOL_USUBPASSINPUT = 316, /* USUBPASSINPUT */ - YYSYMBOL_USUBPASSINPUTMS = 317, /* USUBPASSINPUTMS */ - YYSYMBOL_F16SUBPASSINPUT = 318, /* F16SUBPASSINPUT */ - YYSYMBOL_F16SUBPASSINPUTMS = 319, /* F16SUBPASSINPUTMS */ - YYSYMBOL_SPIRV_INSTRUCTION = 320, /* SPIRV_INSTRUCTION */ - YYSYMBOL_SPIRV_EXECUTION_MODE = 321, /* SPIRV_EXECUTION_MODE */ - YYSYMBOL_SPIRV_EXECUTION_MODE_ID = 322, /* SPIRV_EXECUTION_MODE_ID */ - YYSYMBOL_SPIRV_DECORATE = 323, /* SPIRV_DECORATE */ - YYSYMBOL_SPIRV_DECORATE_ID = 324, /* SPIRV_DECORATE_ID */ - YYSYMBOL_SPIRV_DECORATE_STRING = 325, /* SPIRV_DECORATE_STRING */ - YYSYMBOL_SPIRV_TYPE = 326, /* SPIRV_TYPE */ - YYSYMBOL_SPIRV_STORAGE_CLASS = 327, /* SPIRV_STORAGE_CLASS */ - YYSYMBOL_SPIRV_BY_REFERENCE = 328, /* SPIRV_BY_REFERENCE */ - YYSYMBOL_SPIRV_LITERAL = 329, /* SPIRV_LITERAL */ - YYSYMBOL_ATTACHMENTEXT = 330, /* ATTACHMENTEXT */ - YYSYMBOL_IATTACHMENTEXT = 331, /* IATTACHMENTEXT */ - YYSYMBOL_UATTACHMENTEXT = 332, /* UATTACHMENTEXT */ - YYSYMBOL_LEFT_OP = 333, /* LEFT_OP */ - YYSYMBOL_RIGHT_OP = 334, /* RIGHT_OP */ - YYSYMBOL_INC_OP = 335, /* INC_OP */ - YYSYMBOL_DEC_OP = 336, /* DEC_OP */ - YYSYMBOL_LE_OP = 337, /* LE_OP */ - YYSYMBOL_GE_OP = 338, /* GE_OP */ - YYSYMBOL_EQ_OP = 339, /* EQ_OP */ - YYSYMBOL_NE_OP = 340, /* NE_OP */ - YYSYMBOL_AND_OP = 341, /* AND_OP */ - YYSYMBOL_OR_OP = 342, /* OR_OP */ - YYSYMBOL_XOR_OP = 343, /* XOR_OP */ - YYSYMBOL_MUL_ASSIGN = 344, /* MUL_ASSIGN */ - YYSYMBOL_DIV_ASSIGN = 345, /* DIV_ASSIGN */ - YYSYMBOL_ADD_ASSIGN = 346, /* ADD_ASSIGN */ - YYSYMBOL_MOD_ASSIGN = 347, /* MOD_ASSIGN */ - YYSYMBOL_LEFT_ASSIGN = 348, /* LEFT_ASSIGN */ - YYSYMBOL_RIGHT_ASSIGN = 349, /* RIGHT_ASSIGN */ - YYSYMBOL_AND_ASSIGN = 350, /* AND_ASSIGN */ - YYSYMBOL_XOR_ASSIGN = 351, /* XOR_ASSIGN */ - YYSYMBOL_OR_ASSIGN = 352, /* OR_ASSIGN */ - YYSYMBOL_SUB_ASSIGN = 353, /* SUB_ASSIGN */ - YYSYMBOL_STRING_LITERAL = 354, /* STRING_LITERAL */ - YYSYMBOL_LEFT_PAREN = 355, /* LEFT_PAREN */ - YYSYMBOL_RIGHT_PAREN = 356, /* RIGHT_PAREN */ - YYSYMBOL_LEFT_BRACKET = 357, /* LEFT_BRACKET */ - YYSYMBOL_RIGHT_BRACKET = 358, /* RIGHT_BRACKET */ - YYSYMBOL_LEFT_BRACE = 359, /* LEFT_BRACE */ - YYSYMBOL_RIGHT_BRACE = 360, /* RIGHT_BRACE */ - YYSYMBOL_DOT = 361, /* DOT */ - YYSYMBOL_COMMA = 362, /* COMMA */ - YYSYMBOL_COLON = 363, /* COLON */ - YYSYMBOL_EQUAL = 364, /* EQUAL */ - YYSYMBOL_SEMICOLON = 365, /* SEMICOLON */ - YYSYMBOL_BANG = 366, /* BANG */ - YYSYMBOL_DASH = 367, /* DASH */ - YYSYMBOL_TILDE = 368, /* TILDE */ - YYSYMBOL_PLUS = 369, /* PLUS */ - YYSYMBOL_STAR = 370, /* STAR */ - YYSYMBOL_SLASH = 371, /* SLASH */ - YYSYMBOL_PERCENT = 372, /* PERCENT */ - YYSYMBOL_LEFT_ANGLE = 373, /* LEFT_ANGLE */ - YYSYMBOL_RIGHT_ANGLE = 374, /* RIGHT_ANGLE */ - YYSYMBOL_VERTICAL_BAR = 375, /* VERTICAL_BAR */ - YYSYMBOL_CARET = 376, /* CARET */ - YYSYMBOL_AMPERSAND = 377, /* AMPERSAND */ - YYSYMBOL_QUESTION = 378, /* QUESTION */ - YYSYMBOL_INVARIANT = 379, /* INVARIANT */ - YYSYMBOL_HIGH_PRECISION = 380, /* HIGH_PRECISION */ - YYSYMBOL_MEDIUM_PRECISION = 381, /* MEDIUM_PRECISION */ - YYSYMBOL_LOW_PRECISION = 382, /* LOW_PRECISION */ - YYSYMBOL_PRECISION = 383, /* PRECISION */ - YYSYMBOL_PACKED = 384, /* PACKED */ - YYSYMBOL_RESOURCE = 385, /* RESOURCE */ - YYSYMBOL_SUPERP = 386, /* SUPERP */ - YYSYMBOL_FLOATCONSTANT = 387, /* FLOATCONSTANT */ - YYSYMBOL_INTCONSTANT = 388, /* INTCONSTANT */ - YYSYMBOL_UINTCONSTANT = 389, /* UINTCONSTANT */ - YYSYMBOL_BOOLCONSTANT = 390, /* BOOLCONSTANT */ - YYSYMBOL_IDENTIFIER = 391, /* IDENTIFIER */ - YYSYMBOL_TYPE_NAME = 392, /* TYPE_NAME */ - YYSYMBOL_CENTROID = 393, /* CENTROID */ - YYSYMBOL_IN = 394, /* IN */ - YYSYMBOL_OUT = 395, /* OUT */ - YYSYMBOL_INOUT = 396, /* INOUT */ - YYSYMBOL_STRUCT = 397, /* STRUCT */ - YYSYMBOL_VOID = 398, /* VOID */ - YYSYMBOL_WHILE = 399, /* WHILE */ - YYSYMBOL_BREAK = 400, /* BREAK */ - YYSYMBOL_CONTINUE = 401, /* CONTINUE */ - YYSYMBOL_DO = 402, /* DO */ - YYSYMBOL_ELSE = 403, /* ELSE */ - YYSYMBOL_FOR = 404, /* FOR */ - YYSYMBOL_IF = 405, /* IF */ - YYSYMBOL_DISCARD = 406, /* DISCARD */ - YYSYMBOL_RETURN = 407, /* RETURN */ - YYSYMBOL_SWITCH = 408, /* SWITCH */ - YYSYMBOL_CASE = 409, /* CASE */ - YYSYMBOL_DEFAULT = 410, /* DEFAULT */ - YYSYMBOL_TERMINATE_INVOCATION = 411, /* TERMINATE_INVOCATION */ - YYSYMBOL_TERMINATE_RAY = 412, /* TERMINATE_RAY */ - YYSYMBOL_IGNORE_INTERSECTION = 413, /* IGNORE_INTERSECTION */ - YYSYMBOL_UNIFORM = 414, /* UNIFORM */ - YYSYMBOL_SHARED = 415, /* SHARED */ - YYSYMBOL_BUFFER = 416, /* BUFFER */ - YYSYMBOL_TILEIMAGEEXT = 417, /* TILEIMAGEEXT */ - YYSYMBOL_FLAT = 418, /* FLAT */ - YYSYMBOL_SMOOTH = 419, /* SMOOTH */ - YYSYMBOL_LAYOUT = 420, /* LAYOUT */ - YYSYMBOL_DOUBLECONSTANT = 421, /* DOUBLECONSTANT */ - YYSYMBOL_INT16CONSTANT = 422, /* INT16CONSTANT */ - YYSYMBOL_UINT16CONSTANT = 423, /* UINT16CONSTANT */ - YYSYMBOL_FLOAT16CONSTANT = 424, /* FLOAT16CONSTANT */ - YYSYMBOL_INT32CONSTANT = 425, /* INT32CONSTANT */ - YYSYMBOL_UINT32CONSTANT = 426, /* UINT32CONSTANT */ - YYSYMBOL_INT64CONSTANT = 427, /* INT64CONSTANT */ - YYSYMBOL_UINT64CONSTANT = 428, /* UINT64CONSTANT */ - YYSYMBOL_SUBROUTINE = 429, /* SUBROUTINE */ - YYSYMBOL_DEMOTE = 430, /* DEMOTE */ - YYSYMBOL_PAYLOADNV = 431, /* PAYLOADNV */ - YYSYMBOL_PAYLOADINNV = 432, /* PAYLOADINNV */ - YYSYMBOL_HITATTRNV = 433, /* HITATTRNV */ - YYSYMBOL_CALLDATANV = 434, /* CALLDATANV */ - YYSYMBOL_CALLDATAINNV = 435, /* CALLDATAINNV */ - YYSYMBOL_PAYLOADEXT = 436, /* PAYLOADEXT */ - YYSYMBOL_PAYLOADINEXT = 437, /* PAYLOADINEXT */ - YYSYMBOL_HITATTREXT = 438, /* HITATTREXT */ - YYSYMBOL_CALLDATAEXT = 439, /* CALLDATAEXT */ - YYSYMBOL_CALLDATAINEXT = 440, /* CALLDATAINEXT */ - YYSYMBOL_PATCH = 441, /* PATCH */ - YYSYMBOL_SAMPLE = 442, /* SAMPLE */ - YYSYMBOL_NONUNIFORM = 443, /* NONUNIFORM */ - YYSYMBOL_COHERENT = 444, /* COHERENT */ - YYSYMBOL_VOLATILE = 445, /* VOLATILE */ - YYSYMBOL_RESTRICT = 446, /* RESTRICT */ - YYSYMBOL_READONLY = 447, /* READONLY */ - YYSYMBOL_WRITEONLY = 448, /* WRITEONLY */ - YYSYMBOL_DEVICECOHERENT = 449, /* DEVICECOHERENT */ - YYSYMBOL_QUEUEFAMILYCOHERENT = 450, /* QUEUEFAMILYCOHERENT */ - YYSYMBOL_WORKGROUPCOHERENT = 451, /* WORKGROUPCOHERENT */ - YYSYMBOL_SUBGROUPCOHERENT = 452, /* SUBGROUPCOHERENT */ - YYSYMBOL_NONPRIVATE = 453, /* NONPRIVATE */ - YYSYMBOL_SHADERCALLCOHERENT = 454, /* SHADERCALLCOHERENT */ - YYSYMBOL_NOPERSPECTIVE = 455, /* NOPERSPECTIVE */ - YYSYMBOL_EXPLICITINTERPAMD = 456, /* EXPLICITINTERPAMD */ - YYSYMBOL_PERVERTEXEXT = 457, /* PERVERTEXEXT */ - YYSYMBOL_PERVERTEXNV = 458, /* PERVERTEXNV */ - YYSYMBOL_PERPRIMITIVENV = 459, /* PERPRIMITIVENV */ - YYSYMBOL_PERVIEWNV = 460, /* PERVIEWNV */ - YYSYMBOL_PERTASKNV = 461, /* PERTASKNV */ - YYSYMBOL_PERPRIMITIVEEXT = 462, /* PERPRIMITIVEEXT */ - YYSYMBOL_TASKPAYLOADWORKGROUPEXT = 463, /* TASKPAYLOADWORKGROUPEXT */ - YYSYMBOL_PRECISE = 464, /* PRECISE */ - YYSYMBOL_YYACCEPT = 465, /* $accept */ - YYSYMBOL_variable_identifier = 466, /* variable_identifier */ - YYSYMBOL_primary_expression = 467, /* primary_expression */ - YYSYMBOL_postfix_expression = 468, /* postfix_expression */ - YYSYMBOL_integer_expression = 469, /* integer_expression */ - YYSYMBOL_function_call = 470, /* function_call */ - YYSYMBOL_function_call_or_method = 471, /* function_call_or_method */ - YYSYMBOL_function_call_generic = 472, /* function_call_generic */ - YYSYMBOL_function_call_header_no_parameters = 473, /* function_call_header_no_parameters */ - YYSYMBOL_function_call_header_with_parameters = 474, /* function_call_header_with_parameters */ - YYSYMBOL_function_call_header = 475, /* function_call_header */ - YYSYMBOL_function_identifier = 476, /* function_identifier */ - YYSYMBOL_unary_expression = 477, /* unary_expression */ - YYSYMBOL_unary_operator = 478, /* unary_operator */ - YYSYMBOL_multiplicative_expression = 479, /* multiplicative_expression */ - YYSYMBOL_additive_expression = 480, /* additive_expression */ - YYSYMBOL_shift_expression = 481, /* shift_expression */ - YYSYMBOL_relational_expression = 482, /* relational_expression */ - YYSYMBOL_equality_expression = 483, /* equality_expression */ - YYSYMBOL_and_expression = 484, /* and_expression */ - YYSYMBOL_exclusive_or_expression = 485, /* exclusive_or_expression */ - YYSYMBOL_inclusive_or_expression = 486, /* inclusive_or_expression */ - YYSYMBOL_logical_and_expression = 487, /* logical_and_expression */ - YYSYMBOL_logical_xor_expression = 488, /* logical_xor_expression */ - YYSYMBOL_logical_or_expression = 489, /* logical_or_expression */ - YYSYMBOL_conditional_expression = 490, /* conditional_expression */ - YYSYMBOL_491_1 = 491, /* $@1 */ - YYSYMBOL_assignment_expression = 492, /* assignment_expression */ - YYSYMBOL_assignment_operator = 493, /* assignment_operator */ - YYSYMBOL_expression = 494, /* expression */ - YYSYMBOL_constant_expression = 495, /* constant_expression */ - YYSYMBOL_declaration = 496, /* declaration */ - YYSYMBOL_block_structure = 497, /* block_structure */ - YYSYMBOL_498_2 = 498, /* $@2 */ - YYSYMBOL_identifier_list = 499, /* identifier_list */ - YYSYMBOL_function_prototype = 500, /* function_prototype */ - YYSYMBOL_function_declarator = 501, /* function_declarator */ - YYSYMBOL_function_header_with_parameters = 502, /* function_header_with_parameters */ - YYSYMBOL_function_header = 503, /* function_header */ - YYSYMBOL_parameter_declarator = 504, /* parameter_declarator */ - YYSYMBOL_parameter_declaration = 505, /* parameter_declaration */ - YYSYMBOL_parameter_type_specifier = 506, /* parameter_type_specifier */ - YYSYMBOL_init_declarator_list = 507, /* init_declarator_list */ - YYSYMBOL_single_declaration = 508, /* single_declaration */ - YYSYMBOL_fully_specified_type = 509, /* fully_specified_type */ - YYSYMBOL_invariant_qualifier = 510, /* invariant_qualifier */ - YYSYMBOL_interpolation_qualifier = 511, /* interpolation_qualifier */ - YYSYMBOL_layout_qualifier = 512, /* layout_qualifier */ - YYSYMBOL_layout_qualifier_id_list = 513, /* layout_qualifier_id_list */ - YYSYMBOL_layout_qualifier_id = 514, /* layout_qualifier_id */ - YYSYMBOL_precise_qualifier = 515, /* precise_qualifier */ - YYSYMBOL_type_qualifier = 516, /* type_qualifier */ - YYSYMBOL_single_type_qualifier = 517, /* single_type_qualifier */ - YYSYMBOL_storage_qualifier = 518, /* storage_qualifier */ - YYSYMBOL_non_uniform_qualifier = 519, /* non_uniform_qualifier */ - YYSYMBOL_type_name_list = 520, /* type_name_list */ - YYSYMBOL_type_specifier = 521, /* type_specifier */ - YYSYMBOL_array_specifier = 522, /* array_specifier */ - YYSYMBOL_type_parameter_specifier_opt = 523, /* type_parameter_specifier_opt */ - YYSYMBOL_type_parameter_specifier = 524, /* type_parameter_specifier */ - YYSYMBOL_type_parameter_specifier_list = 525, /* type_parameter_specifier_list */ - YYSYMBOL_type_specifier_nonarray = 526, /* type_specifier_nonarray */ - YYSYMBOL_precision_qualifier = 527, /* precision_qualifier */ - YYSYMBOL_struct_specifier = 528, /* struct_specifier */ - YYSYMBOL_529_3 = 529, /* $@3 */ - YYSYMBOL_530_4 = 530, /* $@4 */ - YYSYMBOL_struct_declaration_list = 531, /* struct_declaration_list */ - YYSYMBOL_struct_declaration = 532, /* struct_declaration */ - YYSYMBOL_struct_declarator_list = 533, /* struct_declarator_list */ - YYSYMBOL_struct_declarator = 534, /* struct_declarator */ - YYSYMBOL_initializer = 535, /* initializer */ - YYSYMBOL_initializer_list = 536, /* initializer_list */ - YYSYMBOL_declaration_statement = 537, /* declaration_statement */ - YYSYMBOL_statement = 538, /* statement */ - YYSYMBOL_simple_statement = 539, /* simple_statement */ - YYSYMBOL_demote_statement = 540, /* demote_statement */ - YYSYMBOL_compound_statement = 541, /* compound_statement */ - YYSYMBOL_542_5 = 542, /* $@5 */ - YYSYMBOL_543_6 = 543, /* $@6 */ - YYSYMBOL_statement_no_new_scope = 544, /* statement_no_new_scope */ - YYSYMBOL_statement_scoped = 545, /* statement_scoped */ - YYSYMBOL_546_7 = 546, /* $@7 */ - YYSYMBOL_547_8 = 547, /* $@8 */ - YYSYMBOL_compound_statement_no_new_scope = 548, /* compound_statement_no_new_scope */ - YYSYMBOL_statement_list = 549, /* statement_list */ - YYSYMBOL_expression_statement = 550, /* expression_statement */ - YYSYMBOL_selection_statement = 551, /* selection_statement */ - YYSYMBOL_selection_statement_nonattributed = 552, /* selection_statement_nonattributed */ - YYSYMBOL_selection_rest_statement = 553, /* selection_rest_statement */ - YYSYMBOL_condition = 554, /* condition */ - YYSYMBOL_switch_statement = 555, /* switch_statement */ - YYSYMBOL_switch_statement_nonattributed = 556, /* switch_statement_nonattributed */ - YYSYMBOL_557_9 = 557, /* $@9 */ - YYSYMBOL_switch_statement_list = 558, /* switch_statement_list */ - YYSYMBOL_case_label = 559, /* case_label */ - YYSYMBOL_iteration_statement = 560, /* iteration_statement */ - YYSYMBOL_iteration_statement_nonattributed = 561, /* iteration_statement_nonattributed */ - YYSYMBOL_562_10 = 562, /* $@10 */ - YYSYMBOL_563_11 = 563, /* $@11 */ - YYSYMBOL_564_12 = 564, /* $@12 */ - YYSYMBOL_for_init_statement = 565, /* for_init_statement */ - YYSYMBOL_conditionopt = 566, /* conditionopt */ - YYSYMBOL_for_rest_statement = 567, /* for_rest_statement */ - YYSYMBOL_jump_statement = 568, /* jump_statement */ - YYSYMBOL_translation_unit = 569, /* translation_unit */ - YYSYMBOL_external_declaration = 570, /* external_declaration */ - YYSYMBOL_function_definition = 571, /* function_definition */ - YYSYMBOL_572_13 = 572, /* $@13 */ - YYSYMBOL_attribute = 573, /* attribute */ - YYSYMBOL_attribute_list = 574, /* attribute_list */ - YYSYMBOL_single_attribute = 575, /* single_attribute */ - YYSYMBOL_spirv_requirements_list = 576, /* spirv_requirements_list */ - YYSYMBOL_spirv_requirements_parameter = 577, /* spirv_requirements_parameter */ - YYSYMBOL_spirv_extension_list = 578, /* spirv_extension_list */ - YYSYMBOL_spirv_capability_list = 579, /* spirv_capability_list */ - YYSYMBOL_spirv_execution_mode_qualifier = 580, /* spirv_execution_mode_qualifier */ - YYSYMBOL_spirv_execution_mode_parameter_list = 581, /* spirv_execution_mode_parameter_list */ - YYSYMBOL_spirv_execution_mode_parameter = 582, /* spirv_execution_mode_parameter */ - YYSYMBOL_spirv_execution_mode_id_parameter_list = 583, /* spirv_execution_mode_id_parameter_list */ - YYSYMBOL_spirv_storage_class_qualifier = 584, /* spirv_storage_class_qualifier */ - YYSYMBOL_spirv_decorate_qualifier = 585, /* spirv_decorate_qualifier */ - YYSYMBOL_spirv_decorate_parameter_list = 586, /* spirv_decorate_parameter_list */ - YYSYMBOL_spirv_decorate_parameter = 587, /* spirv_decorate_parameter */ - YYSYMBOL_spirv_decorate_id_parameter_list = 588, /* spirv_decorate_id_parameter_list */ - YYSYMBOL_spirv_decorate_id_parameter = 589, /* spirv_decorate_id_parameter */ - YYSYMBOL_spirv_decorate_string_parameter_list = 590, /* spirv_decorate_string_parameter_list */ - YYSYMBOL_spirv_type_specifier = 591, /* spirv_type_specifier */ - YYSYMBOL_spirv_type_parameter_list = 592, /* spirv_type_parameter_list */ - YYSYMBOL_spirv_type_parameter = 593, /* spirv_type_parameter */ - YYSYMBOL_spirv_instruction_qualifier = 594, /* spirv_instruction_qualifier */ - YYSYMBOL_spirv_instruction_qualifier_list = 595, /* spirv_instruction_qualifier_list */ - YYSYMBOL_spirv_instruction_qualifier_id = 596 /* spirv_instruction_qualifier_id */ -}; -typedef enum yysymbol_kind_t yysymbol_kind_t; - - -/* Second part of user prologue. */ -#line 111 "MachineIndependent/glslang.y" - - -#define parseContext (*pParseContext) -#define yyerror(context, msg) context->parserError(msg) - -extern int yylex(YYSTYPE*, TParseContext&); - - -#line 736 "MachineIndependent/glslang_tab.cpp" - - -#ifdef short -# undef short -#endif - -/* On compilers that do not define __PTRDIFF_MAX__ etc., make sure - and (if available) are included - so that the code can choose integer types of a good width. */ - -#ifndef __PTRDIFF_MAX__ -# include /* INFRINGES ON USER NAME SPACE */ -# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_STDINT_H -# endif -#endif - -/* Narrow types that promote to a signed type and that can represent a - signed or unsigned integer of at least N bits. In tables they can - save space and decrease cache pressure. Promoting to a signed type - helps avoid bugs in integer arithmetic. */ - -#ifdef __INT_LEAST8_MAX__ -typedef __INT_LEAST8_TYPE__ yytype_int8; -#elif defined YY_STDINT_H -typedef int_least8_t yytype_int8; -#else -typedef signed char yytype_int8; -#endif - -#ifdef __INT_LEAST16_MAX__ -typedef __INT_LEAST16_TYPE__ yytype_int16; -#elif defined YY_STDINT_H -typedef int_least16_t yytype_int16; -#else -typedef short yytype_int16; -#endif - -/* Work around bug in HP-UX 11.23, which defines these macros - incorrectly for preprocessor constants. This workaround can likely - be removed in 2023, as HPE has promised support for HP-UX 11.23 - (aka HP-UX 11i v2) only through the end of 2022; see Table 2 of - . */ -#ifdef __hpux -# undef UINT_LEAST8_MAX -# undef UINT_LEAST16_MAX -# define UINT_LEAST8_MAX 255 -# define UINT_LEAST16_MAX 65535 -#endif - -#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ -typedef __UINT_LEAST8_TYPE__ yytype_uint8; -#elif (!defined __UINT_LEAST8_MAX__ && defined YY_STDINT_H \ - && UINT_LEAST8_MAX <= INT_MAX) -typedef uint_least8_t yytype_uint8; -#elif !defined __UINT_LEAST8_MAX__ && UCHAR_MAX <= INT_MAX -typedef unsigned char yytype_uint8; -#else -typedef short yytype_uint8; -#endif - -#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ -typedef __UINT_LEAST16_TYPE__ yytype_uint16; -#elif (!defined __UINT_LEAST16_MAX__ && defined YY_STDINT_H \ - && UINT_LEAST16_MAX <= INT_MAX) -typedef uint_least16_t yytype_uint16; -#elif !defined __UINT_LEAST16_MAX__ && USHRT_MAX <= INT_MAX -typedef unsigned short yytype_uint16; -#else -typedef int yytype_uint16; -#endif - -#ifndef YYPTRDIFF_T -# if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ -# define YYPTRDIFF_T __PTRDIFF_TYPE__ -# define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ -# elif defined PTRDIFF_MAX -# ifndef ptrdiff_t -# include /* INFRINGES ON USER NAME SPACE */ -# endif -# define YYPTRDIFF_T ptrdiff_t -# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX -# else -# define YYPTRDIFF_T long -# define YYPTRDIFF_MAXIMUM LONG_MAX -# endif -#endif - -#ifndef YYSIZE_T -# ifdef __SIZE_TYPE__ -# define YYSIZE_T __SIZE_TYPE__ -# elif defined size_t -# define YYSIZE_T size_t -# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# else -# define YYSIZE_T unsigned -# endif -#endif - -#define YYSIZE_MAXIMUM \ - YY_CAST (YYPTRDIFF_T, \ - (YYPTRDIFF_MAXIMUM < YY_CAST (YYSIZE_T, -1) \ - ? YYPTRDIFF_MAXIMUM \ - : YY_CAST (YYSIZE_T, -1))) - -#define YYSIZEOF(X) YY_CAST (YYPTRDIFF_T, sizeof (X)) - - -/* Stored state numbers (used for stacks). */ -typedef yytype_int16 yy_state_t; - -/* State numbers in computations. */ -typedef int yy_state_fast_t; - -#ifndef YY_ -# if defined YYENABLE_NLS && YYENABLE_NLS -# if ENABLE_NLS -# include /* INFRINGES ON USER NAME SPACE */ -# define YY_(Msgid) dgettext ("bison-runtime", Msgid) -# endif -# endif -# ifndef YY_ -# define YY_(Msgid) Msgid -# endif -#endif - - -#ifndef YY_ATTRIBUTE_PURE -# if defined __GNUC__ && 2 < __GNUC__ + (96 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_PURE __attribute__ ((__pure__)) -# else -# define YY_ATTRIBUTE_PURE -# endif -#endif - -#ifndef YY_ATTRIBUTE_UNUSED -# if defined __GNUC__ && 2 < __GNUC__ + (7 <= __GNUC_MINOR__) -# define YY_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) -# else -# define YY_ATTRIBUTE_UNUSED -# endif -#endif - -/* Suppress unused-variable warnings by "using" E. */ -#if ! defined lint || defined __GNUC__ -# define YY_USE(E) ((void) (E)) -#else -# define YY_USE(E) /* empty */ -#endif - -/* Suppress an incorrect diagnostic about yylval being uninitialized. */ -#if defined __GNUC__ && ! defined __ICC && 406 <= __GNUC__ * 100 + __GNUC_MINOR__ -# if __GNUC__ * 100 + __GNUC_MINOR__ < 407 -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") -# else -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"") \ - _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") -# endif -# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ - _Pragma ("GCC diagnostic pop") -#else -# define YY_INITIAL_VALUE(Value) Value -#endif -#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN -# define YY_IGNORE_MAYBE_UNINITIALIZED_END -#endif -#ifndef YY_INITIAL_VALUE -# define YY_INITIAL_VALUE(Value) /* Nothing. */ -#endif - -#if defined __cplusplus && defined __GNUC__ && ! defined __ICC && 6 <= __GNUC__ -# define YY_IGNORE_USELESS_CAST_BEGIN \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wuseless-cast\"") -# define YY_IGNORE_USELESS_CAST_END \ - _Pragma ("GCC diagnostic pop") -#endif -#ifndef YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_BEGIN -# define YY_IGNORE_USELESS_CAST_END -#endif - - -#define YY_ASSERT(E) ((void) (0 && (E))) - -#if 1 - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# elif defined __BUILTIN_VA_ARG_INCR -# include /* INFRINGES ON USER NAME SPACE */ -# elif defined _AIX -# define YYSTACK_ALLOC __alloca -# elif defined _MSC_VER -# include /* INFRINGES ON USER NAME SPACE */ -# define alloca _alloca -# else -# define YYSTACK_ALLOC alloca -# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS -# include /* INFRINGES ON USER NAME SPACE */ - /* Use EXIT_SUCCESS as a witness for stdlib.h. */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's 'empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# ifndef YYSTACK_ALLOC_MAXIMUM - /* The OS might guarantee only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - invoke alloca (N) if N exceeds 4096. Use a slightly smaller number - to allow for a few compiler-allocated temporary stack slots. */ -# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ -# endif -# else -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# ifndef YYSTACK_ALLOC_MAXIMUM -# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM -# endif -# if (defined __cplusplus && ! defined EXIT_SUCCESS \ - && ! ((defined YYMALLOC || defined malloc) \ - && (defined YYFREE || defined free))) -# include /* INFRINGES ON USER NAME SPACE */ -# ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -# endif -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# if ! defined malloc && ! defined EXIT_SUCCESS -void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# ifndef YYFREE -# define YYFREE free -# if ! defined free && ! defined EXIT_SUCCESS -void free (void *); /* INFRINGES ON USER NAME SPACE */ -# endif -# endif -# endif -#endif /* 1 */ - -#if (! defined yyoverflow \ - && (! defined __cplusplus \ - || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - yy_state_t yyss_alloc; - YYSTYPE yyvs_alloc; -}; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (YYSIZEOF (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (YYSIZEOF (yy_state_t) + YYSIZEOF (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -# define YYCOPY_NEEDED 1 - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ - do \ - { \ - YYPTRDIFF_T yynewbytes; \ - YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ - Stack = &yyptr->Stack_alloc; \ - yynewbytes = yystacksize * YYSIZEOF (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / YYSIZEOF (*yyptr); \ - } \ - while (0) - -#endif - -#if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from SRC to DST. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(Dst, Src, Count) \ - __builtin_memcpy (Dst, Src, YY_CAST (YYSIZE_T, (Count)) * sizeof (*(Src))) -# else -# define YYCOPY(Dst, Src, Count) \ - do \ - { \ - YYPTRDIFF_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (Dst)[yyi] = (Src)[yyi]; \ - } \ - while (0) -# endif -# endif -#endif /* !YYCOPY_NEEDED */ - -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 452 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 12701 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 465 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 132 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 700 -/* YYNSTATES -- Number of states. */ -#define YYNSTATES 946 - -/* YYMAXUTOK -- Last valid token kind. */ -#define YYMAXUTOK 719 - - -/* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM - as returned by yylex, with out-of-bounds checking. */ -#define YYTRANSLATE(YYX) \ - (0 <= (YYX) && (YYX) <= YYMAXUTOK \ - ? YY_CAST (yysymbol_kind_t, yytranslate[YYX]) \ - : YYSYMBOL_YYUNDEF) - -/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM - as returned by yylex. */ -static const yytype_int16 yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, - 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, - 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, - 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, - 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, - 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, - 455, 456, 457, 458, 459, 460, 461, 462, 463, 464 -}; - -#if YYDEBUG -/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_int16 yyrline[] = -{ - 0, 355, 355, 361, 364, 369, 372, 375, 379, 382, - 385, 389, 393, 397, 401, 405, 409, 415, 422, 425, - 428, 431, 434, 439, 447, 454, 461, 467, 471, 478, - 481, 487, 505, 527, 535, 540, 567, 575, 581, 585, - 589, 609, 610, 611, 612, 618, 619, 624, 629, 638, - 639, 644, 652, 653, 659, 668, 669, 674, 679, 684, - 692, 693, 702, 714, 715, 724, 725, 734, 735, 744, - 745, 753, 754, 762, 763, 771, 772, 772, 790, 791, - 807, 811, 815, 819, 824, 828, 832, 836, 840, 844, - 848, 855, 858, 869, 876, 881, 888, 893, 898, 905, - 909, 913, 917, 922, 927, 936, 936, 947, 951, 958, - 963, 969, 975, 985, 988, 995, 1008, 1031, 1054, 1069, - 1094, 1105, 1115, 1125, 1135, 1144, 1147, 1151, 1155, 1160, - 1168, 1173, 1178, 1183, 1188, 1197, 1207, 1234, 1243, 1250, - 1257, 1264, 1271, 1279, 1287, 1297, 1307, 1314, 1324, 1330, - 1333, 1340, 1344, 1348, 1356, 1365, 1368, 1379, 1382, 1385, - 1389, 1393, 1397, 1401, 1404, 1409, 1413, 1418, 1426, 1430, - 1435, 1441, 1447, 1454, 1459, 1464, 1472, 1477, 1489, 1503, - 1509, 1514, 1522, 1530, 1538, 1546, 1554, 1562, 1570, 1578, - 1586, 1593, 1600, 1604, 1609, 1614, 1619, 1624, 1629, 1634, - 1638, 1642, 1646, 1650, 1656, 1662, 1672, 1679, 1682, 1690, - 1697, 1708, 1713, 1721, 1725, 1735, 1738, 1744, 1750, 1755, - 1763, 1773, 1777, 1781, 1785, 1790, 1794, 1799, 1804, 1809, - 1814, 1819, 1824, 1829, 1834, 1839, 1845, 1851, 1857, 1862, - 1867, 1872, 1877, 1882, 1887, 1892, 1897, 1902, 1907, 1912, - 1917, 1924, 1929, 1934, 1939, 1944, 1949, 1954, 1959, 1964, - 1969, 1974, 1979, 1987, 1995, 2003, 2009, 2015, 2021, 2027, - 2033, 2039, 2045, 2051, 2057, 2063, 2069, 2075, 2081, 2087, - 2093, 2099, 2105, 2111, 2117, 2123, 2129, 2135, 2141, 2147, - 2153, 2159, 2165, 2171, 2177, 2183, 2189, 2195, 2201, 2209, - 2217, 2225, 2233, 2241, 2249, 2257, 2265, 2273, 2281, 2289, - 2297, 2303, 2309, 2315, 2321, 2327, 2333, 2339, 2345, 2351, - 2357, 2363, 2369, 2375, 2381, 2387, 2393, 2399, 2405, 2411, - 2417, 2423, 2429, 2435, 2441, 2447, 2453, 2459, 2465, 2471, - 2477, 2483, 2489, 2495, 2501, 2507, 2513, 2517, 2521, 2525, - 2530, 2535, 2540, 2545, 2550, 2555, 2560, 2565, 2570, 2575, - 2580, 2585, 2590, 2595, 2601, 2607, 2613, 2619, 2625, 2631, - 2637, 2643, 2649, 2655, 2661, 2667, 2673, 2678, 2683, 2688, - 2693, 2698, 2703, 2708, 2713, 2718, 2723, 2728, 2733, 2738, - 2743, 2748, 2753, 2758, 2763, 2768, 2773, 2778, 2783, 2788, - 2793, 2798, 2803, 2808, 2813, 2818, 2823, 2828, 2833, 2838, - 2844, 2850, 2855, 2860, 2865, 2871, 2876, 2881, 2886, 2892, - 2897, 2902, 2907, 2913, 2918, 2923, 2928, 2934, 2940, 2946, - 2952, 2957, 2963, 2969, 2975, 2980, 2985, 2990, 2995, 3000, - 3006, 3011, 3016, 3021, 3027, 3032, 3037, 3042, 3048, 3053, - 3058, 3063, 3069, 3074, 3079, 3084, 3090, 3095, 3100, 3105, - 3111, 3116, 3121, 3126, 3132, 3137, 3142, 3147, 3153, 3158, - 3163, 3168, 3174, 3179, 3184, 3189, 3195, 3200, 3205, 3210, - 3216, 3221, 3226, 3231, 3237, 3242, 3247, 3252, 3258, 3263, - 3268, 3273, 3279, 3284, 3289, 3294, 3300, 3305, 3310, 3315, - 3320, 3325, 3330, 3335, 3340, 3345, 3350, 3355, 3360, 3365, - 3370, 3375, 3380, 3385, 3390, 3395, 3400, 3405, 3410, 3415, - 3420, 3426, 3432, 3438, 3444, 3450, 3456, 3462, 3469, 3476, - 3482, 3488, 3494, 3500, 3507, 3514, 3521, 3528, 3532, 3536, - 3541, 3557, 3562, 3567, 3575, 3575, 3592, 3592, 3602, 3605, - 3618, 3640, 3667, 3671, 3677, 3682, 3693, 3696, 3702, 3708, - 3717, 3720, 3726, 3730, 3731, 3737, 3738, 3739, 3740, 3741, - 3742, 3743, 3744, 3748, 3756, 3757, 3761, 3757, 3773, 3774, - 3778, 3778, 3785, 3785, 3799, 3802, 3810, 3818, 3829, 3830, - 3834, 3837, 3844, 3851, 3855, 3863, 3867, 3880, 3883, 3890, - 3890, 3910, 3913, 3919, 3931, 3943, 3946, 3953, 3953, 3968, - 3968, 3986, 3986, 4007, 4010, 4016, 4019, 4025, 4029, 4036, - 4041, 4046, 4053, 4056, 4060, 4064, 4068, 4077, 4081, 4090, - 4093, 4096, 4104, 4104, 4146, 4151, 4154, 4159, 4162, 4167, - 4170, 4175, 4178, 4183, 4186, 4191, 4194, 4199, 4203, 4208, - 4212, 4217, 4221, 4228, 4231, 4236, 4239, 4242, 4245, 4248, - 4253, 4262, 4273, 4278, 4286, 4290, 4295, 4299, 4304, 4308, - 4313, 4317, 4324, 4327, 4332, 4335, 4338, 4341, 4346, 4349, - 4354, 4360, 4363, 4366, 4369, 4374, 4378, 4383, 4387, 4392, - 4396, 4403, 4406, 4411, 4414, 4419, 4422, 4428, 4431, 4436, - 4439 -}; -#endif - -/** Accessing symbol of state STATE. */ -#define YY_ACCESSING_SYMBOL(State) YY_CAST (yysymbol_kind_t, yystos[State]) - -#if 1 -/* The user-facing name of the symbol whose (internal) number is - YYSYMBOL. No bounds checking. */ -static const char *yysymbol_name (yysymbol_kind_t yysymbol) YY_ATTRIBUTE_UNUSED; - -/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "\"end of file\"", "error", "\"invalid token\"", "CONST", "BOOL", "INT", - "UINT", "FLOAT", "BVEC2", "BVEC3", "BVEC4", "IVEC2", "IVEC3", "IVEC4", - "UVEC2", "UVEC3", "UVEC4", "VEC2", "VEC3", "VEC4", "MAT2", "MAT3", - "MAT4", "MAT2X2", "MAT2X3", "MAT2X4", "MAT3X2", "MAT3X3", "MAT3X4", - "MAT4X2", "MAT4X3", "MAT4X4", "SAMPLER2D", "SAMPLER3D", "SAMPLERCUBE", - "SAMPLER2DSHADOW", "SAMPLERCUBESHADOW", "SAMPLER2DARRAY", - "SAMPLER2DARRAYSHADOW", "ISAMPLER2D", "ISAMPLER3D", "ISAMPLERCUBE", - "ISAMPLER2DARRAY", "USAMPLER2D", "USAMPLER3D", "USAMPLERCUBE", - "USAMPLER2DARRAY", "SAMPLER", "SAMPLERSHADOW", "TEXTURE2D", "TEXTURE3D", - "TEXTURECUBE", "TEXTURE2DARRAY", "ITEXTURE2D", "ITEXTURE3D", - "ITEXTURECUBE", "ITEXTURE2DARRAY", "UTEXTURE2D", "UTEXTURE3D", - "UTEXTURECUBE", "UTEXTURE2DARRAY", "ATTRIBUTE", "VARYING", "FLOAT16_T", - "FLOAT32_T", "DOUBLE", "FLOAT64_T", "INT64_T", "UINT64_T", "INT32_T", - "UINT32_T", "INT16_T", "UINT16_T", "INT8_T", "UINT8_T", "I64VEC2", - "I64VEC3", "I64VEC4", "U64VEC2", "U64VEC3", "U64VEC4", "I32VEC2", - "I32VEC3", "I32VEC4", "U32VEC2", "U32VEC3", "U32VEC4", "I16VEC2", - "I16VEC3", "I16VEC4", "U16VEC2", "U16VEC3", "U16VEC4", "I8VEC2", - "I8VEC3", "I8VEC4", "U8VEC2", "U8VEC3", "U8VEC4", "DVEC2", "DVEC3", - "DVEC4", "DMAT2", "DMAT3", "DMAT4", "F16VEC2", "F16VEC3", "F16VEC4", - "F16MAT2", "F16MAT3", "F16MAT4", "F32VEC2", "F32VEC3", "F32VEC4", - "F32MAT2", "F32MAT3", "F32MAT4", "F64VEC2", "F64VEC3", "F64VEC4", - "F64MAT2", "F64MAT3", "F64MAT4", "DMAT2X2", "DMAT2X3", "DMAT2X4", - "DMAT3X2", "DMAT3X3", "DMAT3X4", "DMAT4X2", "DMAT4X3", "DMAT4X4", - "F16MAT2X2", "F16MAT2X3", "F16MAT2X4", "F16MAT3X2", "F16MAT3X3", - "F16MAT3X4", "F16MAT4X2", "F16MAT4X3", "F16MAT4X4", "F32MAT2X2", - "F32MAT2X3", "F32MAT2X4", "F32MAT3X2", "F32MAT3X3", "F32MAT3X4", - "F32MAT4X2", "F32MAT4X3", "F32MAT4X4", "F64MAT2X2", "F64MAT2X3", - "F64MAT2X4", "F64MAT3X2", "F64MAT3X3", "F64MAT3X4", "F64MAT4X2", - "F64MAT4X3", "F64MAT4X4", "ATOMIC_UINT", "ACCSTRUCTNV", "ACCSTRUCTEXT", - "RAYQUERYEXT", "FCOOPMATNV", "ICOOPMATNV", "UCOOPMATNV", "COOPMAT", - "HITOBJECTNV", "HITOBJECTATTRNV", "SAMPLERCUBEARRAY", - "SAMPLERCUBEARRAYSHADOW", "ISAMPLERCUBEARRAY", "USAMPLERCUBEARRAY", - "SAMPLER1D", "SAMPLER1DARRAY", "SAMPLER1DARRAYSHADOW", "ISAMPLER1D", - "SAMPLER1DSHADOW", "SAMPLER2DRECT", "SAMPLER2DRECTSHADOW", - "ISAMPLER2DRECT", "USAMPLER2DRECT", "SAMPLERBUFFER", "ISAMPLERBUFFER", - "USAMPLERBUFFER", "SAMPLER2DMS", "ISAMPLER2DMS", "USAMPLER2DMS", - "SAMPLER2DMSARRAY", "ISAMPLER2DMSARRAY", "USAMPLER2DMSARRAY", - "SAMPLEREXTERNALOES", "SAMPLEREXTERNAL2DY2YEXT", "ISAMPLER1DARRAY", - "USAMPLER1D", "USAMPLER1DARRAY", "F16SAMPLER1D", "F16SAMPLER2D", - "F16SAMPLER3D", "F16SAMPLER2DRECT", "F16SAMPLERCUBE", - "F16SAMPLER1DARRAY", "F16SAMPLER2DARRAY", "F16SAMPLERCUBEARRAY", - "F16SAMPLERBUFFER", "F16SAMPLER2DMS", "F16SAMPLER2DMSARRAY", - "F16SAMPLER1DSHADOW", "F16SAMPLER2DSHADOW", "F16SAMPLER1DARRAYSHADOW", - "F16SAMPLER2DARRAYSHADOW", "F16SAMPLER2DRECTSHADOW", - "F16SAMPLERCUBESHADOW", "F16SAMPLERCUBEARRAYSHADOW", "IMAGE1D", - "IIMAGE1D", "UIMAGE1D", "IMAGE2D", "IIMAGE2D", "UIMAGE2D", "IMAGE3D", - "IIMAGE3D", "UIMAGE3D", "IMAGE2DRECT", "IIMAGE2DRECT", "UIMAGE2DRECT", - "IMAGECUBE", "IIMAGECUBE", "UIMAGECUBE", "IMAGEBUFFER", "IIMAGEBUFFER", - "UIMAGEBUFFER", "IMAGE1DARRAY", "IIMAGE1DARRAY", "UIMAGE1DARRAY", - "IMAGE2DARRAY", "IIMAGE2DARRAY", "UIMAGE2DARRAY", "IMAGECUBEARRAY", - "IIMAGECUBEARRAY", "UIMAGECUBEARRAY", "IMAGE2DMS", "IIMAGE2DMS", - "UIMAGE2DMS", "IMAGE2DMSARRAY", "IIMAGE2DMSARRAY", "UIMAGE2DMSARRAY", - "F16IMAGE1D", "F16IMAGE2D", "F16IMAGE3D", "F16IMAGE2DRECT", - "F16IMAGECUBE", "F16IMAGE1DARRAY", "F16IMAGE2DARRAY", - "F16IMAGECUBEARRAY", "F16IMAGEBUFFER", "F16IMAGE2DMS", - "F16IMAGE2DMSARRAY", "I64IMAGE1D", "U64IMAGE1D", "I64IMAGE2D", - "U64IMAGE2D", "I64IMAGE3D", "U64IMAGE3D", "I64IMAGE2DRECT", - "U64IMAGE2DRECT", "I64IMAGECUBE", "U64IMAGECUBE", "I64IMAGEBUFFER", - "U64IMAGEBUFFER", "I64IMAGE1DARRAY", "U64IMAGE1DARRAY", - "I64IMAGE2DARRAY", "U64IMAGE2DARRAY", "I64IMAGECUBEARRAY", - "U64IMAGECUBEARRAY", "I64IMAGE2DMS", "U64IMAGE2DMS", "I64IMAGE2DMSARRAY", - "U64IMAGE2DMSARRAY", "TEXTURECUBEARRAY", "ITEXTURECUBEARRAY", - "UTEXTURECUBEARRAY", "TEXTURE1D", "ITEXTURE1D", "UTEXTURE1D", - "TEXTURE1DARRAY", "ITEXTURE1DARRAY", "UTEXTURE1DARRAY", "TEXTURE2DRECT", - "ITEXTURE2DRECT", "UTEXTURE2DRECT", "TEXTUREBUFFER", "ITEXTUREBUFFER", - "UTEXTUREBUFFER", "TEXTURE2DMS", "ITEXTURE2DMS", "UTEXTURE2DMS", - "TEXTURE2DMSARRAY", "ITEXTURE2DMSARRAY", "UTEXTURE2DMSARRAY", - "F16TEXTURE1D", "F16TEXTURE2D", "F16TEXTURE3D", "F16TEXTURE2DRECT", - "F16TEXTURECUBE", "F16TEXTURE1DARRAY", "F16TEXTURE2DARRAY", - "F16TEXTURECUBEARRAY", "F16TEXTUREBUFFER", "F16TEXTURE2DMS", - "F16TEXTURE2DMSARRAY", "SUBPASSINPUT", "SUBPASSINPUTMS", "ISUBPASSINPUT", - "ISUBPASSINPUTMS", "USUBPASSINPUT", "USUBPASSINPUTMS", "F16SUBPASSINPUT", - "F16SUBPASSINPUTMS", "SPIRV_INSTRUCTION", "SPIRV_EXECUTION_MODE", - "SPIRV_EXECUTION_MODE_ID", "SPIRV_DECORATE", "SPIRV_DECORATE_ID", - "SPIRV_DECORATE_STRING", "SPIRV_TYPE", "SPIRV_STORAGE_CLASS", - "SPIRV_BY_REFERENCE", "SPIRV_LITERAL", "ATTACHMENTEXT", "IATTACHMENTEXT", - "UATTACHMENTEXT", "LEFT_OP", "RIGHT_OP", "INC_OP", "DEC_OP", "LE_OP", - "GE_OP", "EQ_OP", "NE_OP", "AND_OP", "OR_OP", "XOR_OP", "MUL_ASSIGN", - "DIV_ASSIGN", "ADD_ASSIGN", "MOD_ASSIGN", "LEFT_ASSIGN", "RIGHT_ASSIGN", - "AND_ASSIGN", "XOR_ASSIGN", "OR_ASSIGN", "SUB_ASSIGN", "STRING_LITERAL", - "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACKET", "RIGHT_BRACKET", - "LEFT_BRACE", "RIGHT_BRACE", "DOT", "COMMA", "COLON", "EQUAL", - "SEMICOLON", "BANG", "DASH", "TILDE", "PLUS", "STAR", "SLASH", "PERCENT", - "LEFT_ANGLE", "RIGHT_ANGLE", "VERTICAL_BAR", "CARET", "AMPERSAND", - "QUESTION", "INVARIANT", "HIGH_PRECISION", "MEDIUM_PRECISION", - "LOW_PRECISION", "PRECISION", "PACKED", "RESOURCE", "SUPERP", - "FLOATCONSTANT", "INTCONSTANT", "UINTCONSTANT", "BOOLCONSTANT", - "IDENTIFIER", "TYPE_NAME", "CENTROID", "IN", "OUT", "INOUT", "STRUCT", - "VOID", "WHILE", "BREAK", "CONTINUE", "DO", "ELSE", "FOR", "IF", - "DISCARD", "RETURN", "SWITCH", "CASE", "DEFAULT", "TERMINATE_INVOCATION", - "TERMINATE_RAY", "IGNORE_INTERSECTION", "UNIFORM", "SHARED", "BUFFER", - "TILEIMAGEEXT", "FLAT", "SMOOTH", "LAYOUT", "DOUBLECONSTANT", - "INT16CONSTANT", "UINT16CONSTANT", "FLOAT16CONSTANT", "INT32CONSTANT", - "UINT32CONSTANT", "INT64CONSTANT", "UINT64CONSTANT", "SUBROUTINE", - "DEMOTE", "PAYLOADNV", "PAYLOADINNV", "HITATTRNV", "CALLDATANV", - "CALLDATAINNV", "PAYLOADEXT", "PAYLOADINEXT", "HITATTREXT", - "CALLDATAEXT", "CALLDATAINEXT", "PATCH", "SAMPLE", "NONUNIFORM", - "COHERENT", "VOLATILE", "RESTRICT", "READONLY", "WRITEONLY", - "DEVICECOHERENT", "QUEUEFAMILYCOHERENT", "WORKGROUPCOHERENT", - "SUBGROUPCOHERENT", "NONPRIVATE", "SHADERCALLCOHERENT", "NOPERSPECTIVE", - "EXPLICITINTERPAMD", "PERVERTEXEXT", "PERVERTEXNV", "PERPRIMITIVENV", - "PERVIEWNV", "PERTASKNV", "PERPRIMITIVEEXT", "TASKPAYLOADWORKGROUPEXT", - "PRECISE", "$accept", "variable_identifier", "primary_expression", - "postfix_expression", "integer_expression", "function_call", - "function_call_or_method", "function_call_generic", - "function_call_header_no_parameters", - "function_call_header_with_parameters", "function_call_header", - "function_identifier", "unary_expression", "unary_operator", - "multiplicative_expression", "additive_expression", "shift_expression", - "relational_expression", "equality_expression", "and_expression", - "exclusive_or_expression", "inclusive_or_expression", - "logical_and_expression", "logical_xor_expression", - "logical_or_expression", "conditional_expression", "$@1", - "assignment_expression", "assignment_operator", "expression", - "constant_expression", "declaration", "block_structure", "$@2", - "identifier_list", "function_prototype", "function_declarator", - "function_header_with_parameters", "function_header", - "parameter_declarator", "parameter_declaration", - "parameter_type_specifier", "init_declarator_list", "single_declaration", - "fully_specified_type", "invariant_qualifier", "interpolation_qualifier", - "layout_qualifier", "layout_qualifier_id_list", "layout_qualifier_id", - "precise_qualifier", "type_qualifier", "single_type_qualifier", - "storage_qualifier", "non_uniform_qualifier", "type_name_list", - "type_specifier", "array_specifier", "type_parameter_specifier_opt", - "type_parameter_specifier", "type_parameter_specifier_list", - "type_specifier_nonarray", "precision_qualifier", "struct_specifier", - "$@3", "$@4", "struct_declaration_list", "struct_declaration", - "struct_declarator_list", "struct_declarator", "initializer", - "initializer_list", "declaration_statement", "statement", - "simple_statement", "demote_statement", "compound_statement", "$@5", - "$@6", "statement_no_new_scope", "statement_scoped", "$@7", "$@8", - "compound_statement_no_new_scope", "statement_list", - "expression_statement", "selection_statement", - "selection_statement_nonattributed", "selection_rest_statement", - "condition", "switch_statement", "switch_statement_nonattributed", "$@9", - "switch_statement_list", "case_label", "iteration_statement", - "iteration_statement_nonattributed", "$@10", "$@11", "$@12", - "for_init_statement", "conditionopt", "for_rest_statement", - "jump_statement", "translation_unit", "external_declaration", - "function_definition", "$@13", "attribute", "attribute_list", - "single_attribute", "spirv_requirements_list", - "spirv_requirements_parameter", "spirv_extension_list", - "spirv_capability_list", "spirv_execution_mode_qualifier", - "spirv_execution_mode_parameter_list", "spirv_execution_mode_parameter", - "spirv_execution_mode_id_parameter_list", - "spirv_storage_class_qualifier", "spirv_decorate_qualifier", - "spirv_decorate_parameter_list", "spirv_decorate_parameter", - "spirv_decorate_id_parameter_list", "spirv_decorate_id_parameter", - "spirv_decorate_string_parameter_list", "spirv_type_specifier", - "spirv_type_parameter_list", "spirv_type_parameter", - "spirv_instruction_qualifier", "spirv_instruction_qualifier_list", - "spirv_instruction_qualifier_id", YY_NULLPTR -}; - -static const char * -yysymbol_name (yysymbol_kind_t yysymbol) -{ - return yytname[yysymbol]; -} -#endif - -#define YYPACT_NINF (-872) - -#define yypact_value_is_default(Yyn) \ - ((Yyn) == YYPACT_NINF) - -#define YYTABLE_NINF (-695) - -#define yytable_value_is_error(Yyn) \ - 0 - -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -static const yytype_int16 yypact[] = -{ - 4648, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -305, -301, - -289, -276, -246, -238, -227, -182, -872, -872, -872, -872, - -872, -168, -872, -872, -872, -872, -872, -55, -872, -872, - -872, -872, -872, -319, -872, -872, -872, -872, -872, -872, - -872, -135, -120, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -327, -114, - -81, -124, 7882, -313, -872, -101, -872, -872, -872, -872, - 5572, -872, -872, -872, -872, -94, -872, -872, 952, -872, - -872, 7882, -73, -872, -872, -872, 6034, -78, -252, -250, - -216, -197, -136, -78, -127, -49, 12303, -872, -13, -346, - -39, -872, -309, -872, -10, -9, 7882, -872, -872, -872, - 7882, -38, -37, -872, -267, -872, -236, -872, -872, 10983, - -2, -872, -872, -872, 3, -35, 7882, -872, -8, -6, - -1, -872, -256, -872, -255, -4, 4, 7, 8, -237, - 10, 11, 13, 14, 15, 18, -232, 9, 19, 27, - -188, -872, -3, 7882, -872, 20, -872, -229, -872, -872, - -219, 9223, -872, -272, 1414, -872, -872, -872, -872, -872, - -2, -277, -872, 9663, -265, -872, -23, -872, -112, 10983, - 10983, -872, 10983, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -253, -872, -872, -872, 29, -204, 11423, 28, - -872, 10983, -872, 31, -321, 17, -9, 32, -872, -325, - -78, -872, 5, -872, -330, 33, -125, 10983, -123, -872, - -130, -119, -146, -118, 34, -103, -78, -872, 11863, -872, - -74, 10983, 36, -49, -872, 7882, 24, 6496, -872, 7882, - 10983, -872, -346, -872, 30, -872, -872, -33, -133, -105, - -303, -11, -14, 21, 23, 48, 52, -316, 41, -872, - 10103, -872, 42, -872, -872, 46, 38, 40, -872, 64, - 67, 60, 10543, 74, 10983, 68, 65, 69, 70, 73, - -167, -872, -872, -47, -872, -114, 77, 31, -872, -872, - -872, -872, -872, 1876, -872, -872, -872, -872, -872, -872, - -872, -872, -872, 5110, 17, 9663, -261, 8343, -872, -872, - 9663, 7882, -872, 50, -872, -872, -872, -203, -872, -872, - 10983, 51, -872, -872, 10983, 87, -872, -872, -872, 10983, - -872, -872, -872, -312, -872, -872, -200, 80, -872, -872, - -872, -872, -872, -872, -199, -872, -196, -872, -872, -195, - 71, -872, -872, -872, -872, -169, -872, -164, -872, -872, - -872, -872, -872, -161, -872, 83, -872, -160, 84, -153, - 80, -872, -278, -152, -872, 91, 94, -872, -872, 24, - -2, -43, -872, -872, -872, 6958, -872, -872, -872, 10983, - 10983, 10983, 10983, 10983, 10983, 10983, 10983, 10983, 10983, 10983, - 10983, 10983, 10983, 10983, 10983, 10983, 10983, 10983, -872, -872, - -872, 93, -872, 2338, -872, -872, -872, 2338, -872, 10983, - -872, -872, -42, 10983, -32, -872, -872, -872, -872, -872, - -872, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, 10983, 10983, -872, -872, -872, -872, -872, -872, -872, - 9663, -872, -872, -76, -872, 7420, -872, -872, 96, 95, - -872, -872, -872, -872, -872, -132, -131, -872, -311, -872, - -330, -872, -330, -872, 10983, 10983, -872, -130, -872, -130, - -872, -146, -146, -872, 101, 34, -872, 11863, -872, 10983, - -872, -872, -41, 17, 24, -872, -872, -872, -872, -872, - -33, -33, -133, -133, -105, -105, -105, -105, -303, -303, - -11, -14, 21, 23, 48, 52, 10983, -872, 2338, 4186, - 59, 3724, -151, -872, -150, -872, -872, -872, -872, -872, - 8783, -872, -872, -872, 105, -872, 72, -872, -149, -872, - -148, -872, -141, -872, -140, -872, -139, -138, -872, -872, - -872, -28, 102, 95, 75, 107, 106, -872, -872, 4186, - 108, -872, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, 10983, -872, 100, 2800, 10983, -872, 104, 109, - 76, 112, 3262, -872, 113, -872, 9663, -872, -872, -872, - -137, 10983, 2800, 108, -872, -872, 2338, -872, 110, 95, - -872, -872, 2338, 114, -872, -872 -}; - -/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. - Performed when YYTABLE does not specify something else to do. Zero - means the default is an error. */ -static const yytype_int16 yydefact[] = -{ - 0, 168, 225, 223, 224, 222, 229, 230, 231, 232, - 233, 234, 235, 236, 237, 226, 227, 228, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 351, 352, 353, 354, 355, 356, 357, 377, 378, 379, - 380, 381, 382, 383, 392, 405, 406, 393, 394, 396, - 395, 397, 398, 399, 400, 401, 402, 403, 404, 177, - 178, 251, 252, 250, 253, 260, 261, 258, 259, 256, - 257, 254, 255, 283, 284, 285, 295, 296, 297, 280, - 281, 282, 292, 293, 294, 277, 278, 279, 289, 290, - 291, 274, 275, 276, 286, 287, 288, 262, 263, 264, - 298, 299, 300, 265, 266, 267, 310, 311, 312, 268, - 269, 270, 322, 323, 324, 271, 272, 273, 334, 335, - 336, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 313, 314, 315, 316, 317, 318, 319, 320, 321, 325, - 326, 327, 328, 329, 330, 331, 332, 333, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 349, 346, 347, - 348, 533, 534, 535, 536, 538, 182, 361, 362, 385, - 388, 350, 359, 360, 376, 358, 407, 408, 411, 412, - 413, 415, 416, 417, 419, 420, 421, 423, 424, 520, - 521, 384, 386, 387, 363, 364, 365, 409, 366, 370, - 371, 374, 414, 418, 422, 367, 368, 372, 373, 410, - 369, 375, 454, 456, 457, 458, 460, 461, 462, 464, - 465, 466, 468, 469, 470, 472, 473, 474, 476, 477, - 478, 480, 481, 482, 484, 485, 486, 488, 489, 490, - 492, 493, 494, 496, 497, 455, 459, 463, 467, 471, - 479, 483, 487, 475, 491, 495, 498, 499, 500, 501, - 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, - 512, 513, 514, 515, 516, 517, 518, 519, 389, 390, - 391, 425, 434, 436, 430, 435, 437, 438, 440, 441, - 442, 444, 445, 446, 448, 449, 450, 452, 453, 426, - 427, 428, 439, 429, 431, 432, 433, 443, 447, 451, - 525, 526, 529, 530, 531, 532, 527, 528, 0, 0, - 0, 0, 0, 0, 0, 0, 166, 167, 522, 523, - 524, 0, 631, 137, 541, 542, 543, 0, 540, 172, - 170, 171, 169, 0, 221, 173, 175, 176, 174, 139, - 138, 0, 203, 184, 186, 181, 188, 190, 185, 187, - 183, 189, 191, 179, 180, 206, 192, 199, 200, 201, - 202, 193, 194, 195, 196, 197, 198, 140, 141, 143, - 142, 144, 146, 147, 145, 205, 154, 630, 0, 632, - 0, 114, 113, 0, 125, 130, 161, 160, 158, 162, - 0, 155, 157, 163, 135, 216, 159, 539, 0, 627, - 629, 0, 0, 164, 165, 537, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 546, 0, 0, - 0, 99, 0, 94, 0, 109, 0, 121, 115, 123, - 0, 124, 0, 97, 131, 102, 0, 156, 136, 0, - 209, 215, 1, 628, 0, 0, 0, 96, 0, 0, - 0, 639, 0, 697, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 637, - 0, 635, 0, 0, 544, 151, 153, 0, 149, 207, - 0, 0, 100, 0, 0, 633, 110, 116, 120, 122, - 118, 126, 117, 0, 132, 105, 0, 103, 0, 0, - 0, 9, 0, 43, 42, 44, 41, 5, 6, 7, - 8, 2, 16, 14, 15, 17, 10, 11, 12, 13, - 3, 18, 37, 20, 25, 26, 0, 0, 30, 0, - 219, 0, 36, 218, 0, 210, 111, 0, 95, 0, - 0, 695, 0, 647, 0, 0, 0, 0, 0, 664, - 0, 0, 0, 0, 0, 0, 0, 689, 0, 662, - 0, 0, 0, 0, 98, 0, 0, 0, 548, 0, - 0, 148, 0, 204, 0, 211, 45, 49, 52, 55, - 60, 63, 65, 67, 69, 71, 73, 75, 0, 34, - 0, 101, 575, 584, 588, 0, 0, 0, 609, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 45, 78, 91, 0, 562, 0, 163, 135, 565, 586, - 564, 572, 563, 0, 566, 567, 590, 568, 597, 569, - 570, 605, 571, 0, 119, 0, 127, 0, 556, 134, - 0, 0, 107, 0, 104, 38, 39, 0, 22, 23, - 0, 0, 28, 27, 0, 221, 31, 33, 40, 0, - 217, 112, 699, 0, 700, 640, 0, 0, 698, 659, - 655, 656, 657, 658, 0, 653, 0, 93, 660, 0, - 0, 674, 675, 676, 677, 0, 672, 0, 681, 682, - 683, 684, 680, 0, 678, 0, 685, 0, 0, 0, - 2, 693, 216, 0, 691, 0, 0, 634, 636, 0, - 554, 0, 552, 547, 549, 0, 152, 150, 208, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 76, 212, - 213, 0, 574, 0, 607, 620, 619, 0, 611, 0, - 623, 621, 0, 0, 0, 604, 624, 625, 626, 573, - 81, 82, 84, 83, 86, 87, 88, 89, 90, 85, - 80, 0, 0, 589, 585, 587, 591, 598, 606, 129, - 0, 559, 560, 0, 133, 0, 108, 4, 0, 24, - 21, 32, 220, 643, 645, 0, 0, 696, 0, 649, - 0, 648, 0, 651, 0, 0, 666, 0, 665, 0, - 668, 0, 0, 670, 0, 0, 690, 0, 687, 0, - 663, 638, 0, 555, 0, 550, 545, 46, 47, 48, - 51, 50, 53, 54, 58, 59, 56, 57, 61, 62, - 64, 66, 68, 70, 72, 74, 0, 214, 576, 0, - 0, 0, 0, 622, 0, 603, 79, 92, 128, 557, - 0, 106, 19, 641, 0, 642, 0, 654, 0, 661, - 0, 673, 0, 679, 0, 686, 0, 0, 692, 551, - 553, 0, 0, 595, 0, 0, 0, 614, 613, 616, - 582, 599, 558, 561, 644, 646, 650, 652, 667, 669, - 671, 688, 0, 577, 0, 0, 0, 615, 0, 0, - 594, 0, 0, 592, 0, 77, 0, 579, 608, 578, - 0, 617, 0, 582, 581, 583, 601, 596, 0, 618, - 612, 593, 602, 0, 610, 600 -}; - -/* YYPGOTO[NTERM-NUM]. */ -static const yytype_int16 yypgoto[] = -{ - -872, -544, -872, -872, -872, -872, -872, -872, -872, -872, - -872, -872, -436, -872, -392, -391, -490, -390, -269, -266, - -268, -264, -262, -260, -872, -482, -872, -499, -872, -492, - -534, 6, -872, -872, -872, 1, -403, -872, -872, 45, - 44, 49, -872, -872, -406, -872, -872, -872, -872, -104, - -872, -389, -375, -872, 12, -872, 0, -433, -872, -872, - -872, -553, 145, -872, -872, -872, -560, -556, -233, -344, - -614, -872, -373, -626, -871, -872, -430, -872, -872, -440, - -437, -872, -872, 63, -737, -363, -872, -144, -872, -399, - -872, -142, -872, -872, -872, -872, -134, -872, -872, -872, - -872, -872, -872, -872, -872, 97, -872, -872, 2, -872, - -71, -308, -416, -872, -872, -872, -304, -307, -302, -872, - -872, -315, -310, -306, -300, -314, -872, -299, -317, -872, - -395, -538 -}; - -/* YYDEFGOTO[NTERM-NUM]. */ -static const yytype_int16 yydefgoto[] = -{ - 0, 530, 531, 532, 798, 533, 534, 535, 536, 537, - 538, 539, 620, 541, 587, 588, 589, 590, 591, 592, - 593, 594, 595, 596, 597, 621, 856, 622, 781, 623, - 711, 624, 388, 651, 508, 625, 390, 391, 392, 437, - 438, 439, 393, 394, 395, 396, 397, 398, 487, 488, - 399, 400, 401, 402, 542, 490, 599, 493, 450, 451, - 544, 405, 406, 407, 579, 483, 577, 578, 721, 722, - 649, 793, 628, 629, 630, 631, 632, 753, 892, 928, - 920, 921, 922, 929, 633, 634, 635, 636, 923, 895, - 637, 638, 924, 943, 639, 640, 641, 859, 757, 861, - 899, 918, 919, 642, 408, 409, 410, 434, 643, 480, - 481, 460, 461, 805, 806, 412, 684, 685, 689, 413, - 414, 695, 696, 703, 704, 707, 415, 713, 714, 416, - 462, 463 -}; - -/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule whose - number is the opposite. If YYTABLE_NINF, syntax error. */ -static const yytype_int16 yytable[] = -{ - 404, 389, 411, 440, 648, 455, 387, 785, 454, 598, - 455, 504, 403, 540, 678, 712, 858, 545, 702, 725, - 657, 724, 456, 688, 679, 447, 747, 456, 476, 672, - 678, 789, 673, 792, 736, 737, 794, 716, 431, 666, - 427, 669, 803, 672, 927, 485, 726, 440, 491, 442, - 417, 935, 443, 670, 418, 586, 492, 680, 681, 682, - 683, 927, 748, 674, 432, 447, 419, 644, 646, 486, - 738, 739, 428, 655, 656, 687, 804, 674, -694, 420, - 491, 447, 658, 659, -694, 600, 687, 645, 502, 687, - 491, 795, 600, 601, 575, 449, 600, 503, 687, 650, - 551, 553, -35, 790, 660, 668, 552, 554, 661, 421, - 466, 468, 470, 472, 474, 475, 478, 422, 751, 559, - 762, 586, 764, 505, 567, 560, 506, 581, 423, 507, - 568, 860, 586, 582, 675, 586, 464, 583, 467, 465, - 675, 465, 675, 584, 586, 675, 648, 675, 648, 675, - 675, 648, 663, 797, 675, 676, 807, 809, 664, 782, - 811, 813, 552, 810, 586, 801, 812, 814, 799, 724, - 572, 709, 469, 424, 573, 465, 868, 770, 771, 772, - 773, 774, 775, 776, 777, 778, 779, 816, 575, 425, - 575, 471, 818, 817, 465, 820, 823, 780, 819, 942, - 447, 821, 824, 826, 828, 900, 901, 906, 907, 827, - 829, 782, 782, 810, 814, 908, 909, 910, 911, 938, - 429, 817, 821, 824, 829, 782, 873, 875, 734, 735, - 874, 876, 785, 802, 732, 430, 733, 455, 436, 724, - 454, 698, 699, 700, 701, 521, 844, 845, 846, 847, - 653, 433, 473, 654, 456, 465, 903, 691, 692, 693, - 694, 477, 575, 686, 465, 690, 465, 862, 465, 697, - 705, 864, 465, 465, 712, 435, 712, 702, 702, 449, - 879, 688, 866, 867, 869, 708, 870, 833, 465, 678, - 444, 648, 457, 837, 838, 839, 586, 586, 586, 586, - 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, - 586, 586, 937, 459, 715, 782, 785, 465, 783, 834, - 782, 834, 835, 863, 889, 334, 335, 336, 740, 741, - 782, 865, 687, 687, 782, 912, 575, 729, 730, 731, - 840, 841, 479, 842, 843, 687, 484, 687, 331, 494, - 848, 849, 489, 500, 501, 491, 547, 548, 549, 546, - 555, 550, 574, 742, 891, 569, 556, 893, 652, 557, - 558, 648, 561, 562, 600, 563, 564, 565, 586, 586, - 566, 570, 571, 667, 580, 662, -34, 502, 706, 745, - 673, 586, 441, 586, 717, 746, 677, 743, 744, 749, - 448, 754, 752, 755, 403, 756, 575, 893, 404, 389, - 411, 404, 403, 925, 387, 720, 404, 458, 411, 758, - 403, 728, 759, 403, 930, 760, 482, 648, 403, 763, - 766, 765, -36, 815, 767, 768, 441, 496, 769, 939, - 441, 796, 800, -29, 808, 822, 825, 830, 403, 543, - 831, 857, 403, 894, 872, 885, 448, 782, 896, 904, - 905, 916, 913, 915, 926, 932, 914, -580, 403, 931, - 456, 602, 936, 850, 945, 944, 852, 851, 727, 933, - 497, 853, 426, 576, 854, 498, 832, 855, 897, 499, - 890, 934, 940, 894, 627, 403, 941, 495, 898, 786, - 917, 787, 718, 877, 882, 453, 626, 881, 878, 788, - 456, 886, 888, 880, 0, 0, 884, 0, 0, 0, - 0, 883, 0, 0, 0, 0, 0, 0, 887, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 671, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 719, 0, 576, 0, 576, - 0, 0, 0, 0, 0, 0, 0, 403, 0, 403, - 0, 403, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 627, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 404, 0, 626, 0, 0, 0, 0, - 0, 576, 0, 0, 0, 403, 0, 0, 0, 0, - 0, 0, 0, 403, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 576, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 403, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 627, 0, 0, 0, 627, 0, 0, - 0, 0, 0, 0, 0, 626, 0, 0, 0, 626, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 576, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 403, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 627, 627, - 0, 627, 0, 411, 0, 0, 0, 0, 0, 0, - 626, 626, 0, 626, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 627, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 626, 0, 0, 0, 627, 0, 0, 0, 0, - 0, 0, 627, 0, 0, 0, 0, 626, 0, 0, - 0, 0, 627, 0, 626, 0, 627, 0, 0, 0, - 0, 0, 627, 0, 626, 0, 0, 0, 626, 0, - 0, 0, 452, 0, 626, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 328, 329, 330, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 331, - 0, 0, 0, 0, 0, 0, 0, 332, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 333, 334, 335, 336, 337, 0, 0, 0, 0, - 0, 0, 0, 0, 338, 339, 340, 341, 342, 343, - 344, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 345, 346, 347, 348, - 349, 350, 351, 0, 0, 0, 0, 0, 0, 0, - 0, 352, 0, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, 385, 386, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 328, 329, 330, 0, 0, 509, - 510, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 511, 512, - 0, 331, 0, 602, 603, 0, 0, 0, 0, 604, - 513, 514, 515, 516, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 333, 334, 335, 336, 337, 0, 0, - 0, 517, 518, 519, 520, 521, 338, 339, 340, 341, - 342, 343, 344, 605, 606, 607, 608, 0, 609, 610, - 611, 612, 613, 614, 615, 616, 617, 618, 345, 346, - 347, 348, 349, 350, 351, 522, 523, 524, 525, 526, - 527, 528, 529, 352, 619, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, 385, 386, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, 328, 329, 330, 0, - 0, 509, 510, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 511, 512, 0, 331, 0, 602, 784, 0, 0, 0, - 0, 604, 513, 514, 515, 516, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 333, 334, 335, 336, 337, - 0, 0, 0, 517, 518, 519, 520, 521, 338, 339, - 340, 341, 342, 343, 344, 605, 606, 607, 608, 0, - 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, - 345, 346, 347, 348, 349, 350, 351, 522, 523, 524, - 525, 526, 527, 528, 529, 352, 619, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, - 386, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, - 330, 0, 0, 509, 510, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 511, 512, 0, 331, 0, 602, 0, 0, - 0, 0, 0, 604, 513, 514, 515, 516, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 333, 334, 335, - 336, 337, 0, 0, 0, 517, 518, 519, 520, 521, - 338, 339, 340, 341, 342, 343, 344, 605, 606, 607, - 608, 0, 609, 610, 611, 612, 613, 614, 615, 616, - 617, 618, 345, 346, 347, 348, 349, 350, 351, 522, - 523, 524, 525, 526, 527, 528, 529, 352, 619, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, 385, 386, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 328, 329, 330, 0, 0, 509, 510, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 511, 512, 0, 331, 0, 494, - 0, 0, 0, 0, 0, 604, 513, 514, 515, 516, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, - 334, 335, 336, 337, 0, 0, 0, 517, 518, 519, - 520, 521, 338, 339, 340, 341, 342, 343, 344, 605, - 606, 607, 608, 0, 609, 610, 611, 612, 613, 614, - 615, 616, 617, 618, 345, 346, 347, 348, 349, 350, - 351, 522, 523, 524, 525, 526, 527, 528, 529, 352, - 619, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, 385, 386, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 328, 329, 330, 0, 0, 509, 510, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 511, 512, 0, 331, - 0, 0, 0, 0, 0, 0, 0, 604, 513, 514, - 515, 516, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 333, 334, 335, 336, 337, 0, 0, 0, 517, - 518, 519, 520, 521, 338, 339, 340, 341, 342, 343, - 344, 605, 606, 607, 608, 0, 609, 610, 611, 612, - 613, 614, 615, 616, 617, 618, 345, 346, 347, 348, - 349, 350, 351, 522, 523, 524, 525, 526, 527, 528, - 529, 352, 619, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, 385, 386, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 328, 329, 330, 0, 0, 509, - 510, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 511, 512, - 0, 331, 0, 0, 0, 0, 0, 0, 0, 604, - 513, 514, 515, 516, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 333, 334, 335, 336, 337, 0, 0, - 0, 517, 518, 519, 520, 521, 338, 339, 340, 341, - 342, 343, 344, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 345, 346, - 347, 348, 349, 350, 351, 522, 523, 524, 525, 526, - 527, 528, 529, 352, 0, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, 385, 386, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 0, 0, 0, 321, - 322, 323, 324, 325, 326, 327, 328, 329, 330, 0, - 0, 509, 510, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 511, 512, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 513, 514, 515, 516, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 333, 334, 335, 336, 0, - 0, 0, 0, 517, 518, 519, 520, 521, 338, 339, - 340, 341, 342, 343, 344, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 345, 346, 347, 348, 349, 350, 351, 522, 523, 524, - 525, 526, 527, 528, 529, 352, 0, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, - 386, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, - 330, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 331, 0, 0, 0, 0, - 0, 0, 0, 332, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 333, 334, 335, - 336, 337, 0, 0, 0, 0, 0, 0, 0, 0, - 338, 339, 340, 341, 342, 343, 344, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 345, 346, 347, 348, 349, 350, 351, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, 385, 386, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 0, 0, 0, 321, 322, 323, 324, 325, 326, 327, - 328, 329, 330, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, - 334, 335, 336, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 338, 339, 340, 341, 342, 343, 344, 605, - 0, 0, 608, 0, 609, 610, 0, 0, 613, 0, - 0, 0, 0, 0, 345, 346, 347, 348, 349, 350, - 351, 0, 0, 0, 0, 0, 0, 0, 0, 352, - 0, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, 385, 386, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 0, 0, 0, 321, 322, 323, 324, 325, - 326, 327, 328, 329, 330, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 445, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 333, 334, 335, 336, 0, 0, 0, 0, 0, - 0, 0, 0, 446, 338, 339, 340, 341, 342, 343, - 344, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 345, 346, 347, 348, - 349, 350, 351, 0, 0, 0, 0, 0, 0, 0, - 0, 352, 0, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, 385, 386, 1, 2, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 0, 0, 0, 321, 322, 323, - 324, 325, 326, 327, 328, 329, 330, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 331, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 333, 334, 335, 336, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 338, 339, 340, 341, - 342, 343, 344, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 345, 346, - 347, 348, 349, 350, 351, 0, 0, 0, 0, 0, - 0, 0, 0, 352, 0, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, 385, 386, 1, - 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 0, 0, 0, 321, - 322, 323, 324, 325, 326, 327, 328, 329, 330, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 723, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 333, 334, 335, 336, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 338, 339, - 340, 341, 342, 343, 344, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 345, 346, 347, 348, 349, 350, 351, 0, 0, 0, - 0, 0, 0, 0, 0, 352, 0, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, - 386, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 314, 315, 316, 317, 0, 0, - 0, 321, 322, 323, 324, 325, 326, 327, 328, 329, - 330, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 836, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 333, 334, 335, - 336, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 338, 339, 340, 341, 342, 343, 344, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 345, 346, 347, 348, 349, 350, 351, 0, - 0, 0, 0, 0, 0, 0, 0, 352, 0, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, 385, 386, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 0, 0, 0, 321, 322, 323, 324, 325, 326, 327, - 328, 329, 330, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 871, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 333, - 334, 335, 336, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 338, 339, 340, 341, 342, 343, 344, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 345, 346, 347, 348, 349, 350, - 351, 0, 0, 0, 0, 0, 0, 0, 0, 352, - 0, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, 385, 386, 1, 2, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 0, 0, 0, 321, 322, 323, 324, 325, - 326, 327, 328, 329, 330, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 333, 334, 335, 336, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 338, 339, 340, 341, 342, 343, - 344, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 345, 346, 347, 348, - 349, 350, 351, 0, 0, 0, 0, 0, 0, 0, - 0, 352, 0, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, 385, 386, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 0, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 0, 0, 0, 0, 0, 0, 324, - 0, 0, 0, 328, 329, 330, 0, 0, 509, 510, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 511, 512, 0, - 0, 0, 647, 791, 0, 0, 0, 0, 0, 513, - 514, 515, 516, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 517, 518, 519, 520, 521, 338, 0, 0, 0, 0, - 343, 344, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 522, 523, 524, 525, 526, 527, - 528, 529, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 365, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 0, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 0, 0, 0, 0, 0, 0, 324, - 0, 0, 0, 328, 329, 330, 0, 0, 509, 510, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 511, 512, 0, - 0, 0, 647, 902, 0, 0, 0, 0, 0, 513, - 514, 515, 516, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 517, 518, 519, 520, 521, 338, 0, 0, 0, 0, - 343, 344, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 522, 523, 524, 525, 526, 527, - 528, 529, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 365, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 0, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 0, 0, 0, 0, 0, 0, 324, - 0, 0, 0, 328, 329, 330, 0, 0, 509, 510, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 511, 512, 0, - 0, 585, 0, 0, 0, 0, 0, 0, 0, 513, - 514, 515, 516, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 517, 518, 519, 520, 521, 338, 0, 0, 0, 0, - 343, 344, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 522, 523, 524, 525, 526, 527, - 528, 529, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 365, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 0, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 0, 0, 0, 0, 0, 0, 324, - 0, 0, 0, 328, 329, 330, 0, 0, 509, 510, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 511, 512, 0, - 0, 0, 647, 0, 0, 0, 0, 0, 0, 513, - 514, 515, 516, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 517, 518, 519, 520, 521, 338, 0, 0, 0, 0, - 343, 344, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 522, 523, 524, 525, 526, 527, - 528, 529, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 365, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 0, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 0, 0, 0, 0, 0, 0, 324, - 0, 0, 0, 328, 329, 330, 0, 0, 509, 510, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 511, 512, 0, - 0, 750, 0, 0, 0, 0, 0, 0, 0, 513, - 514, 515, 516, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 517, 518, 519, 520, 521, 338, 0, 0, 0, 0, - 343, 344, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 522, 523, 524, 525, 526, 527, - 528, 529, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 365, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 0, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 0, 0, 0, 0, 0, 0, 324, - 0, 0, 0, 328, 329, 330, 0, 0, 509, 510, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 511, 512, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 761, 513, - 514, 515, 516, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 517, 518, 519, 520, 521, 338, 0, 0, 0, 0, - 343, 344, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 522, 523, 524, 525, 526, 527, - 528, 529, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 365, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 0, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 0, 0, 0, 0, 0, 0, 324, - 0, 0, 0, 328, 329, 330, 0, 0, 509, 510, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 511, 512, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 513, - 514, 515, 516, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 517, 518, 519, 520, 521, 338, 0, 0, 0, 0, - 343, 344, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 522, 523, 524, 525, 526, 527, - 528, 529, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 365, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 0, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 0, 0, 0, 0, 0, 0, 324, - 0, 0, 0, 328, 329, 330, 0, 0, 509, 510, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 511, 512, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 513, - 514, 515, 516, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 517, 518, 519, 520, 521, 338, 0, 0, 0, 0, - 343, 665, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 522, 523, 524, 525, 526, 527, - 528, 529, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 365, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 0, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 0, 0, 0, 0, 0, 0, 324, - 0, 0, 0, 328, 329, 330, 0, 0, 509, 510, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 511, 512, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 513, - 514, 515, 516, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 517, 518, 519, 520, 710, 338, 0, 0, 0, 0, - 343, 344, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 522, 523, 524, 525, 526, 527, - 528, 529, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 365, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 0, 0, 61, 62, 63, 64, - 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, - 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, - 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, - 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, - 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 0, 167, 168, 169, 170, 171, 172, 173, 174, - 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, - 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, - 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, - 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, - 315, 316, 317, 0, 0, 0, 0, 0, 0, 324, - 0, 0, 0, 328, 329, 330, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 338, 0, 0, 0, 0, - 343, 344 -}; - -static const yytype_int16 yycheck[] = -{ - 0, 0, 0, 392, 503, 411, 0, 633, 411, 491, - 416, 444, 0, 449, 552, 568, 753, 450, 562, 579, - 512, 577, 411, 557, 354, 400, 342, 416, 423, 354, - 568, 645, 357, 647, 337, 338, 650, 571, 365, 538, - 359, 362, 354, 354, 915, 391, 580, 436, 357, 362, - 355, 922, 365, 374, 355, 491, 365, 387, 388, 389, - 390, 932, 378, 388, 391, 440, 355, 500, 501, 415, - 373, 374, 391, 509, 510, 557, 388, 388, 356, 355, - 357, 456, 335, 336, 362, 357, 568, 364, 355, 571, - 357, 651, 357, 365, 483, 373, 357, 364, 580, 364, - 356, 356, 355, 364, 357, 541, 362, 362, 361, 355, - 418, 419, 420, 421, 422, 423, 424, 355, 600, 356, - 612, 557, 614, 359, 356, 362, 362, 356, 355, 365, - 362, 757, 568, 362, 550, 571, 388, 356, 388, 391, - 556, 391, 558, 362, 580, 561, 645, 563, 647, 565, - 566, 650, 356, 356, 570, 550, 356, 356, 362, 362, - 356, 356, 362, 362, 600, 664, 362, 362, 660, 725, - 358, 566, 388, 355, 362, 391, 790, 344, 345, 346, - 347, 348, 349, 350, 351, 352, 353, 356, 577, 357, - 579, 388, 356, 362, 391, 356, 356, 364, 362, 936, - 575, 362, 362, 356, 356, 356, 356, 356, 356, 362, - 362, 362, 362, 362, 362, 356, 356, 356, 356, 356, - 355, 362, 362, 362, 362, 362, 358, 358, 333, 334, - 362, 362, 858, 669, 367, 355, 369, 643, 362, 795, - 643, 387, 388, 389, 390, 391, 736, 737, 738, 739, - 362, 365, 388, 365, 643, 391, 870, 387, 388, 389, - 390, 388, 651, 388, 391, 388, 391, 759, 391, 388, - 388, 763, 391, 391, 827, 356, 829, 821, 822, 373, - 814, 815, 781, 782, 360, 388, 362, 720, 391, 827, - 391, 790, 365, 729, 730, 731, 732, 733, 734, 735, - 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, - 746, 747, 926, 391, 388, 362, 942, 391, 365, 362, - 362, 362, 365, 365, 365, 380, 381, 382, 339, 340, - 362, 363, 814, 815, 362, 363, 725, 370, 371, 372, - 732, 733, 391, 734, 735, 827, 359, 829, 357, 359, - 740, 741, 391, 391, 391, 357, 391, 365, 364, 356, - 364, 362, 365, 377, 856, 356, 362, 859, 391, 362, - 362, 870, 362, 362, 357, 362, 362, 362, 814, 815, - 362, 362, 355, 355, 364, 356, 355, 355, 354, 341, - 357, 827, 392, 829, 358, 343, 391, 376, 375, 358, - 400, 355, 360, 365, 392, 365, 795, 899, 408, 408, - 408, 411, 400, 912, 408, 391, 416, 416, 416, 355, - 408, 391, 355, 411, 916, 365, 426, 926, 416, 355, - 365, 363, 355, 362, 365, 365, 436, 435, 365, 931, - 440, 391, 391, 356, 364, 362, 362, 356, 436, 449, - 356, 358, 440, 859, 358, 354, 456, 362, 399, 354, - 388, 355, 360, 356, 364, 356, 391, 359, 456, 365, - 859, 359, 359, 742, 360, 365, 744, 743, 582, 403, - 436, 745, 337, 483, 746, 440, 719, 747, 861, 440, - 834, 921, 932, 899, 494, 483, 933, 434, 861, 643, - 899, 643, 573, 810, 819, 408, 494, 817, 812, 643, - 899, 825, 829, 815, -1, -1, 822, -1, -1, -1, - -1, 821, -1, -1, -1, -1, -1, -1, 827, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 546, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 575, -1, 577, -1, 579, - -1, -1, -1, -1, -1, -1, -1, 575, -1, 577, - -1, 579, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 633, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 643, -1, 633, -1, -1, -1, -1, - -1, 651, -1, -1, -1, 643, -1, -1, -1, -1, - -1, -1, -1, 651, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 725, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 725, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 753, -1, -1, -1, 757, -1, -1, - -1, -1, -1, -1, -1, 753, -1, -1, -1, 757, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 795, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 795, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 858, 859, - -1, 861, -1, 861, -1, -1, -1, -1, -1, -1, - 858, 859, -1, 861, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 899, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 899, -1, -1, -1, 915, -1, -1, -1, -1, - -1, -1, 922, -1, -1, -1, -1, 915, -1, -1, - -1, -1, 932, -1, 922, -1, 936, -1, -1, -1, - -1, -1, 942, -1, 932, -1, -1, -1, 936, -1, - -1, -1, 0, -1, 942, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 328, 329, 330, 331, 332, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 357, - -1, -1, -1, -1, -1, -1, -1, 365, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 379, 380, 381, 382, 383, -1, -1, -1, -1, - -1, -1, -1, -1, 392, 393, 394, 395, 396, 397, - 398, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 414, 415, 416, 417, - 418, 419, 420, -1, -1, -1, -1, -1, -1, -1, - -1, 429, -1, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, - 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, - 458, 459, 460, 461, 462, 463, 464, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 328, 329, 330, 331, 332, -1, -1, 335, - 336, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 354, 355, - -1, 357, -1, 359, 360, -1, -1, -1, -1, 365, - 366, 367, 368, 369, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 379, 380, 381, 382, 383, -1, -1, - -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, - 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, - 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, - 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, - 456, 457, 458, 459, 460, 461, 462, 463, 464, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 328, 329, 330, 331, 332, -1, - -1, 335, 336, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 354, 355, -1, 357, -1, 359, 360, -1, -1, -1, - -1, 365, 366, 367, 368, 369, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 379, 380, 381, 382, 383, - -1, -1, -1, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, 402, -1, - 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, - 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, - 464, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, - 332, -1, -1, 335, 336, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 354, 355, -1, 357, -1, 359, -1, -1, - -1, -1, -1, 365, 366, 367, 368, 369, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 379, 380, 381, - 382, 383, -1, -1, -1, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - 402, -1, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, - 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, - 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, - 462, 463, 464, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, - 330, 331, 332, -1, -1, 335, 336, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 354, 355, -1, 357, -1, 359, - -1, -1, -1, -1, -1, 365, 366, 367, 368, 369, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 379, - 380, 381, 382, 383, -1, -1, -1, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, 402, -1, 404, 405, 406, 407, 408, 409, - 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, - 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, - 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, - 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, - 460, 461, 462, 463, 464, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 328, 329, 330, 331, 332, -1, -1, 335, 336, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 354, 355, -1, 357, - -1, -1, -1, -1, -1, -1, -1, 365, 366, 367, - 368, 369, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 379, 380, 381, 382, 383, -1, -1, -1, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, 402, -1, 404, 405, 406, 407, - 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, - 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, - 458, 459, 460, 461, 462, 463, 464, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 328, 329, 330, 331, 332, -1, -1, 335, - 336, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 354, 355, - -1, 357, -1, -1, -1, -1, -1, -1, -1, 365, - 366, 367, 368, 369, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 379, 380, 381, 382, 383, -1, -1, - -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 414, 415, - 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, - 426, 427, 428, 429, -1, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, - 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, - 456, 457, 458, 459, 460, 461, 462, 463, 464, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, -1, -1, -1, 323, - 324, 325, 326, 327, 328, 329, 330, 331, 332, -1, - -1, 335, 336, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 354, 355, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 366, 367, 368, 369, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 379, 380, 381, 382, -1, - -1, -1, -1, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, - 424, 425, 426, 427, 428, 429, -1, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, - 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, - 464, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, - 332, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 357, -1, -1, -1, -1, - -1, -1, -1, 365, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 379, 380, 381, - 382, 383, -1, -1, -1, -1, -1, -1, -1, -1, - 392, 393, 394, 395, 396, 397, 398, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 414, 415, 416, 417, 418, 419, 420, -1, - -1, -1, -1, -1, -1, -1, -1, 429, -1, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, - 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, - 462, 463, 464, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - -1, -1, -1, 323, 324, 325, 326, 327, 328, 329, - 330, 331, 332, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 379, - 380, 381, 382, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 392, 393, 394, 395, 396, 397, 398, 399, - -1, -1, 402, -1, 404, 405, -1, -1, 408, -1, - -1, -1, -1, -1, 414, 415, 416, 417, 418, 419, - 420, -1, -1, -1, -1, -1, -1, -1, -1, 429, - -1, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, - 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, - 460, 461, 462, 463, 464, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, -1, -1, -1, 323, 324, 325, 326, 327, - 328, 329, 330, 331, 332, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 365, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 379, 380, 381, 382, -1, -1, -1, -1, -1, - -1, -1, -1, 391, 392, 393, 394, 395, 396, 397, - 398, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 414, 415, 416, 417, - 418, 419, 420, -1, -1, -1, -1, -1, -1, -1, - -1, 429, -1, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, - 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, - 458, 459, 460, 461, 462, 463, 464, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, - 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, -1, -1, -1, 323, 324, 325, - 326, 327, 328, 329, 330, 331, 332, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 357, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 379, 380, 381, 382, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 392, 393, 394, 395, - 396, 397, 398, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 414, 415, - 416, 417, 418, 419, 420, -1, -1, -1, -1, -1, - -1, -1, -1, 429, -1, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, - 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, - 456, 457, 458, 459, 460, 461, 462, 463, 464, 3, - 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, - 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, - 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, - 314, 315, 316, 317, 318, 319, -1, -1, -1, 323, - 324, 325, 326, 327, 328, 329, 330, 331, 332, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 360, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 379, 380, 381, 382, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 392, 393, - 394, 395, 396, 397, 398, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 414, 415, 416, 417, 418, 419, 420, -1, -1, -1, - -1, -1, -1, -1, -1, 429, -1, 431, 432, 433, - 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, - 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, - 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, - 464, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, -1, -1, - -1, 323, 324, 325, 326, 327, 328, 329, 330, 331, - 332, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 360, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 379, 380, 381, - 382, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 392, 393, 394, 395, 396, 397, 398, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 414, 415, 416, 417, 418, 419, 420, -1, - -1, -1, -1, -1, -1, -1, -1, 429, -1, 431, - 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, - 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, - 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, - 462, 463, 464, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, - 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, - 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, - 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, - 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, - -1, -1, -1, 323, 324, 325, 326, 327, 328, 329, - 330, 331, 332, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 360, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 379, - 380, 381, 382, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 392, 393, 394, 395, 396, 397, 398, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 414, 415, 416, 417, 418, 419, - 420, -1, -1, -1, -1, -1, -1, -1, -1, 429, - -1, 431, 432, 433, 434, 435, 436, 437, 438, 439, - 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, - 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, - 460, 461, 462, 463, 464, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, -1, -1, -1, 323, 324, 325, 326, 327, - 328, 329, 330, 331, 332, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 379, 380, 381, 382, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 392, 393, 394, 395, 396, 397, - 398, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 414, 415, 416, 417, - 418, 419, 420, -1, -1, -1, -1, -1, -1, -1, - -1, 429, -1, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, - 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, - 458, 459, 460, 461, 462, 463, 464, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, -1, -1, -1, -1, -1, -1, 326, - -1, -1, -1, 330, 331, 332, -1, -1, 335, 336, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 354, 355, -1, - -1, -1, 359, 360, -1, -1, -1, -1, -1, 366, - 367, 368, 369, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, - 397, 398, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 421, 422, 423, 424, 425, 426, - 427, 428, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 443, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, -1, -1, -1, -1, -1, -1, 326, - -1, -1, -1, 330, 331, 332, -1, -1, 335, 336, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 354, 355, -1, - -1, -1, 359, 360, -1, -1, -1, -1, -1, 366, - 367, 368, 369, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, - 397, 398, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 421, 422, 423, 424, 425, 426, - 427, 428, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 443, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, -1, -1, -1, -1, -1, -1, 326, - -1, -1, -1, 330, 331, 332, -1, -1, 335, 336, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 354, 355, -1, - -1, 358, -1, -1, -1, -1, -1, -1, -1, 366, - 367, 368, 369, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, - 397, 398, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 421, 422, 423, 424, 425, 426, - 427, 428, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 443, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, -1, -1, -1, -1, -1, -1, 326, - -1, -1, -1, 330, 331, 332, -1, -1, 335, 336, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 354, 355, -1, - -1, -1, 359, -1, -1, -1, -1, -1, -1, 366, - 367, 368, 369, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, - 397, 398, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 421, 422, 423, 424, 425, 426, - 427, 428, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 443, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, -1, -1, -1, -1, -1, -1, 326, - -1, -1, -1, 330, 331, 332, -1, -1, 335, 336, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 354, 355, -1, - -1, 358, -1, -1, -1, -1, -1, -1, -1, 366, - 367, 368, 369, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, - 397, 398, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 421, 422, 423, 424, 425, 426, - 427, 428, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 443, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, -1, -1, -1, -1, -1, -1, 326, - -1, -1, -1, 330, 331, 332, -1, -1, 335, 336, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 354, 355, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 365, 366, - 367, 368, 369, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, - 397, 398, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 421, 422, 423, 424, 425, 426, - 427, 428, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 443, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, -1, -1, -1, -1, -1, -1, 326, - -1, -1, -1, 330, 331, 332, -1, -1, 335, 336, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 354, 355, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 366, - 367, 368, 369, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, - 397, 398, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 421, 422, 423, 424, 425, 426, - 427, 428, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 443, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, -1, -1, -1, -1, -1, -1, 326, - -1, -1, -1, 330, 331, 332, -1, -1, 335, 336, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 354, 355, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 366, - 367, 368, 369, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, - 397, 398, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 421, 422, 423, 424, 425, 426, - 427, 428, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 443, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, -1, -1, -1, -1, -1, -1, 326, - -1, -1, -1, 330, 331, 332, -1, -1, 335, 336, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 354, 355, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 366, - 367, 368, 369, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 387, 388, 389, 390, 391, 392, -1, -1, -1, -1, - 397, 398, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 421, 422, 423, 424, 425, 426, - 427, 428, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 443, 4, 5, 6, - 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, - 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, -1, -1, -1, -1, -1, -1, 326, - -1, -1, -1, 330, 331, 332, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 392, -1, -1, -1, -1, - 397, 398 -}; - -/* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of - state STATE-NUM. */ -static const yytype_int16 yystos[] = -{ - 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, - 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, - 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, - 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, - 332, 357, 365, 379, 380, 381, 382, 383, 392, 393, - 394, 395, 396, 397, 398, 414, 415, 416, 417, 418, - 419, 420, 429, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, - 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, - 458, 459, 460, 461, 462, 463, 464, 496, 497, 500, - 501, 502, 503, 507, 508, 509, 510, 511, 512, 515, - 516, 517, 518, 519, 521, 526, 527, 528, 569, 570, - 571, 573, 580, 584, 585, 591, 594, 355, 355, 355, - 355, 355, 355, 355, 355, 357, 527, 359, 391, 355, - 355, 365, 391, 365, 572, 356, 362, 504, 505, 506, - 516, 521, 362, 365, 391, 365, 391, 517, 521, 373, - 523, 524, 0, 570, 501, 509, 516, 365, 500, 391, - 576, 577, 595, 596, 388, 391, 576, 388, 576, 388, - 576, 388, 576, 388, 576, 576, 595, 388, 576, 391, - 574, 575, 521, 530, 359, 391, 415, 513, 514, 391, - 520, 357, 365, 522, 359, 548, 573, 505, 504, 506, - 391, 391, 355, 364, 522, 359, 362, 365, 499, 335, - 336, 354, 355, 366, 367, 368, 369, 387, 388, 389, - 390, 391, 421, 422, 423, 424, 425, 426, 427, 428, - 466, 467, 468, 470, 471, 472, 473, 474, 475, 476, - 477, 478, 519, 521, 525, 522, 356, 391, 365, 364, - 362, 356, 362, 356, 362, 364, 362, 362, 362, 356, - 362, 362, 362, 362, 362, 362, 362, 356, 362, 356, - 362, 355, 358, 362, 365, 516, 521, 531, 532, 529, - 364, 356, 362, 356, 362, 358, 477, 479, 480, 481, - 482, 483, 484, 485, 486, 487, 488, 489, 490, 521, - 357, 365, 359, 360, 365, 399, 400, 401, 402, 404, - 405, 406, 407, 408, 409, 410, 411, 412, 413, 430, - 477, 490, 492, 494, 496, 500, 519, 521, 537, 538, - 539, 540, 541, 549, 550, 551, 552, 555, 556, 559, - 560, 561, 568, 573, 522, 364, 522, 359, 492, 535, - 364, 498, 391, 362, 365, 477, 477, 494, 335, 336, - 357, 361, 356, 356, 362, 398, 492, 355, 477, 362, - 374, 573, 354, 357, 388, 577, 595, 391, 596, 354, - 387, 388, 389, 390, 581, 582, 388, 490, 495, 583, - 388, 387, 388, 389, 390, 586, 587, 388, 387, 388, - 389, 390, 466, 588, 589, 388, 354, 590, 388, 595, - 391, 495, 526, 592, 593, 388, 495, 358, 575, 521, - 391, 533, 534, 360, 532, 531, 495, 514, 391, 370, - 371, 372, 367, 369, 333, 334, 337, 338, 373, 374, - 339, 340, 377, 376, 375, 341, 343, 342, 378, 358, - 358, 490, 360, 542, 355, 365, 365, 563, 355, 355, - 365, 365, 494, 355, 494, 363, 365, 365, 365, 365, - 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, - 364, 493, 362, 365, 360, 538, 552, 556, 561, 535, - 364, 360, 535, 536, 535, 531, 391, 356, 469, 494, - 391, 492, 477, 354, 388, 578, 579, 356, 364, 356, - 362, 356, 362, 356, 362, 362, 356, 362, 356, 362, - 356, 362, 362, 356, 362, 362, 356, 362, 356, 362, - 356, 356, 533, 522, 362, 365, 360, 477, 477, 477, - 479, 479, 480, 480, 481, 481, 481, 481, 482, 482, - 483, 484, 485, 486, 487, 488, 491, 358, 549, 562, - 538, 564, 494, 365, 494, 363, 492, 492, 535, 360, - 362, 360, 358, 358, 362, 358, 362, 582, 581, 495, - 583, 587, 586, 589, 588, 354, 590, 592, 593, 365, - 534, 494, 543, 494, 509, 554, 399, 537, 550, 565, - 356, 356, 360, 535, 354, 388, 356, 356, 356, 356, - 356, 356, 363, 360, 391, 356, 355, 554, 566, 567, - 545, 546, 547, 553, 557, 492, 364, 539, 544, 548, - 494, 365, 356, 403, 541, 539, 359, 535, 356, 494, - 544, 545, 549, 558, 365, 360 -}; - -/* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ -static const yytype_int16 yyr1[] = -{ - 0, 465, 466, 467, 467, 467, 467, 467, 467, 467, - 467, 467, 467, 467, 467, 467, 467, 467, 468, 468, - 468, 468, 468, 468, 469, 470, 471, 472, 472, 473, - 473, 474, 474, 475, 476, 476, 476, 477, 477, 477, - 477, 478, 478, 478, 478, 479, 479, 479, 479, 480, - 480, 480, 481, 481, 481, 482, 482, 482, 482, 482, - 483, 483, 483, 484, 484, 485, 485, 486, 486, 487, - 487, 488, 488, 489, 489, 490, 491, 490, 492, 492, - 493, 493, 493, 493, 493, 493, 493, 493, 493, 493, - 493, 494, 494, 495, 496, 496, 496, 496, 496, 496, - 496, 496, 496, 496, 496, 498, 497, 499, 499, 500, - 500, 500, 500, 501, 501, 502, 502, 503, 504, 504, - 505, 505, 505, 505, 506, 507, 507, 507, 507, 507, - 508, 508, 508, 508, 508, 509, 509, 510, 511, 511, - 511, 511, 511, 511, 511, 511, 511, 511, 512, 513, - 513, 514, 514, 514, 515, 516, 516, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 518, 518, - 518, 518, 518, 518, 518, 518, 518, 518, 518, 518, - 518, 518, 518, 518, 518, 518, 518, 518, 518, 518, - 518, 518, 518, 518, 518, 518, 518, 518, 518, 518, - 518, 518, 518, 518, 518, 518, 519, 520, 520, 521, - 521, 522, 522, 522, 522, 523, 523, 524, 525, 525, - 525, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 526, 526, 526, 526, 526, 526, 526, 526, 526, - 526, 527, 527, 527, 529, 528, 530, 528, 531, 531, - 532, 532, 533, 533, 534, 534, 535, 535, 535, 535, - 536, 536, 537, 538, 538, 539, 539, 539, 539, 539, - 539, 539, 539, 540, 541, 542, 543, 541, 544, 544, - 546, 545, 547, 545, 548, 548, 549, 549, 550, 550, - 551, 551, 552, 553, 553, 554, 554, 555, 555, 557, - 556, 558, 558, 559, 559, 560, 560, 562, 561, 563, - 561, 564, 561, 565, 565, 566, 566, 567, 567, 568, - 568, 568, 568, 568, 568, 568, 568, 569, 569, 570, - 570, 570, 572, 571, 573, 574, 574, 575, 575, 576, - 576, 577, 577, 578, 578, 579, 579, 580, 580, 580, - 580, 580, 580, 581, 581, 582, 582, 582, 582, 582, - 583, 583, 584, 584, 585, 585, 585, 585, 585, 585, - 585, 585, 586, 586, 587, 587, 587, 587, 588, 588, - 589, 589, 589, 589, 589, 590, 590, 591, 591, 591, - 591, 592, 592, 593, 593, 594, 594, 595, 595, 596, - 596 -}; - -/* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ -static const yytype_int8 yyr2[] = -{ - 0, 2, 1, 1, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, - 1, 3, 2, 2, 1, 1, 1, 2, 2, 2, - 1, 2, 3, 2, 1, 1, 1, 1, 2, 2, - 2, 1, 1, 1, 1, 1, 3, 3, 3, 1, - 3, 3, 1, 3, 3, 1, 3, 3, 3, 3, - 1, 3, 3, 1, 3, 1, 3, 1, 3, 1, - 3, 1, 3, 1, 3, 1, 0, 6, 1, 3, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 3, 1, 2, 3, 2, 2, 4, 2, - 3, 4, 2, 3, 4, 0, 6, 2, 3, 2, - 3, 3, 4, 1, 1, 2, 3, 3, 2, 3, - 2, 1, 2, 1, 1, 1, 3, 4, 6, 5, - 1, 2, 3, 5, 4, 1, 2, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 4, 1, - 3, 1, 3, 1, 1, 1, 2, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 4, 1, 1, 1, 3, 2, - 3, 2, 3, 3, 4, 1, 0, 3, 1, 1, - 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 0, 6, 0, 5, 1, 2, - 3, 4, 1, 3, 1, 2, 1, 3, 4, 2, - 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 2, 2, 0, 0, 5, 1, 1, - 0, 2, 0, 2, 2, 3, 1, 2, 1, 2, - 1, 2, 5, 3, 1, 1, 4, 1, 2, 0, - 8, 0, 1, 3, 2, 1, 2, 0, 6, 0, - 8, 0, 7, 1, 1, 1, 0, 2, 3, 2, - 2, 2, 3, 2, 2, 2, 2, 1, 2, 1, - 1, 1, 0, 3, 5, 1, 3, 1, 4, 1, - 3, 5, 5, 1, 3, 1, 3, 4, 6, 6, - 8, 6, 8, 1, 3, 1, 1, 1, 1, 1, - 1, 3, 4, 6, 4, 6, 6, 8, 6, 8, - 6, 8, 1, 3, 1, 1, 1, 1, 1, 3, - 1, 1, 1, 1, 1, 1, 3, 6, 8, 4, - 6, 1, 3, 1, 1, 4, 6, 1, 3, 3, - 3 -}; - - -enum { YYENOMEM = -2 }; - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) - -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab -#define YYNOMEM goto yyexhaustedlab - - -#define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ - do \ - if (yychar == YYEMPTY) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (yylen); \ - yystate = *yyssp; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (pParseContext, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ - while (0) - -/* Backward compatibility with an undocumented macro. - Use YYerror or YYUNDEF. */ -#define YYERRCODE YYUNDEF - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - - - - -# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Kind, Value, pParseContext); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) - - -/*-----------------------------------. -| Print this symbol's value on YYO. | -`-----------------------------------*/ - -static void -yy_symbol_value_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext) -{ - FILE *yyoutput = yyo; - YY_USE (yyoutput); - YY_USE (pParseContext); - if (!yyvaluep) - return; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YY_USE (yykind); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - -/*---------------------------. -| Print this symbol on YYO. | -`---------------------------*/ - -static void -yy_symbol_print (FILE *yyo, - yysymbol_kind_t yykind, YYSTYPE const * const yyvaluep, glslang::TParseContext* pParseContext) -{ - YYFPRINTF (yyo, "%s %s (", - yykind < YYNTOKENS ? "token" : "nterm", yysymbol_name (yykind)); - - yy_symbol_value_print (yyo, yykind, yyvaluep, pParseContext); - YYFPRINTF (yyo, ")"); -} - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -static void -yy_stack_print (yy_state_t *yybottom, yy_state_t *yytop) -{ - YYFPRINTF (stderr, "Stack now"); - for (; yybottom <= yytop; yybottom++) - { - int yybot = *yybottom; - YYFPRINTF (stderr, " %d", yybot); - } - YYFPRINTF (stderr, "\n"); -} - -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) - - -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ - -static void -yy_reduce_print (yy_state_t *yyssp, YYSTYPE *yyvsp, - int yyrule, glslang::TParseContext* pParseContext) -{ - int yylno = yyrline[yyrule]; - int yynrhs = yyr2[yyrule]; - int yyi; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %d):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) - { - YYFPRINTF (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, - YY_ACCESSING_SYMBOL (+yyssp[yyi + 1 - yynrhs]), - &yyvsp[(yyi + 1) - (yynrhs)], pParseContext); - YYFPRINTF (stderr, "\n"); - } -} - -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyssp, yyvsp, Rule, pParseContext); \ -} while (0) - -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) ((void) 0) -# define YY_SYMBOL_PRINT(Title, Kind, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ - - -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif - -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ - -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - - -/* Context of a parse error. */ -typedef struct -{ - yy_state_t *yyssp; - yysymbol_kind_t yytoken; -} yypcontext_t; - -/* Put in YYARG at most YYARGN of the expected tokens given the - current YYCTX, and return the number of tokens stored in YYARG. If - YYARG is null, return the number of expected tokens (guaranteed to - be less than YYNTOKENS). Return YYENOMEM on memory exhaustion. - Return 0 if there are more than YYARGN expected tokens, yet fill - YYARG up to YYARGN. */ -static int -yypcontext_expected_tokens (const yypcontext_t *yyctx, - yysymbol_kind_t yyarg[], int yyargn) -{ - /* Actual size of YYARG. */ - int yycount = 0; - int yyn = yypact[+*yyctx->yyssp]; - if (!yypact_value_is_default (yyn)) - { - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. In other words, skip the first -YYN actions for - this state because they are default actions. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yyx; - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYSYMBOL_YYerror - && !yytable_value_is_error (yytable[yyx + yyn])) - { - if (!yyarg) - ++yycount; - else if (yycount == yyargn) - return 0; - else - yyarg[yycount++] = YY_CAST (yysymbol_kind_t, yyx); - } - } - if (yyarg && yycount == 0 && 0 < yyargn) - yyarg[0] = YYSYMBOL_YYEMPTY; - return yycount; -} - - - - -#ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen(S) (YY_CAST (YYPTRDIFF_T, strlen (S))) -# else -/* Return the length of YYSTR. */ -static YYPTRDIFF_T -yystrlen (const char *yystr) -{ - YYPTRDIFF_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; -} -# endif -#endif - -#ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -yystpcpy (char *yydest, const char *yysrc) -{ - char *yyd = yydest; - const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -#endif - -#ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYPTRDIFF_T -yytnamerr (char *yyres, const char *yystr) -{ - if (*yystr == '"') - { - YYPTRDIFF_T yyn = 0; - char const *yyp = yystr; - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; - - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - else - goto append; - - append: - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; - - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; - } - - if (yyres) - return yystpcpy (yyres, yystr) - yyres; - else - return yystrlen (yystr); -} -#endif - - -static int -yy_syntax_error_arguments (const yypcontext_t *yyctx, - yysymbol_kind_t yyarg[], int yyargn) -{ - /* Actual size of YYARG. */ - int yycount = 0; - /* There are many possibilities here to consider: - - If this state is a consistent state with a default action, then - the only way this function was invoked is if the default action - is an error action. In that case, don't check for expected - tokens because there are none. - - The only way there can be no lookahead present (in yychar) is if - this state is a consistent state with a default action. Thus, - detecting the absence of a lookahead is sufficient to determine - that there is no unexpected or expected token to report. In that - case, just report a simple "syntax error". - - Don't assume there isn't a lookahead just because this state is a - consistent state with a default action. There might have been a - previous inconsistent state, consistent state with a non-default - action, or user semantic action that manipulated yychar. - - Of course, the expected token list depends on states to have - correct lookahead information, and it depends on the parser not - to perform extra reductions after fetching a lookahead from the - scanner and before detecting a syntax error. Thus, state merging - (from LALR or IELR) and default reductions corrupt the expected - token list. However, the list is correct for canonical LR with - one exception: it will still contain any token that will not be - accepted due to an error action in a later state. - */ - if (yyctx->yytoken != YYSYMBOL_YYEMPTY) - { - int yyn; - if (yyarg) - yyarg[yycount] = yyctx->yytoken; - ++yycount; - yyn = yypcontext_expected_tokens (yyctx, - yyarg ? yyarg + 1 : yyarg, yyargn - 1); - if (yyn == YYENOMEM) - return YYENOMEM; - else - yycount += yyn; - } - return yycount; -} - -/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message - about the unexpected token YYTOKEN for the state stack whose top is - YYSSP. - - Return 0 if *YYMSG was successfully written. Return -1 if *YYMSG is - not large enough to hold the message. In that case, also set - *YYMSG_ALLOC to the required number of bytes. Return YYENOMEM if the - required number of bytes is too large to store. */ -static int -yysyntax_error (YYPTRDIFF_T *yymsg_alloc, char **yymsg, - const yypcontext_t *yyctx) -{ - enum { YYARGS_MAX = 5 }; - /* Internationalized format string. */ - const char *yyformat = YY_NULLPTR; - /* Arguments of yyformat: reported tokens (one for the "unexpected", - one per "expected"). */ - yysymbol_kind_t yyarg[YYARGS_MAX]; - /* Cumulated lengths of YYARG. */ - YYPTRDIFF_T yysize = 0; - - /* Actual size of YYARG. */ - int yycount = yy_syntax_error_arguments (yyctx, yyarg, YYARGS_MAX); - if (yycount == YYENOMEM) - return YYENOMEM; - - switch (yycount) - { -#define YYCASE_(N, S) \ - case N: \ - yyformat = S; \ - break - default: /* Avoid compiler warnings. */ - YYCASE_(0, YY_("syntax error")); - YYCASE_(1, YY_("syntax error, unexpected %s")); - YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); - YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); - YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); - YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); -#undef YYCASE_ - } - - /* Compute error message size. Don't count the "%s"s, but reserve - room for the terminator. */ - yysize = yystrlen (yyformat) - 2 * yycount + 1; - { - int yyi; - for (yyi = 0; yyi < yycount; ++yyi) - { - YYPTRDIFF_T yysize1 - = yysize + yytnamerr (YY_NULLPTR, yytname[yyarg[yyi]]); - if (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM) - yysize = yysize1; - else - return YYENOMEM; - } - } - - if (*yymsg_alloc < yysize) - { - *yymsg_alloc = 2 * yysize; - if (! (yysize <= *yymsg_alloc - && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) - *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; - return -1; - } - - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - { - char *yyp = *yymsg; - int yyi = 0; - while ((*yyp = *yyformat) != '\0') - if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yytname[yyarg[yyi++]]); - yyformat += 2; - } - else - { - ++yyp; - ++yyformat; - } - } - return 0; -} - - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -static void -yydestruct (const char *yymsg, - yysymbol_kind_t yykind, YYSTYPE *yyvaluep, glslang::TParseContext* pParseContext) -{ - YY_USE (yyvaluep); - YY_USE (pParseContext); - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yykind, yyvaluep, yylocationp); - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - YY_USE (yykind); - YY_IGNORE_MAYBE_UNINITIALIZED_END -} - - - - - - -/*----------. -| yyparse. | -`----------*/ - -int -yyparse (glslang::TParseContext* pParseContext) -{ -/* Lookahead token kind. */ -int yychar; - - -/* The semantic value of the lookahead symbol. */ -/* Default value used for initialization, for pacifying older GCCs - or non-GCC compilers. */ -YY_INITIAL_VALUE (static YYSTYPE yyval_default;) -YYSTYPE yylval YY_INITIAL_VALUE (= yyval_default); - - /* Number of syntax errors so far. */ - int yynerrs = 0; - - yy_state_fast_t yystate = 0; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus = 0; - - /* Refer to the stacks through separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* Their size. */ - YYPTRDIFF_T yystacksize = YYINITDEPTH; - - /* The state stack: array, bottom, top. */ - yy_state_t yyssa[YYINITDEPTH]; - yy_state_t *yyss = yyssa; - yy_state_t *yyssp = yyss; - - /* The semantic value stack: array, bottom, top. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp = yyvs; - - int yyn; - /* The return value of yyparse. */ - int yyresult; - /* Lookahead symbol kind. */ - yysymbol_kind_t yytoken = YYSYMBOL_YYEMPTY; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYPTRDIFF_T yymsg_alloc = sizeof yymsgbuf; - -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) - - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; - - YYDPRINTF ((stderr, "Starting parse\n")); - - yychar = YYEMPTY; /* Cause a token to be read. */ - - goto yysetstate; - - -/*------------------------------------------------------------. -| yynewstate -- push a new state, which is found in yystate. | -`------------------------------------------------------------*/ -yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; - - -/*--------------------------------------------------------------------. -| yysetstate -- set current state (the top of the stack) to yystate. | -`--------------------------------------------------------------------*/ -yysetstate: - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); - YY_ASSERT (0 <= yystate && yystate < YYNSTATES); - YY_IGNORE_USELESS_CAST_BEGIN - *yyssp = YY_CAST (yy_state_t, yystate); - YY_IGNORE_USELESS_CAST_END - YY_STACK_PRINT (yyss, yyssp); - - if (yyss + yystacksize - 1 <= yyssp) -#if !defined yyoverflow && !defined YYSTACK_RELOCATE - YYNOMEM; -#else - { - /* Get the current used size of the three stacks, in elements. */ - YYPTRDIFF_T yysize = yyssp - yyss + 1; - -# if defined yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - yy_state_t *yyss1 = yyss; - YYSTYPE *yyvs1 = yyvs; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * YYSIZEOF (*yyssp), - &yyvs1, yysize * YYSIZEOF (*yyvsp), - &yystacksize); - yyss = yyss1; - yyvs = yyvs1; - } -# else /* defined YYSTACK_RELOCATE */ - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - YYNOMEM; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; - - { - yy_state_t *yyss1 = yyss; - union yyalloc *yyptr = - YY_CAST (union yyalloc *, - YYSTACK_ALLOC (YY_CAST (YYSIZE_T, YYSTACK_BYTES (yystacksize)))); - if (! yyptr) - YYNOMEM; - YYSTACK_RELOCATE (yyss_alloc, yyss); - YYSTACK_RELOCATE (yyvs_alloc, yyvs); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif - - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - - YY_IGNORE_USELESS_CAST_BEGIN - YYDPRINTF ((stderr, "Stack size increased to %ld\n", - YY_CAST (long, yystacksize))); - YY_IGNORE_USELESS_CAST_END - - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; - } -#endif /* !defined yyoverflow && !defined YYSTACK_RELOCATE */ - - - if (yystate == YYFINAL) - YYACCEPT; - - goto yybackup; - - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: - /* Do appropriate processing given the current state. Read a - lookahead token if we need one and don't already have one. */ - - /* First try to decide what to do without reference to lookahead token. */ - yyn = yypact[yystate]; - if (yypact_value_is_default (yyn)) - goto yydefault; - - /* Not known => get a lookahead token if don't already have one. */ - - /* YYCHAR is either empty, or end-of-input, or a valid lookahead. */ - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token\n")); - yychar = yylex (&yylval, parseContext); - } - - if (yychar <= YYEOF) - { - yychar = YYEOF; - yytoken = YYSYMBOL_YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); - } - else if (yychar == YYerror) - { - /* The scanner already issued an error message, process directly - to error recovery. But do not keep the error token as - lookahead, it is too special and may lead us to an endless - loop in error recovery. */ - yychar = YYUNDEF; - yytoken = YYSYMBOL_YYerror; - goto yyerrlab1; - } - else - { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); - } - - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) - { - if (yytable_value_is_error (yyn)) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; - } - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; - - /* Shift the lookahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); - yystate = yyn; - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - /* Discard the shifted token. */ - yychar = YYEMPTY; - goto yynewstate; - - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; - - -/*-----------------------------. -| yyreduce -- do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - '$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: /* variable_identifier: IDENTIFIER */ -#line 355 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleVariable((yyvsp[0].lex).loc, (yyvsp[0].lex).symbol, (yyvsp[0].lex).string); - } -#line 5211 "MachineIndependent/glslang_tab.cpp" - break; - - case 3: /* primary_expression: variable_identifier */ -#line 361 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 5219 "MachineIndependent/glslang_tab.cpp" - break; - - case 4: /* primary_expression: LEFT_PAREN expression RIGHT_PAREN */ -#line 364 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); - if ((yyval.interm.intermTypedNode)->getAsConstantUnion()) - (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression(); - } -#line 5229 "MachineIndependent/glslang_tab.cpp" - break; - - case 5: /* primary_expression: FLOATCONSTANT */ -#line 369 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); - } -#line 5237 "MachineIndependent/glslang_tab.cpp" - break; - - case 6: /* primary_expression: INTCONSTANT */ -#line 372 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 5245 "MachineIndependent/glslang_tab.cpp" - break; - - case 7: /* primary_expression: UINTCONSTANT */ -#line 375 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 5254 "MachineIndependent/glslang_tab.cpp" - break; - - case 8: /* primary_expression: BOOLCONSTANT */ -#line 379 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); - } -#line 5262 "MachineIndependent/glslang_tab.cpp" - break; - - case 9: /* primary_expression: STRING_LITERAL */ -#line 382 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true); - } -#line 5270 "MachineIndependent/glslang_tab.cpp" - break; - - case 10: /* primary_expression: INT32CONSTANT */ -#line 385 "MachineIndependent/glslang.y" - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 5279 "MachineIndependent/glslang_tab.cpp" - break; - - case 11: /* primary_expression: UINT32CONSTANT */ -#line 389 "MachineIndependent/glslang.y" - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 5288 "MachineIndependent/glslang_tab.cpp" - break; - - case 12: /* primary_expression: INT64CONSTANT */ -#line 393 "MachineIndependent/glslang.y" - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i64, (yyvsp[0].lex).loc, true); - } -#line 5297 "MachineIndependent/glslang_tab.cpp" - break; - - case 13: /* primary_expression: UINT64CONSTANT */ -#line 397 "MachineIndependent/glslang.y" - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u64, (yyvsp[0].lex).loc, true); - } -#line 5306 "MachineIndependent/glslang_tab.cpp" - break; - - case 14: /* primary_expression: INT16CONSTANT */ -#line 401 "MachineIndependent/glslang.y" - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((short)(yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 5315 "MachineIndependent/glslang_tab.cpp" - break; - - case 15: /* primary_expression: UINT16CONSTANT */ -#line 405 "MachineIndependent/glslang.y" - { - parseContext.explicitInt16Check((yyvsp[0].lex).loc, "16-bit unsigned integer literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((unsigned short)(yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 5324 "MachineIndependent/glslang_tab.cpp" - break; - - case 16: /* primary_expression: DOUBLECONSTANT */ -#line 409 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double literal"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtDouble, (yyvsp[0].lex).loc, true); - } -#line 5335 "MachineIndependent/glslang_tab.cpp" - break; - - case 17: /* primary_expression: FLOAT16CONSTANT */ -#line 415 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float literal"); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat16, (yyvsp[0].lex).loc, true); - } -#line 5344 "MachineIndependent/glslang_tab.cpp" - break; - - case 18: /* postfix_expression: primary_expression */ -#line 422 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 5352 "MachineIndependent/glslang_tab.cpp" - break; - - case 19: /* postfix_expression: postfix_expression LEFT_BRACKET integer_expression RIGHT_BRACKET */ -#line 425 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBracketDereference((yyvsp[-2].lex).loc, (yyvsp[-3].interm.intermTypedNode), (yyvsp[-1].interm.intermTypedNode)); - } -#line 5360 "MachineIndependent/glslang_tab.cpp" - break; - - case 20: /* postfix_expression: function_call */ -#line 428 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 5368 "MachineIndependent/glslang_tab.cpp" - break; - - case 21: /* postfix_expression: postfix_expression DOT IDENTIFIER */ -#line 431 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleDotDereference((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode), *(yyvsp[0].lex).string); - } -#line 5376 "MachineIndependent/glslang_tab.cpp" - break; - - case 22: /* postfix_expression: postfix_expression INC_OP */ -#line 434 "MachineIndependent/glslang.y" - { - parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); - parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "++", (yyvsp[-1].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "++", EOpPostIncrement, (yyvsp[-1].interm.intermTypedNode)); - } -#line 5386 "MachineIndependent/glslang_tab.cpp" - break; - - case 23: /* postfix_expression: postfix_expression DEC_OP */ -#line 439 "MachineIndependent/glslang.y" - { - parseContext.variableCheck((yyvsp[-1].interm.intermTypedNode)); - parseContext.lValueErrorCheck((yyvsp[0].lex).loc, "--", (yyvsp[-1].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[0].lex).loc, "--", EOpPostDecrement, (yyvsp[-1].interm.intermTypedNode)); - } -#line 5396 "MachineIndependent/glslang_tab.cpp" - break; - - case 24: /* integer_expression: expression */ -#line 447 "MachineIndependent/glslang.y" - { - parseContext.integerCheck((yyvsp[0].interm.intermTypedNode), "[]"); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 5405 "MachineIndependent/glslang_tab.cpp" - break; - - case 25: /* function_call: function_call_or_method */ -#line 454 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleFunctionCall((yyvsp[0].interm).loc, (yyvsp[0].interm).function, (yyvsp[0].interm).intermNode); - delete (yyvsp[0].interm).function; - } -#line 5414 "MachineIndependent/glslang_tab.cpp" - break; - - case 26: /* function_call_or_method: function_call_generic */ -#line 461 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[0].interm); - } -#line 5422 "MachineIndependent/glslang_tab.cpp" - break; - - case 27: /* function_call_generic: function_call_header_with_parameters RIGHT_PAREN */ -#line 467 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[-1].interm); - (yyval.interm).loc = (yyvsp[0].lex).loc; - } -#line 5431 "MachineIndependent/glslang_tab.cpp" - break; - - case 28: /* function_call_generic: function_call_header_no_parameters RIGHT_PAREN */ -#line 471 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[-1].interm); - (yyval.interm).loc = (yyvsp[0].lex).loc; - } -#line 5440 "MachineIndependent/glslang_tab.cpp" - break; - - case 29: /* function_call_header_no_parameters: function_call_header VOID */ -#line 478 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[-1].interm); - } -#line 5448 "MachineIndependent/glslang_tab.cpp" - break; - - case 30: /* function_call_header_no_parameters: function_call_header */ -#line 481 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[0].interm); - } -#line 5456 "MachineIndependent/glslang_tab.cpp" - break; - - case 31: /* function_call_header_with_parameters: function_call_header assignment_expression */ -#line 487 "MachineIndependent/glslang.y" - { - if (parseContext.spvVersion.vulkan > 0 - && parseContext.spvVersion.vulkanRelaxed - && (yyvsp[0].interm.intermTypedNode)->getType().containsOpaque()) - { - (yyval.interm).intermNode = parseContext.vkRelaxedRemapFunctionArgument((yyval.interm).loc, (yyvsp[-1].interm).function, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).function = (yyvsp[-1].interm).function; - } - else - { - TParameter param = { 0, new TType }; - param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); - - (yyvsp[-1].interm).function->addParameter(param); - (yyval.interm).function = (yyvsp[-1].interm).function; - (yyval.interm).intermNode = (yyvsp[0].interm.intermTypedNode); - } - } -#line 5479 "MachineIndependent/glslang_tab.cpp" - break; - - case 32: /* function_call_header_with_parameters: function_call_header_with_parameters COMMA assignment_expression */ -#line 505 "MachineIndependent/glslang.y" - { - if (parseContext.spvVersion.vulkan > 0 - && parseContext.spvVersion.vulkanRelaxed - && (yyvsp[0].interm.intermTypedNode)->getType().containsOpaque()) - { - TIntermNode* remappedNode = parseContext.vkRelaxedRemapFunctionArgument((yyvsp[-1].lex).loc, (yyvsp[-2].interm).function, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.mergeAggregate((yyvsp[-2].interm).intermNode, remappedNode, (yyvsp[-1].lex).loc); - (yyval.interm).function = (yyvsp[-2].interm).function; - } - else - { - TParameter param = { 0, new TType }; - param.type->shallowCopy((yyvsp[0].interm.intermTypedNode)->getType()); - - (yyvsp[-2].interm).function->addParameter(param); - (yyval.interm).function = (yyvsp[-2].interm).function; - (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc); - } - } -#line 5503 "MachineIndependent/glslang_tab.cpp" - break; - - case 33: /* function_call_header: function_identifier LEFT_PAREN */ -#line 527 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[-1].interm); - } -#line 5511 "MachineIndependent/glslang_tab.cpp" - break; - - case 34: /* function_identifier: type_specifier */ -#line 535 "MachineIndependent/glslang.y" - { - // Constructor - (yyval.interm).intermNode = 0; - (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); - } -#line 5521 "MachineIndependent/glslang_tab.cpp" - break; - - case 35: /* function_identifier: postfix_expression */ -#line 540 "MachineIndependent/glslang.y" - { - // - // Should be a method or subroutine call, but we haven't recognized the arguments yet. - // - (yyval.interm).function = 0; - (yyval.interm).intermNode = 0; - - TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode(); - if (method) { - (yyval.interm).function = new TFunction(&method->getMethodName(), TType(EbtInt), EOpArrayLength); - (yyval.interm).intermNode = method->getObject(); - } else { - TIntermSymbol* symbol = (yyvsp[0].interm.intermTypedNode)->getAsSymbolNode(); - if (symbol) { - parseContext.reservedErrorCheck(symbol->getLoc(), symbol->getName()); - TFunction *function = new TFunction(&symbol->getName(), TType(EbtVoid)); - (yyval.interm).function = function; - } else - parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "function call, method, or subroutine call expected", "", ""); - } - - if ((yyval.interm).function == 0) { - // error recover - TString* empty = NewPoolTString(""); - (yyval.interm).function = new TFunction(empty, TType(EbtVoid), EOpNull); - } - } -#line 5553 "MachineIndependent/glslang_tab.cpp" - break; - - case 36: /* function_identifier: non_uniform_qualifier */ -#line 567 "MachineIndependent/glslang.y" - { - // Constructor - (yyval.interm).intermNode = 0; - (yyval.interm).function = parseContext.handleConstructorCall((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); - } -#line 5563 "MachineIndependent/glslang_tab.cpp" - break; - - case 37: /* unary_expression: postfix_expression */ -#line 575 "MachineIndependent/glslang.y" - { - parseContext.variableCheck((yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - if (TIntermMethod* method = (yyvsp[0].interm.intermTypedNode)->getAsMethodNode()) - parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "incomplete method syntax", method->getMethodName().c_str(), ""); - } -#line 5574 "MachineIndependent/glslang_tab.cpp" - break; - - case 38: /* unary_expression: INC_OP unary_expression */ -#line 581 "MachineIndependent/glslang.y" - { - parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "++", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "++", EOpPreIncrement, (yyvsp[0].interm.intermTypedNode)); - } -#line 5583 "MachineIndependent/glslang_tab.cpp" - break; - - case 39: /* unary_expression: DEC_OP unary_expression */ -#line 585 "MachineIndependent/glslang.y" - { - parseContext.lValueErrorCheck((yyvsp[-1].lex).loc, "--", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].lex).loc, "--", EOpPreDecrement, (yyvsp[0].interm.intermTypedNode)); - } -#line 5592 "MachineIndependent/glslang_tab.cpp" - break; - - case 40: /* unary_expression: unary_operator unary_expression */ -#line 589 "MachineIndependent/glslang.y" - { - if ((yyvsp[-1].interm).op != EOpNull) { - char errorOp[2] = {0, 0}; - switch((yyvsp[-1].interm).op) { - case EOpNegative: errorOp[0] = '-'; break; - case EOpLogicalNot: errorOp[0] = '!'; break; - case EOpBitwiseNot: errorOp[0] = '~'; break; - default: break; // some compilers want this - } - (yyval.interm.intermTypedNode) = parseContext.handleUnaryMath((yyvsp[-1].interm).loc, errorOp, (yyvsp[-1].interm).op, (yyvsp[0].interm.intermTypedNode)); - } else { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - if ((yyval.interm.intermTypedNode)->getAsConstantUnion()) - (yyval.interm.intermTypedNode)->getAsConstantUnion()->setExpression(); - } - } -#line 5613 "MachineIndependent/glslang_tab.cpp" - break; - - case 41: /* unary_operator: PLUS */ -#line 609 "MachineIndependent/glslang.y" - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNull; } -#line 5619 "MachineIndependent/glslang_tab.cpp" - break; - - case 42: /* unary_operator: DASH */ -#line 610 "MachineIndependent/glslang.y" - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpNegative; } -#line 5625 "MachineIndependent/glslang_tab.cpp" - break; - - case 43: /* unary_operator: BANG */ -#line 611 "MachineIndependent/glslang.y" - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLogicalNot; } -#line 5631 "MachineIndependent/glslang_tab.cpp" - break; - - case 44: /* unary_operator: TILDE */ -#line 612 "MachineIndependent/glslang.y" - { (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpBitwiseNot; - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise not"); } -#line 5638 "MachineIndependent/glslang_tab.cpp" - break; - - case 45: /* multiplicative_expression: unary_expression */ -#line 618 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5644 "MachineIndependent/glslang_tab.cpp" - break; - - case 46: /* multiplicative_expression: multiplicative_expression STAR unary_expression */ -#line 619 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "*", EOpMul, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 5654 "MachineIndependent/glslang_tab.cpp" - break; - - case 47: /* multiplicative_expression: multiplicative_expression SLASH unary_expression */ -#line 624 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "/", EOpDiv, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 5664 "MachineIndependent/glslang_tab.cpp" - break; - - case 48: /* multiplicative_expression: multiplicative_expression PERCENT unary_expression */ -#line 629 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "%"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "%", EOpMod, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 5675 "MachineIndependent/glslang_tab.cpp" - break; - - case 49: /* additive_expression: multiplicative_expression */ -#line 638 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5681 "MachineIndependent/glslang_tab.cpp" - break; - - case 50: /* additive_expression: additive_expression PLUS multiplicative_expression */ -#line 639 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "+", EOpAdd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 5691 "MachineIndependent/glslang_tab.cpp" - break; - - case 51: /* additive_expression: additive_expression DASH multiplicative_expression */ -#line 644 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "-", EOpSub, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 5701 "MachineIndependent/glslang_tab.cpp" - break; - - case 52: /* shift_expression: additive_expression */ -#line 652 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5707 "MachineIndependent/glslang_tab.cpp" - break; - - case 53: /* shift_expression: shift_expression LEFT_OP additive_expression */ -#line 653 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift left"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<<", EOpLeftShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 5718 "MachineIndependent/glslang_tab.cpp" - break; - - case 54: /* shift_expression: shift_expression RIGHT_OP additive_expression */ -#line 659 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bit shift right"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">>", EOpRightShift, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 5729 "MachineIndependent/glslang_tab.cpp" - break; - - case 55: /* relational_expression: shift_expression */ -#line 668 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5735 "MachineIndependent/glslang_tab.cpp" - break; - - case 56: /* relational_expression: relational_expression LEFT_ANGLE shift_expression */ -#line 669 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<", EOpLessThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 5745 "MachineIndependent/glslang_tab.cpp" - break; - - case 57: /* relational_expression: relational_expression RIGHT_ANGLE shift_expression */ -#line 674 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">", EOpGreaterThan, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 5755 "MachineIndependent/glslang_tab.cpp" - break; - - case 58: /* relational_expression: relational_expression LE_OP shift_expression */ -#line 679 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "<=", EOpLessThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 5765 "MachineIndependent/glslang_tab.cpp" - break; - - case 59: /* relational_expression: relational_expression GE_OP shift_expression */ -#line 684 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, ">=", EOpGreaterThanEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 5775 "MachineIndependent/glslang_tab.cpp" - break; - - case 60: /* equality_expression: relational_expression */ -#line 692 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5781 "MachineIndependent/glslang_tab.cpp" - break; - - case 61: /* equality_expression: equality_expression EQ_OP relational_expression */ -#line 693 "MachineIndependent/glslang.y" - { - parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); - parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); - parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); - parseContext.referenceCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "=="); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "==", EOpEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 5795 "MachineIndependent/glslang_tab.cpp" - break; - - case 62: /* equality_expression: equality_expression NE_OP relational_expression */ -#line 702 "MachineIndependent/glslang.y" - { - parseContext.arrayObjectCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array comparison"); - parseContext.opaqueCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); - parseContext.specializationCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); - parseContext.referenceCheck((yyvsp[-1].lex).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "!="); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "!=", EOpNotEqual, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 5809 "MachineIndependent/glslang_tab.cpp" - break; - - case 63: /* and_expression: equality_expression */ -#line 714 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5815 "MachineIndependent/glslang_tab.cpp" - break; - - case 64: /* and_expression: and_expression AMPERSAND equality_expression */ -#line 715 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise and"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&", EOpAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 5826 "MachineIndependent/glslang_tab.cpp" - break; - - case 65: /* exclusive_or_expression: and_expression */ -#line 724 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5832 "MachineIndependent/glslang_tab.cpp" - break; - - case 66: /* exclusive_or_expression: exclusive_or_expression CARET and_expression */ -#line 725 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise exclusive or"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^", EOpExclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 5843 "MachineIndependent/glslang_tab.cpp" - break; - - case 67: /* inclusive_or_expression: exclusive_or_expression */ -#line 734 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5849 "MachineIndependent/glslang_tab.cpp" - break; - - case 68: /* inclusive_or_expression: inclusive_or_expression VERTICAL_BAR exclusive_or_expression */ -#line 735 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[-1].lex).loc, "bitwise inclusive or"); - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "|", EOpInclusiveOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 5860 "MachineIndependent/glslang_tab.cpp" - break; - - case 69: /* logical_and_expression: inclusive_or_expression */ -#line 744 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5866 "MachineIndependent/glslang_tab.cpp" - break; - - case 70: /* logical_and_expression: logical_and_expression AND_OP inclusive_or_expression */ -#line 745 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "&&", EOpLogicalAnd, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 5876 "MachineIndependent/glslang_tab.cpp" - break; - - case 71: /* logical_xor_expression: logical_and_expression */ -#line 753 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5882 "MachineIndependent/glslang_tab.cpp" - break; - - case 72: /* logical_xor_expression: logical_xor_expression XOR_OP logical_and_expression */ -#line 754 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "^^", EOpLogicalXor, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 5892 "MachineIndependent/glslang_tab.cpp" - break; - - case 73: /* logical_or_expression: logical_xor_expression */ -#line 762 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5898 "MachineIndependent/glslang_tab.cpp" - break; - - case 74: /* logical_or_expression: logical_or_expression OR_OP logical_xor_expression */ -#line 763 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.handleBinaryMath((yyvsp[-1].lex).loc, "||", EOpLogicalOr, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) - (yyval.interm.intermTypedNode) = parseContext.intermediate.addConstantUnion(false, (yyvsp[-1].lex).loc); - } -#line 5908 "MachineIndependent/glslang_tab.cpp" - break; - - case 75: /* conditional_expression: logical_or_expression */ -#line 771 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5914 "MachineIndependent/glslang_tab.cpp" - break; - - case 76: /* $@1: %empty */ -#line 772 "MachineIndependent/glslang.y" - { - ++parseContext.controlFlowNestingLevel; - } -#line 5922 "MachineIndependent/glslang_tab.cpp" - break; - - case 77: /* conditional_expression: logical_or_expression QUESTION $@1 expression COLON assignment_expression */ -#line 775 "MachineIndependent/glslang.y" - { - --parseContext.controlFlowNestingLevel; - parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-5].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-4].lex).loc, "?", (yyvsp[-5].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-1].lex).loc, ":", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addSelection((yyvsp[-5].interm.intermTypedNode), (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-4].lex).loc); - if ((yyval.interm.intermTypedNode) == 0) { - parseContext.binaryOpError((yyvsp[-4].lex).loc, ":", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), (yyvsp[0].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs())); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } - } -#line 5939 "MachineIndependent/glslang_tab.cpp" - break; - - case 78: /* assignment_expression: conditional_expression */ -#line 790 "MachineIndependent/glslang.y" - { (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); } -#line 5945 "MachineIndependent/glslang_tab.cpp" - break; - - case 79: /* assignment_expression: unary_expression assignment_operator assignment_expression */ -#line 791 "MachineIndependent/glslang.y" - { - parseContext.arrayObjectCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "array assignment"); - parseContext.opaqueCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); - parseContext.storage16BitAssignmentCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); - parseContext.specializationCheck((yyvsp[-1].interm).loc, (yyvsp[-2].interm.intermTypedNode)->getType(), "="); - parseContext.lValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)); - parseContext.rValueErrorCheck((yyvsp[-1].interm).loc, "assign", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.addAssign((yyvsp[-1].interm).loc, (yyvsp[-1].interm).op, (yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - if ((yyval.interm.intermTypedNode) == 0) { - parseContext.assignError((yyvsp[-1].interm).loc, "assign", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), (yyvsp[0].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs())); - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } - } -#line 5963 "MachineIndependent/glslang_tab.cpp" - break; - - case 80: /* assignment_operator: EQUAL */ -#line 807 "MachineIndependent/glslang.y" - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpAssign; - } -#line 5972 "MachineIndependent/glslang_tab.cpp" - break; - - case 81: /* assignment_operator: MUL_ASSIGN */ -#line 811 "MachineIndependent/glslang.y" - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpMulAssign; - } -#line 5981 "MachineIndependent/glslang_tab.cpp" - break; - - case 82: /* assignment_operator: DIV_ASSIGN */ -#line 815 "MachineIndependent/glslang.y" - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpDivAssign; - } -#line 5990 "MachineIndependent/glslang_tab.cpp" - break; - - case 83: /* assignment_operator: MOD_ASSIGN */ -#line 819 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "%="); - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpModAssign; - } -#line 6000 "MachineIndependent/glslang_tab.cpp" - break; - - case 84: /* assignment_operator: ADD_ASSIGN */ -#line 824 "MachineIndependent/glslang.y" - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpAddAssign; - } -#line 6009 "MachineIndependent/glslang_tab.cpp" - break; - - case 85: /* assignment_operator: SUB_ASSIGN */ -#line 828 "MachineIndependent/glslang.y" - { - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).op = EOpSubAssign; - } -#line 6018 "MachineIndependent/glslang_tab.cpp" - break; - - case 86: /* assignment_operator: LEFT_ASSIGN */ -#line 832 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift left assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpLeftShiftAssign; - } -#line 6027 "MachineIndependent/glslang_tab.cpp" - break; - - case 87: /* assignment_operator: RIGHT_ASSIGN */ -#line 836 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bit-shift right assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpRightShiftAssign; - } -#line 6036 "MachineIndependent/glslang_tab.cpp" - break; - - case 88: /* assignment_operator: AND_ASSIGN */ -#line 840 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-and assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpAndAssign; - } -#line 6045 "MachineIndependent/glslang_tab.cpp" - break; - - case 89: /* assignment_operator: XOR_ASSIGN */ -#line 844 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-xor assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpExclusiveOrAssign; - } -#line 6054 "MachineIndependent/glslang_tab.cpp" - break; - - case 90: /* assignment_operator: OR_ASSIGN */ -#line 848 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "bitwise-or assign"); - (yyval.interm).loc = (yyvsp[0].lex).loc; (yyval.interm).op = EOpInclusiveOrAssign; - } -#line 6063 "MachineIndependent/glslang_tab.cpp" - break; - - case 91: /* expression: assignment_expression */ -#line 855 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 6071 "MachineIndependent/glslang_tab.cpp" - break; - - case 92: /* expression: expression COMMA assignment_expression */ -#line 858 "MachineIndependent/glslang.y" - { - parseContext.samplerConstructorLocationCheck((yyvsp[-1].lex).loc, ",", (yyvsp[0].interm.intermTypedNode)); - (yyval.interm.intermTypedNode) = parseContext.intermediate.addComma((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode), (yyvsp[-1].lex).loc); - if ((yyval.interm.intermTypedNode) == 0) { - parseContext.binaryOpError((yyvsp[-1].lex).loc, ",", (yyvsp[-2].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), (yyvsp[0].interm.intermTypedNode)->getCompleteString(parseContext.intermediate.getEnhancedMsgs())); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } - } -#line 6084 "MachineIndependent/glslang_tab.cpp" - break; - - case 93: /* constant_expression: conditional_expression */ -#line 869 "MachineIndependent/glslang.y" - { - parseContext.constantValueCheck((yyvsp[0].interm.intermTypedNode), ""); - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 6093 "MachineIndependent/glslang_tab.cpp" - break; - - case 94: /* declaration: function_prototype SEMICOLON */ -#line 876 "MachineIndependent/glslang.y" - { - parseContext.handleFunctionDeclarator((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).function, true /* prototype */); - (yyval.interm.intermNode) = 0; - // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature - } -#line 6103 "MachineIndependent/glslang_tab.cpp" - break; - - case 95: /* declaration: spirv_instruction_qualifier function_prototype SEMICOLON */ -#line 881 "MachineIndependent/glslang.y" - { - parseContext.requireExtensions((yyvsp[-1].interm).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V instruction qualifier"); - (yyvsp[-1].interm).function->setSpirvInstruction(*(yyvsp[-2].interm.spirvInst)); // Attach SPIR-V intruction qualifier - parseContext.handleFunctionDeclarator((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).function, true /* prototype */); - (yyval.interm.intermNode) = 0; - // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature - } -#line 6115 "MachineIndependent/glslang_tab.cpp" - break; - - case 96: /* declaration: spirv_execution_mode_qualifier SEMICOLON */ -#line 888 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "SPIR-V execution mode qualifier"); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V execution mode qualifier"); - (yyval.interm.intermNode) = 0; - } -#line 6125 "MachineIndependent/glslang_tab.cpp" - break; - - case 97: /* declaration: init_declarator_list SEMICOLON */ -#line 893 "MachineIndependent/glslang.y" - { - if ((yyvsp[-1].interm).intermNode && (yyvsp[-1].interm).intermNode->getAsAggregate()) - (yyvsp[-1].interm).intermNode->getAsAggregate()->setOperator(EOpSequence); - (yyval.interm.intermNode) = (yyvsp[-1].interm).intermNode; - } -#line 6135 "MachineIndependent/glslang_tab.cpp" - break; - - case 98: /* declaration: PRECISION precision_qualifier type_specifier SEMICOLON */ -#line 898 "MachineIndependent/glslang.y" - { - parseContext.profileRequires((yyvsp[-3].lex).loc, ENoProfile, 130, 0, "precision statement"); - // lazy setting of the previous scope's defaults, has effect only the first time it is called in a particular scope - parseContext.symbolTable.setPreviousDefaultPrecisions(&parseContext.defaultPrecision[0]); - parseContext.setDefaultPrecision((yyvsp[-3].lex).loc, (yyvsp[-1].interm.type), (yyvsp[-2].interm.type).qualifier.precision); - (yyval.interm.intermNode) = 0; - } -#line 6147 "MachineIndependent/glslang_tab.cpp" - break; - - case 99: /* declaration: block_structure SEMICOLON */ -#line 905 "MachineIndependent/glslang.y" - { - parseContext.declareBlock((yyvsp[-1].interm).loc, *(yyvsp[-1].interm).typeList); - (yyval.interm.intermNode) = 0; - } -#line 6156 "MachineIndependent/glslang_tab.cpp" - break; - - case 100: /* declaration: block_structure IDENTIFIER SEMICOLON */ -#line 909 "MachineIndependent/glslang.y" - { - parseContext.declareBlock((yyvsp[-2].interm).loc, *(yyvsp[-2].interm).typeList, (yyvsp[-1].lex).string); - (yyval.interm.intermNode) = 0; - } -#line 6165 "MachineIndependent/glslang_tab.cpp" - break; - - case 101: /* declaration: block_structure IDENTIFIER array_specifier SEMICOLON */ -#line 913 "MachineIndependent/glslang.y" - { - parseContext.declareBlock((yyvsp[-3].interm).loc, *(yyvsp[-3].interm).typeList, (yyvsp[-2].lex).string, (yyvsp[-1].interm).arraySizes); - (yyval.interm.intermNode) = 0; - } -#line 6174 "MachineIndependent/glslang_tab.cpp" - break; - - case 102: /* declaration: type_qualifier SEMICOLON */ -#line 917 "MachineIndependent/glslang.y" - { - parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier); - parseContext.updateStandaloneQualifierDefaults((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type)); - (yyval.interm.intermNode) = 0; - } -#line 6184 "MachineIndependent/glslang_tab.cpp" - break; - - case 103: /* declaration: type_qualifier IDENTIFIER SEMICOLON */ -#line 922 "MachineIndependent/glslang.y" - { - parseContext.checkNoShaderLayouts((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).shaderQualifiers); - parseContext.addQualifierToExisting((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, *(yyvsp[-1].lex).string); - (yyval.interm.intermNode) = 0; - } -#line 6194 "MachineIndependent/glslang_tab.cpp" - break; - - case 104: /* declaration: type_qualifier IDENTIFIER identifier_list SEMICOLON */ -#line 927 "MachineIndependent/glslang.y" - { - parseContext.checkNoShaderLayouts((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).shaderQualifiers); - (yyvsp[-1].interm.identifierList)->push_back((yyvsp[-2].lex).string); - parseContext.addQualifierToExisting((yyvsp[-3].interm.type).loc, (yyvsp[-3].interm.type).qualifier, *(yyvsp[-1].interm.identifierList)); - (yyval.interm.intermNode) = 0; - } -#line 6205 "MachineIndependent/glslang_tab.cpp" - break; - - case 105: /* $@2: %empty */ -#line 936 "MachineIndependent/glslang.y" - { parseContext.nestedBlockCheck((yyvsp[-2].interm.type).loc); } -#line 6211 "MachineIndependent/glslang_tab.cpp" - break; - - case 106: /* block_structure: type_qualifier IDENTIFIER LEFT_BRACE $@2 struct_declaration_list RIGHT_BRACE */ -#line 936 "MachineIndependent/glslang.y" - { - --parseContext.blockNestingLevel; - parseContext.blockName = (yyvsp[-4].lex).string; - parseContext.globalQualifierFixCheck((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).qualifier); - parseContext.checkNoShaderLayouts((yyvsp[-5].interm.type).loc, (yyvsp[-5].interm.type).shaderQualifiers); - parseContext.currentBlockQualifier = (yyvsp[-5].interm.type).qualifier; - (yyval.interm).loc = (yyvsp[-5].interm.type).loc; - (yyval.interm).typeList = (yyvsp[-1].interm.typeList); - } -#line 6225 "MachineIndependent/glslang_tab.cpp" - break; - - case 107: /* identifier_list: COMMA IDENTIFIER */ -#line 947 "MachineIndependent/glslang.y" - { - (yyval.interm.identifierList) = new TIdentifierList; - (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); - } -#line 6234 "MachineIndependent/glslang_tab.cpp" - break; - - case 108: /* identifier_list: identifier_list COMMA IDENTIFIER */ -#line 951 "MachineIndependent/glslang.y" - { - (yyval.interm.identifierList) = (yyvsp[-2].interm.identifierList); - (yyval.interm.identifierList)->push_back((yyvsp[0].lex).string); - } -#line 6243 "MachineIndependent/glslang_tab.cpp" - break; - - case 109: /* function_prototype: function_declarator RIGHT_PAREN */ -#line 958 "MachineIndependent/glslang.y" - { - (yyval.interm).function = (yyvsp[-1].interm.function); - if (parseContext.compileOnly) (yyval.interm).function->setExport(); - (yyval.interm).loc = (yyvsp[0].lex).loc; - } -#line 6253 "MachineIndependent/glslang_tab.cpp" - break; - - case 110: /* function_prototype: function_declarator RIGHT_PAREN attribute */ -#line 963 "MachineIndependent/glslang.y" - { - (yyval.interm).function = (yyvsp[-2].interm.function); - if (parseContext.compileOnly) (yyval.interm).function->setExport(); - (yyval.interm).loc = (yyvsp[-1].lex).loc; - parseContext.handleFunctionAttributes((yyvsp[-1].lex).loc, *(yyvsp[0].interm.attributes)); - } -#line 6264 "MachineIndependent/glslang_tab.cpp" - break; - - case 111: /* function_prototype: attribute function_declarator RIGHT_PAREN */ -#line 969 "MachineIndependent/glslang.y" - { - (yyval.interm).function = (yyvsp[-1].interm.function); - if (parseContext.compileOnly) (yyval.interm).function->setExport(); - (yyval.interm).loc = (yyvsp[0].lex).loc; - parseContext.handleFunctionAttributes((yyvsp[0].lex).loc, *(yyvsp[-2].interm.attributes)); - } -#line 6275 "MachineIndependent/glslang_tab.cpp" - break; - - case 112: /* function_prototype: attribute function_declarator RIGHT_PAREN attribute */ -#line 975 "MachineIndependent/glslang.y" - { - (yyval.interm).function = (yyvsp[-2].interm.function); - if (parseContext.compileOnly) (yyval.interm).function->setExport(); - (yyval.interm).loc = (yyvsp[-1].lex).loc; - parseContext.handleFunctionAttributes((yyvsp[-1].lex).loc, *(yyvsp[-3].interm.attributes)); - parseContext.handleFunctionAttributes((yyvsp[-1].lex).loc, *(yyvsp[0].interm.attributes)); - } -#line 6287 "MachineIndependent/glslang_tab.cpp" - break; - - case 113: /* function_declarator: function_header */ -#line 985 "MachineIndependent/glslang.y" - { - (yyval.interm.function) = (yyvsp[0].interm.function); - } -#line 6295 "MachineIndependent/glslang_tab.cpp" - break; - - case 114: /* function_declarator: function_header_with_parameters */ -#line 988 "MachineIndependent/glslang.y" - { - (yyval.interm.function) = (yyvsp[0].interm.function); - } -#line 6303 "MachineIndependent/glslang_tab.cpp" - break; - - case 115: /* function_header_with_parameters: function_header parameter_declaration */ -#line 995 "MachineIndependent/glslang.y" - { - // Add the parameter - (yyval.interm.function) = (yyvsp[-1].interm.function); - if ((yyvsp[0].interm).param.type->getBasicType() != EbtVoid) - { - if (!(parseContext.spvVersion.vulkan > 0 && parseContext.spvVersion.vulkanRelaxed)) - (yyvsp[-1].interm.function)->addParameter((yyvsp[0].interm).param); - else - parseContext.vkRelaxedRemapFunctionParameter((yyvsp[-1].interm.function), (yyvsp[0].interm).param); - } - else - delete (yyvsp[0].interm).param.type; - } -#line 6321 "MachineIndependent/glslang_tab.cpp" - break; - - case 116: /* function_header_with_parameters: function_header_with_parameters COMMA parameter_declaration */ -#line 1008 "MachineIndependent/glslang.y" - { - // - // Only first parameter of one-parameter functions can be void - // The check for named parameters not being void is done in parameter_declarator - // - if ((yyvsp[0].interm).param.type->getBasicType() == EbtVoid) { - // - // This parameter > first is void - // - parseContext.error((yyvsp[-1].lex).loc, "cannot be an argument type except for '(void)'", "void", ""); - delete (yyvsp[0].interm).param.type; - } else { - // Add the parameter - (yyval.interm.function) = (yyvsp[-2].interm.function); - if (!(parseContext.spvVersion.vulkan > 0 && parseContext.spvVersion.vulkanRelaxed)) - (yyvsp[-2].interm.function)->addParameter((yyvsp[0].interm).param); - else - parseContext.vkRelaxedRemapFunctionParameter((yyvsp[-2].interm.function), (yyvsp[0].interm).param); - } - } -#line 6346 "MachineIndependent/glslang_tab.cpp" - break; - - case 117: /* function_header: fully_specified_type IDENTIFIER LEFT_PAREN */ -#line 1031 "MachineIndependent/glslang.y" - { - if ((yyvsp[-2].interm.type).qualifier.storage != EvqGlobal && (yyvsp[-2].interm.type).qualifier.storage != EvqTemporary) { - parseContext.error((yyvsp[-1].lex).loc, "no qualifiers allowed for function return", - GetStorageQualifierString((yyvsp[-2].interm.type).qualifier.storage), ""); - } - if ((yyvsp[-2].interm.type).arraySizes) - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - - // Add the function as a prototype after parsing it (we do not support recursion) - TFunction *function; - TType type((yyvsp[-2].interm.type)); - - // Potentially rename shader entry point function. No-op most of the time. - parseContext.renameShaderFunction((yyvsp[-1].lex).string); - - // Make the function - function = new TFunction((yyvsp[-1].lex).string, type); - (yyval.interm.function) = function; - } -#line 6370 "MachineIndependent/glslang_tab.cpp" - break; - - case 118: /* parameter_declarator: type_specifier IDENTIFIER */ -#line 1054 "MachineIndependent/glslang.y" - { - if ((yyvsp[-1].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-1].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-1].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - parseContext.arraySizeRequiredCheck((yyvsp[-1].interm.type).loc, *(yyvsp[-1].interm.type).arraySizes); - } - if ((yyvsp[-1].interm.type).basicType == EbtVoid) { - parseContext.error((yyvsp[0].lex).loc, "illegal use of type 'void'", (yyvsp[0].lex).string->c_str(), ""); - } - parseContext.reservedErrorCheck((yyvsp[0].lex).loc, *(yyvsp[0].lex).string); - - TParameter param = {(yyvsp[0].lex).string, new TType((yyvsp[-1].interm.type))}; - (yyval.interm).loc = (yyvsp[0].lex).loc; - (yyval.interm).param = param; - } -#line 6390 "MachineIndependent/glslang_tab.cpp" - break; - - case 119: /* parameter_declarator: type_specifier IDENTIFIER array_specifier */ -#line 1069 "MachineIndependent/glslang.y" - { - if ((yyvsp[-2].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - } - TType* type = new TType((yyvsp[-2].interm.type)); - type->transferArraySizes((yyvsp[0].interm).arraySizes); - type->copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); - - parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, type->getArraySizes()); - parseContext.arraySizeRequiredCheck((yyvsp[0].interm).loc, *(yyvsp[0].interm).arraySizes); - parseContext.reservedErrorCheck((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string); - - TParameter param = { (yyvsp[-1].lex).string, type }; - - (yyval.interm).loc = (yyvsp[-1].lex).loc; - (yyval.interm).param = param; - } -#line 6414 "MachineIndependent/glslang_tab.cpp" - break; - - case 120: /* parameter_declaration: type_qualifier parameter_declarator */ -#line 1094 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[0].interm); - if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) - (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision; - parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier(), (yyval.interm).param.type->isCoopMat()); - - parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type); - parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); - - } -#line 6430 "MachineIndependent/glslang_tab.cpp" - break; - - case 121: /* parameter_declaration: parameter_declarator */ -#line 1105 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[0].interm); - - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type); - parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); - parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier(), (yyval.interm).param.type->isCoopMat()); - } -#line 6442 "MachineIndependent/glslang_tab.cpp" - break; - - case 122: /* parameter_declaration: type_qualifier parameter_type_specifier */ -#line 1115 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[0].interm); - if ((yyvsp[-1].interm.type).qualifier.precision != EpqNone) - (yyval.interm).param.type->getQualifier().precision = (yyvsp[-1].interm.type).qualifier.precision; - parseContext.precisionQualifierCheck((yyvsp[-1].interm.type).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier(), (yyval.interm).param.type->isCoopMat()); - - parseContext.checkNoShaderLayouts((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, (yyvsp[-1].interm.type).qualifier.storage, *(yyval.interm).param.type); - parseContext.paramCheckFix((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, *(yyval.interm).param.type); - } -#line 6457 "MachineIndependent/glslang_tab.cpp" - break; - - case 123: /* parameter_declaration: parameter_type_specifier */ -#line 1125 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[0].interm); - - parseContext.parameterTypeCheck((yyvsp[0].interm).loc, EvqIn, *(yyvsp[0].interm).param.type); - parseContext.paramCheckFixStorage((yyvsp[0].interm).loc, EvqTemporary, *(yyval.interm).param.type); - parseContext.precisionQualifierCheck((yyval.interm).loc, (yyval.interm).param.type->getBasicType(), (yyval.interm).param.type->getQualifier(), (yyval.interm).param.type->isCoopMat()); - } -#line 6469 "MachineIndependent/glslang_tab.cpp" - break; - - case 124: /* parameter_type_specifier: type_specifier */ -#line 1135 "MachineIndependent/glslang.y" - { - TParameter param = { 0, new TType((yyvsp[0].interm.type)) }; - (yyval.interm).param = param; - if ((yyvsp[0].interm.type).arraySizes) - parseContext.arraySizeRequiredCheck((yyvsp[0].interm.type).loc, *(yyvsp[0].interm.type).arraySizes); - } -#line 6480 "MachineIndependent/glslang_tab.cpp" - break; - - case 125: /* init_declarator_list: single_declaration */ -#line 1144 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[0].interm); - } -#line 6488 "MachineIndependent/glslang_tab.cpp" - break; - - case 126: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER */ -#line 1147 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[-2].interm); - parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-2].interm).type); - } -#line 6497 "MachineIndependent/glslang_tab.cpp" - break; - - case 127: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER array_specifier */ -#line 1151 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[-3].interm); - parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-3].interm).type, (yyvsp[0].interm).arraySizes); - } -#line 6506 "MachineIndependent/glslang_tab.cpp" - break; - - case 128: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER array_specifier EQUAL initializer */ -#line 1155 "MachineIndependent/glslang.y" - { - (yyval.interm).type = (yyvsp[-5].interm).type; - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-5].interm).type, (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-5].interm).intermNode, initNode, (yyvsp[-1].lex).loc); - } -#line 6516 "MachineIndependent/glslang_tab.cpp" - break; - - case 129: /* init_declarator_list: init_declarator_list COMMA IDENTIFIER EQUAL initializer */ -#line 1160 "MachineIndependent/glslang.y" - { - (yyval.interm).type = (yyvsp[-4].interm).type; - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-4].interm).type, 0, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate((yyvsp[-4].interm).intermNode, initNode, (yyvsp[-1].lex).loc); - } -#line 6526 "MachineIndependent/glslang_tab.cpp" - break; - - case 130: /* single_declaration: fully_specified_type */ -#line 1168 "MachineIndependent/glslang.y" - { - (yyval.interm).type = (yyvsp[0].interm.type); - (yyval.interm).intermNode = 0; - parseContext.declareTypeDefaults((yyval.interm).loc, (yyval.interm).type); - } -#line 6536 "MachineIndependent/glslang_tab.cpp" - break; - - case 131: /* single_declaration: fully_specified_type IDENTIFIER */ -#line 1173 "MachineIndependent/glslang.y" - { - (yyval.interm).type = (yyvsp[-1].interm.type); - (yyval.interm).intermNode = 0; - parseContext.declareVariable((yyvsp[0].lex).loc, *(yyvsp[0].lex).string, (yyvsp[-1].interm.type)); - } -#line 6546 "MachineIndependent/glslang_tab.cpp" - break; - - case 132: /* single_declaration: fully_specified_type IDENTIFIER array_specifier */ -#line 1178 "MachineIndependent/glslang.y" - { - (yyval.interm).type = (yyvsp[-2].interm.type); - (yyval.interm).intermNode = 0; - parseContext.declareVariable((yyvsp[-1].lex).loc, *(yyvsp[-1].lex).string, (yyvsp[-2].interm.type), (yyvsp[0].interm).arraySizes); - } -#line 6556 "MachineIndependent/glslang_tab.cpp" - break; - - case 133: /* single_declaration: fully_specified_type IDENTIFIER array_specifier EQUAL initializer */ -#line 1183 "MachineIndependent/glslang.y" - { - (yyval.interm).type = (yyvsp[-4].interm.type); - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-3].lex).loc, *(yyvsp[-3].lex).string, (yyvsp[-4].interm.type), (yyvsp[-2].interm).arraySizes, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); - } -#line 6566 "MachineIndependent/glslang_tab.cpp" - break; - - case 134: /* single_declaration: fully_specified_type IDENTIFIER EQUAL initializer */ -#line 1188 "MachineIndependent/glslang.y" - { - (yyval.interm).type = (yyvsp[-3].interm.type); - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode)); - (yyval.interm).intermNode = parseContext.intermediate.growAggregate(0, initNode, (yyvsp[-1].lex).loc); - } -#line 6576 "MachineIndependent/glslang_tab.cpp" - break; - - case 135: /* fully_specified_type: type_specifier */ -#line 1197 "MachineIndependent/glslang.y" - { - (yyval.interm.type) = (yyvsp[0].interm.type); - - parseContext.globalQualifierTypeCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyval.interm.type)); - if ((yyvsp[0].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - } - parseContext.precisionQualifierCheck((yyval.interm.type).loc, (yyval.interm.type).basicType, (yyval.interm.type).qualifier, (yyval.interm.type).isCoopmat()); - } -#line 6591 "MachineIndependent/glslang_tab.cpp" - break; - - case 136: /* fully_specified_type: type_qualifier type_specifier */ -#line 1207 "MachineIndependent/glslang.y" - { - parseContext.globalQualifierFixCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, false, &(yyvsp[0].interm.type)); - parseContext.globalQualifierTypeCheck((yyvsp[-1].interm.type).loc, (yyvsp[-1].interm.type).qualifier, (yyvsp[0].interm.type)); - - if ((yyvsp[0].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[0].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[0].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - } - - if ((yyvsp[0].interm.type).arraySizes && parseContext.arrayQualifierError((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).qualifier)) - (yyvsp[0].interm.type).arraySizes = nullptr; - - parseContext.checkNoShaderLayouts((yyvsp[0].interm.type).loc, (yyvsp[-1].interm.type).shaderQualifiers); - (yyvsp[0].interm.type).shaderQualifiers.merge((yyvsp[-1].interm.type).shaderQualifiers); - parseContext.mergeQualifiers((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier, (yyvsp[-1].interm.type).qualifier, true); - parseContext.precisionQualifierCheck((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).basicType, (yyvsp[0].interm.type).qualifier, (yyvsp[0].interm.type).isCoopmat()); - - (yyval.interm.type) = (yyvsp[0].interm.type); - - if (! (yyval.interm.type).qualifier.isInterpolation() && - ((parseContext.language == EShLangVertex && (yyval.interm.type).qualifier.storage == EvqVaryingOut) || - (parseContext.language == EShLangFragment && (yyval.interm.type).qualifier.storage == EvqVaryingIn))) - (yyval.interm.type).qualifier.smooth = true; - } -#line 6620 "MachineIndependent/glslang_tab.cpp" - break; - - case 137: /* invariant_qualifier: INVARIANT */ -#line 1234 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "invariant"); - parseContext.profileRequires((yyval.interm.type).loc, ENoProfile, 120, 0, "invariant"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.invariant = true; - } -#line 6631 "MachineIndependent/glslang_tab.cpp" - break; - - case 138: /* interpolation_qualifier: SMOOTH */ -#line 1243 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "smooth"); - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "smooth"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "smooth"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.smooth = true; - } -#line 6643 "MachineIndependent/glslang_tab.cpp" - break; - - case 139: /* interpolation_qualifier: FLAT */ -#line 1250 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "flat"); - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "flat"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "flat"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.flat = true; - } -#line 6655 "MachineIndependent/glslang_tab.cpp" - break; - - case 140: /* interpolation_qualifier: NOPERSPECTIVE */ -#line 1257 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "noperspective"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_shader_noperspective_interpolation, "noperspective"); - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "noperspective"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.nopersp = true; - } -#line 6667 "MachineIndependent/glslang_tab.cpp" - break; - - case 141: /* interpolation_qualifier: EXPLICITINTERPAMD */ -#line 1264 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "__explicitInterpAMD"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECompatibilityProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.explicitInterp = true; - } -#line 6679 "MachineIndependent/glslang_tab.cpp" - break; - - case 142: /* interpolation_qualifier: PERVERTEXNV */ -#line 1271 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "pervertexNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECompatibilityProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.pervertexNV = true; - } -#line 6692 "MachineIndependent/glslang_tab.cpp" - break; - - case 143: /* interpolation_qualifier: PERVERTEXEXT */ -#line 1279 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "pervertexEXT"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECompatibilityProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 0, E_GL_EXT_fragment_shader_barycentric, "fragment shader barycentric"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.pervertexEXT = true; - } -#line 6705 "MachineIndependent/glslang_tab.cpp" - break; - - case 144: /* interpolation_qualifier: PERPRIMITIVENV */ -#line 1287 "MachineIndependent/glslang.y" - { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck((yyvsp[0].lex).loc, "perprimitiveNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangFragmentMask | EShLangMeshMask), "perprimitiveNV"); - // Fragment shader stage doesn't check for extension. So we explicitly add below extension check. - if (parseContext.language == EShLangFragment) - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_NV_mesh_shader, "perprimitiveNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.perPrimitiveNV = true; - } -#line 6720 "MachineIndependent/glslang_tab.cpp" - break; - - case 145: /* interpolation_qualifier: PERPRIMITIVEEXT */ -#line 1297 "MachineIndependent/glslang.y" - { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck((yyvsp[0].lex).loc, "perprimitiveEXT"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangFragmentMask | EShLangMeshMask), "perprimitiveEXT"); - // Fragment shader stage doesn't check for extension. So we explicitly add below extension check. - if (parseContext.language == EShLangFragment) - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_mesh_shader, "perprimitiveEXT"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.perPrimitiveNV = true; - } -#line 6735 "MachineIndependent/glslang_tab.cpp" - break; - - case 146: /* interpolation_qualifier: PERVIEWNV */ -#line 1307 "MachineIndependent/glslang.y" - { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck((yyvsp[0].lex).loc, "perviewNV"); - parseContext.requireStage((yyvsp[0].lex).loc, EShLangMesh, "perviewNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.perViewNV = true; - } -#line 6747 "MachineIndependent/glslang_tab.cpp" - break; - - case 147: /* interpolation_qualifier: PERTASKNV */ -#line 1314 "MachineIndependent/glslang.y" - { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck((yyvsp[0].lex).loc, "taskNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTaskMask | EShLangMeshMask), "taskNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.perTaskNV = true; - } -#line 6759 "MachineIndependent/glslang_tab.cpp" - break; - - case 148: /* layout_qualifier: LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN */ -#line 1324 "MachineIndependent/glslang.y" - { - (yyval.interm.type) = (yyvsp[-1].interm.type); - } -#line 6767 "MachineIndependent/glslang_tab.cpp" - break; - - case 149: /* layout_qualifier_id_list: layout_qualifier_id */ -#line 1330 "MachineIndependent/glslang.y" - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 6775 "MachineIndependent/glslang_tab.cpp" - break; - - case 150: /* layout_qualifier_id_list: layout_qualifier_id_list COMMA layout_qualifier_id */ -#line 1333 "MachineIndependent/glslang.y" - { - (yyval.interm.type) = (yyvsp[-2].interm.type); - (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); - parseContext.mergeObjectLayoutQualifiers((yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); - } -#line 6785 "MachineIndependent/glslang_tab.cpp" - break; - - case 151: /* layout_qualifier_id: IDENTIFIER */ -#line 1340 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), *(yyvsp[0].lex).string); - } -#line 6794 "MachineIndependent/glslang_tab.cpp" - break; - - case 152: /* layout_qualifier_id: IDENTIFIER EQUAL constant_expression */ -#line 1344 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-2].lex).loc); - parseContext.setLayoutQualifier((yyvsp[-2].lex).loc, (yyval.interm.type), *(yyvsp[-2].lex).string, (yyvsp[0].interm.intermTypedNode)); - } -#line 6803 "MachineIndependent/glslang_tab.cpp" - break; - - case 153: /* layout_qualifier_id: SHARED */ -#line 1348 "MachineIndependent/glslang.y" - { // because "shared" is both an identifier and a keyword - (yyval.interm.type).init((yyvsp[0].lex).loc); - TString strShared("shared"); - parseContext.setLayoutQualifier((yyvsp[0].lex).loc, (yyval.interm.type), strShared); - } -#line 6813 "MachineIndependent/glslang_tab.cpp" - break; - - case 154: /* precise_qualifier: PRECISE */ -#line 1356 "MachineIndependent/glslang.y" - { - parseContext.profileRequires((yyval.interm.type).loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader5, "precise"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 320, Num_AEP_gpu_shader5, AEP_gpu_shader5, "precise"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.noContraction = true; - } -#line 6824 "MachineIndependent/glslang_tab.cpp" - break; - - case 155: /* type_qualifier: single_type_qualifier */ -#line 1365 "MachineIndependent/glslang.y" - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 6832 "MachineIndependent/glslang_tab.cpp" - break; - - case 156: /* type_qualifier: type_qualifier single_type_qualifier */ -#line 1368 "MachineIndependent/glslang.y" - { - (yyval.interm.type) = (yyvsp[-1].interm.type); - if ((yyval.interm.type).basicType == EbtVoid) - (yyval.interm.type).basicType = (yyvsp[0].interm.type).basicType; - - (yyval.interm.type).shaderQualifiers.merge((yyvsp[0].interm.type).shaderQualifiers); - parseContext.mergeQualifiers((yyval.interm.type).loc, (yyval.interm.type).qualifier, (yyvsp[0].interm.type).qualifier, false); - } -#line 6845 "MachineIndependent/glslang_tab.cpp" - break; - - case 157: /* single_type_qualifier: storage_qualifier */ -#line 1379 "MachineIndependent/glslang.y" - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 6853 "MachineIndependent/glslang_tab.cpp" - break; - - case 158: /* single_type_qualifier: layout_qualifier */ -#line 1382 "MachineIndependent/glslang.y" - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 6861 "MachineIndependent/glslang_tab.cpp" - break; - - case 159: /* single_type_qualifier: precision_qualifier */ -#line 1385 "MachineIndependent/glslang.y" - { - parseContext.checkPrecisionQualifier((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type).qualifier.precision); - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 6870 "MachineIndependent/glslang_tab.cpp" - break; - - case 160: /* single_type_qualifier: interpolation_qualifier */ -#line 1389 "MachineIndependent/glslang.y" - { - // allow inheritance of storage qualifier from block declaration - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 6879 "MachineIndependent/glslang_tab.cpp" - break; - - case 161: /* single_type_qualifier: invariant_qualifier */ -#line 1393 "MachineIndependent/glslang.y" - { - // allow inheritance of storage qualifier from block declaration - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 6888 "MachineIndependent/glslang_tab.cpp" - break; - - case 162: /* single_type_qualifier: precise_qualifier */ -#line 1397 "MachineIndependent/glslang.y" - { - // allow inheritance of storage qualifier from block declaration - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 6897 "MachineIndependent/glslang_tab.cpp" - break; - - case 163: /* single_type_qualifier: non_uniform_qualifier */ -#line 1401 "MachineIndependent/glslang.y" - { - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 6905 "MachineIndependent/glslang_tab.cpp" - break; - - case 164: /* single_type_qualifier: spirv_storage_class_qualifier */ -#line 1404 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].interm.type).loc, "spirv_storage_class"); - parseContext.requireExtensions((yyvsp[0].interm.type).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V storage class qualifier"); - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 6915 "MachineIndependent/glslang_tab.cpp" - break; - - case 165: /* single_type_qualifier: spirv_decorate_qualifier */ -#line 1409 "MachineIndependent/glslang.y" - { - parseContext.requireExtensions((yyvsp[0].interm.type).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V decorate qualifier"); - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 6924 "MachineIndependent/glslang_tab.cpp" - break; - - case 166: /* single_type_qualifier: SPIRV_BY_REFERENCE */ -#line 1413 "MachineIndependent/glslang.y" - { - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_reference"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.setSpirvByReference(); - } -#line 6934 "MachineIndependent/glslang_tab.cpp" - break; - - case 167: /* single_type_qualifier: SPIRV_LITERAL */ -#line 1418 "MachineIndependent/glslang.y" - { - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_spirv_intrinsics, "spirv_by_literal"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.setSpirvLiteral(); - } -#line 6944 "MachineIndependent/glslang_tab.cpp" - break; - - case 168: /* storage_qualifier: CONST */ -#line 1426 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqConst; // will later turn into EvqConstReadOnly, if the initializer is not constant - } -#line 6953 "MachineIndependent/glslang_tab.cpp" - break; - - case 169: /* storage_qualifier: INOUT */ -#line 1430 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "inout"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqInOut; - } -#line 6963 "MachineIndependent/glslang_tab.cpp" - break; - - case 170: /* storage_qualifier: IN */ -#line 1435 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "in"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - // whether this is a parameter "in" or a pipeline "in" will get sorted out a bit later - (yyval.interm.type).qualifier.storage = EvqIn; - } -#line 6974 "MachineIndependent/glslang_tab.cpp" - break; - - case 171: /* storage_qualifier: OUT */ -#line 1441 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "out"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - // whether this is a parameter "out" or a pipeline "out" will get sorted out a bit later - (yyval.interm.type).qualifier.storage = EvqOut; - } -#line 6985 "MachineIndependent/glslang_tab.cpp" - break; - - case 172: /* storage_qualifier: CENTROID */ -#line 1447 "MachineIndependent/glslang.y" - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 120, 0, "centroid"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 300, 0, "centroid"); - parseContext.globalCheck((yyvsp[0].lex).loc, "centroid"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.centroid = true; - } -#line 6997 "MachineIndependent/glslang_tab.cpp" - break; - - case 173: /* storage_qualifier: UNIFORM */ -#line 1454 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "uniform"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqUniform; - } -#line 7007 "MachineIndependent/glslang_tab.cpp" - break; - - case 174: /* storage_qualifier: TILEIMAGEEXT */ -#line 1459 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "tileImageEXT"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqTileImageEXT; - } -#line 7017 "MachineIndependent/glslang_tab.cpp" - break; - - case 175: /* storage_qualifier: SHARED */ -#line 1464 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "shared"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared"); - parseContext.profileRequires((yyvsp[0].lex).loc, EEsProfile, 310, 0, "shared"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangComputeMask | EShLangMeshMask | EShLangTaskMask), "shared"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqShared; - } -#line 7030 "MachineIndependent/glslang_tab.cpp" - break; - - case 176: /* storage_qualifier: BUFFER */ -#line 1472 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "buffer"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqBuffer; - } -#line 7040 "MachineIndependent/glslang_tab.cpp" - break; - - case 177: /* storage_qualifier: ATTRIBUTE */ -#line 1477 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangVertex, "attribute"); - parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "attribute"); - parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "attribute"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "attribute"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "attribute"); - - parseContext.globalCheck((yyvsp[0].lex).loc, "attribute"); - - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqVaryingIn; - } -#line 7057 "MachineIndependent/glslang_tab.cpp" - break; - - case 178: /* storage_qualifier: VARYING */ -#line 1489 "MachineIndependent/glslang.y" - { - parseContext.checkDeprecated((yyvsp[0].lex).loc, ENoProfile, 130, "varying"); - parseContext.checkDeprecated((yyvsp[0].lex).loc, ECoreProfile, 130, "varying"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, ECoreProfile, 420, "varying"); - parseContext.requireNotRemoved((yyvsp[0].lex).loc, EEsProfile, 300, "varying"); - - parseContext.globalCheck((yyvsp[0].lex).loc, "varying"); - - (yyval.interm.type).init((yyvsp[0].lex).loc); - if (parseContext.language == EShLangVertex) - (yyval.interm.type).qualifier.storage = EvqVaryingOut; - else - (yyval.interm.type).qualifier.storage = EvqVaryingIn; - } -#line 7076 "MachineIndependent/glslang_tab.cpp" - break; - - case 179: /* storage_qualifier: PATCH */ -#line 1503 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "patch"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTessControlMask | EShLangTessEvaluationMask), "patch"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.patch = true; - } -#line 7087 "MachineIndependent/glslang_tab.cpp" - break; - - case 180: /* storage_qualifier: SAMPLE */ -#line 1509 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "sample"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.sample = true; - } -#line 7097 "MachineIndependent/glslang_tab.cpp" - break; - - case 181: /* storage_qualifier: HITATTRNV */ -#line 1514 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask - | EShLangAnyHitMask), "hitAttributeNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqHitAttr; - } -#line 7110 "MachineIndependent/glslang_tab.cpp" - break; - - case 182: /* storage_qualifier: HITOBJECTATTRNV */ -#line 1522 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask - | EShLangMissMask), "hitObjectAttributeNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_shader_invocation_reorder, "hitObjectAttributeNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqHitObjectAttrNV; - } -#line 7123 "MachineIndependent/glslang_tab.cpp" - break; - - case 183: /* storage_qualifier: HITATTREXT */ -#line 1530 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "hitAttributeEXT"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask - | EShLangAnyHitMask), "hitAttributeEXT"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "hitAttributeNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqHitAttr; - } -#line 7136 "MachineIndependent/glslang_tab.cpp" - break; - - case 184: /* storage_qualifier: PAYLOADNV */ -#line 1538 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | - EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqPayload; - } -#line 7149 "MachineIndependent/glslang_tab.cpp" - break; - - case 185: /* storage_qualifier: PAYLOADEXT */ -#line 1546 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadEXT"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask | - EShLangAnyHitMask | EShLangMissMask), "rayPayloadEXT"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadEXT"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqPayload; - } -#line 7162 "MachineIndependent/glslang_tab.cpp" - break; - - case 186: /* storage_qualifier: PAYLOADINNV */ -#line 1554 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitMask | - EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqPayloadIn; - } -#line 7175 "MachineIndependent/glslang_tab.cpp" - break; - - case 187: /* storage_qualifier: PAYLOADINEXT */ -#line 1562 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "rayPayloadInEXT"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangClosestHitMask | - EShLangAnyHitMask | EShLangMissMask), "rayPayloadInEXT"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "rayPayloadInEXT"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqPayloadIn; - } -#line 7188 "MachineIndependent/glslang_tab.cpp" - break; - - case 188: /* storage_qualifier: CALLDATANV */ -#line 1570 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | - EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqCallableData; - } -#line 7201 "MachineIndependent/glslang_tab.cpp" - break; - - case 189: /* storage_qualifier: CALLDATAEXT */ -#line 1578 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataEXT"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangRayGenMask | - EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataEXT"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataEXT"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqCallableData; - } -#line 7214 "MachineIndependent/glslang_tab.cpp" - break; - - case 190: /* storage_qualifier: CALLDATAINNV */ -#line 1586 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInNV"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqCallableDataIn; - } -#line 7226 "MachineIndependent/glslang_tab.cpp" - break; - - case 191: /* storage_qualifier: CALLDATAINEXT */ -#line 1593 "MachineIndependent/glslang.y" - { - parseContext.globalCheck((yyvsp[0].lex).loc, "callableDataInEXT"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInEXT"); - parseContext.profileRequires((yyvsp[0].lex).loc, ECoreProfile, 460, E_GL_EXT_ray_tracing, "callableDataInEXT"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqCallableDataIn; - } -#line 7238 "MachineIndependent/glslang_tab.cpp" - break; - - case 192: /* storage_qualifier: COHERENT */ -#line 1600 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.coherent = true; - } -#line 7247 "MachineIndependent/glslang_tab.cpp" - break; - - case 193: /* storage_qualifier: DEVICECOHERENT */ -#line 1604 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "devicecoherent"); - (yyval.interm.type).qualifier.devicecoherent = true; - } -#line 7257 "MachineIndependent/glslang_tab.cpp" - break; - - case 194: /* storage_qualifier: QUEUEFAMILYCOHERENT */ -#line 1609 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "queuefamilycoherent"); - (yyval.interm.type).qualifier.queuefamilycoherent = true; - } -#line 7267 "MachineIndependent/glslang_tab.cpp" - break; - - case 195: /* storage_qualifier: WORKGROUPCOHERENT */ -#line 1614 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "workgroupcoherent"); - (yyval.interm.type).qualifier.workgroupcoherent = true; - } -#line 7277 "MachineIndependent/glslang_tab.cpp" - break; - - case 196: /* storage_qualifier: SUBGROUPCOHERENT */ -#line 1619 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "subgroupcoherent"); - (yyval.interm.type).qualifier.subgroupcoherent = true; - } -#line 7287 "MachineIndependent/glslang_tab.cpp" - break; - - case 197: /* storage_qualifier: NONPRIVATE */ -#line 1624 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); - (yyval.interm.type).qualifier.nonprivate = true; - } -#line 7297 "MachineIndependent/glslang_tab.cpp" - break; - - case 198: /* storage_qualifier: SHADERCALLCOHERENT */ -#line 1629 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - parseContext.requireExtensions((yyvsp[0].lex).loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent"); - (yyval.interm.type).qualifier.shadercallcoherent = true; - } -#line 7307 "MachineIndependent/glslang_tab.cpp" - break; - - case 199: /* storage_qualifier: VOLATILE */ -#line 1634 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.volatil = true; - } -#line 7316 "MachineIndependent/glslang_tab.cpp" - break; - - case 200: /* storage_qualifier: RESTRICT */ -#line 1638 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.restrict = true; - } -#line 7325 "MachineIndependent/glslang_tab.cpp" - break; - - case 201: /* storage_qualifier: READONLY */ -#line 1642 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.readonly = true; - } -#line 7334 "MachineIndependent/glslang_tab.cpp" - break; - - case 202: /* storage_qualifier: WRITEONLY */ -#line 1646 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.writeonly = true; - } -#line 7343 "MachineIndependent/glslang_tab.cpp" - break; - - case 203: /* storage_qualifier: SUBROUTINE */ -#line 1650 "MachineIndependent/glslang.y" - { - parseContext.spvRemoved((yyvsp[0].lex).loc, "subroutine"); - parseContext.globalCheck((yyvsp[0].lex).loc, "subroutine"); - parseContext.unimplemented((yyvsp[0].lex).loc, "subroutine"); - (yyval.interm.type).init((yyvsp[0].lex).loc); - } -#line 7354 "MachineIndependent/glslang_tab.cpp" - break; - - case 204: /* storage_qualifier: SUBROUTINE LEFT_PAREN type_name_list RIGHT_PAREN */ -#line 1656 "MachineIndependent/glslang.y" - { - parseContext.spvRemoved((yyvsp[-3].lex).loc, "subroutine"); - parseContext.globalCheck((yyvsp[-3].lex).loc, "subroutine"); - parseContext.unimplemented((yyvsp[-3].lex).loc, "subroutine"); - (yyval.interm.type).init((yyvsp[-3].lex).loc); - } -#line 7365 "MachineIndependent/glslang_tab.cpp" - break; - - case 205: /* storage_qualifier: TASKPAYLOADWORKGROUPEXT */ -#line 1662 "MachineIndependent/glslang.y" - { - // No need for profile version or extension check. Shader stage already checks both. - parseContext.globalCheck((yyvsp[0].lex).loc, "taskPayloadSharedEXT"); - parseContext.requireStage((yyvsp[0].lex).loc, (EShLanguageMask)(EShLangTaskMask | EShLangMeshMask), "taskPayloadSharedEXT "); - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.storage = EvqtaskPayloadSharedEXT; - } -#line 7377 "MachineIndependent/glslang_tab.cpp" - break; - - case 206: /* non_uniform_qualifier: NONUNIFORM */ -#line 1672 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc); - (yyval.interm.type).qualifier.nonUniform = true; - } -#line 7386 "MachineIndependent/glslang_tab.cpp" - break; - - case 207: /* type_name_list: IDENTIFIER */ -#line 1679 "MachineIndependent/glslang.y" - { - // TODO - } -#line 7394 "MachineIndependent/glslang_tab.cpp" - break; - - case 208: /* type_name_list: type_name_list COMMA IDENTIFIER */ -#line 1682 "MachineIndependent/glslang.y" - { - // TODO: 4.0 semantics: subroutines - // 1) make sure each identifier is a type declared earlier with SUBROUTINE - // 2) save all of the identifiers for future comparison with the declared function - } -#line 7404 "MachineIndependent/glslang_tab.cpp" - break; - - case 209: /* type_specifier: type_specifier_nonarray type_parameter_specifier_opt */ -#line 1690 "MachineIndependent/glslang.y" - { - (yyval.interm.type) = (yyvsp[-1].interm.type); - (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type)); - (yyval.interm.type).typeParameters = (yyvsp[0].interm.typeParameters); - parseContext.coopMatTypeParametersCheck((yyvsp[-1].interm.type).loc, (yyval.interm.type)); - - } -#line 7416 "MachineIndependent/glslang_tab.cpp" - break; - - case 210: /* type_specifier: type_specifier_nonarray type_parameter_specifier_opt array_specifier */ -#line 1697 "MachineIndependent/glslang.y" - { - parseContext.arrayOfArrayVersionCheck((yyvsp[0].interm).loc, (yyvsp[0].interm).arraySizes); - (yyval.interm.type) = (yyvsp[-2].interm.type); - (yyval.interm.type).qualifier.precision = parseContext.getDefaultPrecision((yyval.interm.type)); - (yyval.interm.type).typeParameters = (yyvsp[-1].interm.typeParameters); - (yyval.interm.type).arraySizes = (yyvsp[0].interm).arraySizes; - parseContext.coopMatTypeParametersCheck((yyvsp[-2].interm.type).loc, (yyval.interm.type)); - } -#line 7429 "MachineIndependent/glslang_tab.cpp" - break; - - case 211: /* array_specifier: LEFT_BRACKET RIGHT_BRACKET */ -#line 1708 "MachineIndependent/glslang.y" - { - (yyval.interm).loc = (yyvsp[-1].lex).loc; - (yyval.interm).arraySizes = new TArraySizes; - (yyval.interm).arraySizes->addInnerSize(); - } -#line 7439 "MachineIndependent/glslang_tab.cpp" - break; - - case 212: /* array_specifier: LEFT_BRACKET conditional_expression RIGHT_BRACKET */ -#line 1713 "MachineIndependent/glslang.y" - { - (yyval.interm).loc = (yyvsp[-2].lex).loc; - (yyval.interm).arraySizes = new TArraySizes; - - TArraySize size; - parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size"); - (yyval.interm).arraySizes->addInnerSize(size); - } -#line 7452 "MachineIndependent/glslang_tab.cpp" - break; - - case 213: /* array_specifier: array_specifier LEFT_BRACKET RIGHT_BRACKET */ -#line 1721 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[-2].interm); - (yyval.interm).arraySizes->addInnerSize(); - } -#line 7461 "MachineIndependent/glslang_tab.cpp" - break; - - case 214: /* array_specifier: array_specifier LEFT_BRACKET conditional_expression RIGHT_BRACKET */ -#line 1725 "MachineIndependent/glslang.y" - { - (yyval.interm) = (yyvsp[-3].interm); - - TArraySize size; - parseContext.arraySizeCheck((yyvsp[-1].interm.intermTypedNode)->getLoc(), (yyvsp[-1].interm.intermTypedNode), size, "array size"); - (yyval.interm).arraySizes->addInnerSize(size); - } -#line 7473 "MachineIndependent/glslang_tab.cpp" - break; - - case 215: /* type_parameter_specifier_opt: type_parameter_specifier */ -#line 1735 "MachineIndependent/glslang.y" - { - (yyval.interm.typeParameters) = (yyvsp[0].interm.typeParameters); - } -#line 7481 "MachineIndependent/glslang_tab.cpp" - break; - - case 216: /* type_parameter_specifier_opt: %empty */ -#line 1738 "MachineIndependent/glslang.y" - { - (yyval.interm.typeParameters) = 0; - } -#line 7489 "MachineIndependent/glslang_tab.cpp" - break; - - case 217: /* type_parameter_specifier: LEFT_ANGLE type_parameter_specifier_list RIGHT_ANGLE */ -#line 1744 "MachineIndependent/glslang.y" - { - (yyval.interm.typeParameters) = (yyvsp[-1].interm.typeParameters); - } -#line 7497 "MachineIndependent/glslang_tab.cpp" - break; - - case 218: /* type_parameter_specifier_list: type_specifier */ -#line 1750 "MachineIndependent/glslang.y" - { - (yyval.interm.typeParameters) = new TTypeParameters; - (yyval.interm.typeParameters)->arraySizes = new TArraySizes; - (yyval.interm.typeParameters)->basicType = (yyvsp[0].interm.type).basicType; - } -#line 7507 "MachineIndependent/glslang_tab.cpp" - break; - - case 219: /* type_parameter_specifier_list: unary_expression */ -#line 1755 "MachineIndependent/glslang.y" - { - (yyval.interm.typeParameters) = new TTypeParameters; - (yyval.interm.typeParameters)->arraySizes = new TArraySizes; - - TArraySize size; - parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter", true); - (yyval.interm.typeParameters)->arraySizes->addInnerSize(size); - } -#line 7520 "MachineIndependent/glslang_tab.cpp" - break; - - case 220: /* type_parameter_specifier_list: type_parameter_specifier_list COMMA unary_expression */ -#line 1763 "MachineIndependent/glslang.y" - { - (yyval.interm.typeParameters) = (yyvsp[-2].interm.typeParameters); - - TArraySize size; - parseContext.arraySizeCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode), size, "type parameter", true); - (yyval.interm.typeParameters)->arraySizes->addInnerSize(size); - } -#line 7532 "MachineIndependent/glslang_tab.cpp" - break; - - case 221: /* type_specifier_nonarray: VOID */ -#line 1773 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtVoid; - } -#line 7541 "MachineIndependent/glslang_tab.cpp" - break; - - case 222: /* type_specifier_nonarray: FLOAT */ -#line 1777 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - } -#line 7550 "MachineIndependent/glslang_tab.cpp" - break; - - case 223: /* type_specifier_nonarray: INT */ -#line 1781 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - } -#line 7559 "MachineIndependent/glslang_tab.cpp" - break; - - case 224: /* type_specifier_nonarray: UINT */ -#line 1785 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - } -#line 7569 "MachineIndependent/glslang_tab.cpp" - break; - - case 225: /* type_specifier_nonarray: BOOL */ -#line 1790 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - } -#line 7578 "MachineIndependent/glslang_tab.cpp" - break; - - case 226: /* type_specifier_nonarray: VEC2 */ -#line 1794 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(2); - } -#line 7588 "MachineIndependent/glslang_tab.cpp" - break; - - case 227: /* type_specifier_nonarray: VEC3 */ -#line 1799 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(3); - } -#line 7598 "MachineIndependent/glslang_tab.cpp" - break; - - case 228: /* type_specifier_nonarray: VEC4 */ -#line 1804 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(4); - } -#line 7608 "MachineIndependent/glslang_tab.cpp" - break; - - case 229: /* type_specifier_nonarray: BVEC2 */ -#line 1809 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - (yyval.interm.type).setVector(2); - } -#line 7618 "MachineIndependent/glslang_tab.cpp" - break; - - case 230: /* type_specifier_nonarray: BVEC3 */ -#line 1814 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - (yyval.interm.type).setVector(3); - } -#line 7628 "MachineIndependent/glslang_tab.cpp" - break; - - case 231: /* type_specifier_nonarray: BVEC4 */ -#line 1819 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtBool; - (yyval.interm.type).setVector(4); - } -#line 7638 "MachineIndependent/glslang_tab.cpp" - break; - - case 232: /* type_specifier_nonarray: IVEC2 */ -#line 1824 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(2); - } -#line 7648 "MachineIndependent/glslang_tab.cpp" - break; - - case 233: /* type_specifier_nonarray: IVEC3 */ -#line 1829 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(3); - } -#line 7658 "MachineIndependent/glslang_tab.cpp" - break; - - case 234: /* type_specifier_nonarray: IVEC4 */ -#line 1834 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(4); - } -#line 7668 "MachineIndependent/glslang_tab.cpp" - break; - - case 235: /* type_specifier_nonarray: UVEC2 */ -#line 1839 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(2); - } -#line 7679 "MachineIndependent/glslang_tab.cpp" - break; - - case 236: /* type_specifier_nonarray: UVEC3 */ -#line 1845 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(3); - } -#line 7690 "MachineIndependent/glslang_tab.cpp" - break; - - case 237: /* type_specifier_nonarray: UVEC4 */ -#line 1851 "MachineIndependent/glslang.y" - { - parseContext.fullIntegerCheck((yyvsp[0].lex).loc, "unsigned integer vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(4); - } -#line 7701 "MachineIndependent/glslang_tab.cpp" - break; - - case 238: /* type_specifier_nonarray: MAT2 */ -#line 1857 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7711 "MachineIndependent/glslang_tab.cpp" - break; - - case 239: /* type_specifier_nonarray: MAT3 */ -#line 1862 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7721 "MachineIndependent/glslang_tab.cpp" - break; - - case 240: /* type_specifier_nonarray: MAT4 */ -#line 1867 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7731 "MachineIndependent/glslang_tab.cpp" - break; - - case 241: /* type_specifier_nonarray: MAT2X2 */ -#line 1872 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 7741 "MachineIndependent/glslang_tab.cpp" - break; - - case 242: /* type_specifier_nonarray: MAT2X3 */ -#line 1877 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 3); - } -#line 7751 "MachineIndependent/glslang_tab.cpp" - break; - - case 243: /* type_specifier_nonarray: MAT2X4 */ -#line 1882 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 4); - } -#line 7761 "MachineIndependent/glslang_tab.cpp" - break; - - case 244: /* type_specifier_nonarray: MAT3X2 */ -#line 1887 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 2); - } -#line 7771 "MachineIndependent/glslang_tab.cpp" - break; - - case 245: /* type_specifier_nonarray: MAT3X3 */ -#line 1892 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 7781 "MachineIndependent/glslang_tab.cpp" - break; - - case 246: /* type_specifier_nonarray: MAT3X4 */ -#line 1897 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 4); - } -#line 7791 "MachineIndependent/glslang_tab.cpp" - break; - - case 247: /* type_specifier_nonarray: MAT4X2 */ -#line 1902 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 2); - } -#line 7801 "MachineIndependent/glslang_tab.cpp" - break; - - case 248: /* type_specifier_nonarray: MAT4X3 */ -#line 1907 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 3); - } -#line 7811 "MachineIndependent/glslang_tab.cpp" - break; - - case 249: /* type_specifier_nonarray: MAT4X4 */ -#line 1912 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 7821 "MachineIndependent/glslang_tab.cpp" - break; - - case 250: /* type_specifier_nonarray: DOUBLE */ -#line 1917 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - } -#line 7833 "MachineIndependent/glslang_tab.cpp" - break; - - case 251: /* type_specifier_nonarray: FLOAT16_T */ -#line 1924 "MachineIndependent/glslang.y" - { - parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "float16_t", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - } -#line 7843 "MachineIndependent/glslang_tab.cpp" - break; - - case 252: /* type_specifier_nonarray: FLOAT32_T */ -#line 1929 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - } -#line 7853 "MachineIndependent/glslang_tab.cpp" - break; - - case 253: /* type_specifier_nonarray: FLOAT64_T */ -#line 1934 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - } -#line 7863 "MachineIndependent/glslang_tab.cpp" - break; - - case 254: /* type_specifier_nonarray: INT8_T */ -#line 1939 "MachineIndependent/glslang.y" - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - } -#line 7873 "MachineIndependent/glslang_tab.cpp" - break; - - case 255: /* type_specifier_nonarray: UINT8_T */ -#line 1944 "MachineIndependent/glslang.y" - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint8; - } -#line 7883 "MachineIndependent/glslang_tab.cpp" - break; - - case 256: /* type_specifier_nonarray: INT16_T */ -#line 1949 "MachineIndependent/glslang.y" - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - } -#line 7893 "MachineIndependent/glslang_tab.cpp" - break; - - case 257: /* type_specifier_nonarray: UINT16_T */ -#line 1954 "MachineIndependent/glslang.y" - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - } -#line 7903 "MachineIndependent/glslang_tab.cpp" - break; - - case 258: /* type_specifier_nonarray: INT32_T */ -#line 1959 "MachineIndependent/glslang.y" - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - } -#line 7913 "MachineIndependent/glslang_tab.cpp" - break; - - case 259: /* type_specifier_nonarray: UINT32_T */ -#line 1964 "MachineIndependent/glslang.y" - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - } -#line 7923 "MachineIndependent/glslang_tab.cpp" - break; - - case 260: /* type_specifier_nonarray: INT64_T */ -#line 1969 "MachineIndependent/glslang.y" - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - } -#line 7933 "MachineIndependent/glslang_tab.cpp" - break; - - case 261: /* type_specifier_nonarray: UINT64_T */ -#line 1974 "MachineIndependent/glslang.y" - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - } -#line 7943 "MachineIndependent/glslang_tab.cpp" - break; - - case 262: /* type_specifier_nonarray: DVEC2 */ -#line 1979 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(2); - } -#line 7956 "MachineIndependent/glslang_tab.cpp" - break; - - case 263: /* type_specifier_nonarray: DVEC3 */ -#line 1987 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(3); - } -#line 7969 "MachineIndependent/glslang_tab.cpp" - break; - - case 264: /* type_specifier_nonarray: DVEC4 */ -#line 1995 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double vector"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double vector"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(4); - } -#line 7982 "MachineIndependent/glslang_tab.cpp" - break; - - case 265: /* type_specifier_nonarray: F16VEC2 */ -#line 2003 "MachineIndependent/glslang.y" - { - parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setVector(2); - } -#line 7993 "MachineIndependent/glslang_tab.cpp" - break; - - case 266: /* type_specifier_nonarray: F16VEC3 */ -#line 2009 "MachineIndependent/glslang.y" - { - parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setVector(3); - } -#line 8004 "MachineIndependent/glslang_tab.cpp" - break; - - case 267: /* type_specifier_nonarray: F16VEC4 */ -#line 2015 "MachineIndependent/glslang.y" - { - parseContext.float16ScalarVectorCheck((yyvsp[0].lex).loc, "half float vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setVector(4); - } -#line 8015 "MachineIndependent/glslang_tab.cpp" - break; - - case 268: /* type_specifier_nonarray: F32VEC2 */ -#line 2021 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(2); - } -#line 8026 "MachineIndependent/glslang_tab.cpp" - break; - - case 269: /* type_specifier_nonarray: F32VEC3 */ -#line 2027 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(3); - } -#line 8037 "MachineIndependent/glslang_tab.cpp" - break; - - case 270: /* type_specifier_nonarray: F32VEC4 */ -#line 2033 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setVector(4); - } -#line 8048 "MachineIndependent/glslang_tab.cpp" - break; - - case 271: /* type_specifier_nonarray: F64VEC2 */ -#line 2039 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(2); - } -#line 8059 "MachineIndependent/glslang_tab.cpp" - break; - - case 272: /* type_specifier_nonarray: F64VEC3 */ -#line 2045 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(3); - } -#line 8070 "MachineIndependent/glslang_tab.cpp" - break; - - case 273: /* type_specifier_nonarray: F64VEC4 */ -#line 2051 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setVector(4); - } -#line 8081 "MachineIndependent/glslang_tab.cpp" - break; - - case 274: /* type_specifier_nonarray: I8VEC2 */ -#line 2057 "MachineIndependent/glslang.y" - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - (yyval.interm.type).setVector(2); - } -#line 8092 "MachineIndependent/glslang_tab.cpp" - break; - - case 275: /* type_specifier_nonarray: I8VEC3 */ -#line 2063 "MachineIndependent/glslang.y" - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - (yyval.interm.type).setVector(3); - } -#line 8103 "MachineIndependent/glslang_tab.cpp" - break; - - case 276: /* type_specifier_nonarray: I8VEC4 */ -#line 2069 "MachineIndependent/glslang.y" - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt8; - (yyval.interm.type).setVector(4); - } -#line 8114 "MachineIndependent/glslang_tab.cpp" - break; - - case 277: /* type_specifier_nonarray: I16VEC2 */ -#line 2075 "MachineIndependent/glslang.y" - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - (yyval.interm.type).setVector(2); - } -#line 8125 "MachineIndependent/glslang_tab.cpp" - break; - - case 278: /* type_specifier_nonarray: I16VEC3 */ -#line 2081 "MachineIndependent/glslang.y" - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - (yyval.interm.type).setVector(3); - } -#line 8136 "MachineIndependent/glslang_tab.cpp" - break; - - case 279: /* type_specifier_nonarray: I16VEC4 */ -#line 2087 "MachineIndependent/glslang.y" - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt16; - (yyval.interm.type).setVector(4); - } -#line 8147 "MachineIndependent/glslang_tab.cpp" - break; - - case 280: /* type_specifier_nonarray: I32VEC2 */ -#line 2093 "MachineIndependent/glslang.y" - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(2); - } -#line 8158 "MachineIndependent/glslang_tab.cpp" - break; - - case 281: /* type_specifier_nonarray: I32VEC3 */ -#line 2099 "MachineIndependent/glslang.y" - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(3); - } -#line 8169 "MachineIndependent/glslang_tab.cpp" - break; - - case 282: /* type_specifier_nonarray: I32VEC4 */ -#line 2105 "MachineIndependent/glslang.y" - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit signed integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).setVector(4); - } -#line 8180 "MachineIndependent/glslang_tab.cpp" - break; - - case 283: /* type_specifier_nonarray: I64VEC2 */ -#line 2111 "MachineIndependent/glslang.y" - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - (yyval.interm.type).setVector(2); - } -#line 8191 "MachineIndependent/glslang_tab.cpp" - break; - - case 284: /* type_specifier_nonarray: I64VEC3 */ -#line 2117 "MachineIndependent/glslang.y" - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - (yyval.interm.type).setVector(3); - } -#line 8202 "MachineIndependent/glslang_tab.cpp" - break; - - case 285: /* type_specifier_nonarray: I64VEC4 */ -#line 2123 "MachineIndependent/glslang.y" - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt64; - (yyval.interm.type).setVector(4); - } -#line 8213 "MachineIndependent/glslang_tab.cpp" - break; - - case 286: /* type_specifier_nonarray: U8VEC2 */ -#line 2129 "MachineIndependent/glslang.y" - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint8; - (yyval.interm.type).setVector(2); - } -#line 8224 "MachineIndependent/glslang_tab.cpp" - break; - - case 287: /* type_specifier_nonarray: U8VEC3 */ -#line 2135 "MachineIndependent/glslang.y" - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint8; - (yyval.interm.type).setVector(3); - } -#line 8235 "MachineIndependent/glslang_tab.cpp" - break; - - case 288: /* type_specifier_nonarray: U8VEC4 */ -#line 2141 "MachineIndependent/glslang.y" - { - parseContext.int8ScalarVectorCheck((yyvsp[0].lex).loc, "8-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint8; - (yyval.interm.type).setVector(4); - } -#line 8246 "MachineIndependent/glslang_tab.cpp" - break; - - case 289: /* type_specifier_nonarray: U16VEC2 */ -#line 2147 "MachineIndependent/glslang.y" - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - (yyval.interm.type).setVector(2); - } -#line 8257 "MachineIndependent/glslang_tab.cpp" - break; - - case 290: /* type_specifier_nonarray: U16VEC3 */ -#line 2153 "MachineIndependent/glslang.y" - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - (yyval.interm.type).setVector(3); - } -#line 8268 "MachineIndependent/glslang_tab.cpp" - break; - - case 291: /* type_specifier_nonarray: U16VEC4 */ -#line 2159 "MachineIndependent/glslang.y" - { - parseContext.int16ScalarVectorCheck((yyvsp[0].lex).loc, "16-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint16; - (yyval.interm.type).setVector(4); - } -#line 8279 "MachineIndependent/glslang_tab.cpp" - break; - - case 292: /* type_specifier_nonarray: U32VEC2 */ -#line 2165 "MachineIndependent/glslang.y" - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(2); - } -#line 8290 "MachineIndependent/glslang_tab.cpp" - break; - - case 293: /* type_specifier_nonarray: U32VEC3 */ -#line 2171 "MachineIndependent/glslang.y" - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(3); - } -#line 8301 "MachineIndependent/glslang_tab.cpp" - break; - - case 294: /* type_specifier_nonarray: U32VEC4 */ -#line 2177 "MachineIndependent/glslang.y" - { - parseContext.explicitInt32Check((yyvsp[0].lex).loc, "32-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).setVector(4); - } -#line 8312 "MachineIndependent/glslang_tab.cpp" - break; - - case 295: /* type_specifier_nonarray: U64VEC2 */ -#line 2183 "MachineIndependent/glslang.y" - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - (yyval.interm.type).setVector(2); - } -#line 8323 "MachineIndependent/glslang_tab.cpp" - break; - - case 296: /* type_specifier_nonarray: U64VEC3 */ -#line 2189 "MachineIndependent/glslang.y" - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - (yyval.interm.type).setVector(3); - } -#line 8334 "MachineIndependent/glslang_tab.cpp" - break; - - case 297: /* type_specifier_nonarray: U64VEC4 */ -#line 2195 "MachineIndependent/glslang.y" - { - parseContext.int64Check((yyvsp[0].lex).loc, "64-bit unsigned integer vector", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint64; - (yyval.interm.type).setVector(4); - } -#line 8345 "MachineIndependent/glslang_tab.cpp" - break; - - case 298: /* type_specifier_nonarray: DMAT2 */ -#line 2201 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 8358 "MachineIndependent/glslang_tab.cpp" - break; - - case 299: /* type_specifier_nonarray: DMAT3 */ -#line 2209 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 8371 "MachineIndependent/glslang_tab.cpp" - break; - - case 300: /* type_specifier_nonarray: DMAT4 */ -#line 2217 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 8384 "MachineIndependent/glslang_tab.cpp" - break; - - case 301: /* type_specifier_nonarray: DMAT2X2 */ -#line 2225 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 8397 "MachineIndependent/glslang_tab.cpp" - break; - - case 302: /* type_specifier_nonarray: DMAT2X3 */ -#line 2233 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 3); - } -#line 8410 "MachineIndependent/glslang_tab.cpp" - break; - - case 303: /* type_specifier_nonarray: DMAT2X4 */ -#line 2241 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 4); - } -#line 8423 "MachineIndependent/glslang_tab.cpp" - break; - - case 304: /* type_specifier_nonarray: DMAT3X2 */ -#line 2249 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 2); - } -#line 8436 "MachineIndependent/glslang_tab.cpp" - break; - - case 305: /* type_specifier_nonarray: DMAT3X3 */ -#line 2257 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 8449 "MachineIndependent/glslang_tab.cpp" - break; - - case 306: /* type_specifier_nonarray: DMAT3X4 */ -#line 2265 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 4); - } -#line 8462 "MachineIndependent/glslang_tab.cpp" - break; - - case 307: /* type_specifier_nonarray: DMAT4X2 */ -#line 2273 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 2); - } -#line 8475 "MachineIndependent/glslang_tab.cpp" - break; - - case 308: /* type_specifier_nonarray: DMAT4X3 */ -#line 2281 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 3); - } -#line 8488 "MachineIndependent/glslang_tab.cpp" - break; - - case 309: /* type_specifier_nonarray: DMAT4X4 */ -#line 2289 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ECoreProfile | ECompatibilityProfile, "double matrix"); - if (! parseContext.symbolTable.atBuiltInLevel()) - parseContext.doubleCheck((yyvsp[0].lex).loc, "double matrix"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 8501 "MachineIndependent/glslang_tab.cpp" - break; - - case 310: /* type_specifier_nonarray: F16MAT2 */ -#line 2297 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 2); - } -#line 8512 "MachineIndependent/glslang_tab.cpp" - break; - - case 311: /* type_specifier_nonarray: F16MAT3 */ -#line 2303 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 3); - } -#line 8523 "MachineIndependent/glslang_tab.cpp" - break; - - case 312: /* type_specifier_nonarray: F16MAT4 */ -#line 2309 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 4); - } -#line 8534 "MachineIndependent/glslang_tab.cpp" - break; - - case 313: /* type_specifier_nonarray: F16MAT2X2 */ -#line 2315 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 2); - } -#line 8545 "MachineIndependent/glslang_tab.cpp" - break; - - case 314: /* type_specifier_nonarray: F16MAT2X3 */ -#line 2321 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 3); - } -#line 8556 "MachineIndependent/glslang_tab.cpp" - break; - - case 315: /* type_specifier_nonarray: F16MAT2X4 */ -#line 2327 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(2, 4); - } -#line 8567 "MachineIndependent/glslang_tab.cpp" - break; - - case 316: /* type_specifier_nonarray: F16MAT3X2 */ -#line 2333 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 2); - } -#line 8578 "MachineIndependent/glslang_tab.cpp" - break; - - case 317: /* type_specifier_nonarray: F16MAT3X3 */ -#line 2339 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 3); - } -#line 8589 "MachineIndependent/glslang_tab.cpp" - break; - - case 318: /* type_specifier_nonarray: F16MAT3X4 */ -#line 2345 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(3, 4); - } -#line 8600 "MachineIndependent/glslang_tab.cpp" - break; - - case 319: /* type_specifier_nonarray: F16MAT4X2 */ -#line 2351 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 2); - } -#line 8611 "MachineIndependent/glslang_tab.cpp" - break; - - case 320: /* type_specifier_nonarray: F16MAT4X3 */ -#line 2357 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 3); - } -#line 8622 "MachineIndependent/glslang_tab.cpp" - break; - - case 321: /* type_specifier_nonarray: F16MAT4X4 */ -#line 2363 "MachineIndependent/glslang.y" - { - parseContext.float16Check((yyvsp[0].lex).loc, "half float matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat16; - (yyval.interm.type).setMatrix(4, 4); - } -#line 8633 "MachineIndependent/glslang_tab.cpp" - break; - - case 322: /* type_specifier_nonarray: F32MAT2 */ -#line 2369 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 8644 "MachineIndependent/glslang_tab.cpp" - break; - - case 323: /* type_specifier_nonarray: F32MAT3 */ -#line 2375 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 8655 "MachineIndependent/glslang_tab.cpp" - break; - - case 324: /* type_specifier_nonarray: F32MAT4 */ -#line 2381 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 8666 "MachineIndependent/glslang_tab.cpp" - break; - - case 325: /* type_specifier_nonarray: F32MAT2X2 */ -#line 2387 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 2); - } -#line 8677 "MachineIndependent/glslang_tab.cpp" - break; - - case 326: /* type_specifier_nonarray: F32MAT2X3 */ -#line 2393 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 3); - } -#line 8688 "MachineIndependent/glslang_tab.cpp" - break; - - case 327: /* type_specifier_nonarray: F32MAT2X4 */ -#line 2399 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(2, 4); - } -#line 8699 "MachineIndependent/glslang_tab.cpp" - break; - - case 328: /* type_specifier_nonarray: F32MAT3X2 */ -#line 2405 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 2); - } -#line 8710 "MachineIndependent/glslang_tab.cpp" - break; - - case 329: /* type_specifier_nonarray: F32MAT3X3 */ -#line 2411 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 3); - } -#line 8721 "MachineIndependent/glslang_tab.cpp" - break; - - case 330: /* type_specifier_nonarray: F32MAT3X4 */ -#line 2417 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(3, 4); - } -#line 8732 "MachineIndependent/glslang_tab.cpp" - break; - - case 331: /* type_specifier_nonarray: F32MAT4X2 */ -#line 2423 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 2); - } -#line 8743 "MachineIndependent/glslang_tab.cpp" - break; - - case 332: /* type_specifier_nonarray: F32MAT4X3 */ -#line 2429 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 3); - } -#line 8754 "MachineIndependent/glslang_tab.cpp" - break; - - case 333: /* type_specifier_nonarray: F32MAT4X4 */ -#line 2435 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat32Check((yyvsp[0].lex).loc, "float32_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).setMatrix(4, 4); - } -#line 8765 "MachineIndependent/glslang_tab.cpp" - break; - - case 334: /* type_specifier_nonarray: F64MAT2 */ -#line 2441 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 8776 "MachineIndependent/glslang_tab.cpp" - break; - - case 335: /* type_specifier_nonarray: F64MAT3 */ -#line 2447 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 8787 "MachineIndependent/glslang_tab.cpp" - break; - - case 336: /* type_specifier_nonarray: F64MAT4 */ -#line 2453 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 8798 "MachineIndependent/glslang_tab.cpp" - break; - - case 337: /* type_specifier_nonarray: F64MAT2X2 */ -#line 2459 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 2); - } -#line 8809 "MachineIndependent/glslang_tab.cpp" - break; - - case 338: /* type_specifier_nonarray: F64MAT2X3 */ -#line 2465 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 3); - } -#line 8820 "MachineIndependent/glslang_tab.cpp" - break; - - case 339: /* type_specifier_nonarray: F64MAT2X4 */ -#line 2471 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(2, 4); - } -#line 8831 "MachineIndependent/glslang_tab.cpp" - break; - - case 340: /* type_specifier_nonarray: F64MAT3X2 */ -#line 2477 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 2); - } -#line 8842 "MachineIndependent/glslang_tab.cpp" - break; - - case 341: /* type_specifier_nonarray: F64MAT3X3 */ -#line 2483 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 3); - } -#line 8853 "MachineIndependent/glslang_tab.cpp" - break; - - case 342: /* type_specifier_nonarray: F64MAT3X4 */ -#line 2489 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(3, 4); - } -#line 8864 "MachineIndependent/glslang_tab.cpp" - break; - - case 343: /* type_specifier_nonarray: F64MAT4X2 */ -#line 2495 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 2); - } -#line 8875 "MachineIndependent/glslang_tab.cpp" - break; - - case 344: /* type_specifier_nonarray: F64MAT4X3 */ -#line 2501 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 3); - } -#line 8886 "MachineIndependent/glslang_tab.cpp" - break; - - case 345: /* type_specifier_nonarray: F64MAT4X4 */ -#line 2507 "MachineIndependent/glslang.y" - { - parseContext.explicitFloat64Check((yyvsp[0].lex).loc, "float64_t matrix", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtDouble; - (yyval.interm.type).setMatrix(4, 4); - } -#line 8897 "MachineIndependent/glslang_tab.cpp" - break; - - case 346: /* type_specifier_nonarray: ACCSTRUCTNV */ -#line 2513 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtAccStruct; - } -#line 8906 "MachineIndependent/glslang_tab.cpp" - break; - - case 347: /* type_specifier_nonarray: ACCSTRUCTEXT */ -#line 2517 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtAccStruct; - } -#line 8915 "MachineIndependent/glslang_tab.cpp" - break; - - case 348: /* type_specifier_nonarray: RAYQUERYEXT */ -#line 2521 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtRayQuery; - } -#line 8924 "MachineIndependent/glslang_tab.cpp" - break; - - case 349: /* type_specifier_nonarray: ATOMIC_UINT */ -#line 2525 "MachineIndependent/glslang.y" - { - parseContext.vulkanRemoved((yyvsp[0].lex).loc, "atomic counter types"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtAtomicUint; - } -#line 8934 "MachineIndependent/glslang_tab.cpp" - break; - - case 350: /* type_specifier_nonarray: SAMPLER1D */ -#line 2530 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D); - } -#line 8944 "MachineIndependent/glslang_tab.cpp" - break; - - case 351: /* type_specifier_nonarray: SAMPLER2D */ -#line 2535 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D); - } -#line 8954 "MachineIndependent/glslang_tab.cpp" - break; - - case 352: /* type_specifier_nonarray: SAMPLER3D */ -#line 2540 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd3D); - } -#line 8964 "MachineIndependent/glslang_tab.cpp" - break; - - case 353: /* type_specifier_nonarray: SAMPLERCUBE */ -#line 2545 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube); - } -#line 8974 "MachineIndependent/glslang_tab.cpp" - break; - - case 354: /* type_specifier_nonarray: SAMPLER2DSHADOW */ -#line 2550 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, true); - } -#line 8984 "MachineIndependent/glslang_tab.cpp" - break; - - case 355: /* type_specifier_nonarray: SAMPLERCUBESHADOW */ -#line 2555 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube, false, true); - } -#line 8994 "MachineIndependent/glslang_tab.cpp" - break; - - case 356: /* type_specifier_nonarray: SAMPLER2DARRAY */ -#line 2560 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true); - } -#line 9004 "MachineIndependent/glslang_tab.cpp" - break; - - case 357: /* type_specifier_nonarray: SAMPLER2DARRAYSHADOW */ -#line 2565 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, true); - } -#line 9014 "MachineIndependent/glslang_tab.cpp" - break; - - case 358: /* type_specifier_nonarray: SAMPLER1DSHADOW */ -#line 2570 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D, false, true); - } -#line 9024 "MachineIndependent/glslang_tab.cpp" - break; - - case 359: /* type_specifier_nonarray: SAMPLER1DARRAY */ -#line 2575 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true); - } -#line 9034 "MachineIndependent/glslang_tab.cpp" - break; - - case 360: /* type_specifier_nonarray: SAMPLER1DARRAYSHADOW */ -#line 2580 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd1D, true, true); - } -#line 9044 "MachineIndependent/glslang_tab.cpp" - break; - - case 361: /* type_specifier_nonarray: SAMPLERCUBEARRAY */ -#line 2585 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true); - } -#line 9054 "MachineIndependent/glslang_tab.cpp" - break; - - case 362: /* type_specifier_nonarray: SAMPLERCUBEARRAYSHADOW */ -#line 2590 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdCube, true, true); - } -#line 9064 "MachineIndependent/glslang_tab.cpp" - break; - - case 363: /* type_specifier_nonarray: F16SAMPLER1D */ -#line 2595 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D); - } -#line 9075 "MachineIndependent/glslang_tab.cpp" - break; - - case 364: /* type_specifier_nonarray: F16SAMPLER2D */ -#line 2601 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D); - } -#line 9086 "MachineIndependent/glslang_tab.cpp" - break; - - case 365: /* type_specifier_nonarray: F16SAMPLER3D */ -#line 2607 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd3D); - } -#line 9097 "MachineIndependent/glslang_tab.cpp" - break; - - case 366: /* type_specifier_nonarray: F16SAMPLERCUBE */ -#line 2613 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube); - } -#line 9108 "MachineIndependent/glslang_tab.cpp" - break; - - case 367: /* type_specifier_nonarray: F16SAMPLER1DSHADOW */ -#line 2619 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, false, true); - } -#line 9119 "MachineIndependent/glslang_tab.cpp" - break; - - case 368: /* type_specifier_nonarray: F16SAMPLER2DSHADOW */ -#line 2625 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, true); - } -#line 9130 "MachineIndependent/glslang_tab.cpp" - break; - - case 369: /* type_specifier_nonarray: F16SAMPLERCUBESHADOW */ -#line 2631 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, false, true); - } -#line 9141 "MachineIndependent/glslang_tab.cpp" - break; - - case 370: /* type_specifier_nonarray: F16SAMPLER1DARRAY */ -#line 2637 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true); - } -#line 9152 "MachineIndependent/glslang_tab.cpp" - break; - - case 371: /* type_specifier_nonarray: F16SAMPLER2DARRAY */ -#line 2643 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true); - } -#line 9163 "MachineIndependent/glslang_tab.cpp" - break; - - case 372: /* type_specifier_nonarray: F16SAMPLER1DARRAYSHADOW */ -#line 2649 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd1D, true, true); - } -#line 9174 "MachineIndependent/glslang_tab.cpp" - break; - - case 373: /* type_specifier_nonarray: F16SAMPLER2DARRAYSHADOW */ -#line 2655 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, true); - } -#line 9185 "MachineIndependent/glslang_tab.cpp" - break; - - case 374: /* type_specifier_nonarray: F16SAMPLERCUBEARRAY */ -#line 2661 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true); - } -#line 9196 "MachineIndependent/glslang_tab.cpp" - break; - - case 375: /* type_specifier_nonarray: F16SAMPLERCUBEARRAYSHADOW */ -#line 2667 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdCube, true, true); - } -#line 9207 "MachineIndependent/glslang_tab.cpp" - break; - - case 376: /* type_specifier_nonarray: ISAMPLER1D */ -#line 2673 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd1D); - } -#line 9217 "MachineIndependent/glslang_tab.cpp" - break; - - case 377: /* type_specifier_nonarray: ISAMPLER2D */ -#line 2678 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D); - } -#line 9227 "MachineIndependent/glslang_tab.cpp" - break; - - case 378: /* type_specifier_nonarray: ISAMPLER3D */ -#line 2683 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd3D); - } -#line 9237 "MachineIndependent/glslang_tab.cpp" - break; - - case 379: /* type_specifier_nonarray: ISAMPLERCUBE */ -#line 2688 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdCube); - } -#line 9247 "MachineIndependent/glslang_tab.cpp" - break; - - case 380: /* type_specifier_nonarray: ISAMPLER2DARRAY */ -#line 2693 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D, true); - } -#line 9257 "MachineIndependent/glslang_tab.cpp" - break; - - case 381: /* type_specifier_nonarray: USAMPLER2D */ -#line 2698 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D); - } -#line 9267 "MachineIndependent/glslang_tab.cpp" - break; - - case 382: /* type_specifier_nonarray: USAMPLER3D */ -#line 2703 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd3D); - } -#line 9277 "MachineIndependent/glslang_tab.cpp" - break; - - case 383: /* type_specifier_nonarray: USAMPLERCUBE */ -#line 2708 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdCube); - } -#line 9287 "MachineIndependent/glslang_tab.cpp" - break; - - case 384: /* type_specifier_nonarray: ISAMPLER1DARRAY */ -#line 2713 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd1D, true); - } -#line 9297 "MachineIndependent/glslang_tab.cpp" - break; - - case 385: /* type_specifier_nonarray: ISAMPLERCUBEARRAY */ -#line 2718 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdCube, true); - } -#line 9307 "MachineIndependent/glslang_tab.cpp" - break; - - case 386: /* type_specifier_nonarray: USAMPLER1D */ -#line 2723 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd1D); - } -#line 9317 "MachineIndependent/glslang_tab.cpp" - break; - - case 387: /* type_specifier_nonarray: USAMPLER1DARRAY */ -#line 2728 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd1D, true); - } -#line 9327 "MachineIndependent/glslang_tab.cpp" - break; - - case 388: /* type_specifier_nonarray: USAMPLERCUBEARRAY */ -#line 2733 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdCube, true); - } -#line 9337 "MachineIndependent/glslang_tab.cpp" - break; - - case 389: /* type_specifier_nonarray: TEXTURECUBEARRAY */ -#line 2738 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube, true); - } -#line 9347 "MachineIndependent/glslang_tab.cpp" - break; - - case 390: /* type_specifier_nonarray: ITEXTURECUBEARRAY */ -#line 2743 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube, true); - } -#line 9357 "MachineIndependent/glslang_tab.cpp" - break; - - case 391: /* type_specifier_nonarray: UTEXTURECUBEARRAY */ -#line 2748 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube, true); - } -#line 9367 "MachineIndependent/glslang_tab.cpp" - break; - - case 392: /* type_specifier_nonarray: USAMPLER2DARRAY */ -#line 2753 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D, true); - } -#line 9377 "MachineIndependent/glslang_tab.cpp" - break; - - case 393: /* type_specifier_nonarray: TEXTURE2D */ -#line 2758 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D); - } -#line 9387 "MachineIndependent/glslang_tab.cpp" - break; - - case 394: /* type_specifier_nonarray: TEXTURE3D */ -#line 2763 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd3D); - } -#line 9397 "MachineIndependent/glslang_tab.cpp" - break; - - case 395: /* type_specifier_nonarray: TEXTURE2DARRAY */ -#line 2768 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true); - } -#line 9407 "MachineIndependent/glslang_tab.cpp" - break; - - case 396: /* type_specifier_nonarray: TEXTURECUBE */ -#line 2773 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdCube); - } -#line 9417 "MachineIndependent/glslang_tab.cpp" - break; - - case 397: /* type_specifier_nonarray: ITEXTURE2D */ -#line 2778 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D); - } -#line 9427 "MachineIndependent/glslang_tab.cpp" - break; - - case 398: /* type_specifier_nonarray: ITEXTURE3D */ -#line 2783 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd3D); - } -#line 9437 "MachineIndependent/glslang_tab.cpp" - break; - - case 399: /* type_specifier_nonarray: ITEXTURECUBE */ -#line 2788 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdCube); - } -#line 9447 "MachineIndependent/glslang_tab.cpp" - break; - - case 400: /* type_specifier_nonarray: ITEXTURE2DARRAY */ -#line 2793 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true); - } -#line 9457 "MachineIndependent/glslang_tab.cpp" - break; - - case 401: /* type_specifier_nonarray: UTEXTURE2D */ -#line 2798 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D); - } -#line 9467 "MachineIndependent/glslang_tab.cpp" - break; - - case 402: /* type_specifier_nonarray: UTEXTURE3D */ -#line 2803 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd3D); - } -#line 9477 "MachineIndependent/glslang_tab.cpp" - break; - - case 403: /* type_specifier_nonarray: UTEXTURECUBE */ -#line 2808 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdCube); - } -#line 9487 "MachineIndependent/glslang_tab.cpp" - break; - - case 404: /* type_specifier_nonarray: UTEXTURE2DARRAY */ -#line 2813 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true); - } -#line 9497 "MachineIndependent/glslang_tab.cpp" - break; - - case 405: /* type_specifier_nonarray: SAMPLER */ -#line 2818 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setPureSampler(false); - } -#line 9507 "MachineIndependent/glslang_tab.cpp" - break; - - case 406: /* type_specifier_nonarray: SAMPLERSHADOW */ -#line 2823 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setPureSampler(true); - } -#line 9517 "MachineIndependent/glslang_tab.cpp" - break; - - case 407: /* type_specifier_nonarray: SAMPLER2DRECT */ -#line 2828 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdRect); - } -#line 9527 "MachineIndependent/glslang_tab.cpp" - break; - - case 408: /* type_specifier_nonarray: SAMPLER2DRECTSHADOW */ -#line 2833 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdRect, false, true); - } -#line 9537 "MachineIndependent/glslang_tab.cpp" - break; - - case 409: /* type_specifier_nonarray: F16SAMPLER2DRECT */ -#line 2838 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdRect); - } -#line 9548 "MachineIndependent/glslang_tab.cpp" - break; - - case 410: /* type_specifier_nonarray: F16SAMPLER2DRECTSHADOW */ -#line 2844 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdRect, false, true); - } -#line 9559 "MachineIndependent/glslang_tab.cpp" - break; - - case 411: /* type_specifier_nonarray: ISAMPLER2DRECT */ -#line 2850 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdRect); - } -#line 9569 "MachineIndependent/glslang_tab.cpp" - break; - - case 412: /* type_specifier_nonarray: USAMPLER2DRECT */ -#line 2855 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdRect); - } -#line 9579 "MachineIndependent/glslang_tab.cpp" - break; - - case 413: /* type_specifier_nonarray: SAMPLERBUFFER */ -#line 2860 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, EsdBuffer); - } -#line 9589 "MachineIndependent/glslang_tab.cpp" - break; - - case 414: /* type_specifier_nonarray: F16SAMPLERBUFFER */ -#line 2865 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, EsdBuffer); - } -#line 9600 "MachineIndependent/glslang_tab.cpp" - break; - - case 415: /* type_specifier_nonarray: ISAMPLERBUFFER */ -#line 2871 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, EsdBuffer); - } -#line 9610 "MachineIndependent/glslang_tab.cpp" - break; - - case 416: /* type_specifier_nonarray: USAMPLERBUFFER */ -#line 2876 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, EsdBuffer); - } -#line 9620 "MachineIndependent/glslang_tab.cpp" - break; - - case 417: /* type_specifier_nonarray: SAMPLER2DMS */ -#line 2881 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, false, false, true); - } -#line 9630 "MachineIndependent/glslang_tab.cpp" - break; - - case 418: /* type_specifier_nonarray: F16SAMPLER2DMS */ -#line 2886 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, false, false, true); - } -#line 9641 "MachineIndependent/glslang_tab.cpp" - break; - - case 419: /* type_specifier_nonarray: ISAMPLER2DMS */ -#line 2892 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D, false, false, true); - } -#line 9651 "MachineIndependent/glslang_tab.cpp" - break; - - case 420: /* type_specifier_nonarray: USAMPLER2DMS */ -#line 2897 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D, false, false, true); - } -#line 9661 "MachineIndependent/glslang_tab.cpp" - break; - - case 421: /* type_specifier_nonarray: SAMPLER2DMSARRAY */ -#line 2902 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D, true, false, true); - } -#line 9671 "MachineIndependent/glslang_tab.cpp" - break; - - case 422: /* type_specifier_nonarray: F16SAMPLER2DMSARRAY */ -#line 2907 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float sampler", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat16, Esd2D, true, false, true); - } -#line 9682 "MachineIndependent/glslang_tab.cpp" - break; - - case 423: /* type_specifier_nonarray: ISAMPLER2DMSARRAY */ -#line 2913 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtInt, Esd2D, true, false, true); - } -#line 9692 "MachineIndependent/glslang_tab.cpp" - break; - - case 424: /* type_specifier_nonarray: USAMPLER2DMSARRAY */ -#line 2918 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtUint, Esd2D, true, false, true); - } -#line 9702 "MachineIndependent/glslang_tab.cpp" - break; - - case 425: /* type_specifier_nonarray: TEXTURE1D */ -#line 2923 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D); - } -#line 9712 "MachineIndependent/glslang_tab.cpp" - break; - - case 426: /* type_specifier_nonarray: F16TEXTURE1D */ -#line 2928 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D); - } -#line 9723 "MachineIndependent/glslang_tab.cpp" - break; - - case 427: /* type_specifier_nonarray: F16TEXTURE2D */ -#line 2934 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D); - } -#line 9734 "MachineIndependent/glslang_tab.cpp" - break; - - case 428: /* type_specifier_nonarray: F16TEXTURE3D */ -#line 2940 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd3D); - } -#line 9745 "MachineIndependent/glslang_tab.cpp" - break; - - case 429: /* type_specifier_nonarray: F16TEXTURECUBE */ -#line 2946 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube); - } -#line 9756 "MachineIndependent/glslang_tab.cpp" - break; - - case 430: /* type_specifier_nonarray: TEXTURE1DARRAY */ -#line 2952 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd1D, true); - } -#line 9766 "MachineIndependent/glslang_tab.cpp" - break; - - case 431: /* type_specifier_nonarray: F16TEXTURE1DARRAY */ -#line 2957 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd1D, true); - } -#line 9777 "MachineIndependent/glslang_tab.cpp" - break; - - case 432: /* type_specifier_nonarray: F16TEXTURE2DARRAY */ -#line 2963 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true); - } -#line 9788 "MachineIndependent/glslang_tab.cpp" - break; - - case 433: /* type_specifier_nonarray: F16TEXTURECUBEARRAY */ -#line 2969 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdCube, true); - } -#line 9799 "MachineIndependent/glslang_tab.cpp" - break; - - case 434: /* type_specifier_nonarray: ITEXTURE1D */ -#line 2975 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D); - } -#line 9809 "MachineIndependent/glslang_tab.cpp" - break; - - case 435: /* type_specifier_nonarray: ITEXTURE1DARRAY */ -#line 2980 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd1D, true); - } -#line 9819 "MachineIndependent/glslang_tab.cpp" - break; - - case 436: /* type_specifier_nonarray: UTEXTURE1D */ -#line 2985 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D); - } -#line 9829 "MachineIndependent/glslang_tab.cpp" - break; - - case 437: /* type_specifier_nonarray: UTEXTURE1DARRAY */ -#line 2990 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd1D, true); - } -#line 9839 "MachineIndependent/glslang_tab.cpp" - break; - - case 438: /* type_specifier_nonarray: TEXTURE2DRECT */ -#line 2995 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdRect); - } -#line 9849 "MachineIndependent/glslang_tab.cpp" - break; - - case 439: /* type_specifier_nonarray: F16TEXTURE2DRECT */ -#line 3000 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdRect); - } -#line 9860 "MachineIndependent/glslang_tab.cpp" - break; - - case 440: /* type_specifier_nonarray: ITEXTURE2DRECT */ -#line 3006 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdRect); - } -#line 9870 "MachineIndependent/glslang_tab.cpp" - break; - - case 441: /* type_specifier_nonarray: UTEXTURE2DRECT */ -#line 3011 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdRect); - } -#line 9880 "MachineIndependent/glslang_tab.cpp" - break; - - case 442: /* type_specifier_nonarray: TEXTUREBUFFER */ -#line 3016 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, EsdBuffer); - } -#line 9890 "MachineIndependent/glslang_tab.cpp" - break; - - case 443: /* type_specifier_nonarray: F16TEXTUREBUFFER */ -#line 3021 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, EsdBuffer); - } -#line 9901 "MachineIndependent/glslang_tab.cpp" - break; - - case 444: /* type_specifier_nonarray: ITEXTUREBUFFER */ -#line 3027 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, EsdBuffer); - } -#line 9911 "MachineIndependent/glslang_tab.cpp" - break; - - case 445: /* type_specifier_nonarray: UTEXTUREBUFFER */ -#line 3032 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, EsdBuffer); - } -#line 9921 "MachineIndependent/glslang_tab.cpp" - break; - - case 446: /* type_specifier_nonarray: TEXTURE2DMS */ -#line 3037 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, false, false, true); - } -#line 9931 "MachineIndependent/glslang_tab.cpp" - break; - - case 447: /* type_specifier_nonarray: F16TEXTURE2DMS */ -#line 3042 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, false, false, true); - } -#line 9942 "MachineIndependent/glslang_tab.cpp" - break; - - case 448: /* type_specifier_nonarray: ITEXTURE2DMS */ -#line 3048 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, false, false, true); - } -#line 9952 "MachineIndependent/glslang_tab.cpp" - break; - - case 449: /* type_specifier_nonarray: UTEXTURE2DMS */ -#line 3053 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, false, false, true); - } -#line 9962 "MachineIndependent/glslang_tab.cpp" - break; - - case 450: /* type_specifier_nonarray: TEXTURE2DMSARRAY */ -#line 3058 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat, Esd2D, true, false, true); - } -#line 9972 "MachineIndependent/glslang_tab.cpp" - break; - - case 451: /* type_specifier_nonarray: F16TEXTURE2DMSARRAY */ -#line 3063 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float texture", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtFloat16, Esd2D, true, false, true); - } -#line 9983 "MachineIndependent/glslang_tab.cpp" - break; - - case 452: /* type_specifier_nonarray: ITEXTURE2DMSARRAY */ -#line 3069 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtInt, Esd2D, true, false, true); - } -#line 9993 "MachineIndependent/glslang_tab.cpp" - break; - - case 453: /* type_specifier_nonarray: UTEXTURE2DMSARRAY */ -#line 3074 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setTexture(EbtUint, Esd2D, true, false, true); - } -#line 10003 "MachineIndependent/glslang_tab.cpp" - break; - - case 454: /* type_specifier_nonarray: IMAGE1D */ -#line 3079 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D); - } -#line 10013 "MachineIndependent/glslang_tab.cpp" - break; - - case 455: /* type_specifier_nonarray: F16IMAGE1D */ -#line 3084 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D); - } -#line 10024 "MachineIndependent/glslang_tab.cpp" - break; - - case 456: /* type_specifier_nonarray: IIMAGE1D */ -#line 3090 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd1D); - } -#line 10034 "MachineIndependent/glslang_tab.cpp" - break; - - case 457: /* type_specifier_nonarray: UIMAGE1D */ -#line 3095 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd1D); - } -#line 10044 "MachineIndependent/glslang_tab.cpp" - break; - - case 458: /* type_specifier_nonarray: IMAGE2D */ -#line 3100 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D); - } -#line 10054 "MachineIndependent/glslang_tab.cpp" - break; - - case 459: /* type_specifier_nonarray: F16IMAGE2D */ -#line 3105 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D); - } -#line 10065 "MachineIndependent/glslang_tab.cpp" - break; - - case 460: /* type_specifier_nonarray: IIMAGE2D */ -#line 3111 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D); - } -#line 10075 "MachineIndependent/glslang_tab.cpp" - break; - - case 461: /* type_specifier_nonarray: UIMAGE2D */ -#line 3116 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D); - } -#line 10085 "MachineIndependent/glslang_tab.cpp" - break; - - case 462: /* type_specifier_nonarray: IMAGE3D */ -#line 3121 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd3D); - } -#line 10095 "MachineIndependent/glslang_tab.cpp" - break; - - case 463: /* type_specifier_nonarray: F16IMAGE3D */ -#line 3126 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd3D); - } -#line 10106 "MachineIndependent/glslang_tab.cpp" - break; - - case 464: /* type_specifier_nonarray: IIMAGE3D */ -#line 3132 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd3D); - } -#line 10116 "MachineIndependent/glslang_tab.cpp" - break; - - case 465: /* type_specifier_nonarray: UIMAGE3D */ -#line 3137 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd3D); - } -#line 10126 "MachineIndependent/glslang_tab.cpp" - break; - - case 466: /* type_specifier_nonarray: IMAGE2DRECT */ -#line 3142 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdRect); - } -#line 10136 "MachineIndependent/glslang_tab.cpp" - break; - - case 467: /* type_specifier_nonarray: F16IMAGE2DRECT */ -#line 3147 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdRect); - } -#line 10147 "MachineIndependent/glslang_tab.cpp" - break; - - case 468: /* type_specifier_nonarray: IIMAGE2DRECT */ -#line 3153 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdRect); - } -#line 10157 "MachineIndependent/glslang_tab.cpp" - break; - - case 469: /* type_specifier_nonarray: UIMAGE2DRECT */ -#line 3158 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdRect); - } -#line 10167 "MachineIndependent/glslang_tab.cpp" - break; - - case 470: /* type_specifier_nonarray: IMAGECUBE */ -#line 3163 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube); - } -#line 10177 "MachineIndependent/glslang_tab.cpp" - break; - - case 471: /* type_specifier_nonarray: F16IMAGECUBE */ -#line 3168 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube); - } -#line 10188 "MachineIndependent/glslang_tab.cpp" - break; - - case 472: /* type_specifier_nonarray: IIMAGECUBE */ -#line 3174 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdCube); - } -#line 10198 "MachineIndependent/glslang_tab.cpp" - break; - - case 473: /* type_specifier_nonarray: UIMAGECUBE */ -#line 3179 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdCube); - } -#line 10208 "MachineIndependent/glslang_tab.cpp" - break; - - case 474: /* type_specifier_nonarray: IMAGEBUFFER */ -#line 3184 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdBuffer); - } -#line 10218 "MachineIndependent/glslang_tab.cpp" - break; - - case 475: /* type_specifier_nonarray: F16IMAGEBUFFER */ -#line 3189 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdBuffer); - } -#line 10229 "MachineIndependent/glslang_tab.cpp" - break; - - case 476: /* type_specifier_nonarray: IIMAGEBUFFER */ -#line 3195 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdBuffer); - } -#line 10239 "MachineIndependent/glslang_tab.cpp" - break; - - case 477: /* type_specifier_nonarray: UIMAGEBUFFER */ -#line 3200 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdBuffer); - } -#line 10249 "MachineIndependent/glslang_tab.cpp" - break; - - case 478: /* type_specifier_nonarray: IMAGE1DARRAY */ -#line 3205 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd1D, true); - } -#line 10259 "MachineIndependent/glslang_tab.cpp" - break; - - case 479: /* type_specifier_nonarray: F16IMAGE1DARRAY */ -#line 3210 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd1D, true); - } -#line 10270 "MachineIndependent/glslang_tab.cpp" - break; - - case 480: /* type_specifier_nonarray: IIMAGE1DARRAY */ -#line 3216 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd1D, true); - } -#line 10280 "MachineIndependent/glslang_tab.cpp" - break; - - case 481: /* type_specifier_nonarray: UIMAGE1DARRAY */ -#line 3221 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd1D, true); - } -#line 10290 "MachineIndependent/glslang_tab.cpp" - break; - - case 482: /* type_specifier_nonarray: IMAGE2DARRAY */ -#line 3226 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true); - } -#line 10300 "MachineIndependent/glslang_tab.cpp" - break; - - case 483: /* type_specifier_nonarray: F16IMAGE2DARRAY */ -#line 3231 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true); - } -#line 10311 "MachineIndependent/glslang_tab.cpp" - break; - - case 484: /* type_specifier_nonarray: IIMAGE2DARRAY */ -#line 3237 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true); - } -#line 10321 "MachineIndependent/glslang_tab.cpp" - break; - - case 485: /* type_specifier_nonarray: UIMAGE2DARRAY */ -#line 3242 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true); - } -#line 10331 "MachineIndependent/glslang_tab.cpp" - break; - - case 486: /* type_specifier_nonarray: IMAGECUBEARRAY */ -#line 3247 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, EsdCube, true); - } -#line 10341 "MachineIndependent/glslang_tab.cpp" - break; - - case 487: /* type_specifier_nonarray: F16IMAGECUBEARRAY */ -#line 3252 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, EsdCube, true); - } -#line 10352 "MachineIndependent/glslang_tab.cpp" - break; - - case 488: /* type_specifier_nonarray: IIMAGECUBEARRAY */ -#line 3258 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, EsdCube, true); - } -#line 10362 "MachineIndependent/glslang_tab.cpp" - break; - - case 489: /* type_specifier_nonarray: UIMAGECUBEARRAY */ -#line 3263 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, EsdCube, true); - } -#line 10372 "MachineIndependent/glslang_tab.cpp" - break; - - case 490: /* type_specifier_nonarray: IMAGE2DMS */ -#line 3268 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, false, false, true); - } -#line 10382 "MachineIndependent/glslang_tab.cpp" - break; - - case 491: /* type_specifier_nonarray: F16IMAGE2DMS */ -#line 3273 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, false, false, true); - } -#line 10393 "MachineIndependent/glslang_tab.cpp" - break; - - case 492: /* type_specifier_nonarray: IIMAGE2DMS */ -#line 3279 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, false, false, true); - } -#line 10403 "MachineIndependent/glslang_tab.cpp" - break; - - case 493: /* type_specifier_nonarray: UIMAGE2DMS */ -#line 3284 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, false, false, true); - } -#line 10413 "MachineIndependent/glslang_tab.cpp" - break; - - case 494: /* type_specifier_nonarray: IMAGE2DMSARRAY */ -#line 3289 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat, Esd2D, true, false, true); - } -#line 10423 "MachineIndependent/glslang_tab.cpp" - break; - - case 495: /* type_specifier_nonarray: F16IMAGE2DMSARRAY */ -#line 3294 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float image", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtFloat16, Esd2D, true, false, true); - } -#line 10434 "MachineIndependent/glslang_tab.cpp" - break; - - case 496: /* type_specifier_nonarray: IIMAGE2DMSARRAY */ -#line 3300 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt, Esd2D, true, false, true); - } -#line 10444 "MachineIndependent/glslang_tab.cpp" - break; - - case 497: /* type_specifier_nonarray: UIMAGE2DMSARRAY */ -#line 3305 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint, Esd2D, true, false, true); - } -#line 10454 "MachineIndependent/glslang_tab.cpp" - break; - - case 498: /* type_specifier_nonarray: I64IMAGE1D */ -#line 3310 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt64, Esd1D); - } -#line 10464 "MachineIndependent/glslang_tab.cpp" - break; - - case 499: /* type_specifier_nonarray: U64IMAGE1D */ -#line 3315 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint64, Esd1D); - } -#line 10474 "MachineIndependent/glslang_tab.cpp" - break; - - case 500: /* type_specifier_nonarray: I64IMAGE2D */ -#line 3320 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D); - } -#line 10484 "MachineIndependent/glslang_tab.cpp" - break; - - case 501: /* type_specifier_nonarray: U64IMAGE2D */ -#line 3325 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D); - } -#line 10494 "MachineIndependent/glslang_tab.cpp" - break; - - case 502: /* type_specifier_nonarray: I64IMAGE3D */ -#line 3330 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt64, Esd3D); - } -#line 10504 "MachineIndependent/glslang_tab.cpp" - break; - - case 503: /* type_specifier_nonarray: U64IMAGE3D */ -#line 3335 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint64, Esd3D); - } -#line 10514 "MachineIndependent/glslang_tab.cpp" - break; - - case 504: /* type_specifier_nonarray: I64IMAGE2DRECT */ -#line 3340 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt64, EsdRect); - } -#line 10524 "MachineIndependent/glslang_tab.cpp" - break; - - case 505: /* type_specifier_nonarray: U64IMAGE2DRECT */ -#line 3345 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint64, EsdRect); - } -#line 10534 "MachineIndependent/glslang_tab.cpp" - break; - - case 506: /* type_specifier_nonarray: I64IMAGECUBE */ -#line 3350 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt64, EsdCube); - } -#line 10544 "MachineIndependent/glslang_tab.cpp" - break; - - case 507: /* type_specifier_nonarray: U64IMAGECUBE */ -#line 3355 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint64, EsdCube); - } -#line 10554 "MachineIndependent/glslang_tab.cpp" - break; - - case 508: /* type_specifier_nonarray: I64IMAGEBUFFER */ -#line 3360 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt64, EsdBuffer); - } -#line 10564 "MachineIndependent/glslang_tab.cpp" - break; - - case 509: /* type_specifier_nonarray: U64IMAGEBUFFER */ -#line 3365 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint64, EsdBuffer); - } -#line 10574 "MachineIndependent/glslang_tab.cpp" - break; - - case 510: /* type_specifier_nonarray: I64IMAGE1DARRAY */ -#line 3370 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt64, Esd1D, true); - } -#line 10584 "MachineIndependent/glslang_tab.cpp" - break; - - case 511: /* type_specifier_nonarray: U64IMAGE1DARRAY */ -#line 3375 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint64, Esd1D, true); - } -#line 10594 "MachineIndependent/glslang_tab.cpp" - break; - - case 512: /* type_specifier_nonarray: I64IMAGE2DARRAY */ -#line 3380 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D, true); - } -#line 10604 "MachineIndependent/glslang_tab.cpp" - break; - - case 513: /* type_specifier_nonarray: U64IMAGE2DARRAY */ -#line 3385 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D, true); - } -#line 10614 "MachineIndependent/glslang_tab.cpp" - break; - - case 514: /* type_specifier_nonarray: I64IMAGECUBEARRAY */ -#line 3390 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt64, EsdCube, true); - } -#line 10624 "MachineIndependent/glslang_tab.cpp" - break; - - case 515: /* type_specifier_nonarray: U64IMAGECUBEARRAY */ -#line 3395 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint64, EsdCube, true); - } -#line 10634 "MachineIndependent/glslang_tab.cpp" - break; - - case 516: /* type_specifier_nonarray: I64IMAGE2DMS */ -#line 3400 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D, false, false, true); - } -#line 10644 "MachineIndependent/glslang_tab.cpp" - break; - - case 517: /* type_specifier_nonarray: U64IMAGE2DMS */ -#line 3405 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D, false, false, true); - } -#line 10654 "MachineIndependent/glslang_tab.cpp" - break; - - case 518: /* type_specifier_nonarray: I64IMAGE2DMSARRAY */ -#line 3410 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtInt64, Esd2D, true, false, true); - } -#line 10664 "MachineIndependent/glslang_tab.cpp" - break; - - case 519: /* type_specifier_nonarray: U64IMAGE2DMSARRAY */ -#line 3415 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setImage(EbtUint64, Esd2D, true, false, true); - } -#line 10674 "MachineIndependent/glslang_tab.cpp" - break; - - case 520: /* type_specifier_nonarray: SAMPLEREXTERNALOES */ -#line 3420 "MachineIndependent/glslang.y" - { // GL_OES_EGL_image_external - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D); - (yyval.interm.type).sampler.external = true; - } -#line 10685 "MachineIndependent/glslang_tab.cpp" - break; - - case 521: /* type_specifier_nonarray: SAMPLEREXTERNAL2DY2YEXT */ -#line 3426 "MachineIndependent/glslang.y" - { // GL_EXT_YUV_target - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.set(EbtFloat, Esd2D); - (yyval.interm.type).sampler.yuv = true; - } -#line 10696 "MachineIndependent/glslang_tab.cpp" - break; - - case 522: /* type_specifier_nonarray: ATTACHMENTEXT */ -#line 3432 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "attachmentEXT input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setAttachmentEXT(EbtFloat); - } -#line 10707 "MachineIndependent/glslang_tab.cpp" - break; - - case 523: /* type_specifier_nonarray: IATTACHMENTEXT */ -#line 3438 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "attachmentEXT input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setAttachmentEXT(EbtInt); - } -#line 10718 "MachineIndependent/glslang_tab.cpp" - break; - - case 524: /* type_specifier_nonarray: UATTACHMENTEXT */ -#line 3444 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "attachmentEXT input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setAttachmentEXT(EbtUint); - } -#line 10729 "MachineIndependent/glslang_tab.cpp" - break; - - case 525: /* type_specifier_nonarray: SUBPASSINPUT */ -#line 3450 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat); - } -#line 10740 "MachineIndependent/glslang_tab.cpp" - break; - - case 526: /* type_specifier_nonarray: SUBPASSINPUTMS */ -#line 3456 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat, true); - } -#line 10751 "MachineIndependent/glslang_tab.cpp" - break; - - case 527: /* type_specifier_nonarray: F16SUBPASSINPUT */ -#line 3462 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat16); - } -#line 10763 "MachineIndependent/glslang_tab.cpp" - break; - - case 528: /* type_specifier_nonarray: F16SUBPASSINPUTMS */ -#line 3469 "MachineIndependent/glslang.y" - { - parseContext.float16OpaqueCheck((yyvsp[0].lex).loc, "half float subpass input", parseContext.symbolTable.atBuiltInLevel()); - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtFloat16, true); - } -#line 10775 "MachineIndependent/glslang_tab.cpp" - break; - - case 529: /* type_specifier_nonarray: ISUBPASSINPUT */ -#line 3476 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtInt); - } -#line 10786 "MachineIndependent/glslang_tab.cpp" - break; - - case 530: /* type_specifier_nonarray: ISUBPASSINPUTMS */ -#line 3482 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtInt, true); - } -#line 10797 "MachineIndependent/glslang_tab.cpp" - break; - - case 531: /* type_specifier_nonarray: USUBPASSINPUT */ -#line 3488 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtUint); - } -#line 10808 "MachineIndependent/glslang_tab.cpp" - break; - - case 532: /* type_specifier_nonarray: USUBPASSINPUTMS */ -#line 3494 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[0].lex).loc, EShLangFragment, "subpass input"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtSampler; - (yyval.interm.type).sampler.setSubpass(EbtUint, true); - } -#line 10819 "MachineIndependent/glslang_tab.cpp" - break; - - case 533: /* type_specifier_nonarray: FCOOPMATNV */ -#line 3500 "MachineIndependent/glslang.y" - { - parseContext.fcoopmatCheckNV((yyvsp[0].lex).loc, "fcoopmatNV", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtFloat; - (yyval.interm.type).coopmatNV = true; - (yyval.interm.type).coopmatKHR = false; - } -#line 10831 "MachineIndependent/glslang_tab.cpp" - break; - - case 534: /* type_specifier_nonarray: ICOOPMATNV */ -#line 3507 "MachineIndependent/glslang.y" - { - parseContext.intcoopmatCheckNV((yyvsp[0].lex).loc, "icoopmatNV", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtInt; - (yyval.interm.type).coopmatNV = true; - (yyval.interm.type).coopmatKHR = false; - } -#line 10843 "MachineIndependent/glslang_tab.cpp" - break; - - case 535: /* type_specifier_nonarray: UCOOPMATNV */ -#line 3514 "MachineIndependent/glslang.y" - { - parseContext.intcoopmatCheckNV((yyvsp[0].lex).loc, "ucoopmatNV", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtUint; - (yyval.interm.type).coopmatNV = true; - (yyval.interm.type).coopmatKHR = false; - } -#line 10855 "MachineIndependent/glslang_tab.cpp" - break; - - case 536: /* type_specifier_nonarray: COOPMAT */ -#line 3521 "MachineIndependent/glslang.y" - { - parseContext.coopmatCheck((yyvsp[0].lex).loc, "coopmat", parseContext.symbolTable.atBuiltInLevel()); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtCoopmat; - (yyval.interm.type).coopmatNV = false; - (yyval.interm.type).coopmatKHR = true; - } -#line 10867 "MachineIndependent/glslang_tab.cpp" - break; - - case 537: /* type_specifier_nonarray: spirv_type_specifier */ -#line 3528 "MachineIndependent/glslang.y" - { - parseContext.requireExtensions((yyvsp[0].interm.type).loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier"); - (yyval.interm.type) = (yyvsp[0].interm.type); - } -#line 10876 "MachineIndependent/glslang_tab.cpp" - break; - - case 538: /* type_specifier_nonarray: HITOBJECTNV */ -#line 3532 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtHitObjectNV; - } -#line 10885 "MachineIndependent/glslang_tab.cpp" - break; - - case 539: /* type_specifier_nonarray: struct_specifier */ -#line 3536 "MachineIndependent/glslang.y" - { - (yyval.interm.type) = (yyvsp[0].interm.type); - (yyval.interm.type).qualifier.storage = parseContext.symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; - parseContext.structTypeCheck((yyval.interm.type).loc, (yyval.interm.type)); - } -#line 10895 "MachineIndependent/glslang_tab.cpp" - break; - - case 540: /* type_specifier_nonarray: TYPE_NAME */ -#line 3541 "MachineIndependent/glslang.y" - { - // - // This is for user defined type names. The lexical phase looked up the - // type. - // - if (const TVariable* variable = ((yyvsp[0].lex).symbol)->getAsVariable()) { - const TType& structure = variable->getType(); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).basicType = EbtStruct; - (yyval.interm.type).userDef = &structure; - } else - parseContext.error((yyvsp[0].lex).loc, "expected type name", (yyvsp[0].lex).string->c_str(), ""); - } -#line 10913 "MachineIndependent/glslang_tab.cpp" - break; - - case 541: /* precision_qualifier: HIGH_PRECISION */ -#line 3557 "MachineIndependent/glslang.y" - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "highp precision qualifier"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqHigh); - } -#line 10923 "MachineIndependent/glslang_tab.cpp" - break; - - case 542: /* precision_qualifier: MEDIUM_PRECISION */ -#line 3562 "MachineIndependent/glslang.y" - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "mediump precision qualifier"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqMedium); - } -#line 10933 "MachineIndependent/glslang_tab.cpp" - break; - - case 543: /* precision_qualifier: LOW_PRECISION */ -#line 3567 "MachineIndependent/glslang.y" - { - parseContext.profileRequires((yyvsp[0].lex).loc, ENoProfile, 130, 0, "lowp precision qualifier"); - (yyval.interm.type).init((yyvsp[0].lex).loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.handlePrecisionQualifier((yyvsp[0].lex).loc, (yyval.interm.type).qualifier, EpqLow); - } -#line 10943 "MachineIndependent/glslang_tab.cpp" - break; - - case 544: /* $@3: %empty */ -#line 3575 "MachineIndependent/glslang.y" - { parseContext.nestedStructCheck((yyvsp[-2].lex).loc); } -#line 10949 "MachineIndependent/glslang_tab.cpp" - break; - - case 545: /* struct_specifier: STRUCT IDENTIFIER LEFT_BRACE $@3 struct_declaration_list RIGHT_BRACE */ -#line 3575 "MachineIndependent/glslang.y" - { - - TType* structure = new TType((yyvsp[-1].interm.typeList), *(yyvsp[-4].lex).string); - parseContext.structArrayCheck((yyvsp[-4].lex).loc, *structure); - - TVariable* userTypeDef = new TVariable((yyvsp[-4].lex).string, *structure, true); - if (! parseContext.symbolTable.insert(*userTypeDef)) - parseContext.error((yyvsp[-4].lex).loc, "redefinition", (yyvsp[-4].lex).string->c_str(), "struct"); - else if (parseContext.spvVersion.vulkanRelaxed - && structure->containsOpaque()) - parseContext.relaxedSymbols.push_back(structure->getTypeName()); - - (yyval.interm.type).init((yyvsp[-5].lex).loc); - (yyval.interm.type).basicType = EbtStruct; - (yyval.interm.type).userDef = structure; - --parseContext.structNestingLevel; - } -#line 10971 "MachineIndependent/glslang_tab.cpp" - break; - - case 546: /* $@4: %empty */ -#line 3592 "MachineIndependent/glslang.y" - { parseContext.nestedStructCheck((yyvsp[-1].lex).loc); } -#line 10977 "MachineIndependent/glslang_tab.cpp" - break; - - case 547: /* struct_specifier: STRUCT LEFT_BRACE $@4 struct_declaration_list RIGHT_BRACE */ -#line 3592 "MachineIndependent/glslang.y" - { - TType* structure = new TType((yyvsp[-1].interm.typeList), TString("")); - (yyval.interm.type).init((yyvsp[-4].lex).loc); - (yyval.interm.type).basicType = EbtStruct; - (yyval.interm.type).userDef = structure; - --parseContext.structNestingLevel; - } -#line 10989 "MachineIndependent/glslang_tab.cpp" - break; - - case 548: /* struct_declaration_list: struct_declaration */ -#line 3602 "MachineIndependent/glslang.y" - { - (yyval.interm.typeList) = (yyvsp[0].interm.typeList); - } -#line 10997 "MachineIndependent/glslang_tab.cpp" - break; - - case 549: /* struct_declaration_list: struct_declaration_list struct_declaration */ -#line 3605 "MachineIndependent/glslang.y" - { - (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); - for (unsigned int i = 0; i < (yyvsp[0].interm.typeList)->size(); ++i) { - for (unsigned int j = 0; j < (yyval.interm.typeList)->size(); ++j) { - if ((*(yyval.interm.typeList))[j].type->getFieldName() == (*(yyvsp[0].interm.typeList))[i].type->getFieldName()) - parseContext.error((*(yyvsp[0].interm.typeList))[i].loc, "duplicate member name:", "", (*(yyvsp[0].interm.typeList))[i].type->getFieldName().c_str()); - } - (yyval.interm.typeList)->push_back((*(yyvsp[0].interm.typeList))[i]); - } - } -#line 11012 "MachineIndependent/glslang_tab.cpp" - break; - - case 550: /* struct_declaration: type_specifier struct_declarator_list SEMICOLON */ -#line 3618 "MachineIndependent/glslang.y" - { - if ((yyvsp[-2].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - if (parseContext.isEsProfile()) - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - } - - (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); - - parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType); - parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier, (yyvsp[-2].interm.type).isCoopmat()); - - for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) { - TType type((yyvsp[-2].interm.type)); - type.setFieldName((*(yyval.interm.typeList))[i].type->getFieldName()); - type.transferArraySizes((*(yyval.interm.typeList))[i].type->getArraySizes()); - type.copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); - parseContext.arrayOfArrayVersionCheck((*(yyval.interm.typeList))[i].loc, type.getArraySizes()); - (*(yyval.interm.typeList))[i].type->shallowCopy(type); - } - } -#line 11039 "MachineIndependent/glslang_tab.cpp" - break; - - case 551: /* struct_declaration: type_qualifier type_specifier struct_declarator_list SEMICOLON */ -#line 3640 "MachineIndependent/glslang.y" - { - if ((yyvsp[-2].interm.type).arraySizes) { - parseContext.profileRequires((yyvsp[-2].interm.type).loc, ENoProfile, 120, E_GL_3DL_array_objects, "arrayed type"); - parseContext.profileRequires((yyvsp[-2].interm.type).loc, EEsProfile, 300, 0, "arrayed type"); - if (parseContext.isEsProfile()) - parseContext.arraySizeRequiredCheck((yyvsp[-2].interm.type).loc, *(yyvsp[-2].interm.type).arraySizes); - } - - (yyval.interm.typeList) = (yyvsp[-1].interm.typeList); - - parseContext.memberQualifierCheck((yyvsp[-3].interm.type)); - parseContext.voidErrorCheck((yyvsp[-2].interm.type).loc, (*(yyvsp[-1].interm.typeList))[0].type->getFieldName(), (yyvsp[-2].interm.type).basicType); - parseContext.mergeQualifiers((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).qualifier, (yyvsp[-3].interm.type).qualifier, true); - parseContext.precisionQualifierCheck((yyvsp[-2].interm.type).loc, (yyvsp[-2].interm.type).basicType, (yyvsp[-2].interm.type).qualifier, (yyvsp[-2].interm.type).isCoopmat()); - - for (unsigned int i = 0; i < (yyval.interm.typeList)->size(); ++i) { - TType type((yyvsp[-2].interm.type)); - type.setFieldName((*(yyval.interm.typeList))[i].type->getFieldName()); - type.transferArraySizes((*(yyval.interm.typeList))[i].type->getArraySizes()); - type.copyArrayInnerSizes((yyvsp[-2].interm.type).arraySizes); - parseContext.arrayOfArrayVersionCheck((*(yyval.interm.typeList))[i].loc, type.getArraySizes()); - (*(yyval.interm.typeList))[i].type->shallowCopy(type); - } - } -#line 11068 "MachineIndependent/glslang_tab.cpp" - break; - - case 552: /* struct_declarator_list: struct_declarator */ -#line 3667 "MachineIndependent/glslang.y" - { - (yyval.interm.typeList) = new TTypeList; - (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); - } -#line 11077 "MachineIndependent/glslang_tab.cpp" - break; - - case 553: /* struct_declarator_list: struct_declarator_list COMMA struct_declarator */ -#line 3671 "MachineIndependent/glslang.y" - { - (yyval.interm.typeList)->push_back((yyvsp[0].interm.typeLine)); - } -#line 11085 "MachineIndependent/glslang_tab.cpp" - break; - - case 554: /* struct_declarator: IDENTIFIER */ -#line 3677 "MachineIndependent/glslang.y" - { - (yyval.interm.typeLine).type = new TType(EbtVoid); - (yyval.interm.typeLine).loc = (yyvsp[0].lex).loc; - (yyval.interm.typeLine).type->setFieldName(*(yyvsp[0].lex).string); - } -#line 11095 "MachineIndependent/glslang_tab.cpp" - break; - - case 555: /* struct_declarator: IDENTIFIER array_specifier */ -#line 3682 "MachineIndependent/glslang.y" - { - parseContext.arrayOfArrayVersionCheck((yyvsp[-1].lex).loc, (yyvsp[0].interm).arraySizes); - - (yyval.interm.typeLine).type = new TType(EbtVoid); - (yyval.interm.typeLine).loc = (yyvsp[-1].lex).loc; - (yyval.interm.typeLine).type->setFieldName(*(yyvsp[-1].lex).string); - (yyval.interm.typeLine).type->transferArraySizes((yyvsp[0].interm).arraySizes); - } -#line 11108 "MachineIndependent/glslang_tab.cpp" - break; - - case 556: /* initializer: assignment_expression */ -#line 3693 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 11116 "MachineIndependent/glslang_tab.cpp" - break; - - case 557: /* initializer: LEFT_BRACE initializer_list RIGHT_BRACE */ -#line 3696 "MachineIndependent/glslang.y" - { - const char* initFeature = "{ } style initializers"; - parseContext.requireProfile((yyvsp[-2].lex).loc, ~EEsProfile, initFeature); - parseContext.profileRequires((yyvsp[-2].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - (yyval.interm.intermTypedNode) = (yyvsp[-1].interm.intermTypedNode); - } -#line 11127 "MachineIndependent/glslang_tab.cpp" - break; - - case 558: /* initializer: LEFT_BRACE initializer_list COMMA RIGHT_BRACE */ -#line 3702 "MachineIndependent/glslang.y" - { - const char* initFeature = "{ } style initializers"; - parseContext.requireProfile((yyvsp[-3].lex).loc, ~EEsProfile, initFeature); - parseContext.profileRequires((yyvsp[-3].lex).loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); - (yyval.interm.intermTypedNode) = (yyvsp[-2].interm.intermTypedNode); - } -#line 11138 "MachineIndependent/glslang_tab.cpp" - break; - - case 559: /* initializer: LEFT_BRACE RIGHT_BRACE */ -#line 3708 "MachineIndependent/glslang.y" - { - const char* initFeature = "empty { } initializer"; - parseContext.profileRequires((yyvsp[-1].lex).loc, EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); - parseContext.profileRequires((yyvsp[-1].lex).loc, ~EEsProfile, 0, E_GL_EXT_null_initializer, initFeature); - (yyval.interm.intermTypedNode) = parseContext.intermediate.makeAggregate((yyvsp[-1].lex).loc); - } -#line 11149 "MachineIndependent/glslang_tab.cpp" - break; - - case 560: /* initializer_list: initializer */ -#line 3717 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate(0, (yyvsp[0].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)->getLoc()); - } -#line 11157 "MachineIndependent/glslang_tab.cpp" - break; - - case 561: /* initializer_list: initializer_list COMMA initializer */ -#line 3720 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.intermTypedNode)); - } -#line 11165 "MachineIndependent/glslang_tab.cpp" - break; - - case 562: /* declaration_statement: declaration */ -#line 3726 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11171 "MachineIndependent/glslang_tab.cpp" - break; - - case 563: /* statement: compound_statement */ -#line 3730 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11177 "MachineIndependent/glslang_tab.cpp" - break; - - case 564: /* statement: simple_statement */ -#line 3731 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11183 "MachineIndependent/glslang_tab.cpp" - break; - - case 565: /* simple_statement: declaration_statement */ -#line 3737 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11189 "MachineIndependent/glslang_tab.cpp" - break; - - case 566: /* simple_statement: expression_statement */ -#line 3738 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11195 "MachineIndependent/glslang_tab.cpp" - break; - - case 567: /* simple_statement: selection_statement */ -#line 3739 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11201 "MachineIndependent/glslang_tab.cpp" - break; - - case 568: /* simple_statement: switch_statement */ -#line 3740 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11207 "MachineIndependent/glslang_tab.cpp" - break; - - case 569: /* simple_statement: case_label */ -#line 3741 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11213 "MachineIndependent/glslang_tab.cpp" - break; - - case 570: /* simple_statement: iteration_statement */ -#line 3742 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11219 "MachineIndependent/glslang_tab.cpp" - break; - - case 571: /* simple_statement: jump_statement */ -#line 3743 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11225 "MachineIndependent/glslang_tab.cpp" - break; - - case 572: /* simple_statement: demote_statement */ -#line 3744 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11231 "MachineIndependent/glslang_tab.cpp" - break; - - case 573: /* demote_statement: DEMOTE SEMICOLON */ -#line 3748 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "demote"); - parseContext.requireExtensions((yyvsp[-1].lex).loc, 1, &E_GL_EXT_demote_to_helper_invocation, "demote"); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDemote, (yyvsp[-1].lex).loc); - } -#line 11241 "MachineIndependent/glslang_tab.cpp" - break; - - case 574: /* compound_statement: LEFT_BRACE RIGHT_BRACE */ -#line 3756 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = 0; } -#line 11247 "MachineIndependent/glslang_tab.cpp" - break; - - case 575: /* $@5: %empty */ -#line 3757 "MachineIndependent/glslang.y" - { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - } -#line 11256 "MachineIndependent/glslang_tab.cpp" - break; - - case 576: /* $@6: %empty */ -#line 3761 "MachineIndependent/glslang.y" - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - } -#line 11265 "MachineIndependent/glslang_tab.cpp" - break; - - case 577: /* compound_statement: LEFT_BRACE $@5 statement_list $@6 RIGHT_BRACE */ -#line 3765 "MachineIndependent/glslang.y" - { - if ((yyvsp[-2].interm.intermNode) && (yyvsp[-2].interm.intermNode)->getAsAggregate()) - (yyvsp[-2].interm.intermNode)->getAsAggregate()->setOperator(parseContext.intermediate.getDebugInfo() ? EOpScope : EOpSequence); - (yyval.interm.intermNode) = (yyvsp[-2].interm.intermNode); - } -#line 11275 "MachineIndependent/glslang_tab.cpp" - break; - - case 578: /* statement_no_new_scope: compound_statement_no_new_scope */ -#line 3773 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11281 "MachineIndependent/glslang_tab.cpp" - break; - - case 579: /* statement_no_new_scope: simple_statement */ -#line 3774 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); } -#line 11287 "MachineIndependent/glslang_tab.cpp" - break; - - case 580: /* $@7: %empty */ -#line 3778 "MachineIndependent/glslang.y" - { - ++parseContext.controlFlowNestingLevel; - } -#line 11295 "MachineIndependent/glslang_tab.cpp" - break; - - case 581: /* statement_scoped: $@7 compound_statement */ -#line 3781 "MachineIndependent/glslang.y" - { - --parseContext.controlFlowNestingLevel; - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11304 "MachineIndependent/glslang_tab.cpp" - break; - - case 582: /* $@8: %empty */ -#line 3785 "MachineIndependent/glslang.y" - { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 11314 "MachineIndependent/glslang_tab.cpp" - break; - - case 583: /* statement_scoped: $@8 simple_statement */ -#line 3790 "MachineIndependent/glslang.y" - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11325 "MachineIndependent/glslang_tab.cpp" - break; - - case 584: /* compound_statement_no_new_scope: LEFT_BRACE RIGHT_BRACE */ -#line 3799 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = 0; - } -#line 11333 "MachineIndependent/glslang_tab.cpp" - break; - - case 585: /* compound_statement_no_new_scope: LEFT_BRACE statement_list RIGHT_BRACE */ -#line 3802 "MachineIndependent/glslang.y" - { - if ((yyvsp[-1].interm.intermNode) && (yyvsp[-1].interm.intermNode)->getAsAggregate()) - (yyvsp[-1].interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); - (yyval.interm.intermNode) = (yyvsp[-1].interm.intermNode); - } -#line 11343 "MachineIndependent/glslang_tab.cpp" - break; - - case 586: /* statement_list: statement */ -#line 3810 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); - if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || - (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) { - parseContext.wrapupSwitchSubsequence(0, (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case - } - } -#line 11356 "MachineIndependent/glslang_tab.cpp" - break; - - case 587: /* statement_list: statement_list statement */ -#line 3818 "MachineIndependent/glslang.y" - { - if ((yyvsp[0].interm.intermNode) && (yyvsp[0].interm.intermNode)->getAsBranchNode() && ((yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpCase || - (yyvsp[0].interm.intermNode)->getAsBranchNode()->getFlowOp() == EOpDefault)) { - parseContext.wrapupSwitchSubsequence((yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0, (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = 0; // start a fresh subsequence for what's after this case - } else - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); - } -#line 11369 "MachineIndependent/glslang_tab.cpp" - break; - - case 588: /* expression_statement: SEMICOLON */ -#line 3829 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = 0; } -#line 11375 "MachineIndependent/glslang_tab.cpp" - break; - - case 589: /* expression_statement: expression SEMICOLON */ -#line 3830 "MachineIndependent/glslang.y" - { (yyval.interm.intermNode) = static_cast((yyvsp[-1].interm.intermTypedNode)); } -#line 11381 "MachineIndependent/glslang_tab.cpp" - break; - - case 590: /* selection_statement: selection_statement_nonattributed */ -#line 3834 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11389 "MachineIndependent/glslang_tab.cpp" - break; - - case 591: /* selection_statement: attribute selection_statement_nonattributed */ -#line 3837 "MachineIndependent/glslang.y" - { - parseContext.requireExtensions((yyvsp[0].interm.intermNode)->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); - parseContext.handleSelectionAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11399 "MachineIndependent/glslang_tab.cpp" - break; - - case 592: /* selection_statement_nonattributed: IF LEFT_PAREN expression RIGHT_PAREN selection_rest_statement */ -#line 3844 "MachineIndependent/glslang.y" - { - parseContext.boolCheck((yyvsp[-4].lex).loc, (yyvsp[-2].interm.intermTypedNode)); - (yyval.interm.intermNode) = parseContext.intermediate.addSelection((yyvsp[-2].interm.intermTypedNode), (yyvsp[0].interm.nodePair), (yyvsp[-4].lex).loc); - } -#line 11408 "MachineIndependent/glslang_tab.cpp" - break; - - case 593: /* selection_rest_statement: statement_scoped ELSE statement_scoped */ -#line 3851 "MachineIndependent/glslang.y" - { - (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermNode); - (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermNode); - } -#line 11417 "MachineIndependent/glslang_tab.cpp" - break; - - case 594: /* selection_rest_statement: statement_scoped */ -#line 3855 "MachineIndependent/glslang.y" - { - (yyval.interm.nodePair).node1 = (yyvsp[0].interm.intermNode); - (yyval.interm.nodePair).node2 = 0; - } -#line 11426 "MachineIndependent/glslang_tab.cpp" - break; - - case 595: /* condition: expression */ -#line 3863 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - parseContext.boolCheck((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode)); - } -#line 11435 "MachineIndependent/glslang_tab.cpp" - break; - - case 596: /* condition: fully_specified_type IDENTIFIER EQUAL initializer */ -#line 3867 "MachineIndependent/glslang.y" - { - parseContext.boolCheck((yyvsp[-2].lex).loc, (yyvsp[-3].interm.type)); - - TType type((yyvsp[-3].interm.type)); - TIntermNode* initNode = parseContext.declareVariable((yyvsp[-2].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[-3].interm.type), 0, (yyvsp[0].interm.intermTypedNode)); - if (initNode) - (yyval.interm.intermTypedNode) = initNode->getAsTyped(); - else - (yyval.interm.intermTypedNode) = 0; - } -#line 11450 "MachineIndependent/glslang_tab.cpp" - break; - - case 597: /* switch_statement: switch_statement_nonattributed */ -#line 3880 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11458 "MachineIndependent/glslang_tab.cpp" - break; - - case 598: /* switch_statement: attribute switch_statement_nonattributed */ -#line 3883 "MachineIndependent/glslang.y" - { - parseContext.requireExtensions((yyvsp[0].interm.intermNode)->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); - parseContext.handleSwitchAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11468 "MachineIndependent/glslang_tab.cpp" - break; - - case 599: /* $@9: %empty */ -#line 3890 "MachineIndependent/glslang.y" - { - // start new switch sequence on the switch stack - ++parseContext.controlFlowNestingLevel; - ++parseContext.statementNestingLevel; - parseContext.switchSequenceStack.push_back(new TIntermSequence); - parseContext.switchLevel.push_back(parseContext.statementNestingLevel); - parseContext.symbolTable.push(); - } -#line 11481 "MachineIndependent/glslang_tab.cpp" - break; - - case 600: /* switch_statement_nonattributed: SWITCH LEFT_PAREN expression RIGHT_PAREN $@9 LEFT_BRACE switch_statement_list RIGHT_BRACE */ -#line 3898 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.addSwitch((yyvsp[-7].lex).loc, (yyvsp[-5].interm.intermTypedNode), (yyvsp[-1].interm.intermNode) ? (yyvsp[-1].interm.intermNode)->getAsAggregate() : 0); - delete parseContext.switchSequenceStack.back(); - parseContext.switchSequenceStack.pop_back(); - parseContext.switchLevel.pop_back(); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 11495 "MachineIndependent/glslang_tab.cpp" - break; - - case 601: /* switch_statement_list: %empty */ -#line 3910 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = 0; - } -#line 11503 "MachineIndependent/glslang_tab.cpp" - break; - - case 602: /* switch_statement_list: statement_list */ -#line 3913 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11511 "MachineIndependent/glslang_tab.cpp" - break; - - case 603: /* case_label: CASE expression COLON */ -#line 3919 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = 0; - if (parseContext.switchLevel.size() == 0) - parseContext.error((yyvsp[-2].lex).loc, "cannot appear outside switch statement", "case", ""); - else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) - parseContext.error((yyvsp[-2].lex).loc, "cannot be nested inside control flow", "case", ""); - else { - parseContext.constantValueCheck((yyvsp[-1].interm.intermTypedNode), "case"); - parseContext.integerCheck((yyvsp[-1].interm.intermTypedNode), "case"); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpCase, (yyvsp[-1].interm.intermTypedNode), (yyvsp[-2].lex).loc); - } - } -#line 11528 "MachineIndependent/glslang_tab.cpp" - break; - - case 604: /* case_label: DEFAULT COLON */ -#line 3931 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = 0; - if (parseContext.switchLevel.size() == 0) - parseContext.error((yyvsp[-1].lex).loc, "cannot appear outside switch statement", "default", ""); - else if (parseContext.switchLevel.back() != parseContext.statementNestingLevel) - parseContext.error((yyvsp[-1].lex).loc, "cannot be nested inside control flow", "default", ""); - else - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpDefault, (yyvsp[-1].lex).loc); - } -#line 11542 "MachineIndependent/glslang_tab.cpp" - break; - - case 605: /* iteration_statement: iteration_statement_nonattributed */ -#line 3943 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11550 "MachineIndependent/glslang_tab.cpp" - break; - - case 606: /* iteration_statement: attribute iteration_statement_nonattributed */ -#line 3946 "MachineIndependent/glslang.y" - { - parseContext.requireExtensions((yyvsp[0].interm.intermNode)->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute"); - parseContext.handleLoopAttributes(*(yyvsp[-1].interm.attributes), (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11560 "MachineIndependent/glslang_tab.cpp" - break; - - case 607: /* $@10: %empty */ -#line 3953 "MachineIndependent/glslang.y" - { - if (! parseContext.limits.whileLoops) - parseContext.error((yyvsp[-1].lex).loc, "while loops not available", "limitation", ""); - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 11573 "MachineIndependent/glslang_tab.cpp" - break; - - case 608: /* iteration_statement_nonattributed: WHILE LEFT_PAREN $@10 condition RIGHT_PAREN statement_no_new_scope */ -#line 3961 "MachineIndependent/glslang.y" - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, true, (yyvsp[-5].lex).loc); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 11585 "MachineIndependent/glslang_tab.cpp" - break; - - case 609: /* $@11: %empty */ -#line 3968 "MachineIndependent/glslang.y" - { - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 11596 "MachineIndependent/glslang_tab.cpp" - break; - - case 610: /* iteration_statement_nonattributed: DO $@11 statement WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON */ -#line 3974 "MachineIndependent/glslang.y" - { - if (! parseContext.limits.whileLoops) - parseContext.error((yyvsp[-7].lex).loc, "do-while loops not available", "limitation", ""); - - parseContext.boolCheck((yyvsp[0].lex).loc, (yyvsp[-2].interm.intermTypedNode)); - - (yyval.interm.intermNode) = parseContext.intermediate.addLoop((yyvsp[-5].interm.intermNode), (yyvsp[-2].interm.intermTypedNode), 0, false, (yyvsp[-4].lex).loc); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 11613 "MachineIndependent/glslang_tab.cpp" - break; - - case 611: /* $@12: %empty */ -#line 3986 "MachineIndependent/glslang.y" - { - parseContext.symbolTable.push(); - ++parseContext.loopNestingLevel; - ++parseContext.statementNestingLevel; - ++parseContext.controlFlowNestingLevel; - } -#line 11624 "MachineIndependent/glslang_tab.cpp" - break; - - case 612: /* iteration_statement_nonattributed: FOR LEFT_PAREN $@12 for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope */ -#line 3992 "MachineIndependent/glslang.y" - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[-3].interm.intermNode), (yyvsp[-5].lex).loc); - TIntermLoop* forLoop = parseContext.intermediate.addLoop((yyvsp[0].interm.intermNode), reinterpret_cast((yyvsp[-2].interm.nodePair).node1), reinterpret_cast((yyvsp[-2].interm.nodePair).node2), true, (yyvsp[-6].lex).loc); - if (! parseContext.limits.nonInductiveForLoops) - parseContext.inductiveLoopCheck((yyvsp[-6].lex).loc, (yyvsp[-3].interm.intermNode), forLoop); - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyval.interm.intermNode), forLoop, (yyvsp[-6].lex).loc); - (yyval.interm.intermNode)->getAsAggregate()->setOperator(EOpSequence); - --parseContext.loopNestingLevel; - --parseContext.statementNestingLevel; - --parseContext.controlFlowNestingLevel; - } -#line 11641 "MachineIndependent/glslang_tab.cpp" - break; - - case 613: /* for_init_statement: expression_statement */ -#line 4007 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11649 "MachineIndependent/glslang_tab.cpp" - break; - - case 614: /* for_init_statement: declaration_statement */ -#line 4010 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11657 "MachineIndependent/glslang_tab.cpp" - break; - - case 615: /* conditionopt: condition */ -#line 4016 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = (yyvsp[0].interm.intermTypedNode); - } -#line 11665 "MachineIndependent/glslang_tab.cpp" - break; - - case 616: /* conditionopt: %empty */ -#line 4019 "MachineIndependent/glslang.y" - { - (yyval.interm.intermTypedNode) = 0; - } -#line 11673 "MachineIndependent/glslang_tab.cpp" - break; - - case 617: /* for_rest_statement: conditionopt SEMICOLON */ -#line 4025 "MachineIndependent/glslang.y" - { - (yyval.interm.nodePair).node1 = (yyvsp[-1].interm.intermTypedNode); - (yyval.interm.nodePair).node2 = 0; - } -#line 11682 "MachineIndependent/glslang_tab.cpp" - break; - - case 618: /* for_rest_statement: conditionopt SEMICOLON expression */ -#line 4029 "MachineIndependent/glslang.y" - { - (yyval.interm.nodePair).node1 = (yyvsp[-2].interm.intermTypedNode); - (yyval.interm.nodePair).node2 = (yyvsp[0].interm.intermTypedNode); - } -#line 11691 "MachineIndependent/glslang_tab.cpp" - break; - - case 619: /* jump_statement: CONTINUE SEMICOLON */ -#line 4036 "MachineIndependent/glslang.y" - { - if (parseContext.loopNestingLevel <= 0) - parseContext.error((yyvsp[-1].lex).loc, "continue statement only allowed in loops", "", ""); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpContinue, (yyvsp[-1].lex).loc); - } -#line 11701 "MachineIndependent/glslang_tab.cpp" - break; - - case 620: /* jump_statement: BREAK SEMICOLON */ -#line 4041 "MachineIndependent/glslang.y" - { - if (parseContext.loopNestingLevel + parseContext.switchSequenceStack.size() <= 0) - parseContext.error((yyvsp[-1].lex).loc, "break statement only allowed in switch and loops", "", ""); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpBreak, (yyvsp[-1].lex).loc); - } -#line 11711 "MachineIndependent/glslang_tab.cpp" - break; - - case 621: /* jump_statement: RETURN SEMICOLON */ -#line 4046 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpReturn, (yyvsp[-1].lex).loc); - if (parseContext.currentFunctionType->getBasicType() != EbtVoid) - parseContext.error((yyvsp[-1].lex).loc, "non-void function must return a value", "return", ""); - if (parseContext.inMain) - parseContext.postEntryPointReturn = true; - } -#line 11723 "MachineIndependent/glslang_tab.cpp" - break; - - case 622: /* jump_statement: RETURN expression SEMICOLON */ -#line 4053 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.handleReturnValue((yyvsp[-2].lex).loc, (yyvsp[-1].interm.intermTypedNode)); - } -#line 11731 "MachineIndependent/glslang_tab.cpp" - break; - - case 623: /* jump_statement: DISCARD SEMICOLON */ -#line 4056 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "discard"); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpKill, (yyvsp[-1].lex).loc); - } -#line 11740 "MachineIndependent/glslang_tab.cpp" - break; - - case 624: /* jump_statement: TERMINATE_INVOCATION SEMICOLON */ -#line 4060 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[-1].lex).loc, EShLangFragment, "terminateInvocation"); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpTerminateInvocation, (yyvsp[-1].lex).loc); - } -#line 11749 "MachineIndependent/glslang_tab.cpp" - break; - - case 625: /* jump_statement: TERMINATE_RAY SEMICOLON */ -#line 4064 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[-1].lex).loc, EShLangAnyHit, "terminateRayEXT"); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpTerminateRayKHR, (yyvsp[-1].lex).loc); - } -#line 11758 "MachineIndependent/glslang_tab.cpp" - break; - - case 626: /* jump_statement: IGNORE_INTERSECTION SEMICOLON */ -#line 4068 "MachineIndependent/glslang.y" - { - parseContext.requireStage((yyvsp[-1].lex).loc, EShLangAnyHit, "ignoreIntersectionEXT"); - (yyval.interm.intermNode) = parseContext.intermediate.addBranch(EOpIgnoreIntersectionKHR, (yyvsp[-1].lex).loc); - } -#line 11767 "MachineIndependent/glslang_tab.cpp" - break; - - case 627: /* translation_unit: external_declaration */ -#line 4077 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); - } -#line 11776 "MachineIndependent/glslang_tab.cpp" - break; - - case 628: /* translation_unit: translation_unit external_declaration */ -#line 4081 "MachineIndependent/glslang.y" - { - if ((yyvsp[0].interm.intermNode) != nullptr) { - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-1].interm.intermNode), (yyvsp[0].interm.intermNode)); - parseContext.intermediate.setTreeRoot((yyval.interm.intermNode)); - } - } -#line 11787 "MachineIndependent/glslang_tab.cpp" - break; - - case 629: /* external_declaration: function_definition */ -#line 4090 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11795 "MachineIndependent/glslang_tab.cpp" - break; - - case 630: /* external_declaration: declaration */ -#line 4093 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = (yyvsp[0].interm.intermNode); - } -#line 11803 "MachineIndependent/glslang_tab.cpp" - break; - - case 631: /* external_declaration: SEMICOLON */ -#line 4096 "MachineIndependent/glslang.y" - { - parseContext.requireProfile((yyvsp[0].lex).loc, ~EEsProfile, "extraneous semicolon"); - parseContext.profileRequires((yyvsp[0].lex).loc, ~EEsProfile, 460, nullptr, "extraneous semicolon"); - (yyval.interm.intermNode) = nullptr; - } -#line 11813 "MachineIndependent/glslang_tab.cpp" - break; - - case 632: /* $@13: %empty */ -#line 4104 "MachineIndependent/glslang.y" - { - (yyvsp[0].interm).function = parseContext.handleFunctionDeclarator((yyvsp[0].interm).loc, *(yyvsp[0].interm).function, false /* not prototype */); - (yyvsp[0].interm).intermNode = parseContext.handleFunctionDefinition((yyvsp[0].interm).loc, *(yyvsp[0].interm).function); - - // For ES 100 only, according to ES shading language 100 spec: A function - // body has a scope nested inside the function's definition. - if (parseContext.profile == EEsProfile && parseContext.version == 100) - { - parseContext.symbolTable.push(); - ++parseContext.statementNestingLevel; - } - } -#line 11830 "MachineIndependent/glslang_tab.cpp" - break; - - case 633: /* function_definition: function_prototype $@13 compound_statement_no_new_scope */ -#line 4116 "MachineIndependent/glslang.y" - { - // May be best done as post process phase on intermediate code - if (parseContext.currentFunctionType->getBasicType() != EbtVoid && ! parseContext.functionReturnsValue) - parseContext.error((yyvsp[-2].interm).loc, "function does not return a value:", "", (yyvsp[-2].interm).function->getName().c_str()); - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm).intermNode, (yyvsp[0].interm.intermNode)); - (yyval.interm.intermNode)->getAsAggregate()->setLinkType((yyvsp[-2].interm).function->getLinkType()); - parseContext.intermediate.setAggregateOperator((yyval.interm.intermNode), EOpFunction, (yyvsp[-2].interm).function->getType(), (yyvsp[-2].interm).loc); - (yyval.interm.intermNode)->getAsAggregate()->setName((yyvsp[-2].interm).function->getMangledName().c_str()); - - // store the pragma information for debug and optimize and other vendor specific - // information. This information can be queried from the parse tree - (yyval.interm.intermNode)->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); - (yyval.interm.intermNode)->getAsAggregate()->setDebug(parseContext.contextPragma.debug); - (yyval.interm.intermNode)->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable); - - // Set currentFunctionType to empty pointer when goes outside of the function - parseContext.currentFunctionType = nullptr; - - // For ES 100 only, according to ES shading language 100 spec: A function - // body has a scope nested inside the function's definition. - if (parseContext.profile == EEsProfile && parseContext.version == 100) - { - parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); - --parseContext.statementNestingLevel; - } - } -#line 11862 "MachineIndependent/glslang_tab.cpp" - break; - - case 634: /* attribute: LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET */ -#line 4146 "MachineIndependent/glslang.y" - { - (yyval.interm.attributes) = (yyvsp[-2].interm.attributes); - } -#line 11870 "MachineIndependent/glslang_tab.cpp" - break; - - case 635: /* attribute_list: single_attribute */ -#line 4151 "MachineIndependent/glslang.y" - { - (yyval.interm.attributes) = (yyvsp[0].interm.attributes); - } -#line 11878 "MachineIndependent/glslang_tab.cpp" - break; - - case 636: /* attribute_list: attribute_list COMMA single_attribute */ -#line 4154 "MachineIndependent/glslang.y" - { - (yyval.interm.attributes) = parseContext.mergeAttributes((yyvsp[-2].interm.attributes), (yyvsp[0].interm.attributes)); - } -#line 11886 "MachineIndependent/glslang_tab.cpp" - break; - - case 637: /* single_attribute: IDENTIFIER */ -#line 4159 "MachineIndependent/glslang.y" - { - (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[0].lex).string); - } -#line 11894 "MachineIndependent/glslang_tab.cpp" - break; - - case 638: /* single_attribute: IDENTIFIER LEFT_PAREN constant_expression RIGHT_PAREN */ -#line 4162 "MachineIndependent/glslang.y" - { - (yyval.interm.attributes) = parseContext.makeAttributes(*(yyvsp[-3].lex).string, (yyvsp[-1].interm.intermTypedNode)); - } -#line 11902 "MachineIndependent/glslang_tab.cpp" - break; - - case 639: /* spirv_requirements_list: spirv_requirements_parameter */ -#line 4167 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvReq) = (yyvsp[0].interm.spirvReq); - } -#line 11910 "MachineIndependent/glslang_tab.cpp" - break; - - case 640: /* spirv_requirements_list: spirv_requirements_list COMMA spirv_requirements_parameter */ -#line 4170 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvReq) = parseContext.mergeSpirvRequirements((yyvsp[-1].lex).loc, (yyvsp[-2].interm.spirvReq), (yyvsp[0].interm.spirvReq)); - } -#line 11918 "MachineIndependent/glslang_tab.cpp" - break; - - case 641: /* spirv_requirements_parameter: IDENTIFIER EQUAL LEFT_BRACKET spirv_extension_list RIGHT_BRACKET */ -#line 4175 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvReq) = parseContext.makeSpirvRequirement((yyvsp[-3].lex).loc, *(yyvsp[-4].lex).string, (yyvsp[-1].interm.intermNode)->getAsAggregate(), nullptr); - } -#line 11926 "MachineIndependent/glslang_tab.cpp" - break; - - case 642: /* spirv_requirements_parameter: IDENTIFIER EQUAL LEFT_BRACKET spirv_capability_list RIGHT_BRACKET */ -#line 4178 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvReq) = parseContext.makeSpirvRequirement((yyvsp[-3].lex).loc, *(yyvsp[-4].lex).string, nullptr, (yyvsp[-1].interm.intermNode)->getAsAggregate()); - } -#line 11934 "MachineIndependent/glslang_tab.cpp" - break; - - case 643: /* spirv_extension_list: STRING_LITERAL */ -#line 4183 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); - } -#line 11942 "MachineIndependent/glslang_tab.cpp" - break; - - case 644: /* spirv_extension_list: spirv_extension_list COMMA STRING_LITERAL */ -#line 4186 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); - } -#line 11950 "MachineIndependent/glslang_tab.cpp" - break; - - case 645: /* spirv_capability_list: INTCONSTANT */ -#line 4191 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate(parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true)); - } -#line 11958 "MachineIndependent/glslang_tab.cpp" - break; - - case 646: /* spirv_capability_list: spirv_capability_list COMMA INTCONSTANT */ -#line 4194 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true)); - } -#line 11966 "MachineIndependent/glslang_tab.cpp" - break; - - case 647: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT RIGHT_PAREN */ -#line 4199 "MachineIndependent/glslang.y" - { - parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-1].lex).i); - (yyval.interm.intermNode) = 0; - } -#line 11975 "MachineIndependent/glslang_tab.cpp" - break; - - case 648: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN */ -#line 4203 "MachineIndependent/glslang.y" - { - parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); - parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-1].lex).i); - (yyval.interm.intermNode) = 0; - } -#line 11985 "MachineIndependent/glslang_tab.cpp" - break; - - case 649: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN */ -#line 4208 "MachineIndependent/glslang.y" - { - parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); - (yyval.interm.intermNode) = 0; - } -#line 11994 "MachineIndependent/glslang_tab.cpp" - break; - - case 650: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_parameter_list RIGHT_PAREN */ -#line 4212 "MachineIndependent/glslang.y" - { - parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); - parseContext.intermediate.insertSpirvExecutionMode((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); - (yyval.interm.intermNode) = 0; - } -#line 12004 "MachineIndependent/glslang_tab.cpp" - break; - - case 651: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE_ID LEFT_PAREN INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN */ -#line 4217 "MachineIndependent/glslang.y" - { - parseContext.intermediate.insertSpirvExecutionModeId((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); - (yyval.interm.intermNode) = 0; - } -#line 12013 "MachineIndependent/glslang_tab.cpp" - break; - - case 652: /* spirv_execution_mode_qualifier: SPIRV_EXECUTION_MODE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_execution_mode_id_parameter_list RIGHT_PAREN */ -#line 4221 "MachineIndependent/glslang.y" - { - parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); - parseContext.intermediate.insertSpirvExecutionModeId((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); - (yyval.interm.intermNode) = 0; - } -#line 12023 "MachineIndependent/glslang_tab.cpp" - break; - - case 653: /* spirv_execution_mode_parameter_list: spirv_execution_mode_parameter */ -#line 4228 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); - } -#line 12031 "MachineIndependent/glslang_tab.cpp" - break; - - case 654: /* spirv_execution_mode_parameter_list: spirv_execution_mode_parameter_list COMMA spirv_execution_mode_parameter */ -#line 4231 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), (yyvsp[0].interm.intermNode)); - } -#line 12039 "MachineIndependent/glslang_tab.cpp" - break; - - case 655: /* spirv_execution_mode_parameter: FLOATCONSTANT */ -#line 4236 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); - } -#line 12047 "MachineIndependent/glslang_tab.cpp" - break; - - case 656: /* spirv_execution_mode_parameter: INTCONSTANT */ -#line 4239 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 12055 "MachineIndependent/glslang_tab.cpp" - break; - - case 657: /* spirv_execution_mode_parameter: UINTCONSTANT */ -#line 4242 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 12063 "MachineIndependent/glslang_tab.cpp" - break; - - case 658: /* spirv_execution_mode_parameter: BOOLCONSTANT */ -#line 4245 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); - } -#line 12071 "MachineIndependent/glslang_tab.cpp" - break; - - case 659: /* spirv_execution_mode_parameter: STRING_LITERAL */ -#line 4248 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true); - } -#line 12079 "MachineIndependent/glslang_tab.cpp" - break; - - case 660: /* spirv_execution_mode_id_parameter_list: constant_expression */ -#line 4253 "MachineIndependent/glslang.y" - { - if ((yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtFloat && - (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtInt && - (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtUint && - (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtBool && - (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtString) - parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "this type not allowed", (yyvsp[0].interm.intermTypedNode)->getType().getBasicString(), ""); - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermTypedNode)); - } -#line 12093 "MachineIndependent/glslang_tab.cpp" - break; - - case 661: /* spirv_execution_mode_id_parameter_list: spirv_execution_mode_id_parameter_list COMMA constant_expression */ -#line 4262 "MachineIndependent/glslang.y" - { - if ((yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtFloat && - (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtInt && - (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtUint && - (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtBool && - (yyvsp[0].interm.intermTypedNode)->getBasicType() != EbtString) - parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "this type not allowed", (yyvsp[0].interm.intermTypedNode)->getType().getBasicString(), ""); - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), (yyvsp[0].interm.intermTypedNode)); - } -#line 12107 "MachineIndependent/glslang_tab.cpp" - break; - - case 662: /* spirv_storage_class_qualifier: SPIRV_STORAGE_CLASS LEFT_PAREN INTCONSTANT RIGHT_PAREN */ -#line 4273 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-3].lex).loc); - (yyval.interm.type).qualifier.storage = EvqSpirvStorageClass; - (yyval.interm.type).qualifier.spirvStorageClass = (yyvsp[-1].lex).i; - } -#line 12117 "MachineIndependent/glslang_tab.cpp" - break; - - case 663: /* spirv_storage_class_qualifier: SPIRV_STORAGE_CLASS LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN */ -#line 4278 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-5].lex).loc); - parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); - (yyval.interm.type).qualifier.storage = EvqSpirvStorageClass; - (yyval.interm.type).qualifier.spirvStorageClass = (yyvsp[-1].lex).i; - } -#line 12128 "MachineIndependent/glslang_tab.cpp" - break; - - case 664: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN INTCONSTANT RIGHT_PAREN */ -#line 4286 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-3].lex).loc); - (yyval.interm.type).qualifier.setSpirvDecorate((yyvsp[-1].lex).i); - } -#line 12137 "MachineIndependent/glslang_tab.cpp" - break; - - case 665: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT RIGHT_PAREN */ -#line 4290 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-5].lex).loc); - parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); - (yyval.interm.type).qualifier.setSpirvDecorate((yyvsp[-1].lex).i); - } -#line 12147 "MachineIndependent/glslang_tab.cpp" - break; - - case 666: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN */ -#line 4295 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-5].lex).loc); - (yyval.interm.type).qualifier.setSpirvDecorate((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); - } -#line 12156 "MachineIndependent/glslang_tab.cpp" - break; - - case 667: /* spirv_decorate_qualifier: SPIRV_DECORATE LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_parameter_list RIGHT_PAREN */ -#line 4299 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-7].lex).loc); - parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); - (yyval.interm.type).qualifier.setSpirvDecorate((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); - } -#line 12166 "MachineIndependent/glslang_tab.cpp" - break; - - case 668: /* spirv_decorate_qualifier: SPIRV_DECORATE_ID LEFT_PAREN INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN */ -#line 4304 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-5].lex).loc); - (yyval.interm.type).qualifier.setSpirvDecorateId((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); - } -#line 12175 "MachineIndependent/glslang_tab.cpp" - break; - - case 669: /* spirv_decorate_qualifier: SPIRV_DECORATE_ID LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_id_parameter_list RIGHT_PAREN */ -#line 4308 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-7].lex).loc); - parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); - (yyval.interm.type).qualifier.setSpirvDecorateId((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); - } -#line 12185 "MachineIndependent/glslang_tab.cpp" - break; - - case 670: /* spirv_decorate_qualifier: SPIRV_DECORATE_STRING LEFT_PAREN INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN */ -#line 4313 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-5].lex).loc); - (yyval.interm.type).qualifier.setSpirvDecorateString((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); - } -#line 12194 "MachineIndependent/glslang_tab.cpp" - break; - - case 671: /* spirv_decorate_qualifier: SPIRV_DECORATE_STRING LEFT_PAREN spirv_requirements_list COMMA INTCONSTANT COMMA spirv_decorate_string_parameter_list RIGHT_PAREN */ -#line 4317 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-7].lex).loc); - parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); - (yyval.interm.type).qualifier.setSpirvDecorateString((yyvsp[-3].lex).i, (yyvsp[-1].interm.intermNode)->getAsAggregate()); - } -#line 12204 "MachineIndependent/glslang_tab.cpp" - break; - - case 672: /* spirv_decorate_parameter_list: spirv_decorate_parameter */ -#line 4324 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); - } -#line 12212 "MachineIndependent/glslang_tab.cpp" - break; - - case 673: /* spirv_decorate_parameter_list: spirv_decorate_parameter_list COMMA spirv_decorate_parameter */ -#line 4327 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), (yyvsp[0].interm.intermNode)); - } -#line 12220 "MachineIndependent/glslang_tab.cpp" - break; - - case 674: /* spirv_decorate_parameter: FLOATCONSTANT */ -#line 4332 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); - } -#line 12228 "MachineIndependent/glslang_tab.cpp" - break; - - case 675: /* spirv_decorate_parameter: INTCONSTANT */ -#line 4335 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 12236 "MachineIndependent/glslang_tab.cpp" - break; - - case 676: /* spirv_decorate_parameter: UINTCONSTANT */ -#line 4338 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 12244 "MachineIndependent/glslang_tab.cpp" - break; - - case 677: /* spirv_decorate_parameter: BOOLCONSTANT */ -#line 4341 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); - } -#line 12252 "MachineIndependent/glslang_tab.cpp" - break; - - case 678: /* spirv_decorate_id_parameter_list: spirv_decorate_id_parameter */ -#line 4346 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate((yyvsp[0].interm.intermNode)); - } -#line 12260 "MachineIndependent/glslang_tab.cpp" - break; - - case 679: /* spirv_decorate_id_parameter_list: spirv_decorate_id_parameter_list COMMA spirv_decorate_id_parameter */ -#line 4349 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), (yyvsp[0].interm.intermNode)); - } -#line 12268 "MachineIndependent/glslang_tab.cpp" - break; - - case 680: /* spirv_decorate_id_parameter: variable_identifier */ -#line 4354 "MachineIndependent/glslang.y" - { - if ((yyvsp[0].interm.intermTypedNode)->getAsConstantUnion() || (yyvsp[0].interm.intermTypedNode)->getAsSymbolNode()) - (yyval.interm.intermNode) = (yyvsp[0].interm.intermTypedNode); - else - parseContext.error((yyvsp[0].interm.intermTypedNode)->getLoc(), "only allow constants or variables which are not elements of a composite", "", ""); - } -#line 12279 "MachineIndependent/glslang_tab.cpp" - break; - - case 681: /* spirv_decorate_id_parameter: FLOATCONSTANT */ -#line 4360 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).d, EbtFloat, (yyvsp[0].lex).loc, true); - } -#line 12287 "MachineIndependent/glslang_tab.cpp" - break; - - case 682: /* spirv_decorate_id_parameter: INTCONSTANT */ -#line 4363 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).i, (yyvsp[0].lex).loc, true); - } -#line 12295 "MachineIndependent/glslang_tab.cpp" - break; - - case 683: /* spirv_decorate_id_parameter: UINTCONSTANT */ -#line 4366 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).u, (yyvsp[0].lex).loc, true); - } -#line 12303 "MachineIndependent/glslang_tab.cpp" - break; - - case 684: /* spirv_decorate_id_parameter: BOOLCONSTANT */ -#line 4369 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.addConstantUnion((yyvsp[0].lex).b, (yyvsp[0].lex).loc, true); - } -#line 12311 "MachineIndependent/glslang_tab.cpp" - break; - - case 685: /* spirv_decorate_string_parameter_list: STRING_LITERAL */ -#line 4374 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.makeAggregate( - parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); - } -#line 12320 "MachineIndependent/glslang_tab.cpp" - break; - - case 686: /* spirv_decorate_string_parameter_list: spirv_decorate_string_parameter_list COMMA STRING_LITERAL */ -#line 4378 "MachineIndependent/glslang.y" - { - (yyval.interm.intermNode) = parseContext.intermediate.growAggregate((yyvsp[-2].interm.intermNode), parseContext.intermediate.addConstantUnion((yyvsp[0].lex).string, (yyvsp[0].lex).loc, true)); - } -#line 12328 "MachineIndependent/glslang_tab.cpp" - break; - - case 687: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN */ -#line 4383 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-5].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).setSpirvType(*(yyvsp[-3].interm.spirvInst), (yyvsp[-1].interm.spirvTypeParams)); - } -#line 12337 "MachineIndependent/glslang_tab.cpp" - break; - - case 688: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list COMMA spirv_type_parameter_list RIGHT_PAREN */ -#line 4387 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-7].lex).loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.intermediate.insertSpirvRequirement((yyvsp[-5].interm.spirvReq)); - (yyval.interm.type).setSpirvType(*(yyvsp[-3].interm.spirvInst), (yyvsp[-1].interm.spirvTypeParams)); - } -#line 12347 "MachineIndependent/glslang_tab.cpp" - break; - - case 689: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN */ -#line 4392 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-3].lex).loc, parseContext.symbolTable.atGlobalLevel()); - (yyval.interm.type).setSpirvType(*(yyvsp[-1].interm.spirvInst)); - } -#line 12356 "MachineIndependent/glslang_tab.cpp" - break; - - case 690: /* spirv_type_specifier: SPIRV_TYPE LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN */ -#line 4396 "MachineIndependent/glslang.y" - { - (yyval.interm.type).init((yyvsp[-5].lex).loc, parseContext.symbolTable.atGlobalLevel()); - parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); - (yyval.interm.type).setSpirvType(*(yyvsp[-1].interm.spirvInst)); - } -#line 12366 "MachineIndependent/glslang_tab.cpp" - break; - - case 691: /* spirv_type_parameter_list: spirv_type_parameter */ -#line 4403 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvTypeParams) = (yyvsp[0].interm.spirvTypeParams); - } -#line 12374 "MachineIndependent/glslang_tab.cpp" - break; - - case 692: /* spirv_type_parameter_list: spirv_type_parameter_list COMMA spirv_type_parameter */ -#line 4406 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvTypeParams) = parseContext.mergeSpirvTypeParameters((yyvsp[-2].interm.spirvTypeParams), (yyvsp[0].interm.spirvTypeParams)); - } -#line 12382 "MachineIndependent/glslang_tab.cpp" - break; - - case 693: /* spirv_type_parameter: constant_expression */ -#line 4411 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvTypeParams) = parseContext.makeSpirvTypeParameters((yyvsp[0].interm.intermTypedNode)->getLoc(), (yyvsp[0].interm.intermTypedNode)->getAsConstantUnion()); - } -#line 12390 "MachineIndependent/glslang_tab.cpp" - break; - - case 694: /* spirv_type_parameter: type_specifier_nonarray */ -#line 4414 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvTypeParams) = parseContext.makeSpirvTypeParameters((yyvsp[0].interm.type).loc, (yyvsp[0].interm.type)); - } -#line 12398 "MachineIndependent/glslang_tab.cpp" - break; - - case 695: /* spirv_instruction_qualifier: SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN */ -#line 4419 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvInst) = (yyvsp[-1].interm.spirvInst); - } -#line 12406 "MachineIndependent/glslang_tab.cpp" - break; - - case 696: /* spirv_instruction_qualifier: SPIRV_INSTRUCTION LEFT_PAREN spirv_requirements_list COMMA spirv_instruction_qualifier_list RIGHT_PAREN */ -#line 4422 "MachineIndependent/glslang.y" - { - parseContext.intermediate.insertSpirvRequirement((yyvsp[-3].interm.spirvReq)); - (yyval.interm.spirvInst) = (yyvsp[-1].interm.spirvInst); - } -#line 12415 "MachineIndependent/glslang_tab.cpp" - break; - - case 697: /* spirv_instruction_qualifier_list: spirv_instruction_qualifier_id */ -#line 4428 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvInst) = (yyvsp[0].interm.spirvInst); - } -#line 12423 "MachineIndependent/glslang_tab.cpp" - break; - - case 698: /* spirv_instruction_qualifier_list: spirv_instruction_qualifier_list COMMA spirv_instruction_qualifier_id */ -#line 4431 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvInst) = parseContext.mergeSpirvInstruction((yyvsp[-1].lex).loc, (yyvsp[-2].interm.spirvInst), (yyvsp[0].interm.spirvInst)); - } -#line 12431 "MachineIndependent/glslang_tab.cpp" - break; - - case 699: /* spirv_instruction_qualifier_id: IDENTIFIER EQUAL STRING_LITERAL */ -#line 4436 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvInst) = parseContext.makeSpirvInstruction((yyvsp[-1].lex).loc, *(yyvsp[-2].lex).string, *(yyvsp[0].lex).string); - } -#line 12439 "MachineIndependent/glslang_tab.cpp" - break; - - case 700: /* spirv_instruction_qualifier_id: IDENTIFIER EQUAL INTCONSTANT */ -#line 4439 "MachineIndependent/glslang.y" - { - (yyval.interm.spirvInst) = parseContext.makeSpirvInstruction((yyvsp[-1].lex).loc, *(yyvsp[-2].lex).string, (yyvsp[0].lex).i); - } -#line 12447 "MachineIndependent/glslang_tab.cpp" - break; - - -#line 12451 "MachineIndependent/glslang_tab.cpp" - - default: break; - } - /* User semantic actions sometimes alter yychar, and that requires - that yytoken be updated with the new translation. We take the - approach of translating immediately before every use of yytoken. - One alternative is translating here after every semantic action, - but that translation would be missed if the semantic action invokes - YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or - if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an - incorrect destructor might then be invoked immediately. In the - case of YYERROR or YYBACKUP, subsequent parser actions might lead - to an incorrect destructor call or verbose syntax error message - before the lookahead is translated. */ - YY_SYMBOL_PRINT ("-> $$ =", YY_CAST (yysymbol_kind_t, yyr1[yyn]), &yyval, &yyloc); - - YYPOPSTACK (yylen); - yylen = 0; - - *++yyvsp = yyval; - - /* Now 'shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - { - const int yylhs = yyr1[yyn] - YYNTOKENS; - const int yyi = yypgoto[yylhs] + *yyssp; - yystate = (0 <= yyi && yyi <= YYLAST && yycheck[yyi] == *yyssp - ? yytable[yyi] - : yydefgoto[yylhs]); - } - - goto yynewstate; - - -/*--------------------------------------. -| yyerrlab -- here on detecting error. | -`--------------------------------------*/ -yyerrlab: - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = yychar == YYEMPTY ? YYSYMBOL_YYEMPTY : YYTRANSLATE (yychar); - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; - { - yypcontext_t yyctx - = {yyssp, yytoken}; - char const *yymsgp = YY_("syntax error"); - int yysyntax_error_status; - yysyntax_error_status = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx); - if (yysyntax_error_status == 0) - yymsgp = yymsg; - else if (yysyntax_error_status == -1) - { - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = YY_CAST (char *, - YYSTACK_ALLOC (YY_CAST (YYSIZE_T, yymsg_alloc))); - if (yymsg) - { - yysyntax_error_status - = yysyntax_error (&yymsg_alloc, &yymsg, &yyctx); - yymsgp = yymsg; - } - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - yysyntax_error_status = YYENOMEM; - } - } - yyerror (pParseContext, yymsgp); - if (yysyntax_error_status == YYENOMEM) - YYNOMEM; - } - } - - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval, pParseContext); - yychar = YYEMPTY; - } - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - goto yyerrlab1; - - -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: - /* Pacify compilers when the user code never invokes YYERROR and the - label yyerrorlab therefore never appears in user code. */ - if (0) - YYERROR; - ++yynerrs; - - /* Do not reclaim the symbols of the rule whose action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; - - -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ - - /* Pop stack until we find a state that shifts the error token. */ - for (;;) - { - yyn = yypact[yystate]; - if (!yypact_value_is_default (yyn)) - { - yyn += YYSYMBOL_YYerror; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYSYMBOL_YYerror) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } - - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; - - - yydestruct ("Error: popping", - YY_ACCESSING_SYMBOL (yystate), yyvsp, pParseContext); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } - - YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN - *++yyvsp = yylval; - YY_IGNORE_MAYBE_UNINITIALIZED_END - - - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", YY_ACCESSING_SYMBOL (yyn), yyvsp, yylsp); - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturnlab; - - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturnlab; - - -/*-----------------------------------------------------------. -| yyexhaustedlab -- YYNOMEM (memory exhaustion) comes here. | -`-----------------------------------------------------------*/ -yyexhaustedlab: - yyerror (pParseContext, YY_("memory exhausted")); - yyresult = 2; - goto yyreturnlab; - - -/*----------------------------------------------------------. -| yyreturnlab -- parsing is finished, clean up and return. | -`----------------------------------------------------------*/ -yyreturnlab: - if (yychar != YYEMPTY) - { - /* Make sure we have latest lookahead translation. See comments at - user semantic actions for why this is necessary. */ - yytoken = YYTRANSLATE (yychar); - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, pParseContext); - } - /* Do not reclaim the symbols of the rule whose action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - YY_ACCESSING_SYMBOL (+*yyssp), yyvsp, pParseContext); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - return yyresult; -} - -#line 4443 "MachineIndependent/glslang.y" - diff --git a/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h b/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h deleted file mode 100644 index d6484924..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/glslang_tab.cpp.h +++ /dev/null @@ -1,580 +0,0 @@ -/* A Bison parser, made by GNU Bison 3.8.2. */ - -/* Bison interface for Yacc-like parsers in C - - Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2021 Free Software Foundation, - Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* As a special exception, you may create a larger work that contains - part or all of the Bison parser skeleton and distribute that work - under terms of your choice, so long as that work isn't itself a - parser generator using the skeleton or a modified version thereof - as a parser skeleton. Alternatively, if you modify or redistribute - the parser skeleton itself, you may (at your option) remove this - special exception, which will cause the skeleton and the resulting - Bison output files to be licensed under the GNU General Public - License without this special exception. - - This special exception was added by the Free Software Foundation in - version 2.2 of Bison. */ - -/* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, - especially those whose name start with YY_ or yy_. They are - private implementation details that can be changed or removed. */ - -#ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED -# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 1 -#endif -#if YYDEBUG -extern int yydebug; -#endif - -/* Token kinds. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { - YYEMPTY = -2, - YYEOF = 0, /* "end of file" */ - YYerror = 256, /* error */ - YYUNDEF = 257, /* "invalid token" */ - CONST = 258, /* CONST */ - BOOL = 259, /* BOOL */ - INT = 260, /* INT */ - UINT = 261, /* UINT */ - FLOAT = 262, /* FLOAT */ - BVEC2 = 263, /* BVEC2 */ - BVEC3 = 264, /* BVEC3 */ - BVEC4 = 265, /* BVEC4 */ - IVEC2 = 266, /* IVEC2 */ - IVEC3 = 267, /* IVEC3 */ - IVEC4 = 268, /* IVEC4 */ - UVEC2 = 269, /* UVEC2 */ - UVEC3 = 270, /* UVEC3 */ - UVEC4 = 271, /* UVEC4 */ - VEC2 = 272, /* VEC2 */ - VEC3 = 273, /* VEC3 */ - VEC4 = 274, /* VEC4 */ - MAT2 = 275, /* MAT2 */ - MAT3 = 276, /* MAT3 */ - MAT4 = 277, /* MAT4 */ - MAT2X2 = 278, /* MAT2X2 */ - MAT2X3 = 279, /* MAT2X3 */ - MAT2X4 = 280, /* MAT2X4 */ - MAT3X2 = 281, /* MAT3X2 */ - MAT3X3 = 282, /* MAT3X3 */ - MAT3X4 = 283, /* MAT3X4 */ - MAT4X2 = 284, /* MAT4X2 */ - MAT4X3 = 285, /* MAT4X3 */ - MAT4X4 = 286, /* MAT4X4 */ - SAMPLER2D = 287, /* SAMPLER2D */ - SAMPLER3D = 288, /* SAMPLER3D */ - SAMPLERCUBE = 289, /* SAMPLERCUBE */ - SAMPLER2DSHADOW = 290, /* SAMPLER2DSHADOW */ - SAMPLERCUBESHADOW = 291, /* SAMPLERCUBESHADOW */ - SAMPLER2DARRAY = 292, /* SAMPLER2DARRAY */ - SAMPLER2DARRAYSHADOW = 293, /* SAMPLER2DARRAYSHADOW */ - ISAMPLER2D = 294, /* ISAMPLER2D */ - ISAMPLER3D = 295, /* ISAMPLER3D */ - ISAMPLERCUBE = 296, /* ISAMPLERCUBE */ - ISAMPLER2DARRAY = 297, /* ISAMPLER2DARRAY */ - USAMPLER2D = 298, /* USAMPLER2D */ - USAMPLER3D = 299, /* USAMPLER3D */ - USAMPLERCUBE = 300, /* USAMPLERCUBE */ - USAMPLER2DARRAY = 301, /* USAMPLER2DARRAY */ - SAMPLER = 302, /* SAMPLER */ - SAMPLERSHADOW = 303, /* SAMPLERSHADOW */ - TEXTURE2D = 304, /* TEXTURE2D */ - TEXTURE3D = 305, /* TEXTURE3D */ - TEXTURECUBE = 306, /* TEXTURECUBE */ - TEXTURE2DARRAY = 307, /* TEXTURE2DARRAY */ - ITEXTURE2D = 308, /* ITEXTURE2D */ - ITEXTURE3D = 309, /* ITEXTURE3D */ - ITEXTURECUBE = 310, /* ITEXTURECUBE */ - ITEXTURE2DARRAY = 311, /* ITEXTURE2DARRAY */ - UTEXTURE2D = 312, /* UTEXTURE2D */ - UTEXTURE3D = 313, /* UTEXTURE3D */ - UTEXTURECUBE = 314, /* UTEXTURECUBE */ - UTEXTURE2DARRAY = 315, /* UTEXTURE2DARRAY */ - ATTRIBUTE = 316, /* ATTRIBUTE */ - VARYING = 317, /* VARYING */ - FLOAT16_T = 318, /* FLOAT16_T */ - FLOAT32_T = 319, /* FLOAT32_T */ - DOUBLE = 320, /* DOUBLE */ - FLOAT64_T = 321, /* FLOAT64_T */ - INT64_T = 322, /* INT64_T */ - UINT64_T = 323, /* UINT64_T */ - INT32_T = 324, /* INT32_T */ - UINT32_T = 325, /* UINT32_T */ - INT16_T = 326, /* INT16_T */ - UINT16_T = 327, /* UINT16_T */ - INT8_T = 328, /* INT8_T */ - UINT8_T = 329, /* UINT8_T */ - I64VEC2 = 330, /* I64VEC2 */ - I64VEC3 = 331, /* I64VEC3 */ - I64VEC4 = 332, /* I64VEC4 */ - U64VEC2 = 333, /* U64VEC2 */ - U64VEC3 = 334, /* U64VEC3 */ - U64VEC4 = 335, /* U64VEC4 */ - I32VEC2 = 336, /* I32VEC2 */ - I32VEC3 = 337, /* I32VEC3 */ - I32VEC4 = 338, /* I32VEC4 */ - U32VEC2 = 339, /* U32VEC2 */ - U32VEC3 = 340, /* U32VEC3 */ - U32VEC4 = 341, /* U32VEC4 */ - I16VEC2 = 342, /* I16VEC2 */ - I16VEC3 = 343, /* I16VEC3 */ - I16VEC4 = 344, /* I16VEC4 */ - U16VEC2 = 345, /* U16VEC2 */ - U16VEC3 = 346, /* U16VEC3 */ - U16VEC4 = 347, /* U16VEC4 */ - I8VEC2 = 348, /* I8VEC2 */ - I8VEC3 = 349, /* I8VEC3 */ - I8VEC4 = 350, /* I8VEC4 */ - U8VEC2 = 351, /* U8VEC2 */ - U8VEC3 = 352, /* U8VEC3 */ - U8VEC4 = 353, /* U8VEC4 */ - DVEC2 = 354, /* DVEC2 */ - DVEC3 = 355, /* DVEC3 */ - DVEC4 = 356, /* DVEC4 */ - DMAT2 = 357, /* DMAT2 */ - DMAT3 = 358, /* DMAT3 */ - DMAT4 = 359, /* DMAT4 */ - F16VEC2 = 360, /* F16VEC2 */ - F16VEC3 = 361, /* F16VEC3 */ - F16VEC4 = 362, /* F16VEC4 */ - F16MAT2 = 363, /* F16MAT2 */ - F16MAT3 = 364, /* F16MAT3 */ - F16MAT4 = 365, /* F16MAT4 */ - F32VEC2 = 366, /* F32VEC2 */ - F32VEC3 = 367, /* F32VEC3 */ - F32VEC4 = 368, /* F32VEC4 */ - F32MAT2 = 369, /* F32MAT2 */ - F32MAT3 = 370, /* F32MAT3 */ - F32MAT4 = 371, /* F32MAT4 */ - F64VEC2 = 372, /* F64VEC2 */ - F64VEC3 = 373, /* F64VEC3 */ - F64VEC4 = 374, /* F64VEC4 */ - F64MAT2 = 375, /* F64MAT2 */ - F64MAT3 = 376, /* F64MAT3 */ - F64MAT4 = 377, /* F64MAT4 */ - DMAT2X2 = 378, /* DMAT2X2 */ - DMAT2X3 = 379, /* DMAT2X3 */ - DMAT2X4 = 380, /* DMAT2X4 */ - DMAT3X2 = 381, /* DMAT3X2 */ - DMAT3X3 = 382, /* DMAT3X3 */ - DMAT3X4 = 383, /* DMAT3X4 */ - DMAT4X2 = 384, /* DMAT4X2 */ - DMAT4X3 = 385, /* DMAT4X3 */ - DMAT4X4 = 386, /* DMAT4X4 */ - F16MAT2X2 = 387, /* F16MAT2X2 */ - F16MAT2X3 = 388, /* F16MAT2X3 */ - F16MAT2X4 = 389, /* F16MAT2X4 */ - F16MAT3X2 = 390, /* F16MAT3X2 */ - F16MAT3X3 = 391, /* F16MAT3X3 */ - F16MAT3X4 = 392, /* F16MAT3X4 */ - F16MAT4X2 = 393, /* F16MAT4X2 */ - F16MAT4X3 = 394, /* F16MAT4X3 */ - F16MAT4X4 = 395, /* F16MAT4X4 */ - F32MAT2X2 = 396, /* F32MAT2X2 */ - F32MAT2X3 = 397, /* F32MAT2X3 */ - F32MAT2X4 = 398, /* F32MAT2X4 */ - F32MAT3X2 = 399, /* F32MAT3X2 */ - F32MAT3X3 = 400, /* F32MAT3X3 */ - F32MAT3X4 = 401, /* F32MAT3X4 */ - F32MAT4X2 = 402, /* F32MAT4X2 */ - F32MAT4X3 = 403, /* F32MAT4X3 */ - F32MAT4X4 = 404, /* F32MAT4X4 */ - F64MAT2X2 = 405, /* F64MAT2X2 */ - F64MAT2X3 = 406, /* F64MAT2X3 */ - F64MAT2X4 = 407, /* F64MAT2X4 */ - F64MAT3X2 = 408, /* F64MAT3X2 */ - F64MAT3X3 = 409, /* F64MAT3X3 */ - F64MAT3X4 = 410, /* F64MAT3X4 */ - F64MAT4X2 = 411, /* F64MAT4X2 */ - F64MAT4X3 = 412, /* F64MAT4X3 */ - F64MAT4X4 = 413, /* F64MAT4X4 */ - ATOMIC_UINT = 414, /* ATOMIC_UINT */ - ACCSTRUCTNV = 415, /* ACCSTRUCTNV */ - ACCSTRUCTEXT = 416, /* ACCSTRUCTEXT */ - RAYQUERYEXT = 417, /* RAYQUERYEXT */ - FCOOPMATNV = 418, /* FCOOPMATNV */ - ICOOPMATNV = 419, /* ICOOPMATNV */ - UCOOPMATNV = 420, /* UCOOPMATNV */ - COOPMAT = 421, /* COOPMAT */ - HITOBJECTNV = 422, /* HITOBJECTNV */ - HITOBJECTATTRNV = 423, /* HITOBJECTATTRNV */ - SAMPLERCUBEARRAY = 424, /* SAMPLERCUBEARRAY */ - SAMPLERCUBEARRAYSHADOW = 425, /* SAMPLERCUBEARRAYSHADOW */ - ISAMPLERCUBEARRAY = 426, /* ISAMPLERCUBEARRAY */ - USAMPLERCUBEARRAY = 427, /* USAMPLERCUBEARRAY */ - SAMPLER1D = 428, /* SAMPLER1D */ - SAMPLER1DARRAY = 429, /* SAMPLER1DARRAY */ - SAMPLER1DARRAYSHADOW = 430, /* SAMPLER1DARRAYSHADOW */ - ISAMPLER1D = 431, /* ISAMPLER1D */ - SAMPLER1DSHADOW = 432, /* SAMPLER1DSHADOW */ - SAMPLER2DRECT = 433, /* SAMPLER2DRECT */ - SAMPLER2DRECTSHADOW = 434, /* SAMPLER2DRECTSHADOW */ - ISAMPLER2DRECT = 435, /* ISAMPLER2DRECT */ - USAMPLER2DRECT = 436, /* USAMPLER2DRECT */ - SAMPLERBUFFER = 437, /* SAMPLERBUFFER */ - ISAMPLERBUFFER = 438, /* ISAMPLERBUFFER */ - USAMPLERBUFFER = 439, /* USAMPLERBUFFER */ - SAMPLER2DMS = 440, /* SAMPLER2DMS */ - ISAMPLER2DMS = 441, /* ISAMPLER2DMS */ - USAMPLER2DMS = 442, /* USAMPLER2DMS */ - SAMPLER2DMSARRAY = 443, /* SAMPLER2DMSARRAY */ - ISAMPLER2DMSARRAY = 444, /* ISAMPLER2DMSARRAY */ - USAMPLER2DMSARRAY = 445, /* USAMPLER2DMSARRAY */ - SAMPLEREXTERNALOES = 446, /* SAMPLEREXTERNALOES */ - SAMPLEREXTERNAL2DY2YEXT = 447, /* SAMPLEREXTERNAL2DY2YEXT */ - ISAMPLER1DARRAY = 448, /* ISAMPLER1DARRAY */ - USAMPLER1D = 449, /* USAMPLER1D */ - USAMPLER1DARRAY = 450, /* USAMPLER1DARRAY */ - F16SAMPLER1D = 451, /* F16SAMPLER1D */ - F16SAMPLER2D = 452, /* F16SAMPLER2D */ - F16SAMPLER3D = 453, /* F16SAMPLER3D */ - F16SAMPLER2DRECT = 454, /* F16SAMPLER2DRECT */ - F16SAMPLERCUBE = 455, /* F16SAMPLERCUBE */ - F16SAMPLER1DARRAY = 456, /* F16SAMPLER1DARRAY */ - F16SAMPLER2DARRAY = 457, /* F16SAMPLER2DARRAY */ - F16SAMPLERCUBEARRAY = 458, /* F16SAMPLERCUBEARRAY */ - F16SAMPLERBUFFER = 459, /* F16SAMPLERBUFFER */ - F16SAMPLER2DMS = 460, /* F16SAMPLER2DMS */ - F16SAMPLER2DMSARRAY = 461, /* F16SAMPLER2DMSARRAY */ - F16SAMPLER1DSHADOW = 462, /* F16SAMPLER1DSHADOW */ - F16SAMPLER2DSHADOW = 463, /* F16SAMPLER2DSHADOW */ - F16SAMPLER1DARRAYSHADOW = 464, /* F16SAMPLER1DARRAYSHADOW */ - F16SAMPLER2DARRAYSHADOW = 465, /* F16SAMPLER2DARRAYSHADOW */ - F16SAMPLER2DRECTSHADOW = 466, /* F16SAMPLER2DRECTSHADOW */ - F16SAMPLERCUBESHADOW = 467, /* F16SAMPLERCUBESHADOW */ - F16SAMPLERCUBEARRAYSHADOW = 468, /* F16SAMPLERCUBEARRAYSHADOW */ - IMAGE1D = 469, /* IMAGE1D */ - IIMAGE1D = 470, /* IIMAGE1D */ - UIMAGE1D = 471, /* UIMAGE1D */ - IMAGE2D = 472, /* IMAGE2D */ - IIMAGE2D = 473, /* IIMAGE2D */ - UIMAGE2D = 474, /* UIMAGE2D */ - IMAGE3D = 475, /* IMAGE3D */ - IIMAGE3D = 476, /* IIMAGE3D */ - UIMAGE3D = 477, /* UIMAGE3D */ - IMAGE2DRECT = 478, /* IMAGE2DRECT */ - IIMAGE2DRECT = 479, /* IIMAGE2DRECT */ - UIMAGE2DRECT = 480, /* UIMAGE2DRECT */ - IMAGECUBE = 481, /* IMAGECUBE */ - IIMAGECUBE = 482, /* IIMAGECUBE */ - UIMAGECUBE = 483, /* UIMAGECUBE */ - IMAGEBUFFER = 484, /* IMAGEBUFFER */ - IIMAGEBUFFER = 485, /* IIMAGEBUFFER */ - UIMAGEBUFFER = 486, /* UIMAGEBUFFER */ - IMAGE1DARRAY = 487, /* IMAGE1DARRAY */ - IIMAGE1DARRAY = 488, /* IIMAGE1DARRAY */ - UIMAGE1DARRAY = 489, /* UIMAGE1DARRAY */ - IMAGE2DARRAY = 490, /* IMAGE2DARRAY */ - IIMAGE2DARRAY = 491, /* IIMAGE2DARRAY */ - UIMAGE2DARRAY = 492, /* UIMAGE2DARRAY */ - IMAGECUBEARRAY = 493, /* IMAGECUBEARRAY */ - IIMAGECUBEARRAY = 494, /* IIMAGECUBEARRAY */ - UIMAGECUBEARRAY = 495, /* UIMAGECUBEARRAY */ - IMAGE2DMS = 496, /* IMAGE2DMS */ - IIMAGE2DMS = 497, /* IIMAGE2DMS */ - UIMAGE2DMS = 498, /* UIMAGE2DMS */ - IMAGE2DMSARRAY = 499, /* IMAGE2DMSARRAY */ - IIMAGE2DMSARRAY = 500, /* IIMAGE2DMSARRAY */ - UIMAGE2DMSARRAY = 501, /* UIMAGE2DMSARRAY */ - F16IMAGE1D = 502, /* F16IMAGE1D */ - F16IMAGE2D = 503, /* F16IMAGE2D */ - F16IMAGE3D = 504, /* F16IMAGE3D */ - F16IMAGE2DRECT = 505, /* F16IMAGE2DRECT */ - F16IMAGECUBE = 506, /* F16IMAGECUBE */ - F16IMAGE1DARRAY = 507, /* F16IMAGE1DARRAY */ - F16IMAGE2DARRAY = 508, /* F16IMAGE2DARRAY */ - F16IMAGECUBEARRAY = 509, /* F16IMAGECUBEARRAY */ - F16IMAGEBUFFER = 510, /* F16IMAGEBUFFER */ - F16IMAGE2DMS = 511, /* F16IMAGE2DMS */ - F16IMAGE2DMSARRAY = 512, /* F16IMAGE2DMSARRAY */ - I64IMAGE1D = 513, /* I64IMAGE1D */ - U64IMAGE1D = 514, /* U64IMAGE1D */ - I64IMAGE2D = 515, /* I64IMAGE2D */ - U64IMAGE2D = 516, /* U64IMAGE2D */ - I64IMAGE3D = 517, /* I64IMAGE3D */ - U64IMAGE3D = 518, /* U64IMAGE3D */ - I64IMAGE2DRECT = 519, /* I64IMAGE2DRECT */ - U64IMAGE2DRECT = 520, /* U64IMAGE2DRECT */ - I64IMAGECUBE = 521, /* I64IMAGECUBE */ - U64IMAGECUBE = 522, /* U64IMAGECUBE */ - I64IMAGEBUFFER = 523, /* I64IMAGEBUFFER */ - U64IMAGEBUFFER = 524, /* U64IMAGEBUFFER */ - I64IMAGE1DARRAY = 525, /* I64IMAGE1DARRAY */ - U64IMAGE1DARRAY = 526, /* U64IMAGE1DARRAY */ - I64IMAGE2DARRAY = 527, /* I64IMAGE2DARRAY */ - U64IMAGE2DARRAY = 528, /* U64IMAGE2DARRAY */ - I64IMAGECUBEARRAY = 529, /* I64IMAGECUBEARRAY */ - U64IMAGECUBEARRAY = 530, /* U64IMAGECUBEARRAY */ - I64IMAGE2DMS = 531, /* I64IMAGE2DMS */ - U64IMAGE2DMS = 532, /* U64IMAGE2DMS */ - I64IMAGE2DMSARRAY = 533, /* I64IMAGE2DMSARRAY */ - U64IMAGE2DMSARRAY = 534, /* U64IMAGE2DMSARRAY */ - TEXTURECUBEARRAY = 535, /* TEXTURECUBEARRAY */ - ITEXTURECUBEARRAY = 536, /* ITEXTURECUBEARRAY */ - UTEXTURECUBEARRAY = 537, /* UTEXTURECUBEARRAY */ - TEXTURE1D = 538, /* TEXTURE1D */ - ITEXTURE1D = 539, /* ITEXTURE1D */ - UTEXTURE1D = 540, /* UTEXTURE1D */ - TEXTURE1DARRAY = 541, /* TEXTURE1DARRAY */ - ITEXTURE1DARRAY = 542, /* ITEXTURE1DARRAY */ - UTEXTURE1DARRAY = 543, /* UTEXTURE1DARRAY */ - TEXTURE2DRECT = 544, /* TEXTURE2DRECT */ - ITEXTURE2DRECT = 545, /* ITEXTURE2DRECT */ - UTEXTURE2DRECT = 546, /* UTEXTURE2DRECT */ - TEXTUREBUFFER = 547, /* TEXTUREBUFFER */ - ITEXTUREBUFFER = 548, /* ITEXTUREBUFFER */ - UTEXTUREBUFFER = 549, /* UTEXTUREBUFFER */ - TEXTURE2DMS = 550, /* TEXTURE2DMS */ - ITEXTURE2DMS = 551, /* ITEXTURE2DMS */ - UTEXTURE2DMS = 552, /* UTEXTURE2DMS */ - TEXTURE2DMSARRAY = 553, /* TEXTURE2DMSARRAY */ - ITEXTURE2DMSARRAY = 554, /* ITEXTURE2DMSARRAY */ - UTEXTURE2DMSARRAY = 555, /* UTEXTURE2DMSARRAY */ - F16TEXTURE1D = 556, /* F16TEXTURE1D */ - F16TEXTURE2D = 557, /* F16TEXTURE2D */ - F16TEXTURE3D = 558, /* F16TEXTURE3D */ - F16TEXTURE2DRECT = 559, /* F16TEXTURE2DRECT */ - F16TEXTURECUBE = 560, /* F16TEXTURECUBE */ - F16TEXTURE1DARRAY = 561, /* F16TEXTURE1DARRAY */ - F16TEXTURE2DARRAY = 562, /* F16TEXTURE2DARRAY */ - F16TEXTURECUBEARRAY = 563, /* F16TEXTURECUBEARRAY */ - F16TEXTUREBUFFER = 564, /* F16TEXTUREBUFFER */ - F16TEXTURE2DMS = 565, /* F16TEXTURE2DMS */ - F16TEXTURE2DMSARRAY = 566, /* F16TEXTURE2DMSARRAY */ - SUBPASSINPUT = 567, /* SUBPASSINPUT */ - SUBPASSINPUTMS = 568, /* SUBPASSINPUTMS */ - ISUBPASSINPUT = 569, /* ISUBPASSINPUT */ - ISUBPASSINPUTMS = 570, /* ISUBPASSINPUTMS */ - USUBPASSINPUT = 571, /* USUBPASSINPUT */ - USUBPASSINPUTMS = 572, /* USUBPASSINPUTMS */ - F16SUBPASSINPUT = 573, /* F16SUBPASSINPUT */ - F16SUBPASSINPUTMS = 574, /* F16SUBPASSINPUTMS */ - SPIRV_INSTRUCTION = 575, /* SPIRV_INSTRUCTION */ - SPIRV_EXECUTION_MODE = 576, /* SPIRV_EXECUTION_MODE */ - SPIRV_EXECUTION_MODE_ID = 577, /* SPIRV_EXECUTION_MODE_ID */ - SPIRV_DECORATE = 578, /* SPIRV_DECORATE */ - SPIRV_DECORATE_ID = 579, /* SPIRV_DECORATE_ID */ - SPIRV_DECORATE_STRING = 580, /* SPIRV_DECORATE_STRING */ - SPIRV_TYPE = 581, /* SPIRV_TYPE */ - SPIRV_STORAGE_CLASS = 582, /* SPIRV_STORAGE_CLASS */ - SPIRV_BY_REFERENCE = 583, /* SPIRV_BY_REFERENCE */ - SPIRV_LITERAL = 584, /* SPIRV_LITERAL */ - ATTACHMENTEXT = 585, /* ATTACHMENTEXT */ - IATTACHMENTEXT = 586, /* IATTACHMENTEXT */ - UATTACHMENTEXT = 587, /* UATTACHMENTEXT */ - LEFT_OP = 588, /* LEFT_OP */ - RIGHT_OP = 589, /* RIGHT_OP */ - INC_OP = 590, /* INC_OP */ - DEC_OP = 591, /* DEC_OP */ - LE_OP = 592, /* LE_OP */ - GE_OP = 593, /* GE_OP */ - EQ_OP = 594, /* EQ_OP */ - NE_OP = 595, /* NE_OP */ - AND_OP = 596, /* AND_OP */ - OR_OP = 597, /* OR_OP */ - XOR_OP = 598, /* XOR_OP */ - MUL_ASSIGN = 599, /* MUL_ASSIGN */ - DIV_ASSIGN = 600, /* DIV_ASSIGN */ - ADD_ASSIGN = 601, /* ADD_ASSIGN */ - MOD_ASSIGN = 602, /* MOD_ASSIGN */ - LEFT_ASSIGN = 603, /* LEFT_ASSIGN */ - RIGHT_ASSIGN = 604, /* RIGHT_ASSIGN */ - AND_ASSIGN = 605, /* AND_ASSIGN */ - XOR_ASSIGN = 606, /* XOR_ASSIGN */ - OR_ASSIGN = 607, /* OR_ASSIGN */ - SUB_ASSIGN = 608, /* SUB_ASSIGN */ - STRING_LITERAL = 609, /* STRING_LITERAL */ - LEFT_PAREN = 610, /* LEFT_PAREN */ - RIGHT_PAREN = 611, /* RIGHT_PAREN */ - LEFT_BRACKET = 612, /* LEFT_BRACKET */ - RIGHT_BRACKET = 613, /* RIGHT_BRACKET */ - LEFT_BRACE = 614, /* LEFT_BRACE */ - RIGHT_BRACE = 615, /* RIGHT_BRACE */ - DOT = 616, /* DOT */ - COMMA = 617, /* COMMA */ - COLON = 618, /* COLON */ - EQUAL = 619, /* EQUAL */ - SEMICOLON = 620, /* SEMICOLON */ - BANG = 621, /* BANG */ - DASH = 622, /* DASH */ - TILDE = 623, /* TILDE */ - PLUS = 624, /* PLUS */ - STAR = 625, /* STAR */ - SLASH = 626, /* SLASH */ - PERCENT = 627, /* PERCENT */ - LEFT_ANGLE = 628, /* LEFT_ANGLE */ - RIGHT_ANGLE = 629, /* RIGHT_ANGLE */ - VERTICAL_BAR = 630, /* VERTICAL_BAR */ - CARET = 631, /* CARET */ - AMPERSAND = 632, /* AMPERSAND */ - QUESTION = 633, /* QUESTION */ - INVARIANT = 634, /* INVARIANT */ - HIGH_PRECISION = 635, /* HIGH_PRECISION */ - MEDIUM_PRECISION = 636, /* MEDIUM_PRECISION */ - LOW_PRECISION = 637, /* LOW_PRECISION */ - PRECISION = 638, /* PRECISION */ - PACKED = 639, /* PACKED */ - RESOURCE = 640, /* RESOURCE */ - SUPERP = 641, /* SUPERP */ - FLOATCONSTANT = 642, /* FLOATCONSTANT */ - INTCONSTANT = 643, /* INTCONSTANT */ - UINTCONSTANT = 644, /* UINTCONSTANT */ - BOOLCONSTANT = 645, /* BOOLCONSTANT */ - IDENTIFIER = 646, /* IDENTIFIER */ - TYPE_NAME = 647, /* TYPE_NAME */ - CENTROID = 648, /* CENTROID */ - IN = 649, /* IN */ - OUT = 650, /* OUT */ - INOUT = 651, /* INOUT */ - STRUCT = 652, /* STRUCT */ - VOID = 653, /* VOID */ - WHILE = 654, /* WHILE */ - BREAK = 655, /* BREAK */ - CONTINUE = 656, /* CONTINUE */ - DO = 657, /* DO */ - ELSE = 658, /* ELSE */ - FOR = 659, /* FOR */ - IF = 660, /* IF */ - DISCARD = 661, /* DISCARD */ - RETURN = 662, /* RETURN */ - SWITCH = 663, /* SWITCH */ - CASE = 664, /* CASE */ - DEFAULT = 665, /* DEFAULT */ - TERMINATE_INVOCATION = 666, /* TERMINATE_INVOCATION */ - TERMINATE_RAY = 667, /* TERMINATE_RAY */ - IGNORE_INTERSECTION = 668, /* IGNORE_INTERSECTION */ - UNIFORM = 669, /* UNIFORM */ - SHARED = 670, /* SHARED */ - BUFFER = 671, /* BUFFER */ - TILEIMAGEEXT = 672, /* TILEIMAGEEXT */ - FLAT = 673, /* FLAT */ - SMOOTH = 674, /* SMOOTH */ - LAYOUT = 675, /* LAYOUT */ - DOUBLECONSTANT = 676, /* DOUBLECONSTANT */ - INT16CONSTANT = 677, /* INT16CONSTANT */ - UINT16CONSTANT = 678, /* UINT16CONSTANT */ - FLOAT16CONSTANT = 679, /* FLOAT16CONSTANT */ - INT32CONSTANT = 680, /* INT32CONSTANT */ - UINT32CONSTANT = 681, /* UINT32CONSTANT */ - INT64CONSTANT = 682, /* INT64CONSTANT */ - UINT64CONSTANT = 683, /* UINT64CONSTANT */ - SUBROUTINE = 684, /* SUBROUTINE */ - DEMOTE = 685, /* DEMOTE */ - PAYLOADNV = 686, /* PAYLOADNV */ - PAYLOADINNV = 687, /* PAYLOADINNV */ - HITATTRNV = 688, /* HITATTRNV */ - CALLDATANV = 689, /* CALLDATANV */ - CALLDATAINNV = 690, /* CALLDATAINNV */ - PAYLOADEXT = 691, /* PAYLOADEXT */ - PAYLOADINEXT = 692, /* PAYLOADINEXT */ - HITATTREXT = 693, /* HITATTREXT */ - CALLDATAEXT = 694, /* CALLDATAEXT */ - CALLDATAINEXT = 695, /* CALLDATAINEXT */ - PATCH = 696, /* PATCH */ - SAMPLE = 697, /* SAMPLE */ - NONUNIFORM = 698, /* NONUNIFORM */ - COHERENT = 699, /* COHERENT */ - VOLATILE = 700, /* VOLATILE */ - RESTRICT = 701, /* RESTRICT */ - READONLY = 702, /* READONLY */ - WRITEONLY = 703, /* WRITEONLY */ - DEVICECOHERENT = 704, /* DEVICECOHERENT */ - QUEUEFAMILYCOHERENT = 705, /* QUEUEFAMILYCOHERENT */ - WORKGROUPCOHERENT = 706, /* WORKGROUPCOHERENT */ - SUBGROUPCOHERENT = 707, /* SUBGROUPCOHERENT */ - NONPRIVATE = 708, /* NONPRIVATE */ - SHADERCALLCOHERENT = 709, /* SHADERCALLCOHERENT */ - NOPERSPECTIVE = 710, /* NOPERSPECTIVE */ - EXPLICITINTERPAMD = 711, /* EXPLICITINTERPAMD */ - PERVERTEXEXT = 712, /* PERVERTEXEXT */ - PERVERTEXNV = 713, /* PERVERTEXNV */ - PERPRIMITIVENV = 714, /* PERPRIMITIVENV */ - PERVIEWNV = 715, /* PERVIEWNV */ - PERTASKNV = 716, /* PERTASKNV */ - PERPRIMITIVEEXT = 717, /* PERPRIMITIVEEXT */ - TASKPAYLOADWORKGROUPEXT = 718, /* TASKPAYLOADWORKGROUPEXT */ - PRECISE = 719 /* PRECISE */ - }; - typedef enum yytokentype yytoken_kind_t; -#endif - -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -union YYSTYPE -{ -#line 72 "MachineIndependent/glslang.y" - - struct { - glslang::TSourceLoc loc; - union { - glslang::TString *string; - int i; - unsigned int u; - long long i64; - unsigned long long u64; - bool b; - double d; - }; - glslang::TSymbol* symbol; - } lex; - struct { - glslang::TSourceLoc loc; - glslang::TOperator op; - union { - TIntermNode* intermNode; - glslang::TIntermNodePair nodePair; - glslang::TIntermTyped* intermTypedNode; - glslang::TAttributes* attributes; - glslang::TSpirvRequirement* spirvReq; - glslang::TSpirvInstruction* spirvInst; - glslang::TSpirvTypeParameters* spirvTypeParams; - }; - union { - glslang::TPublicType type; - glslang::TFunction* function; - glslang::TParameter param; - glslang::TTypeLoc typeLine; - glslang::TTypeList* typeList; - glslang::TArraySizes* arraySizes; - glslang::TIdentifierList* identifierList; - }; - glslang::TTypeParameters* typeParameters; - } interm; - -#line 567 "MachineIndependent/glslang_tab.cpp.h" - -}; -typedef union YYSTYPE YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - - - -int yyparse (glslang::TParseContext* pParseContext); - - -#endif /* !YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED */ diff --git a/3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp b/3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp deleted file mode 100644 index 5b1414c9..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/intermOut.cpp +++ /dev/null @@ -1,1609 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2012-2016 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "localintermediate.h" -#include "../Include/InfoSink.h" - -#ifdef _MSC_VER -#include -#else -#include -#endif -#include - - -namespace glslang { - -// -// Two purposes: -// 1. Show an example of how to iterate tree. Functions can -// also directly call Traverse() on children themselves to -// have finer grained control over the process than shown here. -// See the last function for how to get started. -// 2. Print out a text based description of the tree. -// - -// -// Use this class to carry along data from node to node in -// the traversal -// -class TOutputTraverser : public TIntermTraverser { -public: - TOutputTraverser(TInfoSink& i) : infoSink(i), extraOutput(NoExtraOutput) { } - - enum EExtraOutput { - NoExtraOutput, - BinaryDoubleOutput - }; - void setDoubleOutput(EExtraOutput extra) { extraOutput = extra; } - - virtual bool visitBinary(TVisit, TIntermBinary* node); - virtual bool visitUnary(TVisit, TIntermUnary* node); - virtual bool visitAggregate(TVisit, TIntermAggregate* node); - virtual bool visitSelection(TVisit, TIntermSelection* node); - virtual void visitConstantUnion(TIntermConstantUnion* node); - virtual void visitSymbol(TIntermSymbol* node); - virtual bool visitLoop(TVisit, TIntermLoop* node); - virtual bool visitBranch(TVisit, TIntermBranch* node); - virtual bool visitSwitch(TVisit, TIntermSwitch* node); - - TInfoSink& infoSink; -protected: - TOutputTraverser(TOutputTraverser&); - TOutputTraverser& operator=(TOutputTraverser&); - - EExtraOutput extraOutput; -}; - -// -// Helper functions for printing, not part of traversing. -// - -static void OutputTreeText(TInfoSink& infoSink, const TIntermNode* node, const int depth) -{ - int i; - - infoSink.debug << node->getLoc().string << ":"; - if (node->getLoc().line) - infoSink.debug << node->getLoc().line; - else - infoSink.debug << "? "; - - for (i = 0; i < depth; ++i) - infoSink.debug << " "; -} - -// -// The rest of the file are the traversal functions. The last one -// is the one that starts the traversal. -// -// Return true from interior nodes to have the external traversal -// continue on to children. If you process children yourself, -// return false. -// - -bool TOutputTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpAssign: out.debug << "move second child to first child"; break; - case EOpAddAssign: out.debug << "add second child into first child"; break; - case EOpSubAssign: out.debug << "subtract second child into first child"; break; - case EOpMulAssign: out.debug << "multiply second child into first child"; break; - case EOpVectorTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break; - case EOpVectorTimesScalarAssign: out.debug << "vector scale second child into first child"; break; - case EOpMatrixTimesScalarAssign: out.debug << "matrix scale second child into first child"; break; - case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break; - case EOpDivAssign: out.debug << "divide second child into first child"; break; - case EOpModAssign: out.debug << "mod second child into first child"; break; - case EOpAndAssign: out.debug << "and second child into first child"; break; - case EOpInclusiveOrAssign: out.debug << "or second child into first child"; break; - case EOpExclusiveOrAssign: out.debug << "exclusive or second child into first child"; break; - case EOpLeftShiftAssign: out.debug << "left shift second child into first child"; break; - case EOpRightShiftAssign: out.debug << "right shift second child into first child"; break; - - case EOpIndexDirect: out.debug << "direct index"; break; - case EOpIndexIndirect: out.debug << "indirect index"; break; - case EOpIndexDirectStruct: - { - bool reference = node->getLeft()->getType().isReference(); - const TTypeList *members = reference ? node->getLeft()->getType().getReferentType()->getStruct() : node->getLeft()->getType().getStruct(); - out.debug << (*members)[node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()].type->getFieldName(); - out.debug << ": direct index for structure"; break; - } - case EOpVectorSwizzle: out.debug << "vector swizzle"; break; - case EOpMatrixSwizzle: out.debug << "matrix swizzle"; break; - - case EOpAdd: out.debug << "add"; break; - case EOpSub: out.debug << "subtract"; break; - case EOpMul: out.debug << "component-wise multiply"; break; - case EOpDiv: out.debug << "divide"; break; - case EOpMod: out.debug << "mod"; break; - case EOpRightShift: out.debug << "right-shift"; break; - case EOpLeftShift: out.debug << "left-shift"; break; - case EOpAnd: out.debug << "bitwise and"; break; - case EOpInclusiveOr: out.debug << "inclusive-or"; break; - case EOpExclusiveOr: out.debug << "exclusive-or"; break; - case EOpEqual: out.debug << "Compare Equal"; break; - case EOpNotEqual: out.debug << "Compare Not Equal"; break; - case EOpLessThan: out.debug << "Compare Less Than"; break; - case EOpGreaterThan: out.debug << "Compare Greater Than"; break; - case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break; - case EOpVectorEqual: out.debug << "Equal"; break; - case EOpVectorNotEqual: out.debug << "NotEqual"; break; - - case EOpVectorTimesScalar: out.debug << "vector-scale"; break; - case EOpVectorTimesMatrix: out.debug << "vector-times-matrix"; break; - case EOpMatrixTimesVector: out.debug << "matrix-times-vector"; break; - case EOpMatrixTimesScalar: out.debug << "matrix-scale"; break; - case EOpMatrixTimesMatrix: out.debug << "matrix-multiply"; break; - - case EOpLogicalOr: out.debug << "logical-or"; break; - case EOpLogicalXor: out.debug << "logical-xor"; break; - case EOpLogicalAnd: out.debug << "logical-and"; break; - - case EOpAbsDifference: out.debug << "absoluteDifference"; break; - case EOpAddSaturate: out.debug << "addSaturate"; break; - case EOpSubSaturate: out.debug << "subtractSaturate"; break; - case EOpAverage: out.debug << "average"; break; - case EOpAverageRounded: out.debug << "averageRounded"; break; - case EOpMul32x16: out.debug << "multiply32x16"; break; - - default: out.debug << ""; - } - - out.debug << " (" << node->getCompleteString() << ")"; - - out.debug << "\n"; - - return true; -} - -bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpNegative: out.debug << "Negate value"; break; - case EOpVectorLogicalNot: - case EOpLogicalNot: out.debug << "Negate conditional"; break; - case EOpBitwiseNot: out.debug << "Bitwise not"; break; - - case EOpPostIncrement: out.debug << "Post-Increment"; break; - case EOpPostDecrement: out.debug << "Post-Decrement"; break; - case EOpPreIncrement: out.debug << "Pre-Increment"; break; - case EOpPreDecrement: out.debug << "Pre-Decrement"; break; - case EOpCopyObject: out.debug << "copy object"; break; - - // * -> bool - case EOpConvInt8ToBool: out.debug << "Convert int8_t to bool"; break; - case EOpConvUint8ToBool: out.debug << "Convert uint8_t to bool"; break; - case EOpConvInt16ToBool: out.debug << "Convert int16_t to bool"; break; - case EOpConvUint16ToBool: out.debug << "Convert uint16_t to bool";break; - case EOpConvIntToBool: out.debug << "Convert int to bool"; break; - case EOpConvUintToBool: out.debug << "Convert uint to bool"; break; - case EOpConvInt64ToBool: out.debug << "Convert int64 to bool"; break; - case EOpConvUint64ToBool: out.debug << "Convert uint64 to bool"; break; - case EOpConvFloat16ToBool: out.debug << "Convert float16_t to bool"; break; - case EOpConvFloatToBool: out.debug << "Convert float to bool"; break; - case EOpConvDoubleToBool: out.debug << "Convert double to bool"; break; - - // bool -> * - case EOpConvBoolToInt8: out.debug << "Convert bool to int8_t"; break; - case EOpConvBoolToUint8: out.debug << "Convert bool to uint8_t"; break; - case EOpConvBoolToInt16: out.debug << "Convert bool to in16t_t"; break; - case EOpConvBoolToUint16: out.debug << "Convert bool to uint16_t";break; - case EOpConvBoolToInt: out.debug << "Convert bool to int" ; break; - case EOpConvBoolToUint: out.debug << "Convert bool to uint"; break; - case EOpConvBoolToInt64: out.debug << "Convert bool to int64"; break; - case EOpConvBoolToUint64: out.debug << "Convert bool to uint64";break; - case EOpConvBoolToFloat16: out.debug << "Convert bool to float16_t"; break; - case EOpConvBoolToFloat: out.debug << "Convert bool to float"; break; - case EOpConvBoolToDouble: out.debug << "Convert bool to double"; break; - - // int8_t -> (u)int* - case EOpConvInt8ToInt16: out.debug << "Convert int8_t to int16_t";break; - case EOpConvInt8ToInt: out.debug << "Convert int8_t to int"; break; - case EOpConvInt8ToInt64: out.debug << "Convert int8_t to int64"; break; - case EOpConvInt8ToUint8: out.debug << "Convert int8_t to uint8_t";break; - case EOpConvInt8ToUint16: out.debug << "Convert int8_t to uint16_t";break; - case EOpConvInt8ToUint: out.debug << "Convert int8_t to uint"; break; - case EOpConvInt8ToUint64: out.debug << "Convert int8_t to uint64"; break; - - // uint8_t -> (u)int* - case EOpConvUint8ToInt8: out.debug << "Convert uint8_t to int8_t";break; - case EOpConvUint8ToInt16: out.debug << "Convert uint8_t to int16_t";break; - case EOpConvUint8ToInt: out.debug << "Convert uint8_t to int"; break; - case EOpConvUint8ToInt64: out.debug << "Convert uint8_t to int64"; break; - case EOpConvUint8ToUint16: out.debug << "Convert uint8_t to uint16_t";break; - case EOpConvUint8ToUint: out.debug << "Convert uint8_t to uint"; break; - case EOpConvUint8ToUint64: out.debug << "Convert uint8_t to uint64"; break; - - // int8_t -> float* - case EOpConvInt8ToFloat16: out.debug << "Convert int8_t to float16_t";break; - case EOpConvInt8ToFloat: out.debug << "Convert int8_t to float"; break; - case EOpConvInt8ToDouble: out.debug << "Convert int8_t to double"; break; - - // uint8_t -> float* - case EOpConvUint8ToFloat16: out.debug << "Convert uint8_t to float16_t";break; - case EOpConvUint8ToFloat: out.debug << "Convert uint8_t to float"; break; - case EOpConvUint8ToDouble: out.debug << "Convert uint8_t to double"; break; - - // int16_t -> (u)int* - case EOpConvInt16ToInt8: out.debug << "Convert int16_t to int8_t";break; - case EOpConvInt16ToInt: out.debug << "Convert int16_t to int"; break; - case EOpConvInt16ToInt64: out.debug << "Convert int16_t to int64"; break; - case EOpConvInt16ToUint8: out.debug << "Convert int16_t to uint8_t";break; - case EOpConvInt16ToUint16: out.debug << "Convert int16_t to uint16_t";break; - case EOpConvInt16ToUint: out.debug << "Convert int16_t to uint"; break; - case EOpConvInt16ToUint64: out.debug << "Convert int16_t to uint64"; break; - - // int16_t -> float* - case EOpConvInt16ToFloat16: out.debug << "Convert int16_t to float16_t";break; - case EOpConvInt16ToFloat: out.debug << "Convert int16_t to float"; break; - case EOpConvInt16ToDouble: out.debug << "Convert int16_t to double"; break; - - // uint16_t -> (u)int* - case EOpConvUint16ToInt8: out.debug << "Convert uint16_t to int8_t";break; - case EOpConvUint16ToInt16: out.debug << "Convert uint16_t to int16_t";break; - case EOpConvUint16ToInt: out.debug << "Convert uint16_t to int"; break; - case EOpConvUint16ToInt64: out.debug << "Convert uint16_t to int64"; break; - case EOpConvUint16ToUint8: out.debug << "Convert uint16_t to uint8_t";break; - case EOpConvUint16ToUint: out.debug << "Convert uint16_t to uint"; break; - case EOpConvUint16ToUint64: out.debug << "Convert uint16_t to uint64"; break; - - // uint16_t -> float* - case EOpConvUint16ToFloat16: out.debug << "Convert uint16_t to float16_t";break; - case EOpConvUint16ToFloat: out.debug << "Convert uint16_t to float"; break; - case EOpConvUint16ToDouble: out.debug << "Convert uint16_t to double"; break; - - // int32_t -> (u)int* - case EOpConvIntToInt8: out.debug << "Convert int to int8_t";break; - case EOpConvIntToInt16: out.debug << "Convert int to int16_t";break; - case EOpConvIntToInt64: out.debug << "Convert int to int64"; break; - case EOpConvIntToUint8: out.debug << "Convert int to uint8_t";break; - case EOpConvIntToUint16: out.debug << "Convert int to uint16_t";break; - case EOpConvIntToUint: out.debug << "Convert int to uint"; break; - case EOpConvIntToUint64: out.debug << "Convert int to uint64"; break; - - // int32_t -> float* - case EOpConvIntToFloat16: out.debug << "Convert int to float16_t";break; - case EOpConvIntToFloat: out.debug << "Convert int to float"; break; - case EOpConvIntToDouble: out.debug << "Convert int to double"; break; - - // uint32_t -> (u)int* - case EOpConvUintToInt8: out.debug << "Convert uint to int8_t";break; - case EOpConvUintToInt16: out.debug << "Convert uint to int16_t";break; - case EOpConvUintToInt: out.debug << "Convert uint to int";break; - case EOpConvUintToInt64: out.debug << "Convert uint to int64"; break; - case EOpConvUintToUint8: out.debug << "Convert uint to uint8_t";break; - case EOpConvUintToUint16: out.debug << "Convert uint to uint16_t";break; - case EOpConvUintToUint64: out.debug << "Convert uint to uint64"; break; - - // uint32_t -> float* - case EOpConvUintToFloat16: out.debug << "Convert uint to float16_t";break; - case EOpConvUintToFloat: out.debug << "Convert uint to float"; break; - case EOpConvUintToDouble: out.debug << "Convert uint to double"; break; - - // int64 -> (u)int* - case EOpConvInt64ToInt8: out.debug << "Convert int64 to int8_t"; break; - case EOpConvInt64ToInt16: out.debug << "Convert int64 to int16_t"; break; - case EOpConvInt64ToInt: out.debug << "Convert int64 to int"; break; - case EOpConvInt64ToUint8: out.debug << "Convert int64 to uint8_t";break; - case EOpConvInt64ToUint16: out.debug << "Convert int64 to uint16_t";break; - case EOpConvInt64ToUint: out.debug << "Convert int64 to uint"; break; - case EOpConvInt64ToUint64: out.debug << "Convert int64 to uint64"; break; - - // int64 -> float* - case EOpConvInt64ToFloat16: out.debug << "Convert int64 to float16_t";break; - case EOpConvInt64ToFloat: out.debug << "Convert int64 to float"; break; - case EOpConvInt64ToDouble: out.debug << "Convert int64 to double"; break; - - // uint64 -> (u)int* - case EOpConvUint64ToInt8: out.debug << "Convert uint64 to int8_t";break; - case EOpConvUint64ToInt16: out.debug << "Convert uint64 to int16_t";break; - case EOpConvUint64ToInt: out.debug << "Convert uint64 to int"; break; - case EOpConvUint64ToInt64: out.debug << "Convert uint64 to int64"; break; - case EOpConvUint64ToUint8: out.debug << "Convert uint64 to uint8_t";break; - case EOpConvUint64ToUint16: out.debug << "Convert uint64 to uint16"; break; - case EOpConvUint64ToUint: out.debug << "Convert uint64 to uint"; break; - - // uint64 -> float* - case EOpConvUint64ToFloat16: out.debug << "Convert uint64 to float16_t";break; - case EOpConvUint64ToFloat: out.debug << "Convert uint64 to float"; break; - case EOpConvUint64ToDouble: out.debug << "Convert uint64 to double"; break; - - // float16_t -> int* - case EOpConvFloat16ToInt8: out.debug << "Convert float16_t to int8_t"; break; - case EOpConvFloat16ToInt16: out.debug << "Convert float16_t to int16_t"; break; - case EOpConvFloat16ToInt: out.debug << "Convert float16_t to int"; break; - case EOpConvFloat16ToInt64: out.debug << "Convert float16_t to int64"; break; - - // float16_t -> uint* - case EOpConvFloat16ToUint8: out.debug << "Convert float16_t to uint8_t"; break; - case EOpConvFloat16ToUint16: out.debug << "Convert float16_t to uint16_t"; break; - case EOpConvFloat16ToUint: out.debug << "Convert float16_t to uint"; break; - case EOpConvFloat16ToUint64: out.debug << "Convert float16_t to uint64"; break; - - // float16_t -> float* - case EOpConvFloat16ToFloat: out.debug << "Convert float16_t to float"; break; - case EOpConvFloat16ToDouble: out.debug << "Convert float16_t to double"; break; - - // float32 -> float* - case EOpConvFloatToFloat16: out.debug << "Convert float to float16_t"; break; - case EOpConvFloatToDouble: out.debug << "Convert float to double"; break; - - // float32_t -> int* - case EOpConvFloatToInt8: out.debug << "Convert float to int8_t"; break; - case EOpConvFloatToInt16: out.debug << "Convert float to int16_t"; break; - case EOpConvFloatToInt: out.debug << "Convert float to int"; break; - case EOpConvFloatToInt64: out.debug << "Convert float to int64"; break; - - // float32_t -> uint* - case EOpConvFloatToUint8: out.debug << "Convert float to uint8_t"; break; - case EOpConvFloatToUint16: out.debug << "Convert float to uint16_t"; break; - case EOpConvFloatToUint: out.debug << "Convert float to uint"; break; - case EOpConvFloatToUint64: out.debug << "Convert float to uint64"; break; - - // double -> float* - case EOpConvDoubleToFloat16: out.debug << "Convert double to float16_t"; break; - case EOpConvDoubleToFloat: out.debug << "Convert double to float"; break; - - // double -> int* - case EOpConvDoubleToInt8: out.debug << "Convert double to int8_t"; break; - case EOpConvDoubleToInt16: out.debug << "Convert double to int16_t"; break; - case EOpConvDoubleToInt: out.debug << "Convert double to int"; break; - case EOpConvDoubleToInt64: out.debug << "Convert double to int64"; break; - - // float32_t -> uint* - case EOpConvDoubleToUint8: out.debug << "Convert double to uint8_t"; break; - case EOpConvDoubleToUint16: out.debug << "Convert double to uint16_t"; break; - case EOpConvDoubleToUint: out.debug << "Convert double to uint"; break; - case EOpConvDoubleToUint64: out.debug << "Convert double to uint64"; break; - - case EOpConvUint64ToPtr: out.debug << "Convert uint64_t to pointer"; break; - case EOpConvPtrToUint64: out.debug << "Convert pointer to uint64_t"; break; - - case EOpConvUint64ToAccStruct: out.debug << "Convert uint64_t to acceleration structure"; break; - case EOpConvUvec2ToAccStruct: out.debug << "Convert uvec2 to acceleration strucuture "; break; - - case EOpRadians: out.debug << "radians"; break; - case EOpDegrees: out.debug << "degrees"; break; - case EOpSin: out.debug << "sine"; break; - case EOpCos: out.debug << "cosine"; break; - case EOpTan: out.debug << "tangent"; break; - case EOpAsin: out.debug << "arc sine"; break; - case EOpAcos: out.debug << "arc cosine"; break; - case EOpAtan: out.debug << "arc tangent"; break; - case EOpSinh: out.debug << "hyp. sine"; break; - case EOpCosh: out.debug << "hyp. cosine"; break; - case EOpTanh: out.debug << "hyp. tangent"; break; - case EOpAsinh: out.debug << "arc hyp. sine"; break; - case EOpAcosh: out.debug << "arc hyp. cosine"; break; - case EOpAtanh: out.debug << "arc hyp. tangent"; break; - - case EOpExp: out.debug << "exp"; break; - case EOpLog: out.debug << "log"; break; - case EOpExp2: out.debug << "exp2"; break; - case EOpLog2: out.debug << "log2"; break; - case EOpSqrt: out.debug << "sqrt"; break; - case EOpInverseSqrt: out.debug << "inverse sqrt"; break; - - case EOpAbs: out.debug << "Absolute value"; break; - case EOpSign: out.debug << "Sign"; break; - case EOpFloor: out.debug << "Floor"; break; - case EOpTrunc: out.debug << "trunc"; break; - case EOpRound: out.debug << "round"; break; - case EOpRoundEven: out.debug << "roundEven"; break; - case EOpCeil: out.debug << "Ceiling"; break; - case EOpFract: out.debug << "Fraction"; break; - - case EOpIsNan: out.debug << "isnan"; break; - case EOpIsInf: out.debug << "isinf"; break; - - case EOpFloatBitsToInt: out.debug << "floatBitsToInt"; break; - case EOpFloatBitsToUint:out.debug << "floatBitsToUint"; break; - case EOpIntBitsToFloat: out.debug << "intBitsToFloat"; break; - case EOpUintBitsToFloat:out.debug << "uintBitsToFloat"; break; - case EOpDoubleBitsToInt64: out.debug << "doubleBitsToInt64"; break; - case EOpDoubleBitsToUint64: out.debug << "doubleBitsToUint64"; break; - case EOpInt64BitsToDouble: out.debug << "int64BitsToDouble"; break; - case EOpUint64BitsToDouble: out.debug << "uint64BitsToDouble"; break; - case EOpFloat16BitsToInt16: out.debug << "float16BitsToInt16"; break; - case EOpFloat16BitsToUint16: out.debug << "float16BitsToUint16"; break; - case EOpInt16BitsToFloat16: out.debug << "int16BitsToFloat16"; break; - case EOpUint16BitsToFloat16: out.debug << "uint16BitsToFloat16"; break; - - case EOpPackSnorm2x16: out.debug << "packSnorm2x16"; break; - case EOpUnpackSnorm2x16:out.debug << "unpackSnorm2x16"; break; - case EOpPackUnorm2x16: out.debug << "packUnorm2x16"; break; - case EOpUnpackUnorm2x16:out.debug << "unpackUnorm2x16"; break; - case EOpPackHalf2x16: out.debug << "packHalf2x16"; break; - case EOpUnpackHalf2x16: out.debug << "unpackHalf2x16"; break; - case EOpPack16: out.debug << "pack16"; break; - case EOpPack32: out.debug << "pack32"; break; - case EOpPack64: out.debug << "pack64"; break; - case EOpUnpack32: out.debug << "unpack32"; break; - case EOpUnpack16: out.debug << "unpack16"; break; - case EOpUnpack8: out.debug << "unpack8"; break; - - case EOpPackSnorm4x8: out.debug << "PackSnorm4x8"; break; - case EOpUnpackSnorm4x8: out.debug << "UnpackSnorm4x8"; break; - case EOpPackUnorm4x8: out.debug << "PackUnorm4x8"; break; - case EOpUnpackUnorm4x8: out.debug << "UnpackUnorm4x8"; break; - case EOpPackDouble2x32: out.debug << "PackDouble2x32"; break; - case EOpUnpackDouble2x32: out.debug << "UnpackDouble2x32"; break; - - case EOpPackInt2x32: out.debug << "packInt2x32"; break; - case EOpUnpackInt2x32: out.debug << "unpackInt2x32"; break; - case EOpPackUint2x32: out.debug << "packUint2x32"; break; - case EOpUnpackUint2x32: out.debug << "unpackUint2x32"; break; - - case EOpPackInt2x16: out.debug << "packInt2x16"; break; - case EOpUnpackInt2x16: out.debug << "unpackInt2x16"; break; - case EOpPackUint2x16: out.debug << "packUint2x16"; break; - case EOpUnpackUint2x16: out.debug << "unpackUint2x16"; break; - - case EOpPackInt4x16: out.debug << "packInt4x16"; break; - case EOpUnpackInt4x16: out.debug << "unpackInt4x16"; break; - case EOpPackUint4x16: out.debug << "packUint4x16"; break; - case EOpUnpackUint4x16: out.debug << "unpackUint4x16"; break; - case EOpPackFloat2x16: out.debug << "packFloat2x16"; break; - case EOpUnpackFloat2x16: out.debug << "unpackFloat2x16"; break; - - case EOpLength: out.debug << "length"; break; - case EOpNormalize: out.debug << "normalize"; break; - case EOpDPdx: out.debug << "dPdx"; break; - case EOpDPdy: out.debug << "dPdy"; break; - case EOpFwidth: out.debug << "fwidth"; break; - case EOpDPdxFine: out.debug << "dPdxFine"; break; - case EOpDPdyFine: out.debug << "dPdyFine"; break; - case EOpFwidthFine: out.debug << "fwidthFine"; break; - case EOpDPdxCoarse: out.debug << "dPdxCoarse"; break; - case EOpDPdyCoarse: out.debug << "dPdyCoarse"; break; - case EOpFwidthCoarse: out.debug << "fwidthCoarse"; break; - - case EOpInterpolateAtCentroid: out.debug << "interpolateAtCentroid"; break; - - case EOpDeterminant: out.debug << "determinant"; break; - case EOpMatrixInverse: out.debug << "inverse"; break; - case EOpTranspose: out.debug << "transpose"; break; - - case EOpAny: out.debug << "any"; break; - case EOpAll: out.debug << "all"; break; - - case EOpArrayLength: out.debug << "array length"; break; - - case EOpEmitStreamVertex: out.debug << "EmitStreamVertex"; break; - case EOpEndStreamPrimitive: out.debug << "EndStreamPrimitive"; break; - - case EOpAtomicCounterIncrement: out.debug << "AtomicCounterIncrement";break; - case EOpAtomicCounterDecrement: out.debug << "AtomicCounterDecrement";break; - case EOpAtomicCounter: out.debug << "AtomicCounter"; break; - - case EOpTextureQuerySize: out.debug << "textureSize"; break; - case EOpTextureQueryLod: out.debug << "textureQueryLod"; break; - case EOpTextureQueryLevels: out.debug << "textureQueryLevels"; break; - case EOpTextureQuerySamples: out.debug << "textureSamples"; break; - case EOpImageQuerySize: out.debug << "imageQuerySize"; break; - case EOpImageQuerySamples: out.debug << "imageQuerySamples"; break; - case EOpImageLoad: out.debug << "imageLoad"; break; - - case EOpBitFieldReverse: out.debug << "bitFieldReverse"; break; - case EOpBitCount: out.debug << "bitCount"; break; - case EOpFindLSB: out.debug << "findLSB"; break; - case EOpFindMSB: out.debug << "findMSB"; break; - - case EOpCountLeadingZeros: out.debug << "countLeadingZeros"; break; - case EOpCountTrailingZeros: out.debug << "countTrailingZeros"; break; - - case EOpNoise: out.debug << "noise"; break; - - case EOpBallot: out.debug << "ballot"; break; - case EOpReadFirstInvocation: out.debug << "readFirstInvocation"; break; - - case EOpAnyInvocation: out.debug << "anyInvocation"; break; - case EOpAllInvocations: out.debug << "allInvocations"; break; - case EOpAllInvocationsEqual: out.debug << "allInvocationsEqual"; break; - - case EOpSubgroupElect: out.debug << "subgroupElect"; break; - case EOpSubgroupAll: out.debug << "subgroupAll"; break; - case EOpSubgroupAny: out.debug << "subgroupAny"; break; - case EOpSubgroupAllEqual: out.debug << "subgroupAllEqual"; break; - case EOpSubgroupBroadcast: out.debug << "subgroupBroadcast"; break; - case EOpSubgroupBroadcastFirst: out.debug << "subgroupBroadcastFirst"; break; - case EOpSubgroupBallot: out.debug << "subgroupBallot"; break; - case EOpSubgroupInverseBallot: out.debug << "subgroupInverseBallot"; break; - case EOpSubgroupBallotBitExtract: out.debug << "subgroupBallotBitExtract"; break; - case EOpSubgroupBallotBitCount: out.debug << "subgroupBallotBitCount"; break; - case EOpSubgroupBallotInclusiveBitCount: out.debug << "subgroupBallotInclusiveBitCount"; break; - case EOpSubgroupBallotExclusiveBitCount: out.debug << "subgroupBallotExclusiveBitCount"; break; - case EOpSubgroupBallotFindLSB: out.debug << "subgroupBallotFindLSB"; break; - case EOpSubgroupBallotFindMSB: out.debug << "subgroupBallotFindMSB"; break; - case EOpSubgroupShuffle: out.debug << "subgroupShuffle"; break; - case EOpSubgroupShuffleXor: out.debug << "subgroupShuffleXor"; break; - case EOpSubgroupShuffleUp: out.debug << "subgroupShuffleUp"; break; - case EOpSubgroupShuffleDown: out.debug << "subgroupShuffleDown"; break; - case EOpSubgroupAdd: out.debug << "subgroupAdd"; break; - case EOpSubgroupMul: out.debug << "subgroupMul"; break; - case EOpSubgroupMin: out.debug << "subgroupMin"; break; - case EOpSubgroupMax: out.debug << "subgroupMax"; break; - case EOpSubgroupAnd: out.debug << "subgroupAnd"; break; - case EOpSubgroupOr: out.debug << "subgroupOr"; break; - case EOpSubgroupXor: out.debug << "subgroupXor"; break; - case EOpSubgroupInclusiveAdd: out.debug << "subgroupInclusiveAdd"; break; - case EOpSubgroupInclusiveMul: out.debug << "subgroupInclusiveMul"; break; - case EOpSubgroupInclusiveMin: out.debug << "subgroupInclusiveMin"; break; - case EOpSubgroupInclusiveMax: out.debug << "subgroupInclusiveMax"; break; - case EOpSubgroupInclusiveAnd: out.debug << "subgroupInclusiveAnd"; break; - case EOpSubgroupInclusiveOr: out.debug << "subgroupInclusiveOr"; break; - case EOpSubgroupInclusiveXor: out.debug << "subgroupInclusiveXor"; break; - case EOpSubgroupExclusiveAdd: out.debug << "subgroupExclusiveAdd"; break; - case EOpSubgroupExclusiveMul: out.debug << "subgroupExclusiveMul"; break; - case EOpSubgroupExclusiveMin: out.debug << "subgroupExclusiveMin"; break; - case EOpSubgroupExclusiveMax: out.debug << "subgroupExclusiveMax"; break; - case EOpSubgroupExclusiveAnd: out.debug << "subgroupExclusiveAnd"; break; - case EOpSubgroupExclusiveOr: out.debug << "subgroupExclusiveOr"; break; - case EOpSubgroupExclusiveXor: out.debug << "subgroupExclusiveXor"; break; - case EOpSubgroupClusteredAdd: out.debug << "subgroupClusteredAdd"; break; - case EOpSubgroupClusteredMul: out.debug << "subgroupClusteredMul"; break; - case EOpSubgroupClusteredMin: out.debug << "subgroupClusteredMin"; break; - case EOpSubgroupClusteredMax: out.debug << "subgroupClusteredMax"; break; - case EOpSubgroupClusteredAnd: out.debug << "subgroupClusteredAnd"; break; - case EOpSubgroupClusteredOr: out.debug << "subgroupClusteredOr"; break; - case EOpSubgroupClusteredXor: out.debug << "subgroupClusteredXor"; break; - case EOpSubgroupQuadBroadcast: out.debug << "subgroupQuadBroadcast"; break; - case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break; - case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break; - case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break; - - case EOpSubgroupPartition: out.debug << "subgroupPartitionNV"; break; - case EOpSubgroupPartitionedAdd: out.debug << "subgroupPartitionedAddNV"; break; - case EOpSubgroupPartitionedMul: out.debug << "subgroupPartitionedMulNV"; break; - case EOpSubgroupPartitionedMin: out.debug << "subgroupPartitionedMinNV"; break; - case EOpSubgroupPartitionedMax: out.debug << "subgroupPartitionedMaxNV"; break; - case EOpSubgroupPartitionedAnd: out.debug << "subgroupPartitionedAndNV"; break; - case EOpSubgroupPartitionedOr: out.debug << "subgroupPartitionedOrNV"; break; - case EOpSubgroupPartitionedXor: out.debug << "subgroupPartitionedXorNV"; break; - case EOpSubgroupPartitionedInclusiveAdd: out.debug << "subgroupPartitionedInclusiveAddNV"; break; - case EOpSubgroupPartitionedInclusiveMul: out.debug << "subgroupPartitionedInclusiveMulNV"; break; - case EOpSubgroupPartitionedInclusiveMin: out.debug << "subgroupPartitionedInclusiveMinNV"; break; - case EOpSubgroupPartitionedInclusiveMax: out.debug << "subgroupPartitionedInclusiveMaxNV"; break; - case EOpSubgroupPartitionedInclusiveAnd: out.debug << "subgroupPartitionedInclusiveAndNV"; break; - case EOpSubgroupPartitionedInclusiveOr: out.debug << "subgroupPartitionedInclusiveOrNV"; break; - case EOpSubgroupPartitionedInclusiveXor: out.debug << "subgroupPartitionedInclusiveXorNV"; break; - case EOpSubgroupPartitionedExclusiveAdd: out.debug << "subgroupPartitionedExclusiveAddNV"; break; - case EOpSubgroupPartitionedExclusiveMul: out.debug << "subgroupPartitionedExclusiveMulNV"; break; - case EOpSubgroupPartitionedExclusiveMin: out.debug << "subgroupPartitionedExclusiveMinNV"; break; - case EOpSubgroupPartitionedExclusiveMax: out.debug << "subgroupPartitionedExclusiveMaxNV"; break; - case EOpSubgroupPartitionedExclusiveAnd: out.debug << "subgroupPartitionedExclusiveAndNV"; break; - case EOpSubgroupPartitionedExclusiveOr: out.debug << "subgroupPartitionedExclusiveOrNV"; break; - case EOpSubgroupPartitionedExclusiveXor: out.debug << "subgroupPartitionedExclusiveXorNV"; break; - - case EOpClip: out.debug << "clip"; break; - case EOpIsFinite: out.debug << "isfinite"; break; - case EOpLog10: out.debug << "log10"; break; - case EOpRcp: out.debug << "rcp"; break; - case EOpSaturate: out.debug << "saturate"; break; - - case EOpSparseTexelsResident: out.debug << "sparseTexelsResident"; break; - - case EOpMinInvocations: out.debug << "minInvocations"; break; - case EOpMaxInvocations: out.debug << "maxInvocations"; break; - case EOpAddInvocations: out.debug << "addInvocations"; break; - case EOpMinInvocationsNonUniform: out.debug << "minInvocationsNonUniform"; break; - case EOpMaxInvocationsNonUniform: out.debug << "maxInvocationsNonUniform"; break; - case EOpAddInvocationsNonUniform: out.debug << "addInvocationsNonUniform"; break; - - case EOpMinInvocationsInclusiveScan: out.debug << "minInvocationsInclusiveScan"; break; - case EOpMaxInvocationsInclusiveScan: out.debug << "maxInvocationsInclusiveScan"; break; - case EOpAddInvocationsInclusiveScan: out.debug << "addInvocationsInclusiveScan"; break; - case EOpMinInvocationsInclusiveScanNonUniform: out.debug << "minInvocationsInclusiveScanNonUniform"; break; - case EOpMaxInvocationsInclusiveScanNonUniform: out.debug << "maxInvocationsInclusiveScanNonUniform"; break; - case EOpAddInvocationsInclusiveScanNonUniform: out.debug << "addInvocationsInclusiveScanNonUniform"; break; - - case EOpMinInvocationsExclusiveScan: out.debug << "minInvocationsExclusiveScan"; break; - case EOpMaxInvocationsExclusiveScan: out.debug << "maxInvocationsExclusiveScan"; break; - case EOpAddInvocationsExclusiveScan: out.debug << "addInvocationsExclusiveScan"; break; - case EOpMinInvocationsExclusiveScanNonUniform: out.debug << "minInvocationsExclusiveScanNonUniform"; break; - case EOpMaxInvocationsExclusiveScanNonUniform: out.debug << "maxInvocationsExclusiveScanNonUniform"; break; - case EOpAddInvocationsExclusiveScanNonUniform: out.debug << "addInvocationsExclusiveScanNonUniform"; break; - - case EOpMbcnt: out.debug << "mbcnt"; break; - - case EOpFragmentMaskFetch: out.debug << "fragmentMaskFetchAMD"; break; - case EOpFragmentFetch: out.debug << "fragmentFetchAMD"; break; - - case EOpCubeFaceIndex: out.debug << "cubeFaceIndex"; break; - case EOpCubeFaceCoord: out.debug << "cubeFaceCoord"; break; - - case EOpSubpassLoad: out.debug << "subpassLoad"; break; - case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break; - - case EOpColorAttachmentReadEXT: out.debug << "colorAttachmentReadEXT"; break; - - case EOpConstructReference: out.debug << "Construct reference type"; break; - - case EOpDeclare: out.debug << "Declare"; break; - - case EOpSpirvInst: out.debug << "spirv_instruction"; break; - - default: out.debug.message(EPrefixError, "Bad unary op"); - } - - out.debug << " (" << node->getCompleteString() << ")"; - - out.debug << "\n"; - - return true; -} - -bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node) -{ - TInfoSink& out = infoSink; - - if (node->getOp() == EOpNull) { - out.debug.message(EPrefixError, "node is still EOpNull!"); - return true; - } - - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpSequence: out.debug << "Sequence\n"; return true; - case EOpScope: out.debug << "Scope\n"; return true; - case EOpLinkerObjects: out.debug << "Linker Objects\n"; return true; - case EOpComma: out.debug << "Comma"; break; - case EOpFunction: out.debug << "Function Definition: " << node->getName(); break; - case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break; - case EOpParameters: out.debug << "Function Parameters: "; break; - - case EOpConstructFloat: out.debug << "Construct float"; break; - case EOpConstructDouble:out.debug << "Construct double"; break; - - case EOpConstructVec2: out.debug << "Construct vec2"; break; - case EOpConstructVec3: out.debug << "Construct vec3"; break; - case EOpConstructVec4: out.debug << "Construct vec4"; break; - case EOpConstructDVec2: out.debug << "Construct dvec2"; break; - case EOpConstructDVec3: out.debug << "Construct dvec3"; break; - case EOpConstructDVec4: out.debug << "Construct dvec4"; break; - case EOpConstructBool: out.debug << "Construct bool"; break; - case EOpConstructBVec2: out.debug << "Construct bvec2"; break; - case EOpConstructBVec3: out.debug << "Construct bvec3"; break; - case EOpConstructBVec4: out.debug << "Construct bvec4"; break; - case EOpConstructInt8: out.debug << "Construct int8_t"; break; - case EOpConstructI8Vec2: out.debug << "Construct i8vec2"; break; - case EOpConstructI8Vec3: out.debug << "Construct i8vec3"; break; - case EOpConstructI8Vec4: out.debug << "Construct i8vec4"; break; - case EOpConstructInt: out.debug << "Construct int"; break; - case EOpConstructIVec2: out.debug << "Construct ivec2"; break; - case EOpConstructIVec3: out.debug << "Construct ivec3"; break; - case EOpConstructIVec4: out.debug << "Construct ivec4"; break; - case EOpConstructUint8: out.debug << "Construct uint8_t"; break; - case EOpConstructU8Vec2: out.debug << "Construct u8vec2"; break; - case EOpConstructU8Vec3: out.debug << "Construct u8vec3"; break; - case EOpConstructU8Vec4: out.debug << "Construct u8vec4"; break; - case EOpConstructUint: out.debug << "Construct uint"; break; - case EOpConstructUVec2: out.debug << "Construct uvec2"; break; - case EOpConstructUVec3: out.debug << "Construct uvec3"; break; - case EOpConstructUVec4: out.debug << "Construct uvec4"; break; - case EOpConstructInt64: out.debug << "Construct int64"; break; - case EOpConstructI64Vec2: out.debug << "Construct i64vec2"; break; - case EOpConstructI64Vec3: out.debug << "Construct i64vec3"; break; - case EOpConstructI64Vec4: out.debug << "Construct i64vec4"; break; - case EOpConstructUint64: out.debug << "Construct uint64"; break; - case EOpConstructU64Vec2: out.debug << "Construct u64vec2"; break; - case EOpConstructU64Vec3: out.debug << "Construct u64vec3"; break; - case EOpConstructU64Vec4: out.debug << "Construct u64vec4"; break; - case EOpConstructInt16: out.debug << "Construct int16_t"; break; - case EOpConstructI16Vec2: out.debug << "Construct i16vec2"; break; - case EOpConstructI16Vec3: out.debug << "Construct i16vec3"; break; - case EOpConstructI16Vec4: out.debug << "Construct i16vec4"; break; - case EOpConstructUint16: out.debug << "Construct uint16_t"; break; - case EOpConstructU16Vec2: out.debug << "Construct u16vec2"; break; - case EOpConstructU16Vec3: out.debug << "Construct u16vec3"; break; - case EOpConstructU16Vec4: out.debug << "Construct u16vec4"; break; - case EOpConstructMat2x2: out.debug << "Construct mat2"; break; - case EOpConstructMat2x3: out.debug << "Construct mat2x3"; break; - case EOpConstructMat2x4: out.debug << "Construct mat2x4"; break; - case EOpConstructMat3x2: out.debug << "Construct mat3x2"; break; - case EOpConstructMat3x3: out.debug << "Construct mat3"; break; - case EOpConstructMat3x4: out.debug << "Construct mat3x4"; break; - case EOpConstructMat4x2: out.debug << "Construct mat4x2"; break; - case EOpConstructMat4x3: out.debug << "Construct mat4x3"; break; - case EOpConstructMat4x4: out.debug << "Construct mat4"; break; - case EOpConstructDMat2x2: out.debug << "Construct dmat2"; break; - case EOpConstructDMat2x3: out.debug << "Construct dmat2x3"; break; - case EOpConstructDMat2x4: out.debug << "Construct dmat2x4"; break; - case EOpConstructDMat3x2: out.debug << "Construct dmat3x2"; break; - case EOpConstructDMat3x3: out.debug << "Construct dmat3"; break; - case EOpConstructDMat3x4: out.debug << "Construct dmat3x4"; break; - case EOpConstructDMat4x2: out.debug << "Construct dmat4x2"; break; - case EOpConstructDMat4x3: out.debug << "Construct dmat4x3"; break; - case EOpConstructDMat4x4: out.debug << "Construct dmat4"; break; - case EOpConstructIMat2x2: out.debug << "Construct imat2"; break; - case EOpConstructIMat2x3: out.debug << "Construct imat2x3"; break; - case EOpConstructIMat2x4: out.debug << "Construct imat2x4"; break; - case EOpConstructIMat3x2: out.debug << "Construct imat3x2"; break; - case EOpConstructIMat3x3: out.debug << "Construct imat3"; break; - case EOpConstructIMat3x4: out.debug << "Construct imat3x4"; break; - case EOpConstructIMat4x2: out.debug << "Construct imat4x2"; break; - case EOpConstructIMat4x3: out.debug << "Construct imat4x3"; break; - case EOpConstructIMat4x4: out.debug << "Construct imat4"; break; - case EOpConstructUMat2x2: out.debug << "Construct umat2"; break; - case EOpConstructUMat2x3: out.debug << "Construct umat2x3"; break; - case EOpConstructUMat2x4: out.debug << "Construct umat2x4"; break; - case EOpConstructUMat3x2: out.debug << "Construct umat3x2"; break; - case EOpConstructUMat3x3: out.debug << "Construct umat3"; break; - case EOpConstructUMat3x4: out.debug << "Construct umat3x4"; break; - case EOpConstructUMat4x2: out.debug << "Construct umat4x2"; break; - case EOpConstructUMat4x3: out.debug << "Construct umat4x3"; break; - case EOpConstructUMat4x4: out.debug << "Construct umat4"; break; - case EOpConstructBMat2x2: out.debug << "Construct bmat2"; break; - case EOpConstructBMat2x3: out.debug << "Construct bmat2x3"; break; - case EOpConstructBMat2x4: out.debug << "Construct bmat2x4"; break; - case EOpConstructBMat3x2: out.debug << "Construct bmat3x2"; break; - case EOpConstructBMat3x3: out.debug << "Construct bmat3"; break; - case EOpConstructBMat3x4: out.debug << "Construct bmat3x4"; break; - case EOpConstructBMat4x2: out.debug << "Construct bmat4x2"; break; - case EOpConstructBMat4x3: out.debug << "Construct bmat4x3"; break; - case EOpConstructBMat4x4: out.debug << "Construct bmat4"; break; - case EOpConstructFloat16: out.debug << "Construct float16_t"; break; - case EOpConstructF16Vec2: out.debug << "Construct f16vec2"; break; - case EOpConstructF16Vec3: out.debug << "Construct f16vec3"; break; - case EOpConstructF16Vec4: out.debug << "Construct f16vec4"; break; - case EOpConstructF16Mat2x2: out.debug << "Construct f16mat2"; break; - case EOpConstructF16Mat2x3: out.debug << "Construct f16mat2x3"; break; - case EOpConstructF16Mat2x4: out.debug << "Construct f16mat2x4"; break; - case EOpConstructF16Mat3x2: out.debug << "Construct f16mat3x2"; break; - case EOpConstructF16Mat3x3: out.debug << "Construct f16mat3"; break; - case EOpConstructF16Mat3x4: out.debug << "Construct f16mat3x4"; break; - case EOpConstructF16Mat4x2: out.debug << "Construct f16mat4x2"; break; - case EOpConstructF16Mat4x3: out.debug << "Construct f16mat4x3"; break; - case EOpConstructF16Mat4x4: out.debug << "Construct f16mat4"; break; - case EOpConstructStruct: out.debug << "Construct structure"; break; - case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break; - case EOpConstructReference: out.debug << "Construct reference"; break; - case EOpConstructCooperativeMatrixNV: out.debug << "Construct cooperative matrix NV"; break; - case EOpConstructCooperativeMatrixKHR: out.debug << "Construct cooperative matrix KHR"; break; - case EOpConstructAccStruct: out.debug << "Construct acceleration structure"; break; - - case EOpLessThan: out.debug << "Compare Less Than"; break; - case EOpGreaterThan: out.debug << "Compare Greater Than"; break; - case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break; - case EOpVectorEqual: out.debug << "Equal"; break; - case EOpVectorNotEqual: out.debug << "NotEqual"; break; - - case EOpMod: out.debug << "mod"; break; - case EOpModf: out.debug << "modf"; break; - case EOpPow: out.debug << "pow"; break; - - case EOpAtan: out.debug << "arc tangent"; break; - - case EOpMin: out.debug << "min"; break; - case EOpMax: out.debug << "max"; break; - case EOpClamp: out.debug << "clamp"; break; - case EOpMix: out.debug << "mix"; break; - case EOpStep: out.debug << "step"; break; - case EOpSmoothStep: out.debug << "smoothstep"; break; - - case EOpDistance: out.debug << "distance"; break; - case EOpDot: out.debug << "dot-product"; break; - case EOpCross: out.debug << "cross-product"; break; - case EOpFaceForward: out.debug << "face-forward"; break; - case EOpReflect: out.debug << "reflect"; break; - case EOpRefract: out.debug << "refract"; break; - case EOpMul: out.debug << "component-wise multiply"; break; - case EOpOuterProduct: out.debug << "outer product"; break; - - case EOpEmitVertex: out.debug << "EmitVertex"; break; - case EOpEndPrimitive: out.debug << "EndPrimitive"; break; - - case EOpBarrier: out.debug << "Barrier"; break; - case EOpMemoryBarrier: out.debug << "MemoryBarrier"; break; - case EOpMemoryBarrierAtomicCounter: out.debug << "MemoryBarrierAtomicCounter"; break; - case EOpMemoryBarrierBuffer: out.debug << "MemoryBarrierBuffer"; break; - case EOpMemoryBarrierImage: out.debug << "MemoryBarrierImage"; break; - case EOpMemoryBarrierShared: out.debug << "MemoryBarrierShared"; break; - case EOpGroupMemoryBarrier: out.debug << "GroupMemoryBarrier"; break; - - case EOpReadInvocation: out.debug << "readInvocation"; break; - - case EOpSwizzleInvocations: out.debug << "swizzleInvocations"; break; - case EOpSwizzleInvocationsMasked: out.debug << "swizzleInvocationsMasked"; break; - case EOpWriteInvocation: out.debug << "writeInvocation"; break; - - case EOpMin3: out.debug << "min3"; break; - case EOpMax3: out.debug << "max3"; break; - case EOpMid3: out.debug << "mid3"; break; - case EOpTime: out.debug << "time"; break; - - case EOpAtomicAdd: out.debug << "AtomicAdd"; break; - case EOpAtomicSubtract: out.debug << "AtomicSubtract"; break; - case EOpAtomicMin: out.debug << "AtomicMin"; break; - case EOpAtomicMax: out.debug << "AtomicMax"; break; - case EOpAtomicAnd: out.debug << "AtomicAnd"; break; - case EOpAtomicOr: out.debug << "AtomicOr"; break; - case EOpAtomicXor: out.debug << "AtomicXor"; break; - case EOpAtomicExchange: out.debug << "AtomicExchange"; break; - case EOpAtomicCompSwap: out.debug << "AtomicCompSwap"; break; - case EOpAtomicLoad: out.debug << "AtomicLoad"; break; - case EOpAtomicStore: out.debug << "AtomicStore"; break; - - case EOpAtomicCounterAdd: out.debug << "AtomicCounterAdd"; break; - case EOpAtomicCounterSubtract: out.debug << "AtomicCounterSubtract"; break; - case EOpAtomicCounterMin: out.debug << "AtomicCounterMin"; break; - case EOpAtomicCounterMax: out.debug << "AtomicCounterMax"; break; - case EOpAtomicCounterAnd: out.debug << "AtomicCounterAnd"; break; - case EOpAtomicCounterOr: out.debug << "AtomicCounterOr"; break; - case EOpAtomicCounterXor: out.debug << "AtomicCounterXor"; break; - case EOpAtomicCounterExchange: out.debug << "AtomicCounterExchange"; break; - case EOpAtomicCounterCompSwap: out.debug << "AtomicCounterCompSwap"; break; - - case EOpImageQuerySize: out.debug << "imageQuerySize"; break; - case EOpImageQuerySamples: out.debug << "imageQuerySamples"; break; - case EOpImageLoad: out.debug << "imageLoad"; break; - case EOpImageStore: out.debug << "imageStore"; break; - case EOpImageAtomicAdd: out.debug << "imageAtomicAdd"; break; - case EOpImageAtomicMin: out.debug << "imageAtomicMin"; break; - case EOpImageAtomicMax: out.debug << "imageAtomicMax"; break; - case EOpImageAtomicAnd: out.debug << "imageAtomicAnd"; break; - case EOpImageAtomicOr: out.debug << "imageAtomicOr"; break; - case EOpImageAtomicXor: out.debug << "imageAtomicXor"; break; - case EOpImageAtomicExchange: out.debug << "imageAtomicExchange"; break; - case EOpImageAtomicCompSwap: out.debug << "imageAtomicCompSwap"; break; - case EOpImageAtomicLoad: out.debug << "imageAtomicLoad"; break; - case EOpImageAtomicStore: out.debug << "imageAtomicStore"; break; - case EOpImageLoadLod: out.debug << "imageLoadLod"; break; - case EOpImageStoreLod: out.debug << "imageStoreLod"; break; - - case EOpTextureQuerySize: out.debug << "textureSize"; break; - case EOpTextureQueryLod: out.debug << "textureQueryLod"; break; - case EOpTextureQueryLevels: out.debug << "textureQueryLevels"; break; - case EOpTextureQuerySamples: out.debug << "textureSamples"; break; - case EOpTexture: out.debug << "texture"; break; - case EOpTextureProj: out.debug << "textureProj"; break; - case EOpTextureLod: out.debug << "textureLod"; break; - case EOpTextureOffset: out.debug << "textureOffset"; break; - case EOpTextureFetch: out.debug << "textureFetch"; break; - case EOpTextureFetchOffset: out.debug << "textureFetchOffset"; break; - case EOpTextureProjOffset: out.debug << "textureProjOffset"; break; - case EOpTextureLodOffset: out.debug << "textureLodOffset"; break; - case EOpTextureProjLod: out.debug << "textureProjLod"; break; - case EOpTextureProjLodOffset: out.debug << "textureProjLodOffset"; break; - case EOpTextureGrad: out.debug << "textureGrad"; break; - case EOpTextureGradOffset: out.debug << "textureGradOffset"; break; - case EOpTextureProjGrad: out.debug << "textureProjGrad"; break; - case EOpTextureProjGradOffset: out.debug << "textureProjGradOffset"; break; - case EOpTextureGather: out.debug << "textureGather"; break; - case EOpTextureGatherOffset: out.debug << "textureGatherOffset"; break; - case EOpTextureGatherOffsets: out.debug << "textureGatherOffsets"; break; - case EOpTextureClamp: out.debug << "textureClamp"; break; - case EOpTextureOffsetClamp: out.debug << "textureOffsetClamp"; break; - case EOpTextureGradClamp: out.debug << "textureGradClamp"; break; - case EOpTextureGradOffsetClamp: out.debug << "textureGradOffsetClamp"; break; - case EOpTextureGatherLod: out.debug << "textureGatherLod"; break; - case EOpTextureGatherLodOffset: out.debug << "textureGatherLodOffset"; break; - case EOpTextureGatherLodOffsets: out.debug << "textureGatherLodOffsets"; break; - - case EOpSparseTexture: out.debug << "sparseTexture"; break; - case EOpSparseTextureOffset: out.debug << "sparseTextureOffset"; break; - case EOpSparseTextureLod: out.debug << "sparseTextureLod"; break; - case EOpSparseTextureLodOffset: out.debug << "sparseTextureLodOffset"; break; - case EOpSparseTextureFetch: out.debug << "sparseTexelFetch"; break; - case EOpSparseTextureFetchOffset: out.debug << "sparseTexelFetchOffset"; break; - case EOpSparseTextureGrad: out.debug << "sparseTextureGrad"; break; - case EOpSparseTextureGradOffset: out.debug << "sparseTextureGradOffset"; break; - case EOpSparseTextureGather: out.debug << "sparseTextureGather"; break; - case EOpSparseTextureGatherOffset: out.debug << "sparseTextureGatherOffset"; break; - case EOpSparseTextureGatherOffsets: out.debug << "sparseTextureGatherOffsets"; break; - case EOpSparseImageLoad: out.debug << "sparseImageLoad"; break; - case EOpSparseTextureClamp: out.debug << "sparseTextureClamp"; break; - case EOpSparseTextureOffsetClamp: out.debug << "sparseTextureOffsetClamp"; break; - case EOpSparseTextureGradClamp: out.debug << "sparseTextureGradClamp"; break; - case EOpSparseTextureGradOffsetClamp: out.debug << "sparseTextureGradOffsetClam"; break; - case EOpSparseTextureGatherLod: out.debug << "sparseTextureGatherLod"; break; - case EOpSparseTextureGatherLodOffset: out.debug << "sparseTextureGatherLodOffset"; break; - case EOpSparseTextureGatherLodOffsets: out.debug << "sparseTextureGatherLodOffsets"; break; - case EOpSparseImageLoadLod: out.debug << "sparseImageLoadLod"; break; - case EOpImageSampleFootprintNV: out.debug << "imageSampleFootprintNV"; break; - case EOpImageSampleFootprintClampNV: out.debug << "imageSampleFootprintClampNV"; break; - case EOpImageSampleFootprintLodNV: out.debug << "imageSampleFootprintLodNV"; break; - case EOpImageSampleFootprintGradNV: out.debug << "imageSampleFootprintGradNV"; break; - case EOpImageSampleFootprintGradClampNV: out.debug << "mageSampleFootprintGradClampNV"; break; - case EOpAddCarry: out.debug << "addCarry"; break; - case EOpSubBorrow: out.debug << "subBorrow"; break; - case EOpUMulExtended: out.debug << "uMulExtended"; break; - case EOpIMulExtended: out.debug << "iMulExtended"; break; - case EOpBitfieldExtract: out.debug << "bitfieldExtract"; break; - case EOpBitfieldInsert: out.debug << "bitfieldInsert"; break; - - case EOpFma: out.debug << "fma"; break; - case EOpFrexp: out.debug << "frexp"; break; - case EOpLdexp: out.debug << "ldexp"; break; - - case EOpInterpolateAtSample: out.debug << "interpolateAtSample"; break; - case EOpInterpolateAtOffset: out.debug << "interpolateAtOffset"; break; - case EOpInterpolateAtVertex: out.debug << "interpolateAtVertex"; break; - - case EOpSinCos: out.debug << "sincos"; break; - case EOpGenMul: out.debug << "mul"; break; - - case EOpAllMemoryBarrierWithGroupSync: out.debug << "AllMemoryBarrierWithGroupSync"; break; - case EOpDeviceMemoryBarrier: out.debug << "DeviceMemoryBarrier"; break; - case EOpDeviceMemoryBarrierWithGroupSync: out.debug << "DeviceMemoryBarrierWithGroupSync"; break; - case EOpWorkgroupMemoryBarrier: out.debug << "WorkgroupMemoryBarrier"; break; - case EOpWorkgroupMemoryBarrierWithGroupSync: out.debug << "WorkgroupMemoryBarrierWithGroupSync"; break; - - case EOpSubgroupBarrier: out.debug << "subgroupBarrier"; break; - case EOpSubgroupMemoryBarrier: out.debug << "subgroupMemoryBarrier"; break; - case EOpSubgroupMemoryBarrierBuffer: out.debug << "subgroupMemoryBarrierBuffer"; break; - case EOpSubgroupMemoryBarrierImage: out.debug << "subgroupMemoryBarrierImage"; break; - case EOpSubgroupMemoryBarrierShared: out.debug << "subgroupMemoryBarrierShared"; break; - case EOpSubgroupElect: out.debug << "subgroupElect"; break; - case EOpSubgroupAll: out.debug << "subgroupAll"; break; - case EOpSubgroupAny: out.debug << "subgroupAny"; break; - case EOpSubgroupAllEqual: out.debug << "subgroupAllEqual"; break; - case EOpSubgroupBroadcast: out.debug << "subgroupBroadcast"; break; - case EOpSubgroupBroadcastFirst: out.debug << "subgroupBroadcastFirst"; break; - case EOpSubgroupBallot: out.debug << "subgroupBallot"; break; - case EOpSubgroupInverseBallot: out.debug << "subgroupInverseBallot"; break; - case EOpSubgroupBallotBitExtract: out.debug << "subgroupBallotBitExtract"; break; - case EOpSubgroupBallotBitCount: out.debug << "subgroupBallotBitCount"; break; - case EOpSubgroupBallotInclusiveBitCount: out.debug << "subgroupBallotInclusiveBitCount"; break; - case EOpSubgroupBallotExclusiveBitCount: out.debug << "subgroupBallotExclusiveBitCount"; break; - case EOpSubgroupBallotFindLSB: out.debug << "subgroupBallotFindLSB"; break; - case EOpSubgroupBallotFindMSB: out.debug << "subgroupBallotFindMSB"; break; - case EOpSubgroupShuffle: out.debug << "subgroupShuffle"; break; - case EOpSubgroupShuffleXor: out.debug << "subgroupShuffleXor"; break; - case EOpSubgroupShuffleUp: out.debug << "subgroupShuffleUp"; break; - case EOpSubgroupShuffleDown: out.debug << "subgroupShuffleDown"; break; - case EOpSubgroupAdd: out.debug << "subgroupAdd"; break; - case EOpSubgroupMul: out.debug << "subgroupMul"; break; - case EOpSubgroupMin: out.debug << "subgroupMin"; break; - case EOpSubgroupMax: out.debug << "subgroupMax"; break; - case EOpSubgroupAnd: out.debug << "subgroupAnd"; break; - case EOpSubgroupOr: out.debug << "subgroupOr"; break; - case EOpSubgroupXor: out.debug << "subgroupXor"; break; - case EOpSubgroupInclusiveAdd: out.debug << "subgroupInclusiveAdd"; break; - case EOpSubgroupInclusiveMul: out.debug << "subgroupInclusiveMul"; break; - case EOpSubgroupInclusiveMin: out.debug << "subgroupInclusiveMin"; break; - case EOpSubgroupInclusiveMax: out.debug << "subgroupInclusiveMax"; break; - case EOpSubgroupInclusiveAnd: out.debug << "subgroupInclusiveAnd"; break; - case EOpSubgroupInclusiveOr: out.debug << "subgroupInclusiveOr"; break; - case EOpSubgroupInclusiveXor: out.debug << "subgroupInclusiveXor"; break; - case EOpSubgroupExclusiveAdd: out.debug << "subgroupExclusiveAdd"; break; - case EOpSubgroupExclusiveMul: out.debug << "subgroupExclusiveMul"; break; - case EOpSubgroupExclusiveMin: out.debug << "subgroupExclusiveMin"; break; - case EOpSubgroupExclusiveMax: out.debug << "subgroupExclusiveMax"; break; - case EOpSubgroupExclusiveAnd: out.debug << "subgroupExclusiveAnd"; break; - case EOpSubgroupExclusiveOr: out.debug << "subgroupExclusiveOr"; break; - case EOpSubgroupExclusiveXor: out.debug << "subgroupExclusiveXor"; break; - case EOpSubgroupClusteredAdd: out.debug << "subgroupClusteredAdd"; break; - case EOpSubgroupClusteredMul: out.debug << "subgroupClusteredMul"; break; - case EOpSubgroupClusteredMin: out.debug << "subgroupClusteredMin"; break; - case EOpSubgroupClusteredMax: out.debug << "subgroupClusteredMax"; break; - case EOpSubgroupClusteredAnd: out.debug << "subgroupClusteredAnd"; break; - case EOpSubgroupClusteredOr: out.debug << "subgroupClusteredOr"; break; - case EOpSubgroupClusteredXor: out.debug << "subgroupClusteredXor"; break; - case EOpSubgroupQuadBroadcast: out.debug << "subgroupQuadBroadcast"; break; - case EOpSubgroupQuadSwapHorizontal: out.debug << "subgroupQuadSwapHorizontal"; break; - case EOpSubgroupQuadSwapVertical: out.debug << "subgroupQuadSwapVertical"; break; - case EOpSubgroupQuadSwapDiagonal: out.debug << "subgroupQuadSwapDiagonal"; break; - - case EOpSubgroupPartition: out.debug << "subgroupPartitionNV"; break; - case EOpSubgroupPartitionedAdd: out.debug << "subgroupPartitionedAddNV"; break; - case EOpSubgroupPartitionedMul: out.debug << "subgroupPartitionedMulNV"; break; - case EOpSubgroupPartitionedMin: out.debug << "subgroupPartitionedMinNV"; break; - case EOpSubgroupPartitionedMax: out.debug << "subgroupPartitionedMaxNV"; break; - case EOpSubgroupPartitionedAnd: out.debug << "subgroupPartitionedAndNV"; break; - case EOpSubgroupPartitionedOr: out.debug << "subgroupPartitionedOrNV"; break; - case EOpSubgroupPartitionedXor: out.debug << "subgroupPartitionedXorNV"; break; - case EOpSubgroupPartitionedInclusiveAdd: out.debug << "subgroupPartitionedInclusiveAddNV"; break; - case EOpSubgroupPartitionedInclusiveMul: out.debug << "subgroupPartitionedInclusiveMulNV"; break; - case EOpSubgroupPartitionedInclusiveMin: out.debug << "subgroupPartitionedInclusiveMinNV"; break; - case EOpSubgroupPartitionedInclusiveMax: out.debug << "subgroupPartitionedInclusiveMaxNV"; break; - case EOpSubgroupPartitionedInclusiveAnd: out.debug << "subgroupPartitionedInclusiveAndNV"; break; - case EOpSubgroupPartitionedInclusiveOr: out.debug << "subgroupPartitionedInclusiveOrNV"; break; - case EOpSubgroupPartitionedInclusiveXor: out.debug << "subgroupPartitionedInclusiveXorNV"; break; - case EOpSubgroupPartitionedExclusiveAdd: out.debug << "subgroupPartitionedExclusiveAddNV"; break; - case EOpSubgroupPartitionedExclusiveMul: out.debug << "subgroupPartitionedExclusiveMulNV"; break; - case EOpSubgroupPartitionedExclusiveMin: out.debug << "subgroupPartitionedExclusiveMinNV"; break; - case EOpSubgroupPartitionedExclusiveMax: out.debug << "subgroupPartitionedExclusiveMaxNV"; break; - case EOpSubgroupPartitionedExclusiveAnd: out.debug << "subgroupPartitionedExclusiveAndNV"; break; - case EOpSubgroupPartitionedExclusiveOr: out.debug << "subgroupPartitionedExclusiveOrNV"; break; - case EOpSubgroupPartitionedExclusiveXor: out.debug << "subgroupPartitionedExclusiveXorNV"; break; - - case EOpSubpassLoad: out.debug << "subpassLoad"; break; - case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break; - - case EOpColorAttachmentReadEXT: out.debug << "colorAttachmentReadEXT"; break; - - case EOpTraceNV: out.debug << "traceNV"; break; - case EOpTraceRayMotionNV: out.debug << "traceRayMotionNV"; break; - case EOpTraceKHR: out.debug << "traceRayKHR"; break; - case EOpReportIntersection: out.debug << "reportIntersectionNV"; break; - case EOpIgnoreIntersectionNV: out.debug << "ignoreIntersectionNV"; break; - case EOpIgnoreIntersectionKHR: out.debug << "ignoreIntersectionKHR"; break; - case EOpTerminateRayNV: out.debug << "terminateRayNV"; break; - case EOpTerminateRayKHR: out.debug << "terminateRayKHR"; break; - case EOpExecuteCallableNV: out.debug << "executeCallableNV"; break; - case EOpExecuteCallableKHR: out.debug << "executeCallableKHR"; break; - case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break; - case EOpEmitMeshTasksEXT: out.debug << "EmitMeshTasksEXT"; break; - case EOpSetMeshOutputsEXT: out.debug << "SetMeshOutputsEXT"; break; - - case EOpRayQueryInitialize: out.debug << "rayQueryInitializeEXT"; break; - case EOpRayQueryTerminate: out.debug << "rayQueryTerminateEXT"; break; - case EOpRayQueryGenerateIntersection: out.debug << "rayQueryGenerateIntersectionEXT"; break; - case EOpRayQueryConfirmIntersection: out.debug << "rayQueryConfirmIntersectionEXT"; break; - case EOpRayQueryProceed: out.debug << "rayQueryProceedEXT"; break; - case EOpRayQueryGetIntersectionType: out.debug << "rayQueryGetIntersectionTypeEXT"; break; - case EOpRayQueryGetRayTMin: out.debug << "rayQueryGetRayTMinEXT"; break; - case EOpRayQueryGetRayFlags: out.debug << "rayQueryGetRayFlagsEXT"; break; - case EOpRayQueryGetIntersectionT: out.debug << "rayQueryGetIntersectionTEXT"; break; - case EOpRayQueryGetIntersectionInstanceCustomIndex: out.debug << "rayQueryGetIntersectionInstanceCustomIndexEXT"; break; - case EOpRayQueryGetIntersectionInstanceId: out.debug << "rayQueryGetIntersectionInstanceIdEXT"; break; - case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: out.debug << "rayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetEXT"; break; - case EOpRayQueryGetIntersectionGeometryIndex: out.debug << "rayQueryGetIntersectionGeometryIndexEXT"; break; - case EOpRayQueryGetIntersectionPrimitiveIndex: out.debug << "rayQueryGetIntersectionPrimitiveIndexEXT"; break; - case EOpRayQueryGetIntersectionBarycentrics: out.debug << "rayQueryGetIntersectionBarycentricsEXT"; break; - case EOpRayQueryGetIntersectionFrontFace: out.debug << "rayQueryGetIntersectionFrontFaceEXT"; break; - case EOpRayQueryGetIntersectionCandidateAABBOpaque: out.debug << "rayQueryGetIntersectionCandidateAABBOpaqueEXT"; break; - case EOpRayQueryGetIntersectionObjectRayDirection: out.debug << "rayQueryGetIntersectionObjectRayDirectionEXT"; break; - case EOpRayQueryGetIntersectionObjectRayOrigin: out.debug << "rayQueryGetIntersectionObjectRayOriginEXT"; break; - case EOpRayQueryGetWorldRayDirection: out.debug << "rayQueryGetWorldRayDirectionEXT"; break; - case EOpRayQueryGetWorldRayOrigin: out.debug << "rayQueryGetWorldRayOriginEXT"; break; - case EOpRayQueryGetIntersectionObjectToWorld: out.debug << "rayQueryGetIntersectionObjectToWorldEXT"; break; - case EOpRayQueryGetIntersectionWorldToObject: out.debug << "rayQueryGetIntersectionWorldToObjectEXT"; break; - case EOpRayQueryGetIntersectionTriangleVertexPositionsEXT: out.debug << "rayQueryGetIntersectionTriangleVertexPositionsEXT"; break; - - case EOpCooperativeMatrixLoad: out.debug << "Load cooperative matrix KHR"; break; - case EOpCooperativeMatrixStore: out.debug << "Store cooperative matrix KHR"; break; - case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices KHR"; break; - case EOpCooperativeMatrixLoadNV: out.debug << "Load cooperative matrix NV"; break; - case EOpCooperativeMatrixStoreNV: out.debug << "Store cooperative matrix NV"; break; - case EOpCooperativeMatrixMulAddNV: out.debug << "MulAdd cooperative matrices NV"; break; - - case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break; - case EOpDebugPrintf: out.debug << "Debug printf"; break; - - case EOpHitObjectTraceRayNV: out.debug << "HitObjectTraceRayNV"; break; - case EOpHitObjectTraceRayMotionNV: out.debug << "HitObjectTraceRayMotionNV"; break; - case EOpHitObjectRecordHitNV: out.debug << "HitObjectRecordHitNV"; break; - case EOpHitObjectRecordHitMotionNV: out.debug << "HitObjectRecordHitMotionNV"; break; - case EOpHitObjectRecordHitWithIndexNV: out.debug << "HitObjectRecordHitWithIndexNV"; break; - case EOpHitObjectRecordHitWithIndexMotionNV: out.debug << "HitObjectRecordHitWithIndexMotionNV"; break; - case EOpHitObjectRecordMissNV: out.debug << "HitObjectRecordMissNV"; break; - case EOpHitObjectRecordMissMotionNV: out.debug << "HitObjectRecordMissMotionNV"; break; - case EOpHitObjectRecordEmptyNV: out.debug << "HitObjectRecordEmptyNV"; break; - case EOpHitObjectExecuteShaderNV: out.debug << "HitObjectExecuteShaderNV"; break; - case EOpHitObjectIsEmptyNV: out.debug << "HitObjectIsEmptyNV"; break; - case EOpHitObjectIsMissNV: out.debug << "HitObjectIsMissNV"; break; - case EOpHitObjectIsHitNV: out.debug << "HitObjectIsHitNV"; break; - case EOpHitObjectGetRayTMinNV: out.debug << "HitObjectGetRayTMinNV"; break; - case EOpHitObjectGetRayTMaxNV: out.debug << "HitObjectGetRayTMaxNV"; break; - case EOpHitObjectGetObjectRayOriginNV: out.debug << "HitObjectGetObjectRayOriginNV"; break; - case EOpHitObjectGetObjectRayDirectionNV: out.debug << "HitObjectGetObjectRayDirectionNV"; break; - case EOpHitObjectGetWorldRayOriginNV: out.debug << "HitObjectGetWorldRayOriginNV"; break; - case EOpHitObjectGetWorldRayDirectionNV: out.debug << "HitObjectGetWorldRayDirectionNV"; break; - case EOpHitObjectGetObjectToWorldNV: out.debug << "HitObjectGetObjectToWorldNV"; break; - case EOpHitObjectGetWorldToObjectNV: out.debug << "HitObjectGetWorldToObjectNV"; break; - case EOpHitObjectGetInstanceCustomIndexNV: out.debug<< "HitObjectGetInstanceCustomIndexNV"; break; - case EOpHitObjectGetInstanceIdNV: out.debug << "HitObjectGetInstaneIdNV"; break; - case EOpHitObjectGetGeometryIndexNV: out.debug << "HitObjectGetGeometryIndexNV"; break; - case EOpHitObjectGetPrimitiveIndexNV: out.debug << "HitObjectGetPrimitiveIndexNV"; break; - case EOpHitObjectGetHitKindNV: out.debug << "HitObjectGetHitKindNV"; break; - case EOpHitObjectGetAttributesNV: out.debug << "HitObjectGetAttributesNV"; break; - case EOpHitObjectGetCurrentTimeNV: out.debug << "HitObjectGetCurrentTimeNV"; break; - case EOpHitObjectGetShaderBindingTableRecordIndexNV: out.debug << "HitObjectGetShaderBindingTableRecordIndexNV"; break; - case EOpHitObjectGetShaderRecordBufferHandleNV: out.debug << "HitObjectReadShaderRecordBufferHandleNV"; break; - case EOpReorderThreadNV: out.debug << "ReorderThreadNV"; break; - case EOpFetchMicroTriangleVertexPositionNV: out.debug << "MicroTriangleVertexPositionNV"; break; - case EOpFetchMicroTriangleVertexBarycentricNV: out.debug << "MicroTriangleVertexBarycentricNV"; break; - - case EOpSpirvInst: out.debug << "spirv_instruction"; break; - case EOpStencilAttachmentReadEXT: out.debug << "stencilAttachmentReadEXT"; break; - case EOpDepthAttachmentReadEXT: out.debug << "depthAttachmentReadEXT"; break; - - default: out.debug.message(EPrefixError, "Bad aggregation op"); - } - - if (node->getOp() != EOpSequence && node->getOp() != EOpScope && node->getOp() != EOpParameters) - out.debug << " (" << node->getCompleteString() << ")"; - - out.debug << "\n"; - - return true; -} - -bool TOutputTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - - out.debug << "Test condition and select"; - out.debug << " (" << node->getCompleteString() << ")"; - - if (node->getShortCircuit() == false) - out.debug << ": no shortcircuit"; - if (node->getFlatten()) - out.debug << ": Flatten"; - if (node->getDontFlatten()) - out.debug << ": DontFlatten"; - out.debug << "\n"; - - ++depth; - - OutputTreeText(out, node, depth); - out.debug << "Condition\n"; - node->getCondition()->traverse(this); - - OutputTreeText(out, node, depth); - if (node->getTrueBlock()) { - out.debug << "true case\n"; - node->getTrueBlock()->traverse(this); - } else - out.debug << "true case is null\n"; - - if (node->getFalseBlock()) { - OutputTreeText(out, node, depth); - out.debug << "false case\n"; - node->getFalseBlock()->traverse(this); - } - - --depth; - - return false; -} - -// Print infinities and NaNs, and numbers in a portable way. -// Goals: -// - portable (across IEEE 754 platforms) -// - shows all possible IEEE values -// - shows simple numbers in a simple way, e.g., no leading/trailing 0s -// - shows all digits, no premature rounding -static void OutputDouble(TInfoSink& out, double value, TOutputTraverser::EExtraOutput extra) -{ - if (std::isinf(value)) { - if (value < 0) - out.debug << "-1.#INF"; - else - out.debug << "+1.#INF"; - } else if (std::isnan(value)) - out.debug << "1.#IND"; - else { - const int maxSize = 340; - char buf[maxSize]; - const char* format = "%f"; - if (fabs(value) > 0.0 && (fabs(value) < 1e-5 || fabs(value) > 1e12)) - format = "%-.13e"; - int len = snprintf(buf, maxSize, format, value); - assert(len < maxSize); - - // remove a leading zero in the 100s slot in exponent; it is not portable - // pattern: XX...XXXe+0XX or XX...XXXe-0XX - if (len > 5) { - if (buf[len-5] == 'e' && (buf[len-4] == '+' || buf[len-4] == '-') && buf[len-3] == '0') { - buf[len-3] = buf[len-2]; - buf[len-2] = buf[len-1]; - buf[len-1] = '\0'; - } - } - - out.debug << buf; - - switch (extra) { - case TOutputTraverser::BinaryDoubleOutput: - { - uint64_t b; - static_assert(sizeof(b) == sizeof(value), "sizeof(uint64_t) != sizeof(double)"); - memcpy(&b, &value, sizeof(b)); - - out.debug << " : "; - for (size_t i = 0; i < 8 * sizeof(value); ++i, ++b) { - out.debug << ((b & 0x8000000000000000) != 0 ? "1" : "0"); - b <<= 1; - } - break; - } - default: - break; - } - } -} - -static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const TConstUnionArray& constUnion, - TOutputTraverser::EExtraOutput extra, int depth) -{ - int size = node->getType().computeNumComponents(); - - for (int i = 0; i < size; i++) { - OutputTreeText(out, node, depth); - switch (constUnion[i].getType()) { - case EbtBool: - if (constUnion[i].getBConst()) - out.debug << "true"; - else - out.debug << "false"; - - out.debug << " (" << "const bool" << ")"; - - out.debug << "\n"; - break; - case EbtFloat: - case EbtDouble: - case EbtFloat16: - OutputDouble(out, constUnion[i].getDConst(), extra); - out.debug << "\n"; - break; - case EbtInt8: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%d (%s)", constUnion[i].getI8Const(), "const int8_t"); - - out.debug << buf << "\n"; - } - break; - case EbtUint8: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%u (%s)", constUnion[i].getU8Const(), "const uint8_t"); - - out.debug << buf << "\n"; - } - break; - case EbtInt16: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%d (%s)", constUnion[i].getI16Const(), "const int16_t"); - - out.debug << buf << "\n"; - } - break; - case EbtUint16: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%u (%s)", constUnion[i].getU16Const(), "const uint16_t"); - - out.debug << buf << "\n"; - } - break; - case EbtInt: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%d (%s)", constUnion[i].getIConst(), "const int"); - - out.debug << buf << "\n"; - } - break; - case EbtUint: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%u (%s)", constUnion[i].getUConst(), "const uint"); - - out.debug << buf << "\n"; - } - break; - case EbtInt64: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%lld (%s)", constUnion[i].getI64Const(), "const int64_t"); - - out.debug << buf << "\n"; - } - break; - case EbtUint64: - { - const int maxSize = 300; - char buf[maxSize]; - snprintf(buf, maxSize, "%llu (%s)", constUnion[i].getU64Const(), "const uint64_t"); - - out.debug << buf << "\n"; - } - break; - case EbtString: - out.debug << "\"" << constUnion[i].getSConst()->c_str() << "\"\n"; - break; - default: - out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc()); - break; - } - } -} - -void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) -{ - OutputTreeText(infoSink, node, depth); - infoSink.debug << "Constant:\n"; - - OutputConstantUnion(infoSink, node, node->getConstArray(), extraOutput, depth + 1); -} - -void TOutputTraverser::visitSymbol(TIntermSymbol* node) -{ - OutputTreeText(infoSink, node, depth); - - infoSink.debug << "'" << node->getName() << "' (" << node->getCompleteString() << ")\n"; - - if (! node->getConstArray().empty()) - OutputConstantUnion(infoSink, node, node->getConstArray(), extraOutput, depth + 1); - else if (node->getConstSubtree()) { - incrementDepth(node); - node->getConstSubtree()->traverse(this); - decrementDepth(); - } -} - -bool TOutputTraverser::visitLoop(TVisit /* visit */, TIntermLoop* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - - out.debug << "Loop with condition "; - if (! node->testFirst()) - out.debug << "not "; - out.debug << "tested first"; - - if (node->getUnroll()) - out.debug << ": Unroll"; - if (node->getDontUnroll()) - out.debug << ": DontUnroll"; - if (node->getLoopDependency()) { - out.debug << ": Dependency "; - out.debug << node->getLoopDependency(); - } - out.debug << "\n"; - - ++depth; - - OutputTreeText(infoSink, node, depth); - if (node->getTest()) { - out.debug << "Loop Condition\n"; - node->getTest()->traverse(this); - } else - out.debug << "No loop condition\n"; - - OutputTreeText(infoSink, node, depth); - if (node->getBody()) { - out.debug << "Loop Body\n"; - node->getBody()->traverse(this); - } else - out.debug << "No loop body\n"; - - if (node->getTerminal()) { - OutputTreeText(infoSink, node, depth); - out.debug << "Loop Terminal Expression\n"; - node->getTerminal()->traverse(this); - } - - --depth; - - return false; -} - -bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - - switch (node->getFlowOp()) { - case EOpKill: out.debug << "Branch: Kill"; break; - case EOpTerminateInvocation: out.debug << "Branch: TerminateInvocation"; break; - case EOpIgnoreIntersectionKHR: out.debug << "Branch: IgnoreIntersectionKHR"; break; - case EOpTerminateRayKHR: out.debug << "Branch: TerminateRayKHR"; break; - case EOpBreak: out.debug << "Branch: Break"; break; - case EOpContinue: out.debug << "Branch: Continue"; break; - case EOpReturn: out.debug << "Branch: Return"; break; - case EOpCase: out.debug << "case: "; break; - case EOpDemote: out.debug << "Demote"; break; - case EOpDefault: out.debug << "default: "; break; - default: out.debug << "Branch: Unknown Branch"; break; - } - - if (node->getExpression()) { - out.debug << " with expression\n"; - ++depth; - node->getExpression()->traverse(this); - --depth; - } else - out.debug << "\n"; - - return false; -} - -bool TOutputTraverser::visitSwitch(TVisit /* visit */, TIntermSwitch* node) -{ - TInfoSink& out = infoSink; - - OutputTreeText(out, node, depth); - out.debug << "switch"; - - if (node->getFlatten()) - out.debug << ": Flatten"; - if (node->getDontFlatten()) - out.debug << ": DontFlatten"; - out.debug << "\n"; - - OutputTreeText(out, node, depth); - out.debug << "condition\n"; - ++depth; - node->getCondition()->traverse(this); - - --depth; - OutputTreeText(out, node, depth); - out.debug << "body\n"; - ++depth; - node->getBody()->traverse(this); - - --depth; - - return false; -} - -// -// This function is the one to call externally to start the traversal. -// Individual functions can be initialized to 0 to skip processing of that -// type of node. It's children will still be processed. -// -void TIntermediate::output(TInfoSink& infoSink, bool tree) -{ - infoSink.debug << "Shader version: " << version << "\n"; - if (requestedExtensions.size() > 0) { - for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) - infoSink.debug << "Requested " << *extIt << "\n"; - } - - if (xfbMode) - infoSink.debug << "in xfb mode\n"; - - if (getSubgroupUniformControlFlow()) - infoSink.debug << "subgroup_uniform_control_flow\n"; - - switch (language) { - case EShLangVertex: - break; - - case EShLangTessControl: - infoSink.debug << "vertices = " << vertices << "\n"; - - if (inputPrimitive != ElgNone) - infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n"; - if (vertexSpacing != EvsNone) - infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n"; - if (vertexOrder != EvoNone) - infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n"; - break; - - case EShLangTessEvaluation: - infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n"; - infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n"; - infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n"; - if (pointMode) - infoSink.debug << "using point mode\n"; - break; - - case EShLangGeometry: - infoSink.debug << "invocations = " << invocations << "\n"; - infoSink.debug << "max_vertices = " << vertices << "\n"; - infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n"; - infoSink.debug << "output primitive = " << TQualifier::getGeometryString(outputPrimitive) << "\n"; - break; - - case EShLangFragment: - if (pixelCenterInteger) - infoSink.debug << "gl_FragCoord pixel center is integer\n"; - if (originUpperLeft) - infoSink.debug << "gl_FragCoord origin is upper left\n"; - if (earlyFragmentTests) - infoSink.debug << "using early_fragment_tests\n"; - if (postDepthCoverage) - infoSink.debug << "using post_depth_coverage\n"; - if (nonCoherentColorAttachmentReadEXT) - infoSink.debug << "using non_coherent_color_attachment_readEXT\n"; - if (nonCoherentDepthAttachmentReadEXT) - infoSink.debug << "using non_coherent_depth_attachment_readEXT\n"; - if (nonCoherentStencilAttachmentReadEXT) - infoSink.debug << "using non_coherent_stencil_attachment_readEXT\n"; - if (depthLayout != EldNone) - infoSink.debug << "using " << TQualifier::getLayoutDepthString(depthLayout) << "\n"; - if (blendEquations != 0) { - infoSink.debug << "using"; - // blendEquations is a mask, decode it - for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) { - if (blendEquations & (1 << be)) - infoSink.debug << " " << TQualifier::getBlendEquationString(be); - } - infoSink.debug << "\n"; - } - if (interlockOrdering != EioNone) - infoSink.debug << "interlock ordering = " << TQualifier::getInterlockOrderingString(interlockOrdering) << "\n"; - break; - - case EShLangMesh: - infoSink.debug << "max_vertices = " << vertices << "\n"; - infoSink.debug << "max_primitives = " << primitives << "\n"; - infoSink.debug << "output primitive = " << TQualifier::getGeometryString(outputPrimitive) << "\n"; - // Fall through - case EShLangTask: - // Fall through - case EShLangCompute: - infoSink.debug << "local_size = (" << localSize[0] << ", " << localSize[1] << ", " << localSize[2] << ")\n"; - { - if (localSizeSpecId[0] != TQualifier::layoutNotSet || - localSizeSpecId[1] != TQualifier::layoutNotSet || - localSizeSpecId[2] != TQualifier::layoutNotSet) { - infoSink.debug << "local_size ids = (" << - localSizeSpecId[0] << ", " << - localSizeSpecId[1] << ", " << - localSizeSpecId[2] << ")\n"; - } - } - break; - - default: - break; - } - - if (treeRoot == nullptr || ! tree) - return; - - TOutputTraverser it(infoSink); - if (getBinaryDoubleOutput()) - it.setDoubleOutput(TOutputTraverser::BinaryDoubleOutput); - treeRoot->traverse(&it); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp b/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp deleted file mode 100644 index ed853256..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/iomapper.cpp +++ /dev/null @@ -1,1714 +0,0 @@ -// -// Copyright (C) 2016-2017 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/Common.h" -#include "../Include/InfoSink.h" -#include "../Include/Types.h" - -#include "gl_types.h" -#include "iomapper.h" -#include "SymbolTable.h" - -// -// Map IO bindings. -// -// High-level algorithm for one stage: -// -// 1. Traverse all code (live+dead) to find the explicitly provided bindings. -// -// 2. Traverse (just) the live code to determine which non-provided bindings -// require auto-numbering. We do not auto-number dead ones. -// -// 3. Traverse all the code to apply the bindings: -// a. explicitly given bindings are offset according to their type -// b. implicit live bindings are auto-numbered into the holes, using -// any open binding slot. -// c. implicit dead bindings are left un-bound. -// - -namespace glslang { - -class TVarGatherTraverser : public TLiveTraverser { -public: - TVarGatherTraverser(const TIntermediate& i, bool traverseDeadCode, TVarLiveMap& inList, TVarLiveMap& outList, TVarLiveMap& uniformList) - : TLiveTraverser(i, traverseDeadCode, true, true, false) - , inputList(inList) - , outputList(outList) - , uniformList(uniformList) - { - } - - virtual void visitSymbol(TIntermSymbol* base) - { - TVarLiveMap* target = nullptr; - if (base->getQualifier().storage == EvqVaryingIn) - target = &inputList; - else if (base->getQualifier().storage == EvqVaryingOut) - target = &outputList; - else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant() && !base->getQualifier().isShaderRecord()) - target = &uniformList; - // If a global is being visited, then we should also traverse it incase it's evaluation - // ends up visiting inputs we want to tag as live - else if (base->getQualifier().storage == EvqGlobal) - addGlobalReference(base->getAccessName()); - - if (target) { - TVarEntryInfo ent = {base->getId(), base, ! traverseAll}; - ent.stage = intermediate.getStage(); - TVarLiveMap::iterator at = target->find( - ent.symbol->getAccessName()); // std::lower_bound(target->begin(), target->end(), ent, TVarEntryInfo::TOrderById()); - if (at != target->end() && at->second.id == ent.id) - at->second.live = at->second.live || ! traverseAll; // update live state - else - (*target)[ent.symbol->getAccessName()] = ent; - } - } - -private: - TVarLiveMap& inputList; - TVarLiveMap& outputList; - TVarLiveMap& uniformList; -}; - -class TVarSetTraverser : public TLiveTraverser -{ -public: - TVarSetTraverser(const TIntermediate& i, const TVarLiveMap& inList, const TVarLiveMap& outList, const TVarLiveMap& uniformList) - : TLiveTraverser(i, true, true, true, false) - , inputList(inList) - , outputList(outList) - , uniformList(uniformList) - { - } - - virtual void visitSymbol(TIntermSymbol* base) { - const TVarLiveMap* source; - if (base->getQualifier().storage == EvqVaryingIn) - source = &inputList; - else if (base->getQualifier().storage == EvqVaryingOut) - source = &outputList; - else if (base->getQualifier().isUniformOrBuffer()) - source = &uniformList; - else - return; - - TVarEntryInfo ent = { base->getId() }; - // Fix a defect, when block has no instance name, we need to find its block name - TVarLiveMap::const_iterator at = source->find(base->getAccessName()); - if (at == source->end()) - return; - - if (at->second.id != ent.id) - return; - - if (at->second.newBinding != -1) - base->getWritableType().getQualifier().layoutBinding = at->second.newBinding; - if (at->second.newSet != -1) - base->getWritableType().getQualifier().layoutSet = at->second.newSet; - if (at->second.newLocation != -1) - base->getWritableType().getQualifier().layoutLocation = at->second.newLocation; - if (at->second.newComponent != -1) - base->getWritableType().getQualifier().layoutComponent = at->second.newComponent; - if (at->second.newIndex != -1) - base->getWritableType().getQualifier().layoutIndex = at->second.newIndex; - if (at->second.upgradedToPushConstant) - base->getWritableType().getQualifier().layoutPushConstant = true; - } - - private: - const TVarLiveMap& inputList; - const TVarLiveMap& outputList; - const TVarLiveMap& uniformList; -}; - -struct TNotifyUniformAdaptor -{ - EShLanguage stage; - TIoMapResolver& resolver; - inline TNotifyUniformAdaptor(EShLanguage s, TIoMapResolver& r) - : stage(s) - , resolver(r) - { - } - - inline void operator()(std::pair& entKey) - { - resolver.notifyBinding(stage, entKey.second); - } - -private: - TNotifyUniformAdaptor& operator=(TNotifyUniformAdaptor&) = delete; -}; - -struct TNotifyInOutAdaptor -{ - EShLanguage stage; - TIoMapResolver& resolver; - inline TNotifyInOutAdaptor(EShLanguage s, TIoMapResolver& r) - : stage(s) - , resolver(r) - { - } - - inline void operator()(std::pair& entKey) - { - resolver.notifyInOut(entKey.second.stage, entKey.second); - } - -private: - TNotifyInOutAdaptor& operator=(TNotifyInOutAdaptor&) = delete; -}; - -struct TResolverUniformAdaptor { - TResolverUniformAdaptor(EShLanguage s, TIoMapResolver& r, TVarLiveMap* uniform[EShLangCount], TInfoSink& i, bool& e) - : stage(s) - , resolver(r) - , infoSink(i) - , error(e) - { - memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*))); - } - - inline void operator()(std::pair& entKey) { - TVarEntryInfo& ent = entKey.second; - ent.clearNewAssignments(); - const bool isValid = resolver.validateBinding(stage, ent); - if (isValid) { - resolver.resolveSet(ent.stage, ent); - resolver.resolveBinding(ent.stage, ent); - resolver.resolveUniformLocation(ent.stage, ent); - - if (ent.newBinding != -1) { - if (ent.newBinding >= int(TQualifier::layoutBindingEnd)) { - TString err = "mapped binding out of range: " + entKey.first; - - infoSink.info.message(EPrefixInternalError, err.c_str()); - error = true; - } - - if (ent.symbol->getQualifier().hasBinding()) { - for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) { - if (idx == ent.stage || uniformVarMap[idx] == nullptr) - continue; - auto entKey2 = uniformVarMap[idx]->find(entKey.first); - if (entKey2 != uniformVarMap[idx]->end()) { - entKey2->second.newBinding = ent.newBinding; - } - } - } - } - if (ent.newSet != -1) { - if (ent.newSet >= int(TQualifier::layoutSetEnd)) { - TString err = "mapped set out of range: " + entKey.first; - - infoSink.info.message(EPrefixInternalError, err.c_str()); - error = true; - } - if (ent.symbol->getQualifier().hasSet()) { - for (uint32_t idx = EShLangVertex; idx < EShLangCount; ++idx) { - if ((idx == stage) || (uniformVarMap[idx] == nullptr)) - continue; - auto entKey2 = uniformVarMap[idx]->find(entKey.first); - if (entKey2 != uniformVarMap[idx]->end()) { - entKey2->second.newSet = ent.newSet; - } - } - } - } - } else { - TString errorMsg = "Invalid binding: " + entKey.first; - infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); - error = true; - } - } - - inline void setStage(EShLanguage s) { stage = s; } - - EShLanguage stage; - TIoMapResolver& resolver; - TInfoSink& infoSink; - bool& error; - TVarLiveMap* uniformVarMap[EShLangCount]; -private: - TResolverUniformAdaptor& operator=(TResolverUniformAdaptor&) = delete; -}; - -struct TResolverInOutAdaptor { - TResolverInOutAdaptor(EShLanguage s, TIoMapResolver& r, TInfoSink& i, bool& e) - : stage(s) - , resolver(r) - , infoSink(i) - , error(e) - { - } - - inline void operator()(std::pair& entKey) - { - TVarEntryInfo& ent = entKey.second; - ent.clearNewAssignments(); - const bool isValid = resolver.validateInOut(ent.stage, ent); - if (isValid) { - resolver.resolveInOutLocation(stage, ent); - resolver.resolveInOutComponent(stage, ent); - resolver.resolveInOutIndex(stage, ent); - } else { - TString errorMsg; - if (ent.symbol->getType().getQualifier().semanticName != nullptr) { - errorMsg = "Invalid shader In/Out variable semantic: "; - errorMsg += ent.symbol->getType().getQualifier().semanticName; - } else { - errorMsg = "Invalid shader In/Out variable: "; - errorMsg += ent.symbol->getName(); - } - infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); - error = true; - } - } - - inline void setStage(EShLanguage s) { stage = s; } - - EShLanguage stage; - TIoMapResolver& resolver; - TInfoSink& infoSink; - bool& error; - -private: - TResolverInOutAdaptor& operator=(TResolverInOutAdaptor&) = delete; -}; - -// The class is used for reserving explicit uniform locations and ubo/ssbo/opaque bindings -// xxTODO: maybe this logic should be moved into the resolver's "validateInOut" and "validateUniform" - -struct TSymbolValidater -{ - TSymbolValidater(TIoMapResolver& r, TInfoSink& i, TVarLiveMap* in[EShLangCount], TVarLiveMap* out[EShLangCount], - TVarLiveMap* uniform[EShLangCount], bool& hadError, EProfile profile, int version) - : resolver(r) - , infoSink(i) - , hadError(hadError) - , profile(profile) - , version(version) - { - memcpy(inVarMaps, in, EShLangCount * (sizeof(TVarLiveMap*))); - memcpy(outVarMaps, out, EShLangCount * (sizeof(TVarLiveMap*))); - memcpy(uniformVarMap, uniform, EShLangCount * (sizeof(TVarLiveMap*))); - - std::map anonymousMemberMap; - std::vector usedUniformLocation; - std::vector usedUniformName; - usedUniformLocation.clear(); - usedUniformName.clear(); - for (int i = 0; i < EShLangCount; i++) { - if (uniformVarMap[i]) { - for (auto uniformVar : *uniformVarMap[i]) - { - TIntermSymbol* pSymbol = uniformVar.second.symbol; - TQualifier qualifier = uniformVar.second.symbol->getQualifier(); - TString symbolName = pSymbol->getAccessName(); - - // All the uniform needs multi-stage location check (block/default) - int uniformLocation = qualifier.layoutLocation; - - if (uniformLocation != TQualifier::layoutLocationEnd) { - // Total size of current uniform, could be block, struct or other types. - int size = TIntermediate::computeTypeUniformLocationSize(pSymbol->getType()); - - TRange locationRange(uniformLocation, uniformLocation + size - 1); - - // Combine location and component ranges - int overlapLocation = -1; - bool diffLocation = false; - - // Check for collisions, except for vertex inputs on desktop targeting OpenGL - overlapLocation = checkLocationOverlap(locationRange, usedUniformLocation, symbolName, usedUniformName, diffLocation); - - // Overlap locations of uniforms, regardless of components (multi stages) - if (overlapLocation == -1) { - usedUniformLocation.push_back(locationRange); - usedUniformName.push_back(symbolName); - } - else if (overlapLocation >= 0) { - if (diffLocation == true) { - TString err = ("Uniform location should be equal for same uniforms: " +std::to_string(overlapLocation)).c_str(); - infoSink.info.message(EPrefixInternalError, err.c_str()); - hadError = true; - break; - } - else { - TString err = ("Uniform location overlaps across stages: " + std::to_string(overlapLocation)).c_str(); - infoSink.info.message(EPrefixInternalError, err.c_str()); - hadError = true; - break; - } - } - } - - if ((uniformVar.second.symbol->getBasicType() == EbtBlock) && - IsAnonymous(uniformVar.second.symbol->getName())) - { - auto blockType = uniformVar.second.symbol->getType().getStruct(); - for (size_t memberIdx = 0; memberIdx < blockType->size(); ++memberIdx) { - auto memberName = (*blockType)[memberIdx].type->getFieldName(); - if (anonymousMemberMap.find(memberName) != anonymousMemberMap.end()) - { - if (anonymousMemberMap[memberName] != uniformVar.second.symbol->getType().getTypeName()) - { - TString err = "Invalid block member name: " + memberName; - infoSink.info.message(EPrefixInternalError, err.c_str()); - hadError = true; - break; - } - } - else - { - anonymousMemberMap[memberName] = uniformVar.second.symbol->getType().getTypeName(); - } - } - } - if (hadError) - break; - } - } - } - } - - // In case we need to new an intermediate, which costs too much - int checkLocationOverlap(const TRange& locationRange, std::vector& usedUniformLocation, const TString symbolName, std::vector& usedUniformName, bool& diffLocation) - { - for (size_t r = 0; r < usedUniformLocation.size(); ++r) { - if (usedUniformName[r] == symbolName) { - diffLocation = true; - return (usedUniformLocation[r].start == locationRange.start && - usedUniformLocation[r].last == locationRange.last) - ? -2 : std::max(locationRange.start, usedUniformLocation[r].start); - } - if (locationRange.overlap(usedUniformLocation[r])) { - // there is a collision; pick one - return std::max(locationRange.start, usedUniformLocation[r].start); - } - } - - return -1; // no collision - } - - inline void operator()(std::pair& entKey) { - TVarEntryInfo& ent1 = entKey.second; - TIntermSymbol* base = ent1.symbol; - const TType& type = ent1.symbol->getType(); - const TString& name = entKey.first; - TString mangleName1, mangleName2; - EShLanguage stage = ent1.stage; - EShLanguage preStage, currentStage, nextStage; - - preStage = EShLangCount; - for (int i = stage - 1; i >= 0; i--) { - if (inVarMaps[i] != nullptr) { - preStage = static_cast(i); - break; - } - } - currentStage = stage; - nextStage = EShLangCount; - for (int i = stage + 1; i < EShLangCount; i++) { - if (inVarMaps[i] != nullptr) { - nextStage = static_cast(i); - break; - } - } - - if (type.getQualifier().isArrayedIo(stage)) { - TType subType(type, 0); - subType.appendMangledName(mangleName1); - } else { - type.appendMangledName(mangleName1); - } - - - // basic checking that symbols match - // more extensive checking in the link stage - if (base->getQualifier().storage == EvqVaryingIn) { - // validate stage in; - if (preStage == EShLangCount) - return; - if (TSymbolTable::isBuiltInSymbol(base->getId())) - return; - if (outVarMaps[preStage] != nullptr) { - auto ent2 = outVarMaps[preStage]->find(name); - uint32_t location = base->getType().getQualifier().layoutLocation; - if (ent2 == outVarMaps[preStage]->end() && - location != glslang::TQualifier::layoutLocationEnd) { - for (auto var = outVarMaps[preStage]->begin(); var != ent2; var++) { - if (var->second.symbol->getType().getQualifier().layoutLocation == location) { - ent2 = var; - break; - } - } - } - if (ent2 != outVarMaps[preStage]->end()) { - auto& type1 = base->getType(); - auto& type2 = ent2->second.symbol->getType(); - hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false); - if (ent2->second.symbol->getType().getQualifier().isArrayedIo(preStage)) { - TType subType(ent2->second.symbol->getType(), 0); - subType.appendMangledName(mangleName2); - } else { - ent2->second.symbol->getType().appendMangledName(mangleName2); - } - - if (mangleName1 == mangleName2) { - // For ES 3.0 only, other versions have no such restrictions - // According to ES 3.0 spec: The type and presence of the interpolation qualifiers and - // storage qualifiers of variables with the same name declared in all linked shaders must - // match, otherwise the link command will fail. - if (profile == EEsProfile && version == 300) { - // Don't need to check smooth qualifier, as it uses the default interpolation mode - if (ent1.stage == EShLangFragment && type1.isBuiltIn() == false) { - if (type1.getQualifier().flat != type2.getQualifier().flat || - type1.getQualifier().nopersp != type2.getQualifier().nopersp) { - TString err = "Interpolation qualifier mismatch : " + entKey.first; - infoSink.info.message(EPrefixInternalError, err.c_str()); - hadError = true; - } - } - } - return; - } - else { - // Deal with input/output pairs where one is a block member but the other is loose, - // e.g. with ARB_separate_shader_objects - if (type1.getBasicType() == EbtBlock && - type1.isStruct() && !type2.isStruct()) { - // Iterate through block members tracking layout - glslang::TString name; - type1.getStruct()->begin()->type->appendMangledName(name); - if (name == mangleName2 - && type1.getQualifier().layoutLocation == type2.getQualifier().layoutLocation) return; - } - if (type2.getBasicType() == EbtBlock && - type2.isStruct() && !type1.isStruct()) { - // Iterate through block members tracking layout - glslang::TString name; - type2.getStruct()->begin()->type->appendMangledName(name); - if (name == mangleName1 - && type1.getQualifier().layoutLocation == type2.getQualifier().layoutLocation) return; - } - TString err = "Invalid In/Out variable type : " + entKey.first; - infoSink.info.message(EPrefixInternalError, err.c_str()); - hadError = true; - } - } - else if (!base->getType().isBuiltIn()) { - // According to spec: A link error is generated if any statically referenced input variable - // or block does not have a matching output - if (profile == EEsProfile && ent1.live) { - hadError = true; - TString errorStr = name + ": not been declare as a output variable in pre shader stage."; - infoSink.info.message(EPrefixError, errorStr.c_str()); - } - } - return; - } - } else if (base->getQualifier().storage == EvqVaryingOut) { - // validate stage out; - if (nextStage == EShLangCount) - return; - if (TSymbolTable::isBuiltInSymbol(base->getId())) - return; - if (inVarMaps[nextStage] != nullptr) { - auto ent2 = inVarMaps[nextStage]->find(name); - if (ent2 != inVarMaps[nextStage]->end()) { - if (ent2->second.symbol->getType().getQualifier().isArrayedIo(nextStage)) { - TType subType(ent2->second.symbol->getType(), 0); - subType.appendMangledName(mangleName2); - } else { - ent2->second.symbol->getType().appendMangledName(mangleName2); - } - if (mangleName1 == mangleName2) - return; - else { - TString err = "Invalid In/Out variable type : " + entKey.first; - infoSink.info.message(EPrefixInternalError, err.c_str()); - hadError = true; - } - } - return; - } - } else if (base->getQualifier().isUniformOrBuffer() && !base->getQualifier().isPushConstant()) { - // validate uniform type; - for (int i = 0; i < EShLangCount; i++) { - if (i != currentStage && outVarMaps[i] != nullptr) { - auto ent2 = uniformVarMap[i]->find(name); - if (ent2 != uniformVarMap[i]->end()) { - ent2->second.symbol->getType().appendMangledName(mangleName2); - if (mangleName1 != mangleName2) { - ent2->second.symbol->getType().sameElementType(type); - TString err = "Invalid Uniform variable type : " + entKey.first; - infoSink.info.message(EPrefixInternalError, err.c_str()); - hadError = true; - } - mangleName2.clear(); - - // validate instance name of blocks - if (hadError == false && - base->getType().getBasicType() == EbtBlock && - IsAnonymous(base->getName()) != IsAnonymous(ent2->second.symbol->getName())) { - TString err = "Matched uniform block names must also either all be lacking " - "an instance name or all having an instance name: " + entKey.first; - infoSink.info.message(EPrefixInternalError, err.c_str()); - hadError = true; - } - - // validate uniform block member qualifier and member names - auto& type1 = base->getType(); - auto& type2 = ent2->second.symbol->getType(); - if (hadError == false && base->getType().getBasicType() == EbtBlock) { - hadError = hadError || typeCheck(&type1, &type2, name.c_str(), true); - } - else { - hadError = hadError || typeCheck(&type1, &type2, name.c_str(), false); - } - } - else if (base->getBasicType() == EbtBlock) - { - if (IsAnonymous(base->getName())) - { - // The name of anonymous block member can't same with default uniform variable. - auto blockType1 = base->getType().getStruct(); - for (size_t memberIdx = 0; memberIdx < blockType1->size(); ++memberIdx) { - auto memberName = (*blockType1)[memberIdx].type->getFieldName(); - if (uniformVarMap[i]->find(memberName) != uniformVarMap[i]->end()) - { - TString err = "Invalid Uniform variable name : " + memberName; - infoSink.info.message(EPrefixInternalError, err.c_str()); - hadError = true; - break; - } - } - } - } - } - } - } - } - - TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], *uniformVarMap[EShLangCount]; - - // Use for mark current shader stage for resolver - TIoMapResolver& resolver; - TInfoSink& infoSink; - bool& hadError; - EProfile profile; - int version; - -private: - TSymbolValidater& operator=(TSymbolValidater&) = delete; - - bool qualifierCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock) - { - bool hasError = false; - const TQualifier& qualifier1 = type1->getQualifier(); - const TQualifier& qualifier2 = type2->getQualifier(); - - if (((isBlock == false) && - (type1->getQualifier().storage == EvqUniform && type2->getQualifier().storage == EvqUniform)) || - (type1->getQualifier().storage == EvqGlobal && type2->getQualifier().storage == EvqGlobal)) { - if (qualifier1.precision != qualifier2.precision) { - hasError = true; - std::string errorStr = name + ": have precision conflict cross stage."; - infoSink.info.message(EPrefixError, errorStr.c_str()); - } - if (qualifier1.hasFormat() && qualifier2.hasFormat()) { - if (qualifier1.layoutFormat != qualifier2.layoutFormat) { - hasError = true; - std::string errorStr = name + ": have layout format conflict cross stage."; - infoSink.info.message(EPrefixError, errorStr.c_str()); - } - - } - } - - if (isBlock == true) { - if (qualifier1.layoutPacking != qualifier2.layoutPacking) { - hasError = true; - std::string errorStr = name + ": have layoutPacking conflict cross stage."; - infoSink.info.message(EPrefixError, errorStr.c_str()); - } - if (qualifier1.layoutMatrix != qualifier2.layoutMatrix) { - hasError = true; - std::string errorStr = name + ": have layoutMatrix conflict cross stage."; - infoSink.info.message(EPrefixError, errorStr.c_str()); - } - if (qualifier1.layoutOffset != qualifier2.layoutOffset) { - hasError = true; - std::string errorStr = name + ": have layoutOffset conflict cross stage."; - infoSink.info.message(EPrefixError, errorStr.c_str()); - } - if (qualifier1.layoutAlign != qualifier2.layoutAlign) { - hasError = true; - std::string errorStr = name + ": have layoutAlign conflict cross stage."; - infoSink.info.message(EPrefixError, errorStr.c_str()); - } - } - - return hasError; - } - - bool typeCheck(const TType* const type1, const TType* const type2, const std::string& name, bool isBlock) - { - bool hasError = false; - if (!(type1->isStruct() && type2->isStruct())) { - hasError = hasError || qualifierCheck(type1, type2, name, isBlock); - } - else { - if (type1->getBasicType() == EbtBlock && type2->getBasicType() == EbtBlock) - isBlock = true; - const TTypeList* typeList1 = type1->getStruct(); - const TTypeList* typeList2 = type2->getStruct(); - - std::string newName = name; - size_t memberCount = typeList1->size(); - size_t index2 = 0; - for (size_t index = 0; index < memberCount; index++, index2++) { - // Skip inactive member - if (typeList1->at(index).type->getBasicType() == EbtVoid) - continue; - while (index2 < typeList2->size() && typeList2->at(index2).type->getBasicType() == EbtVoid) { - ++index2; - } - - // TypeList1 has more members in list - if (index2 == typeList2->size()) { - std::string errorStr = name + ": struct mismatch."; - infoSink.info.message(EPrefixError, errorStr.c_str()); - hasError = true; - break; - } - - if (typeList1->at(index).type->getFieldName() != typeList2->at(index2).type->getFieldName()) { - std::string errorStr = name + ": member name mismatch."; - infoSink.info.message(EPrefixError, errorStr.c_str()); - hasError = true; - } - else { - newName = typeList1->at(index).type->getFieldName().c_str(); - } - hasError = hasError || typeCheck(typeList1->at(index).type, typeList2->at(index2).type, newName, isBlock); - } - - while (index2 < typeList2->size()) - { - // TypeList2 has more members - if (typeList2->at(index2).type->getBasicType() != EbtVoid) { - std::string errorStr = name + ": struct mismatch."; - infoSink.info.message(EPrefixError, errorStr.c_str()); - hasError = true; - break; - } - ++index2; - } - } - return hasError; - } -}; - -struct TSlotCollector { - TSlotCollector(TIoMapResolver& r, TInfoSink& i) : resolver(r), infoSink(i) { } - - inline void operator()(std::pair& entKey) { - resolver.reserverStorageSlot(entKey.second, infoSink); - resolver.reserverResourceSlot(entKey.second, infoSink); - } - TIoMapResolver& resolver; - TInfoSink& infoSink; - -private: - TSlotCollector& operator=(TSlotCollector&) = delete; -}; - -TDefaultIoResolverBase::TDefaultIoResolverBase(const TIntermediate& intermediate) - : referenceIntermediate(intermediate) - , nextUniformLocation(intermediate.getUniformLocationBase()) - , nextInputLocation(0) - , nextOutputLocation(0) -{ - memset(stageMask, false, sizeof(bool) * (EShLangCount + 1)); - memset(stageIntermediates, 0, sizeof(TIntermediate*) * (EShLangCount)); - stageIntermediates[intermediate.getStage()] = &intermediate; -} - -int TDefaultIoResolverBase::getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const { - return stageIntermediates[stage] ? selectBaseBinding(stageIntermediates[stage]->getShiftBinding(res), stageIntermediates[stage]->getShiftBindingForSet(res, set)) - : selectBaseBinding(referenceIntermediate.getShiftBinding(res), referenceIntermediate.getShiftBindingForSet(res, set)); -} - -const std::vector& TDefaultIoResolverBase::getResourceSetBinding(EShLanguage stage) const { - return stageIntermediates[stage] ? stageIntermediates[stage]->getResourceSetBinding() - : referenceIntermediate.getResourceSetBinding(); -} - -bool TDefaultIoResolverBase::doAutoBindingMapping() const { return referenceIntermediate.getAutoMapBindings(); } - -bool TDefaultIoResolverBase::doAutoLocationMapping() const { return referenceIntermediate.getAutoMapLocations(); } - -TDefaultIoResolverBase::TSlotSet::iterator TDefaultIoResolverBase::findSlot(int set, int slot) { - return std::lower_bound(slots[set].begin(), slots[set].end(), slot); -} - -bool TDefaultIoResolverBase::checkEmpty(int set, int slot) { - TSlotSet::iterator at = findSlot(set, slot); - return ! (at != slots[set].end() && *at == slot); -} - -int TDefaultIoResolverBase::reserveSlot(int set, int slot, int size) { - TSlotSet::iterator at = findSlot(set, slot); - // tolerate aliasing, by not double-recording aliases - // (policy about appropriateness of the alias is higher up) - for (int i = 0; i < size; i++) { - if (at == slots[set].end() || *at != slot + i) - at = slots[set].insert(at, slot + i); - ++at; - } - return slot; -} - -int TDefaultIoResolverBase::getFreeSlot(int set, int base, int size) { - TSlotSet::iterator at = findSlot(set, base); - if (at == slots[set].end()) - return reserveSlot(set, base, size); - // look for a big enough gap - for (; at != slots[set].end(); ++at) { - if (*at - base >= size) - break; - base = *at + 1; - } - return reserveSlot(set, base, size); -} - -int TDefaultIoResolverBase::resolveSet(EShLanguage stage, TVarEntryInfo& ent) { - const TType& type = ent.symbol->getType(); - if (type.getQualifier().hasSet()) { - return ent.newSet = type.getQualifier().layoutSet; - } - // If a command line or API option requested a single descriptor set, use that (if not overrided by spaceN) - if (getResourceSetBinding(stage).size() == 1) { - return ent.newSet = atoi(getResourceSetBinding(stage)[0].c_str()); - } - return ent.newSet = 0; -} - -int TDefaultIoResolverBase::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) { - const TType& type = ent.symbol->getType(); - const char* name = ent.symbol->getAccessName().c_str(); - // kick out of not doing this - if (! doAutoLocationMapping()) { - return ent.newLocation = -1; - } - // no locations added if already present, a built-in variable, a block, or an opaque - if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock || - type.isAtomic() || type.isSpirvType() || (type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) { - return ent.newLocation = -1; - } - // no locations on blocks of built-in variables - if (type.isStruct()) { - if (type.getStruct()->size() < 1) { - return ent.newLocation = -1; - } - if ((*type.getStruct())[0].type->isBuiltIn()) { - return ent.newLocation = -1; - } - } - int location = referenceIntermediate.getUniformLocationOverride(name); - if (location != -1) { - return ent.newLocation = location; - } - location = nextUniformLocation; - nextUniformLocation += TIntermediate::computeTypeUniformLocationSize(type); - return ent.newLocation = location; -} - -int TDefaultIoResolverBase::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) { - const TType& type = ent.symbol->getType(); - // kick out of not doing this - if (! doAutoLocationMapping()) { - return ent.newLocation = -1; - } - - // no locations added if already present, a built-in variable, or a variable with SPIR-V decorate - if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getQualifier().hasSpirvDecorate()) { - return ent.newLocation = -1; - } - - // no locations on blocks of built-in variables - if (type.isStruct()) { - if (type.getStruct()->size() < 1) { - return ent.newLocation = -1; - } - if ((*type.getStruct())[0].type->isBuiltIn()) { - return ent.newLocation = -1; - } - } - // point to the right input or output location counter - int& nextLocation = type.getQualifier().isPipeInput() ? nextInputLocation : nextOutputLocation; - // Placeholder. This does not do proper cross-stage lining up, nor - // work with mixed location/no-location declarations. - int location = nextLocation; - int typeLocationSize; - // Don’t take into account the outer-most array if the stage’s - // interface is automatically an array. - typeLocationSize = computeTypeLocationSize(type, stage); - nextLocation += typeLocationSize; - return ent.newLocation = location; -} - -int TDefaultIoResolverBase::resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) { - return ent.newComponent = -1; -} - -int TDefaultIoResolverBase::resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) { return ent.newIndex = -1; } - -uint32_t TDefaultIoResolverBase::computeTypeLocationSize(const TType& type, EShLanguage stage) { - int typeLocationSize; - // Don’t take into account the outer-most array if the stage’s - // interface is automatically an array. - if (type.getQualifier().isArrayedIo(stage)) { - TType elementType(type, 0); - typeLocationSize = TIntermediate::computeTypeLocationSize(elementType, stage); - } else { - typeLocationSize = TIntermediate::computeTypeLocationSize(type, stage); - } - return typeLocationSize; -} - -//TDefaultGlslIoResolver -TResourceType TDefaultGlslIoResolver::getResourceType(const glslang::TType& type) { - if (isImageType(type)) { - return EResImage; - } - if (isTextureType(type)) { - return EResTexture; - } - if (isSsboType(type)) { - return EResSsbo; - } - if (isSamplerType(type)) { - return EResSampler; - } - if (isUboType(type)) { - return EResUbo; - } - return EResCount; -} - -TDefaultGlslIoResolver::TDefaultGlslIoResolver(const TIntermediate& intermediate) - : TDefaultIoResolverBase(intermediate) - , preStage(EShLangCount) - , currentStage(EShLangCount) -{ } - -int TDefaultGlslIoResolver::resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) { - const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getAccessName(); - if (currentStage != stage) { - preStage = currentStage; - currentStage = stage; - } - // kick out if not doing this - if (! doAutoLocationMapping()) { - return ent.newLocation = -1; - } - // expand the location to each element if the symbol is a struct or array - if (type.getQualifier().hasLocation()) { - return ent.newLocation = type.getQualifier().layoutLocation; - } - // no locations added if already present, a built-in variable, or a variable with SPIR-V decorate - if (type.isBuiltIn() || type.getQualifier().hasSpirvDecorate()) { - return ent.newLocation = -1; - } - // no locations on blocks of built-in variables - if (type.isStruct()) { - if (type.getStruct()->size() < 1) { - return ent.newLocation = -1; - } - if ((*type.getStruct())[0].type->isBuiltIn()) { - return ent.newLocation = -1; - } - } - int typeLocationSize = computeTypeLocationSize(type, stage); - int location = type.getQualifier().layoutLocation; - bool hasLocation = false; - EShLanguage keyStage(EShLangCount); - TStorageQualifier storage; - storage = EvqInOut; - if (type.getQualifier().isPipeInput()) { - // If this symbol is a input, search pre stage's out - keyStage = preStage; - } - if (type.getQualifier().isPipeOutput()) { - // If this symbol is a output, search next stage's in - keyStage = currentStage; - } - // The in/out in current stage is not declared with location, but it is possible declared - // with explicit location in other stages, find the storageSlotMap firstly to check whether - // the in/out has location - int resourceKey = buildStorageKey(keyStage, storage); - if (! storageSlotMap[resourceKey].empty()) { - TVarSlotMap::iterator iter = storageSlotMap[resourceKey].find(name); - if (iter != storageSlotMap[resourceKey].end()) { - // If interface resource be found, set it has location and this symbol's new location - // equal the symbol's explicit location declaration in pre or next stage. - // - // vs: out vec4 a; - // fs: layout(..., location = 3,...) in vec4 a; - hasLocation = true; - location = iter->second; - // if we want deal like that: - // vs: layout(location=4) out vec4 a; - // out vec4 b; - // - // fs: in vec4 a; - // layout(location = 4) in vec4 b; - // we need retraverse the map. - } - if (! hasLocation) { - // If interface resource note found, It's mean the location in two stage are both implicit declarat. - // So we should find a new slot for this interface. - // - // vs: out vec4 a; - // fs: in vec4 a; - location = getFreeSlot(resourceKey, 0, typeLocationSize); - storageSlotMap[resourceKey][name] = location; - } - } else { - // the first interface declarated in a program. - TVarSlotMap varSlotMap; - location = getFreeSlot(resourceKey, 0, typeLocationSize); - varSlotMap[name] = location; - storageSlotMap[resourceKey] = varSlotMap; - } - //Update location - return ent.newLocation = location; -} - -int TDefaultGlslIoResolver::resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) { - const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getAccessName(); - // kick out of not doing this - if (! doAutoLocationMapping()) { - return ent.newLocation = -1; - } - // expand the location to each element if the symbol is a struct or array - if (type.getQualifier().hasLocation() && (type.isStruct() || type.isArray())) { - return ent.newLocation = type.getQualifier().layoutLocation; - } else { - // no locations added if already present, a built-in variable, a block, or an opaque - if (type.getQualifier().hasLocation() || type.isBuiltIn() || type.getBasicType() == EbtBlock || - type.isAtomic() || type.isSpirvType() || - (type.containsOpaque() && referenceIntermediate.getSpv().openGl == 0)) { - return ent.newLocation = -1; - } - // no locations on blocks of built-in variables - if (type.isStruct()) { - if (type.getStruct()->size() < 1) { - return ent.newLocation = -1; - } - if ((*type.getStruct())[0].type->isBuiltIn()) { - return ent.newLocation = -1; - } - } - } - int location = referenceIntermediate.getUniformLocationOverride(name.c_str()); - if (location != -1) { - return ent.newLocation = location; - } - - int size = TIntermediate::computeTypeUniformLocationSize(type); - - // The uniform in current stage is not declared with location, but it is possible declared - // with explicit location in other stages, find the storageSlotMap firstly to check whether - // the uniform has location - bool hasLocation = false; - int resourceKey = buildStorageKey(EShLangCount, EvqUniform); - TVarSlotMap& slotMap = storageSlotMap[resourceKey]; - // Check dose shader program has uniform resource - if (! slotMap.empty()) { - // If uniform resource not empty, try find a same name uniform - TVarSlotMap::iterator iter = slotMap.find(name); - if (iter != slotMap.end()) { - // If uniform resource be found, set it has location and this symbol's new location - // equal the uniform's explicit location declaration in other stage. - // - // vs: uniform vec4 a; - // fs: layout(..., location = 3,...) uniform vec4 a; - hasLocation = true; - location = iter->second; - } - if (! hasLocation) { - // No explicit location declaration in other stage. - // So we should find a new slot for this uniform. - // - // vs: uniform vec4 a; - // fs: uniform vec4 a; - location = getFreeSlot(resourceKey, 0, computeTypeLocationSize(type, currentStage)); - storageSlotMap[resourceKey][name] = location; - } - } else { - // the first uniform declaration in a program. - TVarSlotMap varSlotMap; - location = getFreeSlot(resourceKey, 0, size); - varSlotMap[name] = location; - storageSlotMap[resourceKey] = varSlotMap; - } - return ent.newLocation = location; -} - -int TDefaultGlslIoResolver::resolveBinding(EShLanguage stage, TVarEntryInfo& ent) { - const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getAccessName(); - // On OpenGL arrays of opaque types take a separate binding for each element - int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1; - TResourceType resource = getResourceType(type); - // don't need to handle uniform symbol, it will be handled in resolveUniformLocation - if (resource == EResUbo && type.getBasicType() != EbtBlock) { - return ent.newBinding = -1; - } - // There is no 'set' qualifier in OpenGL shading language, each resource has its own - // binding name space, so remap the 'set' to resource type which make each resource - // binding is valid from 0 to MAX_XXRESOURCE_BINDINGS - int set = referenceIntermediate.getSpv().openGl != 0 ? resource : ent.newSet; - int resourceKey = set; - if (resource < EResCount) { - if (type.getQualifier().hasBinding()) { - int newBinding = reserveSlot(resourceKey, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings); - return ent.newBinding = newBinding; - - } else { - // The resource in current stage is not declared with binding, but it is possible declared - // with explicit binding in other stages, find the resourceSlotMap firstly to check whether - // the resource has binding, don't need to allocate if it already has a binding - bool hasBinding = false; - ent.newBinding = -1; // leave as -1 if it isn't set below - - if (! resourceSlotMap[resourceKey].empty()) { - TVarSlotMap::iterator iter = resourceSlotMap[resourceKey].find(name); - if (iter != resourceSlotMap[resourceKey].end()) { - hasBinding = true; - ent.newBinding = iter->second; - } - } - if (!hasBinding && (ent.live && doAutoBindingMapping())) { - // find free slot, the caller did make sure it passes all vars with binding - // first and now all are passed that do not have a binding and needs one - int binding = getFreeSlot(resourceKey, getBaseBinding(stage, resource, set), numBindings); - resourceSlotMap[resourceKey][name] = binding; - ent.newBinding = binding; - } - return ent.newBinding; - } - } - return ent.newBinding = -1; -} - -void TDefaultGlslIoResolver::beginResolve(EShLanguage stage) { - // reset stage state - if (stage == EShLangCount) - preStage = currentStage = stage; - // update stage state - else if (currentStage != stage) { - preStage = currentStage; - currentStage = stage; - } -} - -void TDefaultGlslIoResolver::endResolve(EShLanguage /*stage*/) { - // TODO nothing -} - -void TDefaultGlslIoResolver::beginCollect(EShLanguage stage) { - // reset stage state - if (stage == EShLangCount) - preStage = currentStage = stage; - // update stage state - else if (currentStage != stage) { - preStage = currentStage; - currentStage = stage; - } -} - -void TDefaultGlslIoResolver::endCollect(EShLanguage /*stage*/) { - // TODO nothing -} - -void TDefaultGlslIoResolver::reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) { - const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getAccessName(); - TStorageQualifier storage = type.getQualifier().storage; - EShLanguage stage(EShLangCount); - switch (storage) { - case EvqUniform: - if (type.getBasicType() != EbtBlock && type.getQualifier().hasLocation()) { - // - // Reserve the slots for the uniforms who has explicit location - int storageKey = buildStorageKey(EShLangCount, EvqUniform); - int location = type.getQualifier().layoutLocation; - TVarSlotMap& varSlotMap = storageSlotMap[storageKey]; - TVarSlotMap::iterator iter = varSlotMap.find(name); - if (iter == varSlotMap.end()) { - int numLocations = TIntermediate::computeTypeUniformLocationSize(type); - reserveSlot(storageKey, location, numLocations); - varSlotMap[name] = location; - } else { - // Allocate location by name for OpenGL driver, so the uniform in different - // stages should be declared with the same location - if (iter->second != location) { - TString errorMsg = "Invalid location: " + name; - infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); - hasError = true; - } - } - } - break; - case EvqVaryingIn: - case EvqVaryingOut: - // - // Reserve the slots for the inout who has explicit location - if (type.getQualifier().hasLocation()) { - stage = storage == EvqVaryingIn ? preStage : stage; - stage = storage == EvqVaryingOut ? currentStage : stage; - int storageKey = buildStorageKey(stage, EvqInOut); - int location = type.getQualifier().layoutLocation; - TVarSlotMap& varSlotMap = storageSlotMap[storageKey]; - TVarSlotMap::iterator iter = varSlotMap.find(name); - if (iter == varSlotMap.end()) { - int numLocations = TIntermediate::computeTypeUniformLocationSize(type); - reserveSlot(storageKey, location, numLocations); - varSlotMap[name] = location; - } else { - // Allocate location by name for OpenGL driver, so the uniform in different - // stages should be declared with the same location - if (iter->second != location) { - TString errorMsg = "Invalid location: " + name; - infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); - hasError = true; - } - } - } - break; - default: - break; - } -} - -void TDefaultGlslIoResolver::reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) { - const TType& type = ent.symbol->getType(); - const TString& name = ent.symbol->getAccessName(); - TResourceType resource = getResourceType(type); - int set = referenceIntermediate.getSpv().openGl != 0 ? resource : resolveSet(ent.stage, ent); - int resourceKey = set; - - if (type.getQualifier().hasBinding()) { - TVarSlotMap& varSlotMap = resourceSlotMap[resourceKey]; - TVarSlotMap::iterator iter = varSlotMap.find(name); - int binding = type.getQualifier().layoutBinding + getBaseBinding(ent.stage, resource, set); - - if (iter == varSlotMap.end()) { - // Reserve the slots for the ubo, ssbo and opaques who has explicit binding - int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1; - varSlotMap[name] = binding; - reserveSlot(resourceKey, binding, numBindings); - } else { - // Allocate binding by name for OpenGL driver, so the resource in different - // stages should be declared with the same binding - if (iter->second != binding) { - TString errorMsg = "Invalid binding: " + name; - infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); - hasError = true; - } - } - } -} - -//TDefaultGlslIoResolver end - -/* - * Basic implementation of glslang::TIoMapResolver that replaces the - * previous offset behavior. - * It does the same, uses the offsets for the corresponding uniform - * types. Also respects the EOptionAutoMapBindings flag and binds - * them if needed. - */ -/* - * Default resolver - */ -struct TDefaultIoResolver : public TDefaultIoResolverBase { - TDefaultIoResolver(const TIntermediate& intermediate) : TDefaultIoResolverBase(intermediate) { } - - bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } - - TResourceType getResourceType(const glslang::TType& type) override { - if (isImageType(type)) { - return EResImage; - } - if (isTextureType(type)) { - return EResTexture; - } - if (isSsboType(type)) { - return EResSsbo; - } - if (isSamplerType(type)) { - return EResSampler; - } - if (isUboType(type)) { - return EResUbo; - } - return EResCount; - } - - int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override { - const TType& type = ent.symbol->getType(); - const int set = getLayoutSet(type); - // On OpenGL arrays of opaque types take a seperate binding for each element - int numBindings = referenceIntermediate.getSpv().openGl != 0 && type.isSizedArray() ? type.getCumulativeArraySize() : 1; - TResourceType resource = getResourceType(type); - if (resource < EResCount) { - if (type.getQualifier().hasBinding()) { - return ent.newBinding = reserveSlot( - set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding, numBindings); - } else if (ent.live && doAutoBindingMapping()) { - // find free slot, the caller did make sure it passes all vars with binding - // first and now all are passed that do not have a binding and needs one - return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set), numBindings); - } - } - return ent.newBinding = -1; - } -}; - -#ifdef ENABLE_HLSL -/******************************************************************************** -The following IO resolver maps types in HLSL register space, as follows: - -t - for shader resource views (SRV) - TEXTURE1D - TEXTURE1DARRAY - TEXTURE2D - TEXTURE2DARRAY - TEXTURE3D - TEXTURECUBE - TEXTURECUBEARRAY - TEXTURE2DMS - TEXTURE2DMSARRAY - STRUCTUREDBUFFER - BYTEADDRESSBUFFER - BUFFER - TBUFFER - -s - for samplers - SAMPLER - SAMPLER1D - SAMPLER2D - SAMPLER3D - SAMPLERCUBE - SAMPLERSTATE - SAMPLERCOMPARISONSTATE - -u - for unordered access views (UAV) - RWBYTEADDRESSBUFFER - RWSTRUCTUREDBUFFER - APPENDSTRUCTUREDBUFFER - CONSUMESTRUCTUREDBUFFER - RWBUFFER - RWTEXTURE1D - RWTEXTURE1DARRAY - RWTEXTURE2D - RWTEXTURE2DARRAY - RWTEXTURE3D - -b - for constant buffer views (CBV) - CBUFFER - CONSTANTBUFFER - ********************************************************************************/ -struct TDefaultHlslIoResolver : public TDefaultIoResolverBase { - TDefaultHlslIoResolver(const TIntermediate& intermediate) : TDefaultIoResolverBase(intermediate) { } - - bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } - - TResourceType getResourceType(const glslang::TType& type) override { - if (isUavType(type)) { - return EResUav; - } - if (isSrvType(type)) { - return EResTexture; - } - if (isSamplerType(type)) { - return EResSampler; - } - if (isUboType(type)) { - return EResUbo; - } - return EResCount; - } - - int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) override { - const TType& type = ent.symbol->getType(); - const int set = getLayoutSet(type); - TResourceType resource = getResourceType(type); - if (resource < EResCount) { - if (type.getQualifier().hasBinding()) { - return ent.newBinding = reserveSlot(set, getBaseBinding(stage, resource, set) + type.getQualifier().layoutBinding); - } else if (ent.live && doAutoBindingMapping()) { - // find free slot, the caller did make sure it passes all vars with binding - // first and now all are passed that do not have a binding and needs one - return ent.newBinding = getFreeSlot(set, getBaseBinding(stage, resource, set)); - } - } - return ent.newBinding = -1; - } -}; -#endif - -// Map I/O variables to provided offsets, and make bindings for -// unbound but live variables. -// -// Returns false if the input is too malformed to do this. -bool TIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) { - bool somethingToDo = ! intermediate.getResourceSetBinding().empty() || intermediate.getAutoMapBindings() || - intermediate.getAutoMapLocations(); - // Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce - // unnecessary or insignificant for-loop operation after 'somethingToDo' have been true. - for (int res = 0; (res < EResCount && !somethingToDo); ++res) { - somethingToDo = somethingToDo || (intermediate.getShiftBinding(TResourceType(res)) != 0) || - intermediate.hasShiftBindingForSet(TResourceType(res)); - } - if (! somethingToDo && resolver == nullptr) - return true; - if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive()) - return false; - TIntermNode* root = intermediate.getTreeRoot(); - if (root == nullptr) - return false; - // if no resolver is provided, use the default resolver with the given shifts and auto map settings - TDefaultIoResolver defaultResolver(intermediate); -#ifdef ENABLE_HLSL - TDefaultHlslIoResolver defaultHlslResolver(intermediate); - if (resolver == nullptr) { - // TODO: use a passed in IO mapper for this - if (intermediate.usingHlslIoMapping()) - resolver = &defaultHlslResolver; - else - resolver = &defaultResolver; - } -#else - resolver = &defaultResolver; -#endif - resolver->addStage(stage, intermediate); - - TVarLiveMap inVarMap, outVarMap, uniformVarMap; - TVarLiveVector inVector, outVector, uniformVector; - TVarGatherTraverser iter_binding_all(intermediate, true, inVarMap, outVarMap, uniformVarMap); - TVarGatherTraverser iter_binding_live(intermediate, false, inVarMap, outVarMap, uniformVarMap); - root->traverse(&iter_binding_all); - iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str()); - while (! iter_binding_live.destinations.empty()) { - TIntermNode* destination = iter_binding_live.destinations.back(); - iter_binding_live.destinations.pop_back(); - destination->traverse(&iter_binding_live); - } - - // sort entries by priority. see TVarEntryInfo::TOrderByPriority for info. - for (auto& var : inVarMap) { inVector.push_back(var); } - std::sort(inVector.begin(), inVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { - return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); - }); - for (auto& var : outVarMap) { outVector.push_back(var); } - std::sort(outVector.begin(), outVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { - return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); - }); - for (auto& var : uniformVarMap) { uniformVector.push_back(var); } - std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { - return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); - }); - bool hadError = false; - TVarLiveMap* dummyUniformVarMap[EShLangCount] = {}; - TNotifyInOutAdaptor inOutNotify(stage, *resolver); - TNotifyUniformAdaptor uniformNotify(stage, *resolver); - TResolverUniformAdaptor uniformResolve(stage, *resolver, dummyUniformVarMap, infoSink, hadError); - TResolverInOutAdaptor inOutResolve(stage, *resolver, infoSink, hadError); - resolver->beginNotifications(stage); - std::for_each(inVector.begin(), inVector.end(), inOutNotify); - std::for_each(outVector.begin(), outVector.end(), inOutNotify); - std::for_each(uniformVector.begin(), uniformVector.end(), uniformNotify); - resolver->endNotifications(stage); - resolver->beginResolve(stage); - for (auto& var : inVector) { inOutResolve(var); } - std::for_each(inVector.begin(), inVector.end(), [&inVarMap](TVarLivePair p) { - auto at = inVarMap.find(p.second.symbol->getAccessName()); - if (at != inVarMap.end() && p.second.id == at->second.id) - at->second = p.second; - }); - for (auto& var : outVector) { inOutResolve(var); } - std::for_each(outVector.begin(), outVector.end(), [&outVarMap](TVarLivePair p) { - auto at = outVarMap.find(p.second.symbol->getAccessName()); - if (at != outVarMap.end() && p.second.id == at->second.id) - at->second = p.second; - }); - std::for_each(uniformVector.begin(), uniformVector.end(), uniformResolve); - std::for_each(uniformVector.begin(), uniformVector.end(), [&uniformVarMap](TVarLivePair p) { - auto at = uniformVarMap.find(p.second.symbol->getAccessName()); - if (at != uniformVarMap.end() && p.second.id == at->second.id) - at->second = p.second; - }); - resolver->endResolve(stage); - if (!hadError) { - TVarSetTraverser iter_iomap(intermediate, inVarMap, outVarMap, uniformVarMap); - root->traverse(&iter_iomap); - } - return !hadError; -} - -// Map I/O variables to provided offsets, and make bindings for -// unbound but live variables. -// -// Returns false if the input is too malformed to do this. -bool TGlslIoMapper::addStage(EShLanguage stage, TIntermediate& intermediate, TInfoSink& infoSink, TIoMapResolver* resolver) { - bool somethingToDo = !intermediate.getResourceSetBinding().empty() || - intermediate.getAutoMapBindings() || - intermediate.getAutoMapLocations(); - - // Profile and version are use for symbol validate. - profile = intermediate.getProfile(); - version = intermediate.getVersion(); - - // Restrict the stricter condition to further check 'somethingToDo' only if 'somethingToDo' has not been set, reduce - // unnecessary or insignificant for-loop operation after 'somethingToDo' have been true. - for (int res = 0; (res < EResCount && !somethingToDo); ++res) { - somethingToDo = somethingToDo || (intermediate.getShiftBinding(TResourceType(res)) != 0) || - intermediate.hasShiftBindingForSet(TResourceType(res)); - } - if (! somethingToDo && resolver == nullptr) { - return true; - } - if (intermediate.getNumEntryPoints() != 1 || intermediate.isRecursive()) { - return false; - } - TIntermNode* root = intermediate.getTreeRoot(); - if (root == nullptr) { - return false; - } - // if no resolver is provided, use the default resolver with the given shifts and auto map settings - TDefaultGlslIoResolver defaultResolver(intermediate); -#ifdef ENABLE_HLSL - TDefaultHlslIoResolver defaultHlslResolver(intermediate); - if (resolver == nullptr) { - // TODO: use a passed in IO mapper for this - if (intermediate.usingHlslIoMapping()) - resolver = &defaultHlslResolver; - else - resolver = &defaultResolver; - } -#else - if (resolver == nullptr) { - resolver = &defaultResolver; - } -#endif - resolver->addStage(stage, intermediate); - inVarMaps[stage] = new TVarLiveMap(); outVarMaps[stage] = new TVarLiveMap(); uniformVarMap[stage] = new TVarLiveMap(); - TVarGatherTraverser iter_binding_all(intermediate, true, *inVarMaps[stage], *outVarMaps[stage], - *uniformVarMap[stage]); - TVarGatherTraverser iter_binding_live(intermediate, false, *inVarMaps[stage], *outVarMaps[stage], - *uniformVarMap[stage]); - root->traverse(&iter_binding_all); - iter_binding_live.pushFunction(intermediate.getEntryPointMangledName().c_str()); - while (! iter_binding_live.destinations.empty()) { - TIntermNode* destination = iter_binding_live.destinations.back(); - iter_binding_live.destinations.pop_back(); - destination->traverse(&iter_binding_live); - } - - TNotifyInOutAdaptor inOutNotify(stage, *resolver); - TNotifyUniformAdaptor uniformNotify(stage, *resolver); - // Resolve current stage input symbol location with previous stage output here, - // uniform symbol, ubo, ssbo and opaque symbols are per-program resource, - // will resolve uniform symbol location and ubo/ssbo/opaque binding in doMap() - resolver->beginNotifications(stage); - std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), inOutNotify); - std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), inOutNotify); - std::for_each(uniformVarMap[stage]->begin(), uniformVarMap[stage]->end(), uniformNotify); - resolver->endNotifications(stage); - TSlotCollector slotCollector(*resolver, infoSink); - resolver->beginCollect(stage); - std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), slotCollector); - std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), slotCollector); - std::for_each(uniformVarMap[stage]->begin(), uniformVarMap[stage]->end(), slotCollector); - resolver->endCollect(stage); - intermediates[stage] = &intermediate; - return !hadError; -} - -bool TGlslIoMapper::doMap(TIoMapResolver* resolver, TInfoSink& infoSink) { - resolver->endResolve(EShLangCount); - if (!hadError) { - //Resolve uniform location, ubo/ssbo/opaque bindings across stages - TResolverUniformAdaptor uniformResolve(EShLangCount, *resolver, uniformVarMap, infoSink, hadError); - TResolverInOutAdaptor inOutResolve(EShLangCount, *resolver, infoSink, hadError); - TSymbolValidater symbolValidater(*resolver, infoSink, inVarMaps, - outVarMaps, uniformVarMap, hadError, profile, version); - - TVarLiveVector inVectors[EShLangCount]; - TVarLiveVector outVectors[EShLangCount]; - TVarLiveVector uniformVector; - - resolver->beginResolve(EShLangCount); - for (int stage = EShLangVertex; stage < EShLangCount; stage++) { - if (inVarMaps[stage] != nullptr) { - inOutResolve.setStage(EShLanguage(stage)); - - // copy vars into a sorted list - std::for_each(inVarMaps[stage]->begin(), inVarMaps[stage]->end(), - [&inVectors, stage](TVarLivePair p) { inVectors[stage].push_back(p); }); - std::sort(inVectors[stage].begin(), inVectors[stage].end(), - [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { - return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); - }); - - std::for_each(outVarMaps[stage]->begin(), outVarMaps[stage]->end(), - [&outVectors, stage](TVarLivePair p) { outVectors[stage].push_back(p); }); - std::sort(outVectors[stage].begin(), outVectors[stage].end(), - [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { - return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); - }); - - for (auto& var : inVectors[stage]) { symbolValidater(var); } - for (auto& var : inVectors[stage]) { inOutResolve(var); } - for (auto& var : outVectors[stage]) { symbolValidater(var); } - for (auto& var : outVectors[stage]) { inOutResolve(var); } - - // copy results back into maps - std::for_each(inVectors[stage].begin(), inVectors[stage].end(), - [this, stage](TVarLivePair p) { - auto at = inVarMaps[stage]->find(p.first); - if (at != inVarMaps[stage]->end()) - at->second = p.second; - }); - - std::for_each(outVectors[stage].begin(), outVectors[stage].end(), - [this, stage](TVarLivePair p) { - auto at = outVarMaps[stage]->find(p.first); - if (at != outVarMaps[stage]->end()) - at->second = p.second; - }); - - } - if (uniformVarMap[stage] != nullptr) { - uniformResolve.setStage(EShLanguage(stage)); - for (auto& var : *(uniformVarMap[stage])) { uniformVector.push_back(var); } - } - } - std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { - return TVarEntryInfo::TOrderByPriorityAndLive()(p1.second, p2.second); - }); - for (auto& var : uniformVector) { symbolValidater(var); } - for (auto& var : uniformVector) { uniformResolve(var); } - std::sort(uniformVector.begin(), uniformVector.end(), [](const TVarLivePair& p1, const TVarLivePair& p2) -> bool { - return TVarEntryInfo::TOrderByPriority()(p1.second, p2.second); - }); - resolver->endResolve(EShLangCount); - if (autoPushConstantBlockName.length()) { - bool upgraded = false; - for (size_t stage = 0; stage < EShLangCount; stage++) { - if (intermediates[stage] != nullptr) { - TVarLiveMap** pUniformVarMap = uniformResolve.uniformVarMap; - auto at = pUniformVarMap[stage]->find(autoPushConstantBlockName); - if (at == pUniformVarMap[stage]->end()) - continue; - TQualifier& qualifier = at->second.symbol->getQualifier(); - if (!qualifier.isUniform()) - continue; - TType& t = at->second.symbol->getWritableType(); - int size, stride; - TIntermediate::getBaseAlignment(t, size, stride, autoPushConstantBlockPacking, - qualifier.layoutMatrix == ElmRowMajor); - if (size <= int(autoPushConstantMaxSize)) { - qualifier.setBlockStorage(EbsPushConstant); - qualifier.layoutPacking = autoPushConstantBlockPacking; - // Push constants don't have set/binding etc. decorations, remove those. - qualifier.layoutSet = TQualifier::layoutSetEnd; - at->second.clearNewAssignments(); - - upgraded = true; - } - } - } - // If it's been upgraded to push_constant, then set the flag so when its traversed - // in the next for loop, all references to this symbol will get their flag changed. - // so it doesn't get a set/binding assigned to it. - if (upgraded) { - std::for_each(uniformVector.begin(), uniformVector.end(), - [this](TVarLivePair& p) { - if (p.first == autoPushConstantBlockName) { - p.second.upgradedToPushConstant = true; - } - }); - } - } - for (size_t stage = 0; stage < EShLangCount; stage++) { - if (intermediates[stage] != nullptr) { - // traverse each stage, set new location to each input/output and unifom symbol, set new binding to - // ubo, ssbo and opaque symbols. Assign push_constant upgrades as well. - TVarLiveMap** pUniformVarMap = uniformResolve.uniformVarMap; - std::for_each(uniformVector.begin(), uniformVector.end(), [pUniformVarMap, stage](TVarLivePair p) { - auto at = pUniformVarMap[stage]->find(p.second.symbol->getAccessName()); - if (at != pUniformVarMap[stage]->end() && at->second.id == p.second.id){ - if (p.second.upgradedToPushConstant) { - at->second.upgradedToPushConstant = true; - } else { - int resolvedBinding = at->second.newBinding; - at->second = p.second; - if (resolvedBinding > 0) - at->second.newBinding = resolvedBinding; - } - } - }); - TVarSetTraverser iter_iomap(*intermediates[stage], *inVarMaps[stage], *outVarMaps[stage], - *uniformResolve.uniformVarMap[stage]); - intermediates[stage]->getTreeRoot()->traverse(&iter_iomap); - } - } - return !hadError; - } else { - return false; - } -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/iomapper.h b/3rdparty/glslang/glslang/MachineIndependent/iomapper.h deleted file mode 100644 index 35babbce..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/iomapper.h +++ /dev/null @@ -1,359 +0,0 @@ -// -// Copyright (C) 2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _IOMAPPER_INCLUDED -#define _IOMAPPER_INCLUDED - -#include -#include "LiveTraverser.h" -#include -#include -// -// A reflection database and its interface, consistent with the OpenGL API reflection queries. -// - -class TInfoSink; - -namespace glslang { - -class TIntermediate; -struct TVarEntryInfo { - long long id; - TIntermSymbol* symbol; - bool live; - bool upgradedToPushConstant; - int newBinding; - int newSet; - int newLocation; - int newComponent; - int newIndex; - EShLanguage stage; - - void clearNewAssignments() { - upgradedToPushConstant = false; - newBinding = -1; - newSet = -1; - newLocation = -1; - newComponent = -1; - newIndex = -1; - } - - struct TOrderById { - inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; } - }; - - struct TOrderByPriority { - // ordering: - // 1) has both binding and set - // 2) has binding but no set - // 3) has no binding but set - // 4) has no binding and no set - inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { - const TQualifier& lq = l.symbol->getQualifier(); - const TQualifier& rq = r.symbol->getQualifier(); - - // simple rules: - // has binding gives 2 points - // has set gives 1 point - // who has the most points is more important. - int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0); - int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0); - - if (lPoints == rPoints) - return l.id < r.id; - return lPoints > rPoints; - } - }; - - struct TOrderByPriorityAndLive { - // ordering: - // 1) do live variables first - // 2) has both binding and set - // 3) has binding but no set - // 4) has no binding but set - // 5) has no binding and no set - inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { - - const TQualifier& lq = l.symbol->getQualifier(); - const TQualifier& rq = r.symbol->getQualifier(); - - // simple rules: - // has binding gives 2 points - // has set gives 1 point - // who has the most points is more important. - int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0); - int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0); - - if (l.live != r.live) - return l.live > r.live; - - if (lPoints != rPoints) - return lPoints > rPoints; - - return l.id < r.id; - } - }; -}; - -// Base class for shared TIoMapResolver services, used by several derivations. -struct TDefaultIoResolverBase : public glslang::TIoMapResolver { -public: - TDefaultIoResolverBase(const TIntermediate& intermediate); - typedef std::vector TSlotSet; - typedef std::unordered_map TSlotSetMap; - - // grow the reflection stage by stage - void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {} - void notifyInOut(EShLanguage, TVarEntryInfo& /*ent*/) override {} - void beginNotifications(EShLanguage) override {} - void endNotifications(EShLanguage) override {} - void beginResolve(EShLanguage) override {} - void endResolve(EShLanguage) override {} - void beginCollect(EShLanguage) override {} - void endCollect(EShLanguage) override {} - void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} - void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} - int getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const; - const std::vector& getResourceSetBinding(EShLanguage stage) const; - virtual TResourceType getResourceType(const glslang::TType& type) = 0; - bool doAutoBindingMapping() const; - bool doAutoLocationMapping() const; - TSlotSet::iterator findSlot(int set, int slot); - bool checkEmpty(int set, int slot); - bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } - int reserveSlot(int set, int slot, int size = 1); - int getFreeSlot(int set, int base, int size = 1); - int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override; - int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; - int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; - int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override; - int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override; - void addStage(EShLanguage stage, TIntermediate& stageIntermediate) override { - if (stage < EShLangCount) { - stageMask[stage] = true; - stageIntermediates[stage] = &stageIntermediate; - } - } - uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage); - - TSlotSetMap slots; - bool hasError = false; - -protected: - TDefaultIoResolverBase(TDefaultIoResolverBase&); - TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&); - const TIntermediate& referenceIntermediate; - int nextUniformLocation; - int nextInputLocation; - int nextOutputLocation; - bool stageMask[EShLangCount + 1]; - const TIntermediate* stageIntermediates[EShLangCount]; - - // Return descriptor set specific base if there is one, and the generic base otherwise. - int selectBaseBinding(int base, int descriptorSetBase) const { - return descriptorSetBase != -1 ? descriptorSetBase : base; - } - - static int getLayoutSet(const glslang::TType& type) { - if (type.getQualifier().hasSet()) - return type.getQualifier().layoutSet; - else - return 0; - } - - static bool isSamplerType(const glslang::TType& type) { - return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler(); - } - - static bool isTextureType(const glslang::TType& type) { - return (type.getBasicType() == glslang::EbtSampler && - (type.getSampler().isTexture() || type.getSampler().isSubpass())); - } - - static bool isUboType(const glslang::TType& type) { - return type.getQualifier().storage == EvqUniform; - } - - static bool isImageType(const glslang::TType& type) { - return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage(); - } - - static bool isSsboType(const glslang::TType& type) { - return type.getQualifier().storage == EvqBuffer; - } - - // Return true if this is a SRV (shader resource view) type: - static bool isSrvType(const glslang::TType& type) { - return isTextureType(type) || type.getQualifier().storage == EvqBuffer; - } - - // Return true if this is a UAV (unordered access view) type: - static bool isUavType(const glslang::TType& type) { - if (type.getQualifier().isReadOnly()) - return false; - return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) || - (type.getQualifier().storage == EvqBuffer); - } -}; - -// Default I/O resolver for OpenGL -struct TDefaultGlslIoResolver : public TDefaultIoResolverBase { -public: - typedef std::map TVarSlotMap; // - typedef std::map TSlotMap; // - TDefaultGlslIoResolver(const TIntermediate& intermediate); - bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; } - TResourceType getResourceType(const glslang::TType& type) override; - int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; - int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override; - int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override; - void beginResolve(EShLanguage /*stage*/) override; - void endResolve(EShLanguage stage) override; - void beginCollect(EShLanguage) override; - void endCollect(EShLanguage) override; - void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; - void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override; - // in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol. - // We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage. - // if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key. - // Note: both stage and type must less then 0xffff. - int buildStorageKey(EShLanguage stage, TStorageQualifier type) { - assert(static_cast(stage) <= 0x0000ffff && static_cast(type) <= 0x0000ffff); - return (stage << 16) | type; - } - -protected: - // Use for mark pre stage, to get more interface symbol information. - EShLanguage preStage; - // Use for mark current shader stage for resolver - EShLanguage currentStage; - // Slot map for storage resource(location of uniform and interface symbol) It's a program share slot - TSlotMap resourceSlotMap; - // Slot map for other resource(image, ubo, ssbo), It's a program share slot. - TSlotMap storageSlotMap; -}; - -typedef std::map TVarLiveMap; - -// override function "operator=", if a vector being sort, -// when use vc++, the sort function will call : -// pair& operator=(const pair<_Other1, _Other2>& _Right) -// { -// first = _Right.first; -// second = _Right.second; -// return (*this); -// } -// that will make a const type handing on left. -// override this function can avoid a compiler error. -// In the future, if the vc++ compiler can handle such a situation, -// this part of the code will be removed. -struct TVarLivePair : std::pair { - TVarLivePair(const std::pair& _Right) : pair(_Right.first, _Right.second) {} - TVarLivePair& operator=(const TVarLivePair& _Right) { - const_cast(first) = _Right.first; - second = _Right.second; - return (*this); - } - TVarLivePair(const TVarLivePair& src) : pair(src) { } -}; -typedef std::vector TVarLiveVector; - -// I/O mapper -class TIoMapper { -public: - TIoMapper() {} - virtual ~TIoMapper() {} - // grow the reflection stage by stage - bool virtual addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*); - bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; } -}; - -// I/O mapper for GLSL -class TGlslIoMapper : public TIoMapper { -public: - TGlslIoMapper() { - memset(inVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1)); - memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1)); - memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1)); - memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1)); - profile = ENoProfile; - version = 0; - autoPushConstantMaxSize = 128; - autoPushConstantBlockPacking = ElpStd430; - } - virtual ~TGlslIoMapper() { - for (size_t stage = 0; stage < EShLangCount; stage++) { - if (inVarMaps[stage] != nullptr) { - delete inVarMaps[stage]; - inVarMaps[stage] = nullptr; - } - if (outVarMaps[stage] != nullptr) { - delete outVarMaps[stage]; - outVarMaps[stage] = nullptr; - } - if (uniformVarMap[stage] != nullptr) { - delete uniformVarMap[stage]; - uniformVarMap[stage] = nullptr; - } - if (intermediates[stage] != nullptr) - intermediates[stage] = nullptr; - } - } - // If set, the uniform block with the given name will be changed to be backed by - // push_constant if it's size is <= maxSize - void setAutoPushConstantBlock(const char* name, unsigned int maxSize, TLayoutPacking packing) { - autoPushConstantBlockName = name; - autoPushConstantMaxSize = maxSize; - autoPushConstantBlockPacking = packing; - } - // grow the reflection stage by stage - bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override; - bool doMap(TIoMapResolver*, TInfoSink&) override; - TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount], - *uniformVarMap[EShLangCount]; - TIntermediate* intermediates[EShLangCount]; - bool hadError = false; - EProfile profile; - int version; - -private: - TString autoPushConstantBlockName; - unsigned int autoPushConstantMaxSize; - TLayoutPacking autoPushConstantBlockPacking; -}; - -} // end namespace glslang - -#endif // _IOMAPPER_INCLUDED diff --git a/3rdparty/glslang/glslang/MachineIndependent/limits.cpp b/3rdparty/glslang/glslang/MachineIndependent/limits.cpp deleted file mode 100644 index 4404beca..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/limits.cpp +++ /dev/null @@ -1,198 +0,0 @@ -// -// Copyright (C) 2013 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Do sub tree walks for -// 1) inductive loop bodies to see if the inductive variable is modified -// 2) array-index expressions to see if they are "constant-index-expression" -// -// These are per Appendix A of ES 2.0: -// -// "Within the body of the loop, the loop index is not statically assigned to nor is it used as the -// argument to a function out or inout parameter." -// -// "The following are constant-index-expressions: -// - Constant expressions -// - Loop indices as defined in section 4 -// - Expressions composed of both of the above" -// -// N.B.: assuming the last rule excludes function calls -// - -#include "ParseHelper.h" - -namespace glslang { - -// -// The inductive loop-body traverser. -// -// Just look at things that might modify the loop index. -// - -class TInductiveTraverser : public TIntermTraverser { -public: - TInductiveTraverser(long long id, TSymbolTable& st) - : loopId(id), symbolTable(st), bad(false) { } - - virtual bool visitBinary(TVisit, TIntermBinary* node); - virtual bool visitUnary(TVisit, TIntermUnary* node); - virtual bool visitAggregate(TVisit, TIntermAggregate* node); - - long long loopId; // unique ID of the symbol that's the loop inductive variable - TSymbolTable& symbolTable; - bool bad; - TSourceLoc badLoc; - -protected: - TInductiveTraverser(TInductiveTraverser&); - TInductiveTraverser& operator=(TInductiveTraverser&); -}; - -// check binary operations for those modifying the loop index -bool TInductiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node) -{ - if (node->modifiesState() && node->getLeft()->getAsSymbolNode() && - node->getLeft()->getAsSymbolNode()->getId() == loopId) { - bad = true; - badLoc = node->getLoc(); - } - - return true; -} - -// check unary operations for those modifying the loop index -bool TInductiveTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node) -{ - if (node->modifiesState() && node->getOperand()->getAsSymbolNode() && - node->getOperand()->getAsSymbolNode()->getId() == loopId) { - bad = true; - badLoc = node->getLoc(); - } - - return true; -} - -// check function calls for arguments modifying the loop index -bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node) -{ - if (node->getOp() == EOpFunctionCall) { - // see if an out or inout argument is the loop index - const TIntermSequence& args = node->getSequence(); - for (int i = 0; i < (int)args.size(); ++i) { - if (args[i]->getAsSymbolNode() && args[i]->getAsSymbolNode()->getId() == loopId) { - TSymbol* function = symbolTable.find(node->getName()); - const TType* type = (*function->getAsFunction())[i].type; - if (type->getQualifier().storage == EvqOut || - type->getQualifier().storage == EvqInOut) { - bad = true; - badLoc = node->getLoc(); - } - } - } - } - - return true; -} - -// -// External function to call for loop check. -// -void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, long long loopId, TSymbolTable& symbolTable) -{ - TInductiveTraverser it(loopId, symbolTable); - - if (body == nullptr) - return; - - body->traverse(&it); - - if (it.bad) - error(it.badLoc, "inductive loop index modified", "limitations", ""); -} - -// -// The "constant-index-expression" tranverser. -// -// Just look at things that can form an index. -// - -class TIndexTraverser : public TIntermTraverser { -public: - TIndexTraverser(const TIdSetType& ids) : inductiveLoopIds(ids), bad(false) { } - virtual void visitSymbol(TIntermSymbol* symbol); - virtual bool visitAggregate(TVisit, TIntermAggregate* node); - const TIdSetType& inductiveLoopIds; - bool bad; - TSourceLoc badLoc; - -protected: - TIndexTraverser(TIndexTraverser&); - TIndexTraverser& operator=(TIndexTraverser&); -}; - -// make sure symbols are inductive-loop indexes -void TIndexTraverser::visitSymbol(TIntermSymbol* symbol) -{ - if (inductiveLoopIds.find(symbol->getId()) == inductiveLoopIds.end()) { - bad = true; - badLoc = symbol->getLoc(); - } -} - -// check for function calls, assuming they are bad; spec. doesn't really say -bool TIndexTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node) -{ - if (node->getOp() == EOpFunctionCall) { - bad = true; - badLoc = node->getLoc(); - } - - return true; -} - -// -// External function to call for loop check. -// -void TParseContext::constantIndexExpressionCheck(TIntermNode* index) -{ - TIndexTraverser it(inductiveLoopIds); - - index->traverse(&it); - - if (it.bad) - error(it.badLoc, "Non-constant-index-expression", "limitations", ""); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp b/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp deleted file mode 100644 index d69300b8..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/linkValidate.cpp +++ /dev/null @@ -1,2386 +0,0 @@ -// -// Copyright (C) 2013 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Do link-time merging and validation of intermediate representations. -// -// Basic model is that during compilation, each compilation unit (shader) is -// compiled into one TIntermediate instance. Then, at link time, multiple -// units for the same stage can be merged together, which can generate errors. -// Then, after all merging, a single instance of TIntermediate represents -// the whole stage. A final error check can be done on the resulting stage, -// even if no merging was done (i.e., the stage was only one compilation unit). -// - -#include "localintermediate.h" -#include "../Include/InfoSink.h" -#include "SymbolTable.h" - -namespace glslang { - -// -// Link-time error emitter. -// -void TIntermediate::error(TInfoSink& infoSink, const char* message, EShLanguage unitStage) -{ - infoSink.info.prefix(EPrefixError); - if (unitStage < EShLangCount) - infoSink.info << "Linking " << StageName(getStage()) << " and " << StageName(unitStage) << " stages: " << message << "\n"; - else - infoSink.info << "Linking " << StageName(language) << " stage: " << message << "\n"; - - ++numErrors; -} - -// Link-time warning. -void TIntermediate::warn(TInfoSink& infoSink, const char* message, EShLanguage unitStage) -{ - infoSink.info.prefix(EPrefixWarning); - if (unitStage < EShLangCount) - infoSink.info << "Linking " << StageName(language) << " and " << StageName(unitStage) << " stages: " << message << "\n"; - else - infoSink.info << "Linking " << StageName(language) << " stage: " << message << "\n"; -} - -// TODO: 4.4 offset/align: "Two blocks linked together in the same program with the same block -// name must have the exact same set of members qualified with offset and their integral-constant -// expression values must be the same, or a link-time error results." - -// -// Merge the information from 'unit' into 'this' -// -void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) -{ - mergeCallGraphs(infoSink, unit); - mergeModes(infoSink, unit); - mergeTrees(infoSink, unit); -} - -// -// check that link objects between stages -// -void TIntermediate::mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit) { - if (unit.treeRoot == nullptr || treeRoot == nullptr) - return; - - // Get the linker-object lists - TIntermSequence& linkerObjects = findLinkerObjects()->getSequence(); - TIntermSequence unitLinkerObjects = unit.findLinkerObjects()->getSequence(); - - // filter unitLinkerObjects to only contain uniforms - auto end = std::remove_if(unitLinkerObjects.begin(), unitLinkerObjects.end(), - [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqUniform && - node->getAsSymbolNode()->getQualifier().storage != EvqBuffer; }); - unitLinkerObjects.resize(end - unitLinkerObjects.begin()); - - // merge uniforms and do error checking - bool mergeExistingOnly = false; - mergeGlobalUniformBlocks(infoSink, unit, mergeExistingOnly); - mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage()); -} - -// -// do error checking on the shader boundary in / out vars -// -void TIntermediate::checkStageIO(TInfoSink& infoSink, TIntermediate& unit) { - if (unit.treeRoot == nullptr || treeRoot == nullptr) - return; - - // Get copies of the linker-object lists - TIntermSequence linkerObjects = findLinkerObjects()->getSequence(); - TIntermSequence unitLinkerObjects = unit.findLinkerObjects()->getSequence(); - - // filter linkerObjects to only contain out variables - auto end = std::remove_if(linkerObjects.begin(), linkerObjects.end(), - [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqVaryingOut; }); - linkerObjects.resize(end - linkerObjects.begin()); - - // filter unitLinkerObjects to only contain in variables - auto unitEnd = std::remove_if(unitLinkerObjects.begin(), unitLinkerObjects.end(), - [](TIntermNode* node) {return node->getAsSymbolNode()->getQualifier().storage != EvqVaryingIn; }); - unitLinkerObjects.resize(unitEnd - unitLinkerObjects.begin()); - - // do matching and error checking - mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage()); - - // TODO: final check; make sure that any statically used `in` have matching `out` written to -} - -void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit) -{ - if (unit.getNumEntryPoints() > 0) { - if (getNumEntryPoints() > 0) - error(infoSink, "can't handle multiple entry points per stage"); - else { - entryPointName = unit.getEntryPointName(); - entryPointMangledName = unit.getEntryPointMangledName(); - } - } - numEntryPoints += unit.getNumEntryPoints(); - - callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end()); -} - -#define MERGE_MAX(member) member = std::max(member, unit.member) -#define MERGE_TRUE(member) if (unit.member) member = unit.member; - -void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit) -{ - if (language != unit.language) - error(infoSink, "stages must match when linking into a single stage"); - - if (getSource() == EShSourceNone) - setSource(unit.getSource()); - if (getSource() != unit.getSource()) - error(infoSink, "can't link compilation units from different source languages"); - - if (treeRoot == nullptr) { - profile = unit.profile; - version = unit.version; - requestedExtensions = unit.requestedExtensions; - } else { - if ((isEsProfile()) != (unit.isEsProfile())) - error(infoSink, "Cannot cross link ES and desktop profiles"); - else if (unit.profile == ECompatibilityProfile) - profile = ECompatibilityProfile; - version = std::max(version, unit.version); - requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end()); - } - - MERGE_MAX(spvVersion.spv); - MERGE_MAX(spvVersion.vulkanGlsl); - MERGE_MAX(spvVersion.vulkan); - MERGE_MAX(spvVersion.openGl); - MERGE_TRUE(spvVersion.vulkanRelaxed); - - numErrors += unit.getNumErrors(); - // Only one push_constant is allowed, mergeLinkerObjects() will ensure the push_constant - // is the same for all units. - if (numPushConstants > 1 || unit.numPushConstants > 1) - error(infoSink, "Only one push_constant block is allowed per stage"); - numPushConstants = std::min(numPushConstants + unit.numPushConstants, 1); - - if (unit.invocations != TQualifier::layoutNotSet) { - if (invocations == TQualifier::layoutNotSet) - invocations = unit.invocations; - else if (invocations != unit.invocations) - error(infoSink, "number of invocations must match between compilation units"); - } - - if (vertices == TQualifier::layoutNotSet) - vertices = unit.vertices; - else if (unit.vertices != TQualifier::layoutNotSet && vertices != unit.vertices) { - if (language == EShLangGeometry || language == EShLangMesh) - error(infoSink, "Contradictory layout max_vertices values"); - else if (language == EShLangTessControl) - error(infoSink, "Contradictory layout vertices values"); - else - assert(0); - } - if (primitives == TQualifier::layoutNotSet) - primitives = unit.primitives; - else if (primitives != unit.primitives) { - if (language == EShLangMesh) - error(infoSink, "Contradictory layout max_primitives values"); - else - assert(0); - } - - if (inputPrimitive == ElgNone) - inputPrimitive = unit.inputPrimitive; - else if (unit.inputPrimitive != ElgNone && inputPrimitive != unit.inputPrimitive) - error(infoSink, "Contradictory input layout primitives"); - - if (outputPrimitive == ElgNone) - outputPrimitive = unit.outputPrimitive; - else if (unit.outputPrimitive != ElgNone && outputPrimitive != unit.outputPrimitive) - error(infoSink, "Contradictory output layout primitives"); - - if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger) - error(infoSink, "gl_FragCoord redeclarations must match across shaders"); - - if (vertexSpacing == EvsNone) - vertexSpacing = unit.vertexSpacing; - else if (vertexSpacing != unit.vertexSpacing) - error(infoSink, "Contradictory input vertex spacing"); - - if (vertexOrder == EvoNone) - vertexOrder = unit.vertexOrder; - else if (vertexOrder != unit.vertexOrder) - error(infoSink, "Contradictory triangle ordering"); - - MERGE_TRUE(pointMode); - - for (int i = 0; i < 3; ++i) { - if (unit.localSizeNotDefault[i]) { - if (!localSizeNotDefault[i]) { - localSize[i] = unit.localSize[i]; - localSizeNotDefault[i] = true; - } - else if (localSize[i] != unit.localSize[i]) - error(infoSink, "Contradictory local size"); - } - - if (localSizeSpecId[i] == TQualifier::layoutNotSet) - localSizeSpecId[i] = unit.localSizeSpecId[i]; - else if (localSizeSpecId[i] != unit.localSizeSpecId[i]) - error(infoSink, "Contradictory local size specialization ids"); - } - - MERGE_TRUE(earlyFragmentTests); - MERGE_TRUE(postDepthCoverage); - MERGE_TRUE(nonCoherentColorAttachmentReadEXT); - MERGE_TRUE(nonCoherentDepthAttachmentReadEXT); - MERGE_TRUE(nonCoherentStencilAttachmentReadEXT); - - if (depthLayout == EldNone) - depthLayout = unit.depthLayout; - else if (depthLayout != unit.depthLayout) - error(infoSink, "Contradictory depth layouts"); - - MERGE_TRUE(depthReplacing); - MERGE_TRUE(hlslFunctionality1); - - blendEquations |= unit.blendEquations; - - MERGE_TRUE(xfbMode); - - for (size_t b = 0; b < xfbBuffers.size(); ++b) { - if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd) - xfbBuffers[b].stride = unit.xfbBuffers[b].stride; - else if (xfbBuffers[b].stride != unit.xfbBuffers[b].stride) - error(infoSink, "Contradictory xfb_stride"); - xfbBuffers[b].implicitStride = std::max(xfbBuffers[b].implicitStride, unit.xfbBuffers[b].implicitStride); - if (unit.xfbBuffers[b].contains64BitType) - xfbBuffers[b].contains64BitType = true; - if (unit.xfbBuffers[b].contains32BitType) - xfbBuffers[b].contains32BitType = true; - if (unit.xfbBuffers[b].contains16BitType) - xfbBuffers[b].contains16BitType = true; - // TODO: 4.4 link: enhanced layouts: compare ranges - } - - MERGE_TRUE(multiStream); - MERGE_TRUE(layoutOverrideCoverage); - MERGE_TRUE(geoPassthroughEXT); - - for (unsigned int i = 0; i < unit.shiftBinding.size(); ++i) { - if (unit.shiftBinding[i] > 0) - setShiftBinding((TResourceType)i, unit.shiftBinding[i]); - } - - for (unsigned int i = 0; i < unit.shiftBindingForSet.size(); ++i) { - for (auto it = unit.shiftBindingForSet[i].begin(); it != unit.shiftBindingForSet[i].end(); ++it) - setShiftBindingForSet((TResourceType)i, it->second, it->first); - } - - resourceSetBinding.insert(resourceSetBinding.end(), unit.resourceSetBinding.begin(), unit.resourceSetBinding.end()); - - MERGE_TRUE(autoMapBindings); - MERGE_TRUE(autoMapLocations); - MERGE_TRUE(invertY); - MERGE_TRUE(dxPositionW); - MERGE_TRUE(debugInfo); - MERGE_TRUE(flattenUniformArrays); - MERGE_TRUE(useUnknownFormat); - MERGE_TRUE(hlslOffsets); - MERGE_TRUE(useStorageBuffer); - MERGE_TRUE(invariantAll); - MERGE_TRUE(hlslIoMapping); - - // TODO: sourceFile - // TODO: sourceText - // TODO: processes - - MERGE_TRUE(needToLegalize); - MERGE_TRUE(binaryDoubleOutput); - MERGE_TRUE(usePhysicalStorageBuffer); -} - -// -// Merge the 'unit' AST into 'this' AST. -// That includes rationalizing the unique IDs, which were set up independently, -// and might have overlaps that are not the same symbol, or might have different -// IDs for what should be the same shared symbol. -// -void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit) -{ - if (unit.treeRoot == nullptr) - return; - - if (treeRoot == nullptr) { - treeRoot = unit.treeRoot; - return; - } - - // Getting this far means we have two existing trees to merge... - numShaderRecordBlocks += unit.numShaderRecordBlocks; - numTaskNVBlocks += unit.numTaskNVBlocks; - - // Get the top-level globals of each unit - TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence(); - TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence(); - - // Get the linker-object lists - TIntermSequence& linkerObjects = findLinkerObjects()->getSequence(); - const TIntermSequence& unitLinkerObjects = unit.findLinkerObjects()->getSequence(); - - // Map by global name to unique ID to rationalize the same object having - // differing IDs in different trees. - TIdMaps idMaps; - long long idShift; - seedIdMap(idMaps, idShift); - remapIds(idMaps, idShift + 1, unit); - - mergeBodies(infoSink, globals, unitGlobals); - bool mergeExistingOnly = false; - mergeGlobalUniformBlocks(infoSink, unit, mergeExistingOnly); - mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects, unit.getStage()); - ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end()); -} - -static const TString& getNameForIdMap(TIntermSymbol* symbol) -{ - TShaderInterface si = symbol->getType().getShaderInterface(); - if (si == EsiNone) - return symbol->getName(); - else - return symbol->getType().getTypeName(); -} - - - -// Traverser that seeds an ID map with all built-ins, and tracks the -// maximum ID used, currently using (maximum ID + 1) as new symbol id shift seed. -// Level id will keep same after shifting. -// (It would be nice to put this in a function, but that causes warnings -// on having no bodies for the copy-constructor/operator=.) -class TBuiltInIdTraverser : public TIntermTraverser { -public: - TBuiltInIdTraverser(TIdMaps& idMaps) : idMaps(idMaps), idShift(0) { } - // If it's a built in, add it to the map. - virtual void visitSymbol(TIntermSymbol* symbol) - { - const TQualifier& qualifier = symbol->getType().getQualifier(); - if (qualifier.builtIn != EbvNone) { - TShaderInterface si = symbol->getType().getShaderInterface(); - idMaps[si][getNameForIdMap(symbol)] = symbol->getId(); - } - idShift = (symbol->getId() & ~TSymbolTable::uniqueIdMask) | - std::max(idShift & TSymbolTable::uniqueIdMask, - symbol->getId() & TSymbolTable::uniqueIdMask); - } - long long getIdShift() const { return idShift; } -protected: - TBuiltInIdTraverser(TBuiltInIdTraverser&); - TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&); - TIdMaps& idMaps; - long long idShift; -}; - -// Traverser that seeds an ID map with non-builtins. -// (It would be nice to put this in a function, but that causes warnings -// on having no bodies for the copy-constructor/operator=.) -class TUserIdTraverser : public TIntermTraverser { -public: - TUserIdTraverser(TIdMaps& idMaps) : idMaps(idMaps) { } - // If its a non-built-in global, add it to the map. - virtual void visitSymbol(TIntermSymbol* symbol) - { - const TQualifier& qualifier = symbol->getType().getQualifier(); - if (qualifier.builtIn == EbvNone) { - TShaderInterface si = symbol->getType().getShaderInterface(); - idMaps[si][getNameForIdMap(symbol)] = symbol->getId(); - } - } - -protected: - TUserIdTraverser(TUserIdTraverser&); - TUserIdTraverser& operator=(TUserIdTraverser&); - TIdMaps& idMaps; // over biggest id -}; - -// Initialize the the ID map with what we know of 'this' AST. -void TIntermediate::seedIdMap(TIdMaps& idMaps, long long& idShift) -{ - // all built-ins everywhere need to align on IDs and contribute to the max ID - TBuiltInIdTraverser builtInIdTraverser(idMaps); - treeRoot->traverse(&builtInIdTraverser); - idShift = builtInIdTraverser.getIdShift() & TSymbolTable::uniqueIdMask; - - // user variables in the linker object list need to align on ids - TUserIdTraverser userIdTraverser(idMaps); - findLinkerObjects()->traverse(&userIdTraverser); -} - -// Traverser to map an AST ID to what was known from the seeding AST. -// (It would be nice to put this in a function, but that causes warnings -// on having no bodies for the copy-constructor/operator=.) -class TRemapIdTraverser : public TIntermTraverser { -public: - TRemapIdTraverser(const TIdMaps& idMaps, long long idShift) : idMaps(idMaps), idShift(idShift) { } - // Do the mapping: - // - if the same symbol, adopt the 'this' ID - // - otherwise, ensure a unique ID by shifting to a new space - virtual void visitSymbol(TIntermSymbol* symbol) - { - const TQualifier& qualifier = symbol->getType().getQualifier(); - bool remapped = false; - if (qualifier.isLinkable() || qualifier.builtIn != EbvNone) { - TShaderInterface si = symbol->getType().getShaderInterface(); - auto it = idMaps[si].find(getNameForIdMap(symbol)); - if (it != idMaps[si].end()) { - uint64_t id = (symbol->getId() & ~TSymbolTable::uniqueIdMask) | - (it->second & TSymbolTable::uniqueIdMask); - symbol->changeId(id); - remapped = true; - } - } - if (!remapped) - symbol->changeId(symbol->getId() + idShift); - } -protected: - TRemapIdTraverser(TRemapIdTraverser&); - TRemapIdTraverser& operator=(TRemapIdTraverser&); - const TIdMaps& idMaps; - long long idShift; -}; - -void TIntermediate::remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate& unit) -{ - // Remap all IDs to either share or be unique, as dictated by the idMap and idShift. - TRemapIdTraverser idTraverser(idMaps, idShift); - unit.getTreeRoot()->traverse(&idTraverser); -} - -// -// Merge the function bodies and global-level initializers from unitGlobals into globals. -// Will error check duplication of function bodies for the same signature. -// -void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, const TIntermSequence& unitGlobals) -{ - // TODO: link-time performance: Processing in alphabetical order will be faster - - // Error check the global objects, not including the linker objects - for (unsigned int child = 0; child < globals.size() - 1; ++child) { - for (unsigned int unitChild = 0; unitChild < unitGlobals.size() - 1; ++unitChild) { - TIntermAggregate* body = globals[child]->getAsAggregate(); - TIntermAggregate* unitBody = unitGlobals[unitChild]->getAsAggregate(); - if (body && unitBody && body->getOp() == EOpFunction && unitBody->getOp() == EOpFunction && body->getName() == unitBody->getName()) { - error(infoSink, "Multiple function bodies in multiple compilation units for the same signature in the same stage:"); - infoSink.info << " " << globals[child]->getAsAggregate()->getName() << "\n"; - } - } - } - - // Merge the global objects, just in front of the linker objects - globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1); -} - -static inline bool isSameInterface(TIntermSymbol* symbol, EShLanguage stage, TIntermSymbol* unitSymbol, EShLanguage unitStage) { - return // 1) same stage and same shader interface - (stage == unitStage && symbol->getType().getShaderInterface() == unitSymbol->getType().getShaderInterface()) || - // 2) accross stages and both are uniform or buffer - (symbol->getQualifier().storage == EvqUniform && unitSymbol->getQualifier().storage == EvqUniform) || - (symbol->getQualifier().storage == EvqBuffer && unitSymbol->getQualifier().storage == EvqBuffer) || - // 3) in/out matched across stage boundary - (stage < unitStage && symbol->getQualifier().storage == EvqVaryingOut && unitSymbol->getQualifier().storage == EvqVaryingIn) || - (unitStage < stage && symbol->getQualifier().storage == EvqVaryingIn && unitSymbol->getQualifier().storage == EvqVaryingOut); -} - -// -// Global Unfiform block stores any default uniforms (i.e. uniforms without a block) -// If two linked stages declare the same member, they are meant to be the same uniform -// and need to be in the same block -// merge the members of different stages to allow them to be linked properly -// as a single block -// -void TIntermediate::mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly) -{ - TIntermSequence& linkerObjects = findLinkerObjects()->getSequence(); - TIntermSequence& unitLinkerObjects = unit.findLinkerObjects()->getSequence(); - - // build lists of default blocks from the intermediates - TIntermSequence defaultBlocks; - TIntermSequence unitDefaultBlocks; - - auto filter = [](TIntermSequence& list, TIntermNode* node) { - if (node->getAsSymbolNode()->getQualifier().defaultBlock) { - list.push_back(node); - } - }; - - std::for_each(linkerObjects.begin(), linkerObjects.end(), - [&defaultBlocks, &filter](TIntermNode* node) { - filter(defaultBlocks, node); - }); - std::for_each(unitLinkerObjects.begin(), unitLinkerObjects.end(), - [&unitDefaultBlocks, &filter](TIntermNode* node) { - filter(unitDefaultBlocks, node); - }); - - auto itUnitBlock = unitDefaultBlocks.begin(); - for (; itUnitBlock != unitDefaultBlocks.end(); itUnitBlock++) { - - bool add = !mergeExistingOnly; - auto itBlock = defaultBlocks.begin(); - - for (; itBlock != defaultBlocks.end(); itBlock++) { - TIntermSymbol* block = (*itBlock)->getAsSymbolNode(); - TIntermSymbol* unitBlock = (*itUnitBlock)->getAsSymbolNode(); - - assert(block && unitBlock); - - // if the two default blocks match, then merge their definitions - if (block->getType().getTypeName() == unitBlock->getType().getTypeName() && - block->getQualifier().storage == unitBlock->getQualifier().storage) { - add = false; - mergeBlockDefinitions(infoSink, block, unitBlock, &unit); - } - } - if (add) { - // push back on original list; won't change the size of the list we're iterating over - linkerObjects.push_back(*itUnitBlock); - } - } -} - -void TIntermediate::mergeBlockDefinitions(TInfoSink& infoSink, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unit) { - - if (block->getType().getTypeName() != unitBlock->getType().getTypeName() || - block->getType().getBasicType() != unitBlock->getType().getBasicType() || - block->getQualifier().storage != unitBlock->getQualifier().storage || - block->getQualifier().layoutSet != unitBlock->getQualifier().layoutSet) { - // different block names likely means different blocks - return; - } - - // merge the struct - // order of declarations doesn't matter and they matched based on member name - TTypeList* memberList = block->getType().getWritableStruct(); - TTypeList* unitMemberList = unitBlock->getType().getWritableStruct(); - - // keep track of which members have changed position - // so we don't have to search the array again - std::map memberIndexUpdates; - - size_t memberListStartSize = memberList->size(); - for (unsigned int i = 0; i < unitMemberList->size(); ++i) { - bool merge = true; - for (unsigned int j = 0; j < memberListStartSize; ++j) { - if ((*memberList)[j].type->getFieldName() == (*unitMemberList)[i].type->getFieldName()) { - merge = false; - const TType* memberType = (*memberList)[j].type; - const TType* unitMemberType = (*unitMemberList)[i].type; - - // compare types - // don't need as many checks as when merging symbols, since - // initializers and most qualifiers are stripped when the member is moved into the block - if ((*memberType) != (*unitMemberType)) { - error(infoSink, "Types must match:"); - infoSink.info << " " << memberType->getFieldName() << ": "; - infoSink.info << "\"" << memberType->getCompleteString() << "\" versus "; - infoSink.info << "\"" << unitMemberType->getCompleteString() << "\"\n"; - } - - memberIndexUpdates[i] = j; - } - } - if (merge) { - memberList->push_back((*unitMemberList)[i]); - memberIndexUpdates[i] = (unsigned int)memberList->size() - 1; - } - } - - // update symbol node in unit tree, - // and other nodes that may reference it - class TMergeBlockTraverser : public TIntermTraverser { - public: - TMergeBlockTraverser(const TIntermSymbol* newSym) - : newSymbol(newSym), newType(nullptr), unit(nullptr), memberIndexUpdates(nullptr) - { - } - TMergeBlockTraverser(const TIntermSymbol* newSym, const glslang::TType* unitType, glslang::TIntermediate* unit, - const std::map* memberIdxUpdates) - : TIntermTraverser(false, true), newSymbol(newSym), newType(unitType), unit(unit), memberIndexUpdates(memberIdxUpdates) - { - } - virtual ~TMergeBlockTraverser() {} - - const TIntermSymbol* newSymbol; - const glslang::TType* newType; // shallow copy of the new type - glslang::TIntermediate* unit; // intermediate that is being updated - const std::map* memberIndexUpdates; - - virtual void visitSymbol(TIntermSymbol* symbol) - { - if (newSymbol->getAccessName() == symbol->getAccessName() && - newSymbol->getQualifier().getBlockStorage() == symbol->getQualifier().getBlockStorage()) { - // Each symbol node may have a local copy of the block structure. - // Update those structures to match the new one post-merge - *(symbol->getWritableType().getWritableStruct()) = *(newSymbol->getType().getStruct()); - } - } - - virtual bool visitBinary(TVisit, glslang::TIntermBinary* node) - { - if (!unit || !newType || !memberIndexUpdates || memberIndexUpdates->empty()) - return true; - - if (node->getOp() == EOpIndexDirectStruct && node->getLeft()->getType() == *newType) { - // this is a dereference to a member of the block since the - // member list changed, need to update this to point to the - // right index - assert(node->getRight()->getAsConstantUnion()); - - glslang::TIntermConstantUnion* constNode = node->getRight()->getAsConstantUnion(); - unsigned int memberIdx = constNode->getConstArray()[0].getUConst(); - unsigned int newIdx = memberIndexUpdates->at(memberIdx); - TIntermTyped* newConstNode = unit->addConstantUnion(newIdx, node->getRight()->getLoc()); - - node->setRight(newConstNode); - delete constNode; - - return true; - } - return true; - } - }; - - // 'this' may have symbols that are using the old block structure, so traverse the tree to update those - // in 'visitSymbol' - TMergeBlockTraverser finalLinkTraverser(block); - getTreeRoot()->traverse(&finalLinkTraverser); - - // The 'unit' intermediate needs the block structures update, but also structure entry indices - // may have changed from the old block to the new one that it was merged into, so update those - // in 'visitBinary' - TType newType; - newType.shallowCopy(block->getType()); - TMergeBlockTraverser unitFinalLinkTraverser(block, &newType, unit, &memberIndexUpdates); - unit->getTreeRoot()->traverse(&unitFinalLinkTraverser); - - // update the member list - (*unitMemberList) = (*memberList); -} - -// -// Merge the linker objects from unitLinkerObjects into linkerObjects. -// Duplication is expected and filtered out, but contradictions are an error. -// -void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage unitStage) -{ - // Error check and merge the linker objects (duplicates should not be created) - std::size_t initialNumLinkerObjects = linkerObjects.size(); - for (unsigned int unitLinkObj = 0; unitLinkObj < unitLinkerObjects.size(); ++unitLinkObj) { - bool merge = true; - for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) { - TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode(); - TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode(); - assert(symbol && unitSymbol); - - bool isSameSymbol = false; - // If they are both blocks in the same shader interface, - // match by the block-name, not the identifier name. - if (symbol->getType().getBasicType() == EbtBlock && unitSymbol->getType().getBasicType() == EbtBlock) { - if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) { - isSameSymbol = symbol->getType().getTypeName() == unitSymbol->getType().getTypeName(); - } - } - else if (symbol->getName() == unitSymbol->getName()) - isSameSymbol = true; - - if (isSameSymbol) { - // filter out copy - merge = false; - - // but if one has an initializer and the other does not, update - // the initializer - if (symbol->getConstArray().empty() && ! unitSymbol->getConstArray().empty()) - symbol->setConstArray(unitSymbol->getConstArray()); - - // Similarly for binding - if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding()) - symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding; - - // Similarly for location - if (!symbol->getQualifier().hasLocation() && unitSymbol->getQualifier().hasLocation()) { - symbol->getQualifier().layoutLocation = unitSymbol->getQualifier().layoutLocation; - } - - // Update implicit array sizes - if (symbol->getWritableType().isImplicitlySizedArray() && unitSymbol->getType().isImplicitlySizedArray()) { - if (unitSymbol->getType().getImplicitArraySize() > symbol->getType().getImplicitArraySize()){ - symbol->getWritableType().updateImplicitArraySize(unitSymbol->getType().getImplicitArraySize()); - } - } - else if (symbol->getWritableType().isImplicitlySizedArray() && unitSymbol->getType().isSizedArray()) { - if (symbol->getWritableType().getImplicitArraySize() > unitSymbol->getType().getOuterArraySize()) - error(infoSink, "Implicit size of unsized array doesn't match same symbol among multiple shaders."); - } - else if (unitSymbol->getType().isImplicitlySizedArray() && symbol->getWritableType().isSizedArray()) { - if (unitSymbol->getType().getImplicitArraySize() > symbol->getWritableType().getOuterArraySize()) - error(infoSink, "Implicit size of unsized array doesn't match same symbol among multiple shaders."); - } - - // Update implicit array sizes - mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType()); - - // Check for consistent types/qualification/initializers etc. - mergeErrorCheck(infoSink, *symbol, *unitSymbol, unitStage); - } - // If different symbols, verify they arn't push_constant since there can only be one per stage - else if (symbol->getQualifier().isPushConstant() && unitSymbol->getQualifier().isPushConstant() && getStage() == unitStage) - error(infoSink, "Only one push_constant block is allowed per stage"); - } - - // Check conflicts between preset primitives and sizes of I/O variables among multiple geometry shaders - if (language == EShLangGeometry && unitStage == EShLangGeometry) - { - TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode(); - if (unitSymbol->isArray() && unitSymbol->getQualifier().storage == EvqVaryingIn && unitSymbol->getQualifier().builtIn == EbvNone) - if ((unitSymbol->getArraySizes()->isImplicitlySized() && - unitSymbol->getArraySizes()->getImplicitSize() != TQualifier::mapGeometryToSize(getInputPrimitive())) || - (! unitSymbol->getArraySizes()->isImplicitlySized() && - unitSymbol->getArraySizes()->getDimSize(0) != TQualifier::mapGeometryToSize(getInputPrimitive()))) - error(infoSink, "Not all array sizes match across all geometry shaders in the program"); - } - - if (merge) { - linkerObjects.push_back(unitLinkerObjects[unitLinkObj]); - - // for anonymous blocks, check that their members don't conflict with other names - if (unitLinkerObjects[unitLinkObj]->getAsSymbolNode()->getBasicType() == EbtBlock && - IsAnonymous(unitLinkerObjects[unitLinkObj]->getAsSymbolNode()->getName())) { - for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) { - TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode(); - TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode(); - assert(symbol && unitSymbol); - - auto checkName = [this, unitSymbol, &infoSink](const TString& name) { - for (unsigned int i = 0; i < unitSymbol->getType().getStruct()->size(); ++i) { - if (name == (*unitSymbol->getType().getStruct())[i].type->getFieldName() - && !((*unitSymbol->getType().getStruct())[i].type->getQualifier().hasLocation() - || unitSymbol->getType().getQualifier().hasLocation()) - ) { - error(infoSink, "Anonymous member name used for global variable or other anonymous member: "); - infoSink.info << (*unitSymbol->getType().getStruct())[i].type->getCompleteString() << "\n"; - } - } - }; - - if (isSameInterface(symbol, getStage(), unitSymbol, unitStage)) { - checkName(symbol->getName()); - - // check members of other anonymous blocks - if (symbol->getBasicType() == EbtBlock && IsAnonymous(symbol->getName())) { - for (unsigned int i = 0; i < symbol->getType().getStruct()->size(); ++i) { - checkName((*symbol->getType().getStruct())[i].type->getFieldName()); - } - } - } - } - } - } - } -} - -// TODO 4.5 link functionality: cull distance array size checking - -// Recursively merge the implicit array sizes through the objects' respective type trees. -void TIntermediate::mergeImplicitArraySizes(TType& type, const TType& unitType) -{ - if (type.isUnsizedArray()) { - if (unitType.isUnsizedArray()) { - type.updateImplicitArraySize(unitType.getImplicitArraySize()); - if (unitType.isArrayVariablyIndexed()) - type.setArrayVariablyIndexed(); - } else if (unitType.isSizedArray()) - type.changeOuterArraySize(unitType.getOuterArraySize()); - } - - // Type mismatches are caught and reported after this, just be careful for now. - if (! type.isStruct() || ! unitType.isStruct() || type.getStruct()->size() != unitType.getStruct()->size()) - return; - - for (int i = 0; i < (int)type.getStruct()->size(); ++i) - mergeImplicitArraySizes(*(*type.getStruct())[i].type, *(*unitType.getStruct())[i].type); -} - -// -// Compare two global objects from two compilation units and see if they match -// well enough. Rules can be different for intra- vs. cross-stage matching. -// -// This function only does one of intra- or cross-stage matching per call. -// -void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, EShLanguage unitStage) -{ - bool crossStage = getStage() != unitStage; - bool writeTypeComparison = false; - bool errorReported = false; - bool printQualifiers = false; - bool printPrecision = false; - bool printType = false; - - // Types have to match - { - // but, we make an exception if one is an implicit array and the other is sized - // or if the array sizes differ because of the extra array dimension on some in/out boundaries - bool arraysMatch = false; - if (isIoResizeArray(symbol.getType(), getStage()) || isIoResizeArray(unitSymbol.getType(), unitStage)) { - // if the arrays have an extra dimension because of the stage. - // compare dimensions while ignoring the outer dimension - unsigned int firstDim = isIoResizeArray(symbol.getType(), getStage()) ? 1 : 0; - unsigned int numDim = symbol.getArraySizes() - ? symbol.getArraySizes()->getNumDims() : 0; - unsigned int unitFirstDim = isIoResizeArray(unitSymbol.getType(), unitStage) ? 1 : 0; - unsigned int unitNumDim = unitSymbol.getArraySizes() - ? unitSymbol.getArraySizes()->getNumDims() : 0; - arraysMatch = (numDim - firstDim) == (unitNumDim - unitFirstDim); - // check that array sizes match as well - for (unsigned int i = 0; i < (numDim - firstDim) && arraysMatch; i++) { - if (symbol.getArraySizes()->getDimSize(firstDim + i) != - unitSymbol.getArraySizes()->getDimSize(unitFirstDim + i)) { - arraysMatch = false; - break; - } - } - } - else { - arraysMatch = symbol.getType().sameArrayness(unitSymbol.getType()) || - (symbol.getType().isArray() && unitSymbol.getType().isArray() && - (symbol.getType().isImplicitlySizedArray() || unitSymbol.getType().isImplicitlySizedArray() || - symbol.getType().isUnsizedArray() || unitSymbol.getType().isUnsizedArray())); - } - - int lpidx = -1; - int rpidx = -1; - if (!symbol.getType().sameElementType(unitSymbol.getType(), &lpidx, &rpidx)) { - if (lpidx >= 0 && rpidx >= 0) { - error(infoSink, "Member names and types must match:", unitStage); - infoSink.info << " Block: " << symbol.getType().getTypeName() << "\n"; - infoSink.info << " " << StageName(getStage()) << " stage: \"" - << (*symbol.getType().getStruct())[lpidx].type->getCompleteString(true, false, false, true, - (*symbol.getType().getStruct())[lpidx].type->getFieldName()) << "\"\n"; - infoSink.info << " " << StageName(unitStage) << " stage: \"" - << (*unitSymbol.getType().getStruct())[rpidx].type->getCompleteString(true, false, false, true, - (*unitSymbol.getType().getStruct())[rpidx].type->getFieldName()) << "\"\n"; - errorReported = true; - } else if (lpidx >= 0 && rpidx == -1) { - TString errmsg = StageName(getStage()); - errmsg.append(" block member has no corresponding member in ").append(StageName(unitStage)).append(" block:"); - error(infoSink, errmsg.c_str(), unitStage); - infoSink.info << " " << StageName(getStage()) << " stage: Block: " << symbol.getType().getTypeName() << ", Member: " - << (*symbol.getType().getStruct())[lpidx].type->getFieldName() << "\n"; - infoSink.info << " " << StageName(unitStage) << " stage: Block: " << unitSymbol.getType().getTypeName() << ", Member: n/a \n"; - errorReported = true; - } else if (lpidx == -1 && rpidx >= 0) { - TString errmsg = StageName(unitStage); - errmsg.append(" block member has no corresponding member in ").append(StageName(getStage())).append(" block:"); - error(infoSink, errmsg.c_str(), unitStage); - infoSink.info << " " << StageName(unitStage) << " stage: Block: " << unitSymbol.getType().getTypeName() << ", Member: " - << (*unitSymbol.getType().getStruct())[rpidx].type->getFieldName() << "\n"; - infoSink.info << " " << StageName(getStage()) << " stage: Block: " << symbol.getType().getTypeName() << ", Member: n/a \n"; - errorReported = true; - } else { - error(infoSink, "Types must match:", unitStage); - writeTypeComparison = true; - printType = true; - } - } else if (!arraysMatch) { - error(infoSink, "Array sizes must be compatible:", unitStage); - writeTypeComparison = true; - printType = true; - } else if (!symbol.getType().sameTypeParameters(unitSymbol.getType())) { - error(infoSink, "Type parameters must match:", unitStage); - writeTypeComparison = true; - printType = true; - } - } - - // Interface block member-wise layout qualifiers have to match - if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock && - symbol.getType().getStruct() && unitSymbol.getType().getStruct() && - symbol.getType().sameStructType(unitSymbol.getType())) { - unsigned int li = 0; - unsigned int ri = 0; - while (li < symbol.getType().getStruct()->size() && ri < unitSymbol.getType().getStruct()->size()) { - if ((*symbol.getType().getStruct())[li].type->hiddenMember()) { - ++li; - continue; - } - if ((*unitSymbol.getType().getStruct())[ri].type->hiddenMember()) { - ++ri; - continue; - } - const TQualifier& qualifier = (*symbol.getType().getStruct())[li].type->getQualifier(); - const TQualifier & unitQualifier = (*unitSymbol.getType().getStruct())[ri].type->getQualifier(); - bool layoutQualifierError = false; - if (qualifier.layoutMatrix != unitQualifier.layoutMatrix) { - error(infoSink, "Interface block member layout matrix qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (qualifier.layoutOffset != unitQualifier.layoutOffset) { - error(infoSink, "Interface block member layout offset qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (qualifier.layoutAlign != unitQualifier.layoutAlign) { - error(infoSink, "Interface block member layout align qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (qualifier.layoutLocation != unitQualifier.layoutLocation) { - error(infoSink, "Interface block member layout location qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (qualifier.layoutComponent != unitQualifier.layoutComponent) { - error(infoSink, "Interface block member layout component qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (layoutQualifierError) { - infoSink.info << " " << StageName(getStage()) << " stage: Block: " << symbol.getType().getTypeName() << ", Member: " - << (*symbol.getType().getStruct())[li].type->getFieldName() << " \"" - << (*symbol.getType().getStruct())[li].type->getCompleteString(true, true, false, false) << "\"\n"; - infoSink.info << " " << StageName(unitStage) << " stage: Block: " << unitSymbol.getType().getTypeName() << ", Member: " - << (*unitSymbol.getType().getStruct())[ri].type->getFieldName() << " \"" - << (*unitSymbol.getType().getStruct())[ri].type->getCompleteString(true, true, false, false) << "\"\n"; - errorReported = true; - } - ++li; - ++ri; - } - } - - bool isInOut = crossStage && - ((symbol.getQualifier().storage == EvqVaryingIn && unitSymbol.getQualifier().storage == EvqVaryingOut) || - (symbol.getQualifier().storage == EvqVaryingOut && unitSymbol.getQualifier().storage == EvqVaryingIn)); - - // Qualifiers have to (almost) match - // Storage... - if (!isInOut && symbol.getQualifier().storage != unitSymbol.getQualifier().storage) { - error(infoSink, "Storage qualifiers must match:", unitStage); - writeTypeComparison = true; - printQualifiers = true; - } - - // Uniform and buffer blocks must either both have an instance name, or - // must both be anonymous. The names don't need to match though. - if (symbol.getQualifier().isUniformOrBuffer() && - (IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()))) { - error(infoSink, "Matched Uniform or Storage blocks must all be anonymous," - " or all be named:", unitStage); - writeTypeComparison = true; - } - - if (symbol.getQualifier().storage == unitSymbol.getQualifier().storage && - (IsAnonymous(symbol.getName()) != IsAnonymous(unitSymbol.getName()) || - (!IsAnonymous(symbol.getName()) && symbol.getName() != unitSymbol.getName()))) { - warn(infoSink, "Matched shader interfaces are using different instance names.", unitStage); - writeTypeComparison = true; - } - - // Precision... - if (!isInOut && symbol.getQualifier().precision != unitSymbol.getQualifier().precision) { - error(infoSink, "Precision qualifiers must match:", unitStage); - writeTypeComparison = true; - printPrecision = true; - } - - // Invariance... - if (! crossStage && symbol.getQualifier().invariant != unitSymbol.getQualifier().invariant) { - error(infoSink, "Presence of invariant qualifier must match:", unitStage); - writeTypeComparison = true; - printQualifiers = true; - } - - // Precise... - if (! crossStage && symbol.getQualifier().isNoContraction() != unitSymbol.getQualifier().isNoContraction()) { - error(infoSink, "Presence of precise qualifier must match:", unitStage); - writeTypeComparison = true; - printPrecision = true; - } - - // Auxiliary and interpolation... - // "interpolation qualification (e.g., flat) and auxiliary qualification (e.g. centroid) may differ. - // These mismatches are allowed between any pair of stages ... - // those provided in the fragment shader supersede those provided in previous stages." - if (!crossStage && - (symbol.getQualifier().centroid != unitSymbol.getQualifier().centroid || - symbol.getQualifier().smooth != unitSymbol.getQualifier().smooth || - symbol.getQualifier().flat != unitSymbol.getQualifier().flat || - symbol.getQualifier().isSample()!= unitSymbol.getQualifier().isSample() || - symbol.getQualifier().isPatch() != unitSymbol.getQualifier().isPatch() || - symbol.getQualifier().isNonPerspective() != unitSymbol.getQualifier().isNonPerspective())) { - error(infoSink, "Interpolation and auxiliary storage qualifiers must match:", unitStage); - writeTypeComparison = true; - printQualifiers = true; - } - - // Memory... - bool memoryQualifierError = false; - if (symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent) { - error(infoSink, "Memory coherent qualifier must match:", unitStage); - memoryQualifierError = true; - } - if (symbol.getQualifier().devicecoherent != unitSymbol.getQualifier().devicecoherent) { - error(infoSink, "Memory devicecoherent qualifier must match:", unitStage); - memoryQualifierError = true; - } - if (symbol.getQualifier().queuefamilycoherent != unitSymbol.getQualifier().queuefamilycoherent) { - error(infoSink, "Memory queuefamilycoherent qualifier must match:", unitStage); - memoryQualifierError = true; - } - if (symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent) { - error(infoSink, "Memory workgroupcoherent qualifier must match:", unitStage); - memoryQualifierError = true; - } - if (symbol.getQualifier().subgroupcoherent != unitSymbol.getQualifier().subgroupcoherent) { - error(infoSink, "Memory subgroupcoherent qualifier must match:", unitStage); - memoryQualifierError = true; - } - if (symbol.getQualifier().shadercallcoherent != unitSymbol.getQualifier().shadercallcoherent) { - error(infoSink, "Memory shadercallcoherent qualifier must match:", unitStage); - memoryQualifierError = true; - } - if (symbol.getQualifier().nonprivate != unitSymbol.getQualifier().nonprivate) { - error(infoSink, "Memory nonprivate qualifier must match:", unitStage); - memoryQualifierError = true; - } - if (symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil) { - error(infoSink, "Memory volatil qualifier must match:", unitStage); - memoryQualifierError = true; - } - if (symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict) { - error(infoSink, "Memory restrict qualifier must match:", unitStage); - memoryQualifierError = true; - } - if (symbol.getQualifier().readonly != unitSymbol.getQualifier().readonly) { - error(infoSink, "Memory readonly qualifier must match:", unitStage); - memoryQualifierError = true; - } - if (symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) { - error(infoSink, "Memory writeonly qualifier must match:", unitStage); - memoryQualifierError = true; - } - if (memoryQualifierError) { - writeTypeComparison = true; - printQualifiers = true; - } - - // Layouts... - // TODO: 4.4 enhanced layouts: Generalize to include offset/align: current spec - // requires separate user-supplied offset from actual computed offset, but - // current implementation only has one offset. - bool layoutQualifierError = false; - if (symbol.getQualifier().layoutMatrix != unitSymbol.getQualifier().layoutMatrix) { - error(infoSink, "Layout matrix qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (symbol.getQualifier().layoutPacking != unitSymbol.getQualifier().layoutPacking) { - error(infoSink, "Layout packing qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (symbol.getQualifier().hasLocation() && unitSymbol.getQualifier().hasLocation() && symbol.getQualifier().layoutLocation != unitSymbol.getQualifier().layoutLocation) { - error(infoSink, "Layout location qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (symbol.getQualifier().layoutComponent != unitSymbol.getQualifier().layoutComponent) { - error(infoSink, "Layout component qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (symbol.getQualifier().layoutIndex != unitSymbol.getQualifier().layoutIndex) { - error(infoSink, "Layout index qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (symbol.getQualifier().hasBinding() && unitSymbol.getQualifier().hasBinding() && symbol.getQualifier().layoutBinding != unitSymbol.getQualifier().layoutBinding) { - error(infoSink, "Layout binding qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (symbol.getQualifier().hasBinding() && (symbol.getQualifier().layoutOffset != unitSymbol.getQualifier().layoutOffset)) { - error(infoSink, "Layout offset qualifier must match:", unitStage); - layoutQualifierError = true; - } - if (layoutQualifierError) { - writeTypeComparison = true; - printQualifiers = true; - } - - // Initializers have to match, if both are present, and if we don't already know the types don't match - if (! writeTypeComparison && ! errorReported) { - if (! symbol.getConstArray().empty() && ! unitSymbol.getConstArray().empty()) { - if (symbol.getConstArray() != unitSymbol.getConstArray()) { - error(infoSink, "Initializers must match:", unitStage); - infoSink.info << " " << symbol.getName() << "\n"; - } - } - } - - if (writeTypeComparison) { - if (symbol.getType().getBasicType() == EbtBlock && unitSymbol.getType().getBasicType() == EbtBlock && - symbol.getType().getStruct() && unitSymbol.getType().getStruct()) { - if (printType) { - infoSink.info << " " << StageName(getStage()) << " stage: \"" << symbol.getType().getCompleteString(true, printQualifiers, printPrecision, - printType, symbol.getName(), symbol.getType().getTypeName()) << "\"\n"; - infoSink.info << " " << StageName(unitStage) << " stage: \"" << unitSymbol.getType().getCompleteString(true, printQualifiers, printPrecision, - printType, unitSymbol.getName(), unitSymbol.getType().getTypeName()) << "\"\n"; - } else { - infoSink.info << " " << StageName(getStage()) << " stage: Block: " << symbol.getType().getTypeName() << " Instance: " << symbol.getName() - << ": \"" << symbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType) << "\"\n"; - infoSink.info << " " << StageName(unitStage) << " stage: Block: " << unitSymbol.getType().getTypeName() << " Instance: " << unitSymbol.getName() - << ": \"" << unitSymbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType) << "\"\n"; - } - } else { - if (printType) { - infoSink.info << " " << StageName(getStage()) << " stage: \"" - << symbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType, symbol.getName()) << "\"\n"; - infoSink.info << " " << StageName(unitStage) << " stage: \"" - << unitSymbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType, unitSymbol.getName()) << "\"\n"; - } else { - infoSink.info << " " << StageName(getStage()) << " stage: " << symbol.getName() << " \"" - << symbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType) << "\"\n"; - infoSink.info << " " << StageName(unitStage) << " stage: " << unitSymbol.getName() << " \"" - << unitSymbol.getType().getCompleteString(true, printQualifiers, printPrecision, printType) << "\"\n"; - } - } - } -} - -void TIntermediate::sharedBlockCheck(TInfoSink& infoSink) -{ - bool has_shared_block = false; - bool has_shared_non_block = false; - TIntermSequence& linkObjects = findLinkerObjects()->getSequence(); - for (size_t i = 0; i < linkObjects.size(); ++i) { - const TType& type = linkObjects[i]->getAsTyped()->getType(); - const TQualifier& qualifier = type.getQualifier(); - if (qualifier.storage == glslang::EvqShared) { - if (type.getBasicType() == glslang::EbtBlock) - has_shared_block = true; - else - has_shared_non_block = true; - } - } - if (has_shared_block && has_shared_non_block) - error(infoSink, "cannot mix use of shared variables inside and outside blocks"); -} - -// -// Do final link-time error checking of a complete (merged) intermediate representation. -// (Much error checking was done during merging). -// -// Also, lock in defaults of things not set, including array sizes. -// -void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled) -{ - if (getTreeRoot() == nullptr) - return; - - if (numEntryPoints < 1) { - if (getSource() == EShSourceGlsl) - error(infoSink, "Missing entry point: Each stage requires one entry point"); - else - warn(infoSink, "Entry point not found"); - } - - // recursion and missing body checking - checkCallGraphCycles(infoSink); - checkCallGraphBodies(infoSink, keepUncalled); - - // overlap/alias/missing I/O, etc. - inOutLocationCheck(infoSink); - - if (getNumPushConstants() > 1) - error(infoSink, "Only one push_constant block is allowed per stage"); - - // invocations - if (invocations == TQualifier::layoutNotSet) - invocations = 1; - - if (inIoAccessed("gl_ClipDistance") && inIoAccessed("gl_ClipVertex")) - error(infoSink, "Can only use one of gl_ClipDistance or gl_ClipVertex (gl_ClipDistance is preferred)"); - if (inIoAccessed("gl_CullDistance") && inIoAccessed("gl_ClipVertex")) - error(infoSink, "Can only use one of gl_CullDistance or gl_ClipVertex (gl_ClipDistance is preferred)"); - - if (userOutputUsed() && (inIoAccessed("gl_FragColor") || inIoAccessed("gl_FragData"))) - error(infoSink, "Cannot use gl_FragColor or gl_FragData when using user-defined outputs"); - if (inIoAccessed("gl_FragColor") && inIoAccessed("gl_FragData")) - error(infoSink, "Cannot use both gl_FragColor and gl_FragData"); - - for (size_t b = 0; b < xfbBuffers.size(); ++b) { - if (xfbBuffers[b].contains64BitType) - RoundToPow2(xfbBuffers[b].implicitStride, 8); - else if (xfbBuffers[b].contains32BitType) - RoundToPow2(xfbBuffers[b].implicitStride, 4); - else if (xfbBuffers[b].contains16BitType) - RoundToPow2(xfbBuffers[b].implicitStride, 2); - - // "It is a compile-time or link-time error to have - // any xfb_offset that overflows xfb_stride, whether stated on declarations before or after the xfb_stride, or - // in different compilation units. While xfb_stride can be declared multiple times for the same buffer, it is a - // compile-time or link-time error to have different values specified for the stride for the same buffer." - if (xfbBuffers[b].stride != TQualifier::layoutXfbStrideEnd && xfbBuffers[b].implicitStride > xfbBuffers[b].stride) { - error(infoSink, "xfb_stride is too small to hold all buffer entries:"); - infoSink.info.prefix(EPrefixError); - infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << ", minimum stride needed: " << xfbBuffers[b].implicitStride << "\n"; - } - if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd) - xfbBuffers[b].stride = xfbBuffers[b].implicitStride; - - // "If the buffer is capturing any - // outputs with double-precision or 64-bit integer components, the stride must be a multiple of 8, otherwise it must be a - // multiple of 4, or a compile-time or link-time error results." - if (xfbBuffers[b].contains64BitType && ! IsMultipleOfPow2(xfbBuffers[b].stride, 8)) { - error(infoSink, "xfb_stride must be multiple of 8 for buffer holding a double or 64-bit integer:"); - infoSink.info.prefix(EPrefixError); - infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n"; - } else if (xfbBuffers[b].contains32BitType && ! IsMultipleOfPow2(xfbBuffers[b].stride, 4)) { - error(infoSink, "xfb_stride must be multiple of 4:"); - infoSink.info.prefix(EPrefixError); - infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n"; - } - // "If the buffer is capturing any - // outputs with half-precision or 16-bit integer components, the stride must be a multiple of 2" - else if (xfbBuffers[b].contains16BitType && ! IsMultipleOfPow2(xfbBuffers[b].stride, 2)) { - error(infoSink, "xfb_stride must be multiple of 2 for buffer holding a half float or 16-bit integer:"); - infoSink.info.prefix(EPrefixError); - infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n"; - } - - // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the - // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents." - if (xfbBuffers[b].stride > (unsigned int)(4 * resources->maxTransformFeedbackInterleavedComponents)) { - error(infoSink, "xfb_stride is too large:"); - infoSink.info.prefix(EPrefixError); - infoSink.info << " xfb_buffer " << (unsigned int)b << ", components (1/4 stride) needed are " << xfbBuffers[b].stride/4 << ", gl_MaxTransformFeedbackInterleavedComponents is " << resources->maxTransformFeedbackInterleavedComponents << "\n"; - } - } - - switch (language) { - case EShLangVertex: - break; - case EShLangTessControl: - if (vertices == TQualifier::layoutNotSet) - error(infoSink, "At least one shader must specify an output layout(vertices=...)"); - break; - case EShLangTessEvaluation: - if (getSource() == EShSourceGlsl) { - if (inputPrimitive == ElgNone) - error(infoSink, "At least one shader must specify an input layout primitive"); - if (vertexSpacing == EvsNone) - vertexSpacing = EvsEqual; - if (vertexOrder == EvoNone) - vertexOrder = EvoCcw; - } - break; - case EShLangGeometry: - if (inputPrimitive == ElgNone) - error(infoSink, "At least one shader must specify an input layout primitive"); - if (outputPrimitive == ElgNone) - error(infoSink, "At least one shader must specify an output layout primitive"); - if (vertices == TQualifier::layoutNotSet) - error(infoSink, "At least one shader must specify a layout(max_vertices = value)"); - break; - case EShLangFragment: - // for GL_ARB_post_depth_coverage, EarlyFragmentTest is set automatically in - // ParseHelper.cpp. So if we reach here, this must be GL_EXT_post_depth_coverage - // requiring explicit early_fragment_tests - if (getPostDepthCoverage() && !getEarlyFragmentTests()) - error(infoSink, "post_depth_coverage requires early_fragment_tests"); - break; - case EShLangCompute: - sharedBlockCheck(infoSink); - break; - case EShLangRayGen: - case EShLangIntersect: - case EShLangAnyHit: - case EShLangClosestHit: - case EShLangMiss: - case EShLangCallable: - if (numShaderRecordBlocks > 1) - error(infoSink, "Only one shaderRecordNV buffer block is allowed per stage"); - break; - case EShLangMesh: - // NV_mesh_shader doesn't allow use of both single-view and per-view builtins. - if (inIoAccessed("gl_Position") && inIoAccessed("gl_PositionPerViewNV")) - error(infoSink, "Can only use one of gl_Position or gl_PositionPerViewNV"); - if (inIoAccessed("gl_ClipDistance") && inIoAccessed("gl_ClipDistancePerViewNV")) - error(infoSink, "Can only use one of gl_ClipDistance or gl_ClipDistancePerViewNV"); - if (inIoAccessed("gl_CullDistance") && inIoAccessed("gl_CullDistancePerViewNV")) - error(infoSink, "Can only use one of gl_CullDistance or gl_CullDistancePerViewNV"); - if (inIoAccessed("gl_Layer") && inIoAccessed("gl_LayerPerViewNV")) - error(infoSink, "Can only use one of gl_Layer or gl_LayerPerViewNV"); - if (inIoAccessed("gl_ViewportMask") && inIoAccessed("gl_ViewportMaskPerViewNV")) - error(infoSink, "Can only use one of gl_ViewportMask or gl_ViewportMaskPerViewNV"); - if (outputPrimitive == ElgNone) - error(infoSink, "At least one shader must specify an output layout primitive"); - if (vertices == TQualifier::layoutNotSet) - error(infoSink, "At least one shader must specify a layout(max_vertices = value)"); - if (primitives == TQualifier::layoutNotSet) - error(infoSink, "At least one shader must specify a layout(max_primitives = value)"); - // fall through - case EShLangTask: - if (numTaskNVBlocks > 1) - error(infoSink, "Only one taskNV interface block is allowed per shader"); - if (numTaskEXTPayloads > 1) - error(infoSink, "Only single variable of type taskPayloadSharedEXT is allowed per shader"); - sharedBlockCheck(infoSink); - break; - default: - error(infoSink, "Unknown Stage."); - break; - } - - // Process the tree for any node-specific work. - class TFinalLinkTraverser : public TIntermTraverser { - public: - TFinalLinkTraverser() { } - virtual ~TFinalLinkTraverser() { } - - virtual void visitSymbol(TIntermSymbol* symbol) - { - // Implicitly size arrays. - // If an unsized array is left as unsized, it effectively - // becomes run-time sized. - symbol->getWritableType().adoptImplicitArraySizes(false); - } - } finalLinkTraverser; - - treeRoot->traverse(&finalLinkTraverser); -} - -// -// See if the call graph contains any static recursion, which is disallowed -// by the specification. -// -void TIntermediate::checkCallGraphCycles(TInfoSink& infoSink) -{ - // Clear fields we'll use for this. - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - call->visited = false; - call->currentPath = false; - call->errorGiven = false; - } - - // - // Loop, looking for a new connected subgraph. One subgraph is handled per loop iteration. - // - - TCall* newRoot; - do { - // See if we have unvisited parts of the graph. - newRoot = nullptr; - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - if (! call->visited) { - newRoot = &(*call); - break; - } - } - - // If not, we are done. - if (! newRoot) - break; - - // Otherwise, we found a new subgraph, process it: - // See what all can be reached by this new root, and if any of - // that is recursive. This is done by depth-first traversals, seeing - // if a new call is found that was already in the currentPath (a back edge), - // thereby detecting recursion. - std::list stack; - newRoot->currentPath = true; // currentPath will be true iff it is on the stack - stack.push_back(newRoot); - while (! stack.empty()) { - // get a caller - TCall* call = stack.back(); - - // Add to the stack just one callee. - // This algorithm always terminates, because only !visited and !currentPath causes a push - // and all pushes change currentPath to true, and all pops change visited to true. - TGraph::iterator child = callGraph.begin(); - for (; child != callGraph.end(); ++child) { - - // If we already visited this node, its whole subgraph has already been processed, so skip it. - if (child->visited) - continue; - - if (call->callee == child->caller) { - if (child->currentPath) { - // Then, we found a back edge - if (! child->errorGiven) { - error(infoSink, "Recursion detected:"); - infoSink.info << " " << call->callee << " calling " << child->callee << "\n"; - child->errorGiven = true; - recursive = true; - } - } else { - child->currentPath = true; - stack.push_back(&(*child)); - break; - } - } - } - if (child == callGraph.end()) { - // no more callees, we bottomed out, never look at this node again - stack.back()->currentPath = false; - stack.back()->visited = true; - stack.pop_back(); - } - } // end while, meaning nothing left to process in this subtree - - } while (newRoot); // redundant loop check; should always exit via the 'break' above -} - -// -// See which functions are reachable from the entry point and which have bodies. -// Reachable ones with missing bodies are errors. -// Unreachable bodies are dead code. -// -void TIntermediate::checkCallGraphBodies(TInfoSink& infoSink, bool keepUncalled) -{ - // Clear fields we'll use for this. - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - call->visited = false; - call->calleeBodyPosition = -1; - } - - // The top level of the AST includes function definitions (bodies). - // Compare these to function calls in the call graph. - // We'll end up knowing which have bodies, and if so, - // how to map the call-graph node to the location in the AST. - TIntermSequence &functionSequence = getTreeRoot()->getAsAggregate()->getSequence(); - std::vector reachable(functionSequence.size(), true); // so that non-functions are reachable - for (int f = 0; f < (int)functionSequence.size(); ++f) { - glslang::TIntermAggregate* node = functionSequence[f]->getAsAggregate(); - if (node && (node->getOp() == glslang::EOpFunction)) { - if (node->getName().compare(getEntryPointMangledName().c_str()) != 0) - reachable[f] = false; // so that function bodies are unreachable, until proven otherwise - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - if (call->callee == node->getName()) - call->calleeBodyPosition = f; - } - } - } - - // Start call-graph traversal by visiting the entry point nodes. - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - if (call->caller.compare(getEntryPointMangledName().c_str()) == 0) - call->visited = true; - } - - // Propagate 'visited' through the call-graph to every part of the graph it - // can reach (seeded with the entry-point setting above). - bool changed; - do { - changed = false; - for (auto call1 = callGraph.begin(); call1 != callGraph.end(); ++call1) { - if (call1->visited) { - for (TGraph::iterator call2 = callGraph.begin(); call2 != callGraph.end(); ++call2) { - if (! call2->visited) { - if (call1->callee == call2->caller) { - changed = true; - call2->visited = true; - } - } - } - } - } - } while (changed); - - // Any call-graph node set to visited but without a callee body is an error. - for (TGraph::iterator call = callGraph.begin(); call != callGraph.end(); ++call) { - if (call->visited) { - if (call->calleeBodyPosition == -1) { - error(infoSink, "No function definition (body) found: "); - infoSink.info << " " << call->callee << "\n"; - } else - reachable[call->calleeBodyPosition] = true; - } - } - - // Bodies in the AST not reached by the call graph are dead; - // clear them out, since they can't be reached and also can't - // be translated further due to possibility of being ill defined. - if (! keepUncalled) { - for (int f = 0; f < (int)functionSequence.size(); ++f) { - if (! reachable[f]) - { - resetTopLevelUncalledStatus(functionSequence[f]->getAsAggregate()->getName()); - functionSequence[f] = nullptr; - } - } - functionSequence.erase(std::remove(functionSequence.begin(), functionSequence.end(), nullptr), functionSequence.end()); - } -} - -// -// Satisfy rules for location qualifiers on inputs and outputs -// -void TIntermediate::inOutLocationCheck(TInfoSink& infoSink) -{ - // ES 3.0 requires all outputs to have location qualifiers if there is more than one output - bool fragOutWithNoLocation = false; - int numFragOut = 0; - - // TODO: linker functionality: location collision checking - - TIntermSequence& linkObjects = findLinkerObjects()->getSequence(); - for (size_t i = 0; i < linkObjects.size(); ++i) { - const TType& type = linkObjects[i]->getAsTyped()->getType(); - const TQualifier& qualifier = type.getQualifier(); - if (language == EShLangFragment) { - if (qualifier.storage == EvqVaryingOut && qualifier.builtIn == EbvNone) { - ++numFragOut; - if (!qualifier.hasAnyLocation()) - fragOutWithNoLocation = true; - } - } - } - - if (isEsProfile()) { - if (numFragOut > 1 && fragOutWithNoLocation) - error(infoSink, "when more than one fragment shader output, all must have location qualifiers"); - } -} - -TIntermAggregate* TIntermediate::findLinkerObjects() const -{ - // Get the top-level globals - TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence(); - - // Get the last member of the sequences, expected to be the linker-object lists - assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects); - - return globals.back()->getAsAggregate(); -} - -// See if a variable was both a user-declared output and used. -// Note: the spec discusses writing to one, but this looks at read or write, which -// is more useful, and perhaps the spec should be changed to reflect that. -bool TIntermediate::userOutputUsed() const -{ - const TIntermSequence& linkerObjects = findLinkerObjects()->getSequence(); - - bool found = false; - for (size_t i = 0; i < linkerObjects.size(); ++i) { - const TIntermSymbol& symbolNode = *linkerObjects[i]->getAsSymbolNode(); - if (symbolNode.getQualifier().storage == EvqVaryingOut && - symbolNode.getName().compare(0, 3, "gl_") != 0 && - inIoAccessed(symbolNode.getName())) { - found = true; - break; - } - } - - return found; -} - -// Accumulate locations used for inputs, outputs, and uniforms, payload, callable data, and tileImageEXT -// and check for collisions as the accumulation is done. -// -// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. -// -// typeCollision is set to true if there is no direct collision, but the types in the same location -// are different. -// -int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& type, bool& typeCollision) -{ - typeCollision = false; - - int set; - if (qualifier.isPipeInput()) - set = 0; - else if (qualifier.isPipeOutput()) - set = 1; - else if (qualifier.storage == EvqUniform) - set = 2; - else if (qualifier.storage == EvqBuffer) - set = 3; - else if (qualifier.storage == EvqTileImageEXT) - set = 4; - else if (qualifier.isAnyPayload()) - set = 0; - else if (qualifier.isAnyCallable()) - set = 1; - else if (qualifier.isHitObjectAttrNV()) - set = 2; - else - return -1; - - int size; - if (qualifier.isAnyPayload() || qualifier.isAnyCallable()) { - size = 1; - } else if (qualifier.isUniformOrBuffer() || qualifier.isTaskMemory()) { - if (type.isSizedArray()) - size = type.getCumulativeArraySize(); - else - size = 1; - } else { - // Strip off the outer array dimension for those having an extra one. - if (type.isArray() && qualifier.isArrayedIo(language)) { - TType elementType(type, 0); - size = computeTypeLocationSize(elementType, language); - } else - size = computeTypeLocationSize(type, language); - } - - // Locations, and components within locations. - // - // Almost always, dealing with components means a single location is involved. - // The exception is a dvec3. From the spec: - // - // "A dvec3 will consume all four components of the first location and components 0 and 1 of - // the second location. This leaves components 2 and 3 available for other component-qualified - // declarations." - // - // That means, without ever mentioning a component, a component range - // for a different location gets specified, if it's not a vertex shader input. (!) - // (A vertex shader input will show using only one location, even for a dvec3/4.) - // - // So, for the case of dvec3, we need two independent ioRanges. - // - // For raytracing IO (payloads and callabledata) each declaration occupies a single - // slot irrespective of type. - int collision = -1; // no collision - if (qualifier.isAnyPayload() || qualifier.isAnyCallable() || qualifier.isHitObjectAttrNV()) { - TRange range(qualifier.layoutLocation, qualifier.layoutLocation); - collision = checkLocationRT(set, qualifier.layoutLocation); - if (collision < 0) - usedIoRT[set].push_back(range); - return collision; - } - if (size == 2 && type.getBasicType() == EbtDouble && type.getVectorSize() == 3 && - (qualifier.isPipeInput() || qualifier.isPipeOutput())) { - // Dealing with dvec3 in/out split across two locations. - // Need two io-ranges. - // The case where the dvec3 doesn't start at component 0 was previously caught as overflow. - - // First range: - TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation); - TRange componentRange(0, 3); - TIoRange range(locationRange, componentRange, type.getBasicType(), 0); - - // check for collisions - collision = checkLocationRange(set, range, type, typeCollision); - if (collision < 0) { - usedIo[set].push_back(range); - - // Second range: - TRange locationRange2(qualifier.layoutLocation + 1, qualifier.layoutLocation + 1); - TRange componentRange2(0, 1); - TIoRange range2(locationRange2, componentRange2, type.getBasicType(), 0); - - // check for collisions - collision = checkLocationRange(set, range2, type, typeCollision); - if (collision < 0) - usedIo[set].push_back(range2); - } - return collision; - } - - // Not a dvec3 in/out split across two locations, generic path. - // Need a single IO-range block. - - TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation + size - 1); - TRange componentRange(0, 3); - if (qualifier.hasComponent() || type.getVectorSize() > 0) { - int consumedComponents = type.getVectorSize() * (type.getBasicType() == EbtDouble ? 2 : 1); - if (qualifier.hasComponent()) - componentRange.start = qualifier.layoutComponent; - componentRange.last = componentRange.start + consumedComponents - 1; - } - - // combine location and component ranges - TBasicType basicTy = type.getBasicType(); - if (basicTy == EbtSampler && type.getSampler().isAttachmentEXT()) - basicTy = type.getSampler().type; - TIoRange range(locationRange, componentRange, basicTy, qualifier.hasIndex() ? qualifier.getIndex() : 0); - - // check for collisions, except for vertex inputs on desktop targeting OpenGL - if (! (!isEsProfile() && language == EShLangVertex && qualifier.isPipeInput()) || spvVersion.vulkan > 0) - collision = checkLocationRange(set, range, type, typeCollision); - - if (collision < 0) - usedIo[set].push_back(range); - - return collision; -} - -// Compare a new (the passed in) 'range' against the existing set, and see -// if there are any collisions. -// -// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. -// -int TIntermediate::checkLocationRange(int set, const TIoRange& range, const TType& type, bool& typeCollision) -{ - for (size_t r = 0; r < usedIo[set].size(); ++r) { - if (range.overlap(usedIo[set][r])) { - // there is a collision; pick one - return std::max(range.location.start, usedIo[set][r].location.start); - } else if (range.location.overlap(usedIo[set][r].location) && type.getBasicType() != usedIo[set][r].basicType) { - // aliased-type mismatch - typeCollision = true; - return std::max(range.location.start, usedIo[set][r].location.start); - } - } - - // check typeCollision between tileImageEXT and out - if (set == 4 || set == 1) { - // if the set is "tileImageEXT", check against "out" and vice versa - int againstSet = (set == 4) ? 1 : 4; - for (size_t r = 0; r < usedIo[againstSet].size(); ++r) { - if (range.location.overlap(usedIo[againstSet][r].location) && type.getBasicType() != usedIo[againstSet][r].basicType) { - // aliased-type mismatch - typeCollision = true; - return std::max(range.location.start, usedIo[againstSet][r].location.start); - } - } - } - - return -1; // no collision -} - -int TIntermediate::checkLocationRT(int set, int location) { - TRange range(location, location); - for (size_t r = 0; r < usedIoRT[set].size(); ++r) { - if (range.overlap(usedIoRT[set][r])) { - return range.start; - } - } - return -1; // no collision -} - -// Accumulate bindings and offsets, and check for collisions -// as the accumulation is done. -// -// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. -// -int TIntermediate::addUsedOffsets(int binding, int offset, int numOffsets) -{ - TRange bindingRange(binding, binding); - TRange offsetRange(offset, offset + numOffsets - 1); - TOffsetRange range(bindingRange, offsetRange); - - // check for collisions, except for vertex inputs on desktop - for (size_t r = 0; r < usedAtomics.size(); ++r) { - if (range.overlap(usedAtomics[r])) { - // there is a collision; pick one - return std::max(offset, usedAtomics[r].offset.start); - } - } - - usedAtomics.push_back(range); - - return -1; // no collision -} - -// Accumulate used constant_id values. -// -// Return false is one was already used. -bool TIntermediate::addUsedConstantId(int id) -{ - if (usedConstantId.find(id) != usedConstantId.end()) - return false; - - usedConstantId.insert(id); - - return true; -} - -// Recursively figure out how many locations are used up by an input or output type. -// Return the size of type, as measured by "locations". -int TIntermediate::computeTypeLocationSize(const TType& type, EShLanguage stage) -{ - // "If the declared input is an array of size n and each element takes m locations, it will be assigned m * n - // consecutive locations..." - if (type.isArray()) { - // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness - // TODO: are there valid cases of having an unsized array with a location? If so, running this code too early. - TType elementType(type, 0); - if (type.isSizedArray() && !type.getQualifier().isPerView()) - return type.getOuterArraySize() * computeTypeLocationSize(elementType, stage); - else { - // unset perViewNV attributes for arrayed per-view outputs: "perviewNV vec4 v[MAX_VIEWS][3];" - elementType.getQualifier().perViewNV = false; - return computeTypeLocationSize(elementType, stage); - } - } - - // "The locations consumed by block and structure members are determined by applying the rules above - // recursively..." - if (type.isStruct()) { - int size = 0; - for (int member = 0; member < (int)type.getStruct()->size(); ++member) { - TType memberType(type, member); - size += computeTypeLocationSize(memberType, stage); - } - return size; - } - - // ES: "If a shader input is any scalar or vector type, it will consume a single location." - - // Desktop: "If a vertex shader input is any scalar or vector type, it will consume a single location. If a non-vertex - // shader input is a scalar or vector type other than dvec3 or dvec4, it will consume a single location, while - // types dvec3 or dvec4 will consume two consecutive locations. Inputs of type double and dvec2 will - // consume only a single location, in all stages." - if (type.isScalar()) - return 1; - if (type.isVector()) { - if (stage == EShLangVertex && type.getQualifier().isPipeInput()) - return 1; - if (type.getBasicType() == EbtDouble && type.getVectorSize() > 2) - return 2; - else - return 1; - } - - // "If the declared input is an n x m single- or double-precision matrix, ... - // The number of locations assigned for each matrix will be the same as - // for an n-element array of m-component vectors..." - if (type.isMatrix()) { - TType columnType(type, 0); - return type.getMatrixCols() * computeTypeLocationSize(columnType, stage); - } - - assert(0); - return 1; -} - -// Same as computeTypeLocationSize but for uniforms -int TIntermediate::computeTypeUniformLocationSize(const TType& type) -{ - // "Individual elements of a uniform array are assigned - // consecutive locations with the first element taking location - // location." - if (type.isArray()) { - // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness - TType elementType(type, 0); - if (type.isSizedArray()) { - return type.getOuterArraySize() * computeTypeUniformLocationSize(elementType); - } else { - // TODO: are there valid cases of having an implicitly-sized array with a location? If so, running this code too early. - return computeTypeUniformLocationSize(elementType); - } - } - - // "Each subsequent inner-most member or element gets incremental - // locations for the entire structure or array." - if (type.isStruct()) { - int size = 0; - for (int member = 0; member < (int)type.getStruct()->size(); ++member) { - TType memberType(type, member); - size += computeTypeUniformLocationSize(memberType); - } - return size; - } - - return 1; -} - -// Accumulate xfb buffer ranges and check for collisions as the accumulation is done. -// -// Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. -// -int TIntermediate::addXfbBufferOffset(const TType& type) -{ - const TQualifier& qualifier = type.getQualifier(); - - assert(qualifier.hasXfbOffset() && qualifier.hasXfbBuffer()); - TXfbBuffer& buffer = xfbBuffers[qualifier.layoutXfbBuffer]; - - // compute the range - unsigned int size = computeTypeXfbSize(type, buffer.contains64BitType, buffer.contains32BitType, buffer.contains16BitType); - buffer.implicitStride = std::max(buffer.implicitStride, qualifier.layoutXfbOffset + size); - TRange range(qualifier.layoutXfbOffset, qualifier.layoutXfbOffset + size - 1); - - // check for collisions - for (size_t r = 0; r < buffer.ranges.size(); ++r) { - if (range.overlap(buffer.ranges[r])) { - // there is a collision; pick an example to return - return std::max(range.start, buffer.ranges[r].start); - } - } - - buffer.ranges.push_back(range); - - return -1; // no collision -} - -// Recursively figure out how many bytes of xfb buffer are used by the given type. -// Return the size of type, in bytes. -// Sets contains64BitType to true if the type contains a 64-bit data type. -// Sets contains32BitType to true if the type contains a 32-bit data type. -// Sets contains16BitType to true if the type contains a 16-bit data type. -// N.B. Caller must set contains64BitType, contains32BitType, and contains16BitType to false before calling. -unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const -{ - // "...if applied to an aggregate containing a double or 64-bit integer, the offset must also be a multiple of 8, - // and the space taken in the buffer will be a multiple of 8. - // ...within the qualified entity, subsequent components are each - // assigned, in order, to the next available offset aligned to a multiple of - // that component's size. Aggregate types are flattened down to the component - // level to get this sequence of components." - - if (type.isSizedArray()) { - // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness - // Unsized array use to xfb should be a compile error. - TType elementType(type, 0); - return type.getOuterArraySize() * computeTypeXfbSize(elementType, contains64BitType, contains16BitType, contains16BitType); - } - - if (type.isStruct()) { - unsigned int size = 0; - bool structContains64BitType = false; - bool structContains32BitType = false; - bool structContains16BitType = false; - for (int member = 0; member < (int)type.getStruct()->size(); ++member) { - TType memberType(type, member); - // "... if applied to - // an aggregate containing a double or 64-bit integer, the offset must also be a multiple of 8, - // and the space taken in the buffer will be a multiple of 8." - bool memberContains64BitType = false; - bool memberContains32BitType = false; - bool memberContains16BitType = false; - int memberSize = computeTypeXfbSize(memberType, memberContains64BitType, memberContains32BitType, memberContains16BitType); - if (memberContains64BitType) { - structContains64BitType = true; - RoundToPow2(size, 8); - } else if (memberContains32BitType) { - structContains32BitType = true; - RoundToPow2(size, 4); - } else if (memberContains16BitType) { - structContains16BitType = true; - RoundToPow2(size, 2); - } - size += memberSize; - } - - if (structContains64BitType) { - contains64BitType = true; - RoundToPow2(size, 8); - } else if (structContains32BitType) { - contains32BitType = true; - RoundToPow2(size, 4); - } else if (structContains16BitType) { - contains16BitType = true; - RoundToPow2(size, 2); - } - return size; - } - - int numComponents {0}; - if (type.isScalar()) - numComponents = 1; - else if (type.isVector()) - numComponents = type.getVectorSize(); - else if (type.isMatrix()) - numComponents = type.getMatrixCols() * type.getMatrixRows(); - else { - assert(0); - numComponents = 1; - } - - if (type.getBasicType() == EbtDouble || type.getBasicType() == EbtInt64 || type.getBasicType() == EbtUint64) { - contains64BitType = true; - return 8 * numComponents; - } else if (type.getBasicType() == EbtFloat16 || type.getBasicType() == EbtInt16 || type.getBasicType() == EbtUint16) { - contains16BitType = true; - return 2 * numComponents; - } else if (type.getBasicType() == EbtInt8 || type.getBasicType() == EbtUint8) - return numComponents; - else { - contains32BitType = true; - return 4 * numComponents; - } -} - -const int baseAlignmentVec4Std140 = 16; - -// Return the size and alignment of a component of the given type. -// The size is returned in the 'size' parameter -// Return value is the alignment.. -int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size) -{ - switch (type.getBasicType()) { - case EbtInt64: - case EbtUint64: - case EbtDouble: size = 8; return 8; - case EbtFloat16: size = 2; return 2; - case EbtInt8: - case EbtUint8: size = 1; return 1; - case EbtInt16: - case EbtUint16: size = 2; return 2; - case EbtReference: size = 8; return 8; - case EbtSampler: - { - if (type.isBindlessImage() || type.isBindlessTexture()) { - size = 8; return 8; - } - else { - size = 4; return 4; - } - } - default: size = 4; return 4; - } -} - -// Implement base-alignment and size rules from section 7.6.2.2 Standard Uniform Block Layout -// Operates recursively. -// -// If std140 is true, it does the rounding up to vec4 size required by std140, -// otherwise it does not, yielding std430 rules. -// -// The size is returned in the 'size' parameter -// -// The stride is only non-0 for arrays or matrices, and is the stride of the -// top-level object nested within the type. E.g., for an array of matrices, -// it is the distances needed between matrices, despite the rules saying the -// stride comes from the flattening down to vectors. -// -// Return value is the alignment of the type. -int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor) -{ - int alignment; - - bool std140 = layoutPacking == glslang::ElpStd140; - // When using the std140 storage layout, structures will be laid out in buffer - // storage with its members stored in monotonically increasing order based on their - // location in the declaration. A structure and each structure member have a base - // offset and a base alignment, from which an aligned offset is computed by rounding - // the base offset up to a multiple of the base alignment. The base offset of the first - // member of a structure is taken from the aligned offset of the structure itself. The - // base offset of all other structure members is derived by taking the offset of the - // last basic machine unit consumed by the previous member and adding one. Each - // structure member is stored in memory at its aligned offset. The members of a top- - // level uniform block are laid out in buffer storage by treating the uniform block as - // a structure with a base offset of zero. - // - // 1. If the member is a scalar consuming N basic machine units, the base alignment is N. - // - // 2. If the member is a two- or four-component vector with components consuming N basic - // machine units, the base alignment is 2N or 4N, respectively. - // - // 3. If the member is a three-component vector with components consuming N - // basic machine units, the base alignment is 4N. - // - // 4. If the member is an array of scalars or vectors, the base alignment and array - // stride are set to match the base alignment of a single array element, according - // to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The - // array may have padding at the end; the base offset of the member following - // the array is rounded up to the next multiple of the base alignment. - // - // 5. If the member is a column-major matrix with C columns and R rows, the - // matrix is stored identically to an array of C column vectors with R - // components each, according to rule (4). - // - // 6. If the member is an array of S column-major matrices with C columns and - // R rows, the matrix is stored identically to a row of S X C column vectors - // with R components each, according to rule (4). - // - // 7. If the member is a row-major matrix with C columns and R rows, the matrix - // is stored identically to an array of R row vectors with C components each, - // according to rule (4). - // - // 8. If the member is an array of S row-major matrices with C columns and R - // rows, the matrix is stored identically to a row of S X R row vectors with C - // components each, according to rule (4). - // - // 9. If the member is a structure, the base alignment of the structure is N , where - // N is the largest base alignment value of any of its members, and rounded - // up to the base alignment of a vec4. The individual members of this substructure - // are then assigned offsets by applying this set of rules recursively, - // where the base offset of the first member of the sub-structure is equal to the - // aligned offset of the structure. The structure may have padding at the end; - // the base offset of the member following the sub-structure is rounded up to - // the next multiple of the base alignment of the structure. - // - // 10. If the member is an array of S structures, the S elements of the array are laid - // out in order, according to rule (9). - // - // Assuming, for rule 10: The stride is the same as the size of an element. - - stride = 0; - int dummyStride; - - // rules 4, 6, 8, and 10 - if (type.isArray()) { - // TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness - TType derefType(type, 0); - alignment = getBaseAlignment(derefType, size, dummyStride, layoutPacking, rowMajor); - if (std140) - alignment = std::max(baseAlignmentVec4Std140, alignment); - RoundToPow2(size, alignment); - stride = size; // uses full matrix size for stride of an array of matrices (not quite what rule 6/8, but what's expected) - // uses the assumption for rule 10 in the comment above - // use one element to represent the last member of SSBO which is unsized array - int arraySize = (type.isUnsizedArray() && (type.getOuterArraySize() == 0)) ? 1 : type.getOuterArraySize(); - size = stride * arraySize; - return alignment; - } - - // rule 9 - if (type.getBasicType() == EbtStruct || type.getBasicType() == EbtBlock) { - const TTypeList& memberList = *type.getStruct(); - - size = 0; - int maxAlignment = std140 ? baseAlignmentVec4Std140 : 0; - for (size_t m = 0; m < memberList.size(); ++m) { - int memberSize; - // modify just the children's view of matrix layout, if there is one for this member - TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix; - int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, layoutPacking, - (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor); - maxAlignment = std::max(maxAlignment, memberAlignment); - RoundToPow2(size, memberAlignment); - size += memberSize; - } - - // The structure may have padding at the end; the base offset of - // the member following the sub-structure is rounded up to the next - // multiple of the base alignment of the structure. - RoundToPow2(size, maxAlignment); - - return maxAlignment; - } - - // rule 1 - if (type.isScalar()) - return getBaseAlignmentScalar(type, size); - - // rules 2 and 3 - if (type.isVector()) { - int scalarAlign = getBaseAlignmentScalar(type, size); - switch (type.getVectorSize()) { - case 1: // HLSL has this, GLSL does not - return scalarAlign; - case 2: - size *= 2; - return 2 * scalarAlign; - default: - size *= type.getVectorSize(); - return 4 * scalarAlign; - } - } - - // rules 5 and 7 - if (type.isMatrix()) { - // rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows - TType derefType(type, 0, rowMajor); - - alignment = getBaseAlignment(derefType, size, dummyStride, layoutPacking, rowMajor); - if (std140) - alignment = std::max(baseAlignmentVec4Std140, alignment); - RoundToPow2(size, alignment); - stride = size; // use intra-matrix stride for stride of a just a matrix - if (rowMajor) - size = stride * type.getMatrixRows(); - else - size = stride * type.getMatrixCols(); - - return alignment; - } - - assert(0); // all cases should be covered above - size = baseAlignmentVec4Std140; - return baseAlignmentVec4Std140; -} - -// To aid the basic HLSL rule about crossing vec4 boundaries. -bool TIntermediate::improperStraddle(const TType& type, int size, int offset) -{ - if (! type.isVector() || type.isArray()) - return false; - - return size <= 16 ? offset / 16 != (offset + size - 1) / 16 - : offset % 16 != 0; -} - -int TIntermediate::getScalarAlignment(const TType& type, int& size, int& stride, bool rowMajor) -{ - int alignment; - - stride = 0; - int dummyStride; - - if (type.isArray()) { - TType derefType(type, 0); - alignment = getScalarAlignment(derefType, size, dummyStride, rowMajor); - - stride = size; - RoundToPow2(stride, alignment); - - size = stride * (type.getOuterArraySize() - 1) + size; - return alignment; - } - - if (type.getBasicType() == EbtStruct) { - const TTypeList& memberList = *type.getStruct(); - - size = 0; - int maxAlignment = 0; - for (size_t m = 0; m < memberList.size(); ++m) { - int memberSize; - // modify just the children's view of matrix layout, if there is one for this member - TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix; - int memberAlignment = getScalarAlignment(*memberList[m].type, memberSize, dummyStride, - (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor); - maxAlignment = std::max(maxAlignment, memberAlignment); - RoundToPow2(size, memberAlignment); - size += memberSize; - } - - return maxAlignment; - } - - if (type.isScalar()) - return getBaseAlignmentScalar(type, size); - - if (type.isVector()) { - int scalarAlign = getBaseAlignmentScalar(type, size); - - size *= type.getVectorSize(); - return scalarAlign; - } - - if (type.isMatrix()) { - TType derefType(type, 0, rowMajor); - - alignment = getScalarAlignment(derefType, size, dummyStride, rowMajor); - - stride = size; // use intra-matrix stride for stride of a just a matrix - if (rowMajor) - size = stride * type.getMatrixRows(); - else - size = stride * type.getMatrixCols(); - - return alignment; - } - - assert(0); // all cases should be covered above - size = 1; - return 1; -} - -int TIntermediate::getMemberAlignment(const TType& type, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor) -{ - if (layoutPacking == glslang::ElpScalar) { - return getScalarAlignment(type, size, stride, rowMajor); - } else { - return getBaseAlignment(type, size, stride, layoutPacking, rowMajor); - } -} - -// shared calculation by getOffset and getOffsets -void TIntermediate::updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize) -{ - int dummyStride; - - // modify just the children's view of matrix layout, if there is one for this member - TLayoutMatrix subMatrixLayout = memberType.getQualifier().layoutMatrix; - int memberAlignment = getMemberAlignment(memberType, memberSize, dummyStride, - parentType.getQualifier().layoutPacking, - subMatrixLayout != ElmNone - ? subMatrixLayout == ElmRowMajor - : parentType.getQualifier().layoutMatrix == ElmRowMajor); - RoundToPow2(offset, memberAlignment); -} - -// Lookup or calculate the offset of a block member, using the recursively -// defined block offset rules. -int TIntermediate::getOffset(const TType& type, int index) -{ - const TTypeList& memberList = *type.getStruct(); - - // Don't calculate offset if one is present, it could be user supplied - // and different than what would be calculated. That is, this is faster, - // but not just an optimization. - if (memberList[index].type->getQualifier().hasOffset()) - return memberList[index].type->getQualifier().layoutOffset; - - int memberSize = 0; - int offset = 0; - for (int m = 0; m <= index; ++m) { - updateOffset(type, *memberList[m].type, offset, memberSize); - - if (m < index) - offset += memberSize; - } - - return offset; -} - -// Calculate the block data size. -// Block arrayness is not taken into account, each element is backed by a separate buffer. -int TIntermediate::getBlockSize(const TType& blockType) -{ - const TTypeList& memberList = *blockType.getStruct(); - int lastIndex = (int)memberList.size() - 1; - int lastOffset = getOffset(blockType, lastIndex); - - int lastMemberSize; - int dummyStride; - getMemberAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride, - blockType.getQualifier().layoutPacking, - blockType.getQualifier().layoutMatrix == ElmRowMajor); - - return lastOffset + lastMemberSize; -} - -int TIntermediate::computeBufferReferenceTypeSize(const TType& type) -{ - assert(type.isReference()); - int size = getBlockSize(*type.getReferentType()); - - int align = type.getBufferReferenceAlignment(); - - if (align) { - size = (size + align - 1) & ~(align-1); - } - - return size; -} - -bool TIntermediate::isIoResizeArray(const TType& type, EShLanguage language) { - return type.isArray() && - ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || - (language == EShLangTessControl && (type.getQualifier().storage == EvqVaryingIn || type.getQualifier().storage == EvqVaryingOut) && - ! type.getQualifier().patch) || - (language == EShLangTessEvaluation && type.getQualifier().storage == EvqVaryingIn) || - (language == EShLangFragment && type.getQualifier().storage == EvqVaryingIn && - (type.getQualifier().pervertexNV || type.getQualifier().pervertexEXT)) || - (language == EShLangMesh && type.getQualifier().storage == EvqVaryingOut && - !type.getQualifier().perTaskNV)); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h b/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h deleted file mode 100644 index c73f2b4d..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/localintermediate.h +++ /dev/null @@ -1,1265 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2016 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _LOCAL_INTERMEDIATE_INCLUDED_ -#define _LOCAL_INTERMEDIATE_INCLUDED_ - -#include "../Include/intermediate.h" -#include "../Public/ShaderLang.h" -#include "Versions.h" - -#include -#include -#include -#include -#include -#include - -class TInfoSink; - -namespace glslang { - -struct TMatrixSelector { - int coord1; // stay agnostic about column/row; this is parse order - int coord2; -}; - -typedef int TVectorSelector; - -const int MaxSwizzleSelectors = 4; - -template -class TSwizzleSelectors { -public: - TSwizzleSelectors() : size_(0) { } - - void push_back(selectorType comp) - { - if (size_ < MaxSwizzleSelectors) - components[size_++] = comp; - } - void resize(int s) - { - assert(s <= size_); - size_ = s; - } - int size() const { return size_; } - selectorType operator[](int i) const - { - assert(i < MaxSwizzleSelectors); - return components[i]; - } - -private: - int size_; - selectorType components[MaxSwizzleSelectors]; -}; - -// -// Some helper structures for TIntermediate. Their contents are encapsulated -// by TIntermediate. -// - -// Used for call-graph algorithms for detecting recursion, missing bodies, and dead bodies. -// A "call" is a pair: . -// There can be duplicates. General assumption is the list is small. -struct TCall { - TCall(const TString& pCaller, const TString& pCallee) : caller(pCaller), callee(pCallee) { } - TString caller; - TString callee; - bool visited; - bool currentPath; - bool errorGiven; - int calleeBodyPosition; -}; - -// A generic 1-D range. -struct TRange { - TRange(int start, int last) : start(start), last(last) { } - bool overlap(const TRange& rhs) const - { - return last >= rhs.start && start <= rhs.last; - } - int start; - int last; -}; - -// An IO range is a 3-D rectangle; the set of (location, component, index) triples all lying -// within the same location range, component range, and index value. Locations don't alias unless -// all other dimensions of their range overlap. -struct TIoRange { - TIoRange(TRange location, TRange component, TBasicType basicType, int index) - : location(location), component(component), basicType(basicType), index(index) { } - bool overlap(const TIoRange& rhs) const - { - return location.overlap(rhs.location) && component.overlap(rhs.component) && index == rhs.index; - } - TRange location; - TRange component; - TBasicType basicType; - int index; -}; - -// An offset range is a 2-D rectangle; the set of (binding, offset) pairs all lying -// within the same binding and offset range. -struct TOffsetRange { - TOffsetRange(TRange binding, TRange offset) - : binding(binding), offset(offset) { } - bool overlap(const TOffsetRange& rhs) const - { - return binding.overlap(rhs.binding) && offset.overlap(rhs.offset); - } - TRange binding; - TRange offset; -}; - -// Things that need to be tracked per xfb buffer. -struct TXfbBuffer { - TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false), - contains32BitType(false), contains16BitType(false) { } - std::vector ranges; // byte offsets that have already been assigned - unsigned int stride; - unsigned int implicitStride; - bool contains64BitType; - bool contains32BitType; - bool contains16BitType; -}; - -// Track a set of strings describing how the module was processed. -// This includes command line options, transforms, etc., ideally inclusive enough -// to reproduce the steps used to transform the input source to the output. -// E.g., see SPIR-V OpModuleProcessed. -// Each "process" or "transform" uses is expressed in the form: -// process arg0 arg1 arg2 ... -// process arg0 arg1 arg2 ... -// where everything is textual, and there can be zero or more arguments -class TProcesses { -public: - TProcesses() {} - ~TProcesses() {} - - void addProcess(const char* process) - { - processes.push_back(process); - } - void addProcess(const std::string& process) - { - processes.push_back(process); - } - void addArgument(int arg) - { - processes.back().append(" "); - std::string argString = std::to_string(arg); - processes.back().append(argString); - } - void addArgument(const char* arg) - { - processes.back().append(" "); - processes.back().append(arg); - } - void addArgument(const std::string& arg) - { - processes.back().append(" "); - processes.back().append(arg); - } - void addIfNonZero(const char* process, int value) - { - if (value != 0) { - addProcess(process); - addArgument(value); - } - } - - const std::vector& getProcesses() const { return processes; } - -private: - std::vector processes; -}; - -class TSymbolTable; -class TSymbol; -class TVariable; - -// -// Texture and Sampler transformation mode. -// -enum ComputeDerivativeMode { - LayoutDerivativeNone, // default layout as SPV_NV_compute_shader_derivatives not enabled - LayoutDerivativeGroupQuads, // derivative_group_quadsNV - LayoutDerivativeGroupLinear, // derivative_group_linearNV -}; - -// -// Status type on AST level. Some uncalled status or functions would be reset in call graph. -// Currently we will keep status set by explicitly declared layout or variable decl. -// -enum AstRefType { - AstRefTypeVar, // Status set by variable decl - AstRefTypeFunc, // Status set by function decl - AstRefTypeLayout, // Status set by layout decl -}; - -class TIdMaps { -public: - TMap& operator[](long long i) { return maps[i]; } - const TMap& operator[](long long i) const { return maps[i]; } -private: - TMap maps[EsiCount]; -}; - -class TNumericFeatures { -public: - TNumericFeatures() : features(0) { } - TNumericFeatures(const TNumericFeatures&) = delete; - TNumericFeatures& operator=(const TNumericFeatures&) = delete; - typedef enum : unsigned int { - shader_explicit_arithmetic_types = 1 << 0, - shader_explicit_arithmetic_types_int8 = 1 << 1, - shader_explicit_arithmetic_types_int16 = 1 << 2, - shader_explicit_arithmetic_types_int32 = 1 << 3, - shader_explicit_arithmetic_types_int64 = 1 << 4, - shader_explicit_arithmetic_types_float16 = 1 << 5, - shader_explicit_arithmetic_types_float32 = 1 << 6, - shader_explicit_arithmetic_types_float64 = 1 << 7, - shader_implicit_conversions = 1 << 8, - gpu_shader_fp64 = 1 << 9, - gpu_shader_int16 = 1 << 10, - gpu_shader_half_float = 1 << 11, - } feature; - void insert(feature f) { features |= f; } - void erase(feature f) { features &= ~f; } - bool contains(feature f) const { return (features & f) != 0; } -private: - unsigned int features; -}; - -// MustBeAssigned wraps a T, asserting that it has been assigned with -// operator =() before attempting to read with operator T() or operator ->(). -// Used to catch cases where fields are read before they have been assigned. -template -class MustBeAssigned -{ -public: - MustBeAssigned() = default; - MustBeAssigned(const T& v) : value(v) {} - operator const T&() const { assert(isSet); return value; } - const T* operator ->() const { assert(isSet); return &value; } - MustBeAssigned& operator = (const T& v) { value = v; isSet = true; return *this; } -private: - T value; - bool isSet = false; -}; - -// -// Set of helper functions to help parse and build the tree. -// -class TIntermediate { -public: - explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : - language(l), - profile(p), version(v), - treeRoot(nullptr), - resources(TBuiltInResource{}), - numEntryPoints(0), numErrors(0), numPushConstants(0), recursive(false), - invertY(false), - dxPositionW(false), - enhancedMsgs(false), - debugInfo(false), - useStorageBuffer(false), - invariantAll(false), - nanMinMaxClamp(false), - depthReplacing(false), - stencilReplacing(false), - uniqueId(0), - globalUniformBlockName(""), - atomicCounterBlockName(""), - globalUniformBlockSet(TQualifier::layoutSetEnd), - globalUniformBlockBinding(TQualifier::layoutBindingEnd), - atomicCounterBlockSet(TQualifier::layoutSetEnd), - implicitThisName("@this"), implicitCounterName("@count"), - source(EShSourceNone), - useVulkanMemoryModel(false), - invocations(TQualifier::layoutNotSet), vertices(TQualifier::layoutNotSet), - inputPrimitive(ElgNone), outputPrimitive(ElgNone), - pixelCenterInteger(false), originUpperLeft(false),texCoordBuiltinRedeclared(false), - vertexSpacing(EvsNone), vertexOrder(EvoNone), interlockOrdering(EioNone), pointMode(false), earlyFragmentTests(false), - postDepthCoverage(false), earlyAndLateFragmentTestsAMD(false), - nonCoherentColorAttachmentReadEXT(false), - nonCoherentDepthAttachmentReadEXT(false), - nonCoherentStencilAttachmentReadEXT(false), - depthLayout(EldNone), - stencilLayout(ElsNone), - hlslFunctionality1(false), - blendEquations(0), xfbMode(false), multiStream(false), - layoutOverrideCoverage(false), - geoPassthroughEXT(false), - numShaderRecordBlocks(0), - computeDerivativeMode(LayoutDerivativeNone), - primitives(TQualifier::layoutNotSet), - numTaskNVBlocks(0), - layoutPrimitiveCulling(false), - numTaskEXTPayloads(0), - autoMapBindings(false), - autoMapLocations(false), - flattenUniformArrays(false), - useUnknownFormat(false), - hlslOffsets(false), - hlslIoMapping(false), - useVariablePointers(false), - textureSamplerTransformMode(EShTexSampTransKeep), - needToLegalize(false), - binaryDoubleOutput(false), - subgroupUniformControlFlow(false), - usePhysicalStorageBuffer(false), - spirvRequirement(nullptr), - spirvExecutionMode(nullptr), - uniformLocationBase(0) - { - localSize[0] = 1; - localSize[1] = 1; - localSize[2] = 1; - localSizeNotDefault[0] = false; - localSizeNotDefault[1] = false; - localSizeNotDefault[2] = false; - localSizeSpecId[0] = TQualifier::layoutNotSet; - localSizeSpecId[1] = TQualifier::layoutNotSet; - localSizeSpecId[2] = TQualifier::layoutNotSet; - xfbBuffers.resize(TQualifier::layoutXfbBufferEnd); - shiftBinding.fill(0); - } - - void setVersion(int v) - { - version = v; - } - void setProfile(EProfile p) - { - profile = p; - } - - int getVersion() const { return version; } - EProfile getProfile() const { return profile; } - void setSpv(const SpvVersion& s) - { - spvVersion = s; - - // client processes - if (spvVersion.vulkan > 0) - processes.addProcess("client vulkan100"); - if (spvVersion.openGl > 0) - processes.addProcess("client opengl100"); - - // target SPV - switch (spvVersion.spv) { - case 0: - break; - case EShTargetSpv_1_0: - break; - case EShTargetSpv_1_1: - processes.addProcess("target-env spirv1.1"); - break; - case EShTargetSpv_1_2: - processes.addProcess("target-env spirv1.2"); - break; - case EShTargetSpv_1_3: - processes.addProcess("target-env spirv1.3"); - break; - case EShTargetSpv_1_4: - processes.addProcess("target-env spirv1.4"); - break; - case EShTargetSpv_1_5: - processes.addProcess("target-env spirv1.5"); - break; - case EShTargetSpv_1_6: - processes.addProcess("target-env spirv1.6"); - break; - default: - processes.addProcess("target-env spirvUnknown"); - break; - } - - // target-environment processes - switch (spvVersion.vulkan) { - case 0: - break; - case EShTargetVulkan_1_0: - processes.addProcess("target-env vulkan1.0"); - break; - case EShTargetVulkan_1_1: - processes.addProcess("target-env vulkan1.1"); - break; - case EShTargetVulkan_1_2: - processes.addProcess("target-env vulkan1.2"); - break; - case EShTargetVulkan_1_3: - processes.addProcess("target-env vulkan1.3"); - break; - default: - processes.addProcess("target-env vulkanUnknown"); - break; - } - if (spvVersion.openGl > 0) - processes.addProcess("target-env opengl"); - } - const SpvVersion& getSpv() const { return spvVersion; } - EShLanguage getStage() const { return language; } - void addRequestedExtension(const char* extension) { requestedExtensions.insert(extension); } - const std::set& getRequestedExtensions() const { return requestedExtensions; } - bool isRayTracingStage() const { - return language >= EShLangRayGen && language <= EShLangCallableNV; - } - - void setTreeRoot(TIntermNode* r) { treeRoot = r; } - TIntermNode* getTreeRoot() const { return treeRoot; } - void incrementEntryPointCount() { ++numEntryPoints; } - int getNumEntryPoints() const { return numEntryPoints; } - int getNumErrors() const { return numErrors; } - void addPushConstantCount() { ++numPushConstants; } - void setLimits(const TBuiltInResource& r) { resources = r; } - const TBuiltInResource& getLimits() const { return resources; } - - bool postProcess(TIntermNode*, EShLanguage); - void removeTree(); - - void setEntryPointName(const char* ep) - { - entryPointName = ep; - processes.addProcess("entry-point"); - processes.addArgument(entryPointName); - } - void setEntryPointMangledName(const char* ep) { entryPointMangledName = ep; } - const std::string& getEntryPointName() const { return entryPointName; } - const std::string& getEntryPointMangledName() const { return entryPointMangledName; } - - void setDebugInfo(bool debuginfo) - { - debugInfo = debuginfo; - } - bool getDebugInfo() const { return debugInfo; } - - void setInvertY(bool invert) - { - invertY = invert; - if (invertY) - processes.addProcess("invert-y"); - } - bool getInvertY() const { return invertY; } - - void setDxPositionW(bool dxPosW) - { - dxPositionW = dxPosW; - if (dxPositionW) - processes.addProcess("dx-position-w"); - } - bool getDxPositionW() const { return dxPositionW; } - - void setEnhancedMsgs() - { - enhancedMsgs = true; - } - bool getEnhancedMsgs() const { return enhancedMsgs && getSource() == EShSourceGlsl; } - -#ifdef ENABLE_HLSL - void setSource(EShSource s) { source = s; } - EShSource getSource() const { return source; } -#else - void setSource(EShSource s) { assert(s == EShSourceGlsl); (void)s; } - EShSource getSource() const { return EShSourceGlsl; } -#endif - - bool isRecursive() const { return recursive; } - - TIntermSymbol* addSymbol(const TVariable&); - TIntermSymbol* addSymbol(const TVariable&, const TSourceLoc&); - TIntermSymbol* addSymbol(const TType&, const TSourceLoc&); - TIntermSymbol* addSymbol(const TIntermSymbol&); - TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); - std::tuple addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1); - TIntermTyped* addUniShapeConversion(TOperator, const TType&, TIntermTyped*); - TIntermTyped* addConversion(TBasicType convertTo, TIntermTyped* node) const; - void addBiShapeConversion(TOperator, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode); - TIntermTyped* addShapeConversion(const TType&, TIntermTyped*); - TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); - TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); - TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&); - TIntermTyped* addUnaryMath(TOperator, TIntermTyped* child, const TSourceLoc&); - TIntermTyped* addBuiltInFunctionCall(const TSourceLoc& line, TOperator, bool unary, TIntermNode*, const TType& returnType); - bool canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op = EOpNull) const; - bool isIntegralPromotion(TBasicType from, TBasicType to) const; - bool isFPPromotion(TBasicType from, TBasicType to) const; - bool isIntegralConversion(TBasicType from, TBasicType to) const; - bool isFPConversion(TBasicType from, TBasicType to) const; - bool isFPIntegralConversion(TBasicType from, TBasicType to) const; - TOperator mapTypeToConstructorOp(const TType&) const; - TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right); - TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); - TIntermAggregate* mergeAggregate(TIntermNode* left, TIntermNode* right); - TIntermAggregate* mergeAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); - TIntermAggregate* makeAggregate(TIntermNode* node); - TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); - TIntermAggregate* makeAggregate(const TSourceLoc&); - TIntermTyped* setAggregateOperator(TIntermNode*, TOperator, const TType& type, const TSourceLoc&); - bool areAllChildConst(TIntermAggregate* aggrNode); - TIntermSelection* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); - TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); - TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); - TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, const TSourceLoc&); - TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, const TSourceLoc&, bool literal = false) const; - TIntermConstantUnion* addConstantUnion(signed char, const TSourceLoc&, bool literal = false) const; - TIntermConstantUnion* addConstantUnion(unsigned char, const TSourceLoc&, bool literal = false) const; - TIntermConstantUnion* addConstantUnion(signed short, const TSourceLoc&, bool literal = false) const; - TIntermConstantUnion* addConstantUnion(unsigned short, const TSourceLoc&, bool literal = false) const; - TIntermConstantUnion* addConstantUnion(int, const TSourceLoc&, bool literal = false) const; - TIntermConstantUnion* addConstantUnion(unsigned int, const TSourceLoc&, bool literal = false) const; - TIntermConstantUnion* addConstantUnion(long long, const TSourceLoc&, bool literal = false) const; - TIntermConstantUnion* addConstantUnion(unsigned long long, const TSourceLoc&, bool literal = false) const; - TIntermConstantUnion* addConstantUnion(bool, const TSourceLoc&, bool literal = false) const; - TIntermConstantUnion* addConstantUnion(double, TBasicType, const TSourceLoc&, bool literal = false) const; - TIntermConstantUnion* addConstantUnion(const TString*, const TSourceLoc&, bool literal = false) const; - TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const; - bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false); - TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&); - TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, - const TSourceLoc&, TIntermLoop*&); - TIntermBranch* addBranch(TOperator, const TSourceLoc&); - TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); - template TIntermTyped* addSwizzle(TSwizzleSelectors&, const TSourceLoc&); - - // Low level functions to add nodes (no conversions or other higher level transformations) - // If a type is provided, the node's type will be set to it. - TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&) const; - TIntermBinary* addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, - const TType&) const; - TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&) const; - TIntermUnary* addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc&, const TType&) const; - - // Constant folding (in Constant.cpp) - TIntermTyped* fold(TIntermAggregate* aggrNode); - TIntermTyped* foldConstructor(TIntermAggregate* aggrNode); - TIntermTyped* foldDereference(TIntermTyped* node, int index, const TSourceLoc&); - TIntermTyped* foldSwizzle(TIntermTyped* node, TSwizzleSelectors& fields, const TSourceLoc&); - - // Tree ops - static const TIntermTyped* traverseLValueBase(const TIntermTyped*, bool swizzleOkay, bool bufferReferenceOk = false, - std::function proc = {}); - - // Linkage related - void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); - void addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol&); - TIntermAggregate* findLinkerObjects() const; - - void setGlobalUniformBlockName(const char* name) { globalUniformBlockName = std::string(name); } - const char* getGlobalUniformBlockName() const { return globalUniformBlockName.c_str(); } - void setGlobalUniformSet(unsigned int set) { globalUniformBlockSet = set; } - unsigned int getGlobalUniformSet() const { return globalUniformBlockSet; } - void setGlobalUniformBinding(unsigned int binding) { globalUniformBlockBinding = binding; } - unsigned int getGlobalUniformBinding() const { return globalUniformBlockBinding; } - - void setAtomicCounterBlockName(const char* name) { atomicCounterBlockName = std::string(name); } - const char* getAtomicCounterBlockName() const { return atomicCounterBlockName.c_str(); } - void setAtomicCounterBlockSet(unsigned int set) { atomicCounterBlockSet = set; } - unsigned int getAtomicCounterBlockSet() const { return atomicCounterBlockSet; } - - - void setUseStorageBuffer() { useStorageBuffer = true; } - bool usingStorageBuffer() const { return useStorageBuffer; } - void setInvariantAll() { invariantAll = true; } - bool isInvariantAll() const { return invariantAll; } - void setDepthReplacing() { depthReplacing = true; } - bool isDepthReplacing() const { return depthReplacing; } - void setStencilReplacing() { stencilReplacing = true; } - bool isStencilReplacing() const { return stencilReplacing; } - bool setLocalSize(int dim, int size) - { - if (localSizeNotDefault[dim]) - return size == localSize[dim]; - localSizeNotDefault[dim] = true; - localSize[dim] = size; - return true; - } - unsigned int getLocalSize(int dim) const { return localSize[dim]; } - bool isLocalSizeSet() const - { - // Return true if any component has been set (i.e. any component is not default). - return localSizeNotDefault[0] || localSizeNotDefault[1] || localSizeNotDefault[2]; - } - bool setLocalSizeSpecId(int dim, int id) - { - if (localSizeSpecId[dim] != TQualifier::layoutNotSet) - return id == localSizeSpecId[dim]; - localSizeSpecId[dim] = id; - return true; - } - int getLocalSizeSpecId(int dim) const { return localSizeSpecId[dim]; } - bool isLocalSizeSpecialized() const - { - // Return true if any component has been specialized. - return localSizeSpecId[0] != TQualifier::layoutNotSet || - localSizeSpecId[1] != TQualifier::layoutNotSet || - localSizeSpecId[2] != TQualifier::layoutNotSet; - } - void output(TInfoSink&, bool tree); - - bool isEsProfile() const { return profile == EEsProfile; } - - void setShiftBinding(TResourceType res, unsigned int shift) - { - shiftBinding[res] = shift; - - const char* name = getResourceName(res); - if (name != nullptr) - processes.addIfNonZero(name, shift); - } - - unsigned int getShiftBinding(TResourceType res) const { return shiftBinding[res]; } - - void setShiftBindingForSet(TResourceType res, unsigned int shift, unsigned int set) - { - if (shift == 0) // ignore if there's no shift: it's a no-op. - return; - - shiftBindingForSet[res][set] = shift; - - const char* name = getResourceName(res); - if (name != nullptr) { - processes.addProcess(name); - processes.addArgument(shift); - processes.addArgument(set); - } - } - - int getShiftBindingForSet(TResourceType res, unsigned int set) const - { - const auto shift = shiftBindingForSet[res].find(set); - return shift == shiftBindingForSet[res].end() ? -1 : shift->second; - } - bool hasShiftBindingForSet(TResourceType res) const { return !shiftBindingForSet[res].empty(); } - - void setResourceSetBinding(const std::vector& shift) - { - resourceSetBinding = shift; - if (shift.size() > 0) { - processes.addProcess("resource-set-binding"); - for (int s = 0; s < (int)shift.size(); ++s) - processes.addArgument(shift[s]); - } - } - const std::vector& getResourceSetBinding() const { return resourceSetBinding; } - void setAutoMapBindings(bool map) - { - autoMapBindings = map; - if (autoMapBindings) - processes.addProcess("auto-map-bindings"); - } - bool getAutoMapBindings() const { return autoMapBindings; } - void setAutoMapLocations(bool map) - { - autoMapLocations = map; - if (autoMapLocations) - processes.addProcess("auto-map-locations"); - } - bool getAutoMapLocations() const { return autoMapLocations; } - -#ifdef ENABLE_HLSL - void setFlattenUniformArrays(bool flatten) - { - flattenUniformArrays = flatten; - if (flattenUniformArrays) - processes.addProcess("flatten-uniform-arrays"); - } - bool getFlattenUniformArrays() const { return flattenUniformArrays; } -#endif - void setNoStorageFormat(bool b) - { - useUnknownFormat = b; - if (useUnknownFormat) - processes.addProcess("no-storage-format"); - } - bool getNoStorageFormat() const { return useUnknownFormat; } - void setUseVulkanMemoryModel() - { - useVulkanMemoryModel = true; - processes.addProcess("use-vulkan-memory-model"); - } - bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; } - void setUsePhysicalStorageBuffer() - { - usePhysicalStorageBuffer = true; - } - bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; } - void setUseVariablePointers() - { - useVariablePointers = true; - processes.addProcess("use-variable-pointers"); - } - // Set the global flag for bindless texture - void setBindlessTextureMode(const TString& currentCaller, AstRefType type) - { - // When type is not func, currentCaller should be "" (empty string) - bindlessTextureModeCaller[currentCaller] = type; - } - - // Get the global flag for bindless texture - bool getBindlessTextureMode() const - { - return (bindlessTextureModeCaller.size() > 0); - } - - // Set the global flag for bindless image - void setBindlessImageMode(const TString& currentCaller, AstRefType type) - { - // When type is not func, currentCaller should be "" (empty string) - bindlessImageModeCaller[currentCaller] = type; - } - - // Get the global flag for bindless image - bool getBindlessImageMode() const - { - return (bindlessImageModeCaller.size() > 0); - } - - // Get the global flag for bindless texture - bool resetTopLevelUncalledStatus(const TString& deadCaller) - { - // For reflection collection purpose, currently uniform layout setting and some - // flags introduced by variables (IO, global, etc,.) won't be reset here. - // Remove each global status (AST top level) introduced by uncalled functions. - // If a status is set by several functions, keep those which in call graph. - bool result = false; - - // For two types of bindless mode flag, we would only reset which is set by an uncalled function. - // If one status flag's key in caller vec is empty, it should be come from a non-function setting. - if (!bindlessTextureModeCaller.empty()) { - auto caller = bindlessTextureModeCaller.find(deadCaller); - if (caller != bindlessTextureModeCaller.end() && bindlessTextureModeCaller[deadCaller] == AstRefTypeFunc) { - bindlessTextureModeCaller.erase(caller); - result = true; - } - } - if (!bindlessImageModeCaller.empty()) { - auto caller = bindlessImageModeCaller.find(deadCaller); - if (caller != bindlessImageModeCaller.end() && bindlessImageModeCaller[deadCaller] == AstRefTypeFunc) { - bindlessImageModeCaller.erase(caller); - result = true; - } - } - return result; - } - - bool getBindlessMode() const - { - return getBindlessTextureMode() || getBindlessImageMode(); - } - - bool usingVariablePointers() const { return useVariablePointers; } - -#ifdef ENABLE_HLSL - template T addCounterBufferName(const T& name) const { return name + implicitCounterName; } - bool hasCounterBufferName(const TString& name) const { - size_t len = strlen(implicitCounterName); - return name.size() > len && - name.compare(name.size() - len, len, implicitCounterName) == 0; - } -#endif - - void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { textureSamplerTransformMode = mode; } - int getNumPushConstants() const { return numPushConstants; } - void addShaderRecordCount() { ++numShaderRecordBlocks; } - void addTaskNVCount() { ++numTaskNVBlocks; } - void addTaskPayloadEXTCount() { ++numTaskEXTPayloads; } - - bool setInvocations(int i) - { - if (invocations != TQualifier::layoutNotSet) - return invocations == i; - invocations = i; - return true; - } - int getInvocations() const { return invocations; } - bool setVertices(int m) - { - if (vertices != TQualifier::layoutNotSet) - return vertices == m; - vertices = m; - return true; - } - int getVertices() const { return vertices; } - bool setInputPrimitive(TLayoutGeometry p) - { - if (inputPrimitive != ElgNone) - return inputPrimitive == p; - inputPrimitive = p; - return true; - } - TLayoutGeometry getInputPrimitive() const { return inputPrimitive; } - bool setVertexSpacing(TVertexSpacing s) - { - if (vertexSpacing != EvsNone) - return vertexSpacing == s; - vertexSpacing = s; - return true; - } - TVertexSpacing getVertexSpacing() const { return vertexSpacing; } - bool setVertexOrder(TVertexOrder o) - { - if (vertexOrder != EvoNone) - return vertexOrder == o; - vertexOrder = o; - return true; - } - TVertexOrder getVertexOrder() const { return vertexOrder; } - void setPointMode() { pointMode = true; } - bool getPointMode() const { return pointMode; } - - bool setInterlockOrdering(TInterlockOrdering o) - { - if (interlockOrdering != EioNone) - return interlockOrdering == o; - interlockOrdering = o; - return true; - } - TInterlockOrdering getInterlockOrdering() const { return interlockOrdering; } - - void setXfbMode() { xfbMode = true; } - bool getXfbMode() const { return xfbMode; } - void setMultiStream() { multiStream = true; } - bool isMultiStream() const { return multiStream; } - bool setOutputPrimitive(TLayoutGeometry p) - { - if (outputPrimitive != ElgNone) - return outputPrimitive == p; - outputPrimitive = p; - return true; - } - TLayoutGeometry getOutputPrimitive() const { return outputPrimitive; } - void setNonCoherentColorAttachmentReadEXT() { nonCoherentColorAttachmentReadEXT = true; } - bool getNonCoherentColorAttachmentReadEXT() const { return nonCoherentColorAttachmentReadEXT; } - void setNonCoherentDepthAttachmentReadEXT() { nonCoherentDepthAttachmentReadEXT = true; } - bool getNonCoherentDepthAttachmentReadEXT() const { return nonCoherentDepthAttachmentReadEXT; } - void setNonCoherentStencilAttachmentReadEXT() { nonCoherentStencilAttachmentReadEXT = true; } - bool getNonCoherentStencilAttachmentReadEXT() const { return nonCoherentStencilAttachmentReadEXT; } - void setPostDepthCoverage() { postDepthCoverage = true; } - bool getPostDepthCoverage() const { return postDepthCoverage; } - void setEarlyFragmentTests() { earlyFragmentTests = true; } - void setEarlyAndLateFragmentTestsAMD() { earlyAndLateFragmentTestsAMD = true; } - bool getEarlyFragmentTests() const { return earlyFragmentTests; } - bool getEarlyAndLateFragmentTestsAMD() const { return earlyAndLateFragmentTestsAMD; } - bool setDepth(TLayoutDepth d) - { - if (depthLayout != EldNone) - return depthLayout == d; - depthLayout = d; - return true; - } - bool setStencil(TLayoutStencil s) - { - if (stencilLayout != ElsNone) - return stencilLayout == s; - stencilLayout = s; - return true; - } - TLayoutDepth getDepth() const { return depthLayout; } - TLayoutStencil getStencil() const { return stencilLayout; } - void setOriginUpperLeft() { originUpperLeft = true; } - bool getOriginUpperLeft() const { return originUpperLeft; } - void setPixelCenterInteger() { pixelCenterInteger = true; } - bool getPixelCenterInteger() const { return pixelCenterInteger; } - void setTexCoordRedeclared() { texCoordBuiltinRedeclared = true; } - bool getTexCoordRedeclared() const { return texCoordBuiltinRedeclared; } - void addBlendEquation(TBlendEquationShift b) { blendEquations |= (1 << b); } - unsigned int getBlendEquations() const { return blendEquations; } - bool setXfbBufferStride(int buffer, unsigned stride) - { - if (xfbBuffers[buffer].stride != TQualifier::layoutXfbStrideEnd) - return xfbBuffers[buffer].stride == stride; - xfbBuffers[buffer].stride = stride; - return true; - } - unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; } - int addXfbBufferOffset(const TType&); - unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const; - unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const; - void setLayoutOverrideCoverage() { layoutOverrideCoverage = true; } - bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; } - void setGeoPassthroughEXT() { geoPassthroughEXT = true; } - bool getGeoPassthroughEXT() const { return geoPassthroughEXT; } - void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; } - bool hasLayoutDerivativeModeNone() const { return computeDerivativeMode != LayoutDerivativeNone; } - ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; } - void setLayoutPrimitiveCulling() { layoutPrimitiveCulling = true; } - bool getLayoutPrimitiveCulling() const { return layoutPrimitiveCulling; } - bool setPrimitives(int m) - { - if (primitives != TQualifier::layoutNotSet) - return primitives == m; - primitives = m; - return true; - } - int getPrimitives() const { return primitives; } - const char* addSemanticName(const TString& name) - { - return semanticNameSet.insert(name).first->c_str(); - } - void addUniformLocationOverride(const char* nameStr, int location) - { - std::string name = nameStr; - uniformLocationOverrides[name] = location; - } - - int getUniformLocationOverride(const char* nameStr) const - { - std::string name = nameStr; - auto pos = uniformLocationOverrides.find(name); - if (pos == uniformLocationOverrides.end()) - return -1; - else - return pos->second; - } - - void setUniformLocationBase(int base) { uniformLocationBase = base; } - int getUniformLocationBase() const { return uniformLocationBase; } - - void setNeedsLegalization() { needToLegalize = true; } - bool needsLegalization() const { return needToLegalize; } - - void setBinaryDoubleOutput() { binaryDoubleOutput = true; } - bool getBinaryDoubleOutput() { return binaryDoubleOutput; } - - void setSubgroupUniformControlFlow() { subgroupUniformControlFlow = true; } - bool getSubgroupUniformControlFlow() const { return subgroupUniformControlFlow; } - - // GL_EXT_spirv_intrinsics - void insertSpirvRequirement(const TSpirvRequirement* spirvReq); - bool hasSpirvRequirement() const { return spirvRequirement != nullptr; } - const TSpirvRequirement& getSpirvRequirement() const { return *spirvRequirement; } - void insertSpirvExecutionMode(int executionMode, const TIntermAggregate* args = nullptr); - void insertSpirvExecutionModeId(int executionMode, const TIntermAggregate* args); - bool hasSpirvExecutionMode() const { return spirvExecutionMode != nullptr; } - const TSpirvExecutionMode& getSpirvExecutionMode() const { return *spirvExecutionMode; } - - void addBlockStorageOverride(const char* nameStr, TBlockStorageClass backing) - { - std::string name(nameStr); - blockBackingOverrides[name] = backing; - } - TBlockStorageClass getBlockStorageOverride(const char* nameStr) const - { - std::string name = nameStr; - auto pos = blockBackingOverrides.find(name); - if (pos == blockBackingOverrides.end()) - return EbsNone; - else - return pos->second; - } -#ifdef ENABLE_HLSL - void setHlslFunctionality1() { hlslFunctionality1 = true; } - bool getHlslFunctionality1() const { return hlslFunctionality1; } - void setHlslOffsets() - { - hlslOffsets = true; - if (hlslOffsets) - processes.addProcess("hlsl-offsets"); - } - bool usingHlslOffsets() const { return hlslOffsets; } - void setHlslIoMapping(bool b) - { - hlslIoMapping = b; - if (hlslIoMapping) - processes.addProcess("hlsl-iomap"); - } - bool usingHlslIoMapping() { return hlslIoMapping; } -#else - bool getHlslFunctionality1() const { return false; } - bool usingHlslOffsets() const { return false; } - bool usingHlslIoMapping() { return false; } -#endif - - bool usingScalarBlockLayout() const { - for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt) { - if (*extIt == E_GL_EXT_scalar_block_layout) - return true; - } - return false; - } - - bool IsRequestedExtension(const char* extension) const - { - return (requestedExtensions.find(extension) != requestedExtensions.end()); - } - - void addToCallGraph(TInfoSink&, const TString& caller, const TString& callee); - void merge(TInfoSink&, TIntermediate&); - void finalCheck(TInfoSink&, bool keepUncalled); - - void mergeGlobalUniformBlocks(TInfoSink& infoSink, TIntermediate& unit, bool mergeExistingOnly); - void mergeUniformObjects(TInfoSink& infoSink, TIntermediate& unit); - void checkStageIO(TInfoSink&, TIntermediate&); - - bool buildConvertOp(TBasicType dst, TBasicType src, TOperator& convertOp) const; - TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const; - - void addIoAccessed(const TString& name) { ioAccessed.insert(name); } - bool inIoAccessed(const TString& name) const { return ioAccessed.find(name) != ioAccessed.end(); } - - int addUsedLocation(const TQualifier&, const TType&, bool& typeCollision); - int checkLocationRange(int set, const TIoRange& range, const TType&, bool& typeCollision); - int checkLocationRT(int set, int location); - int addUsedOffsets(int binding, int offset, int numOffsets); - bool addUsedConstantId(int id); - static int computeTypeLocationSize(const TType&, EShLanguage); - static int computeTypeUniformLocationSize(const TType&); - - static int getBaseAlignmentScalar(const TType&, int& size); - static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); - static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor); - static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor); - static bool improperStraddle(const TType& type, int size, int offset); - static void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize); - static int getOffset(const TType& type, int index); - static int getBlockSize(const TType& blockType); - static int computeBufferReferenceTypeSize(const TType&); - static bool isIoResizeArray(const TType& type, EShLanguage language); - - bool promote(TIntermOperator*); - void setNanMinMaxClamp(bool setting) { nanMinMaxClamp = setting; } - bool getNanMinMaxClamp() const { return nanMinMaxClamp; } - - void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; } - const std::string& getSourceFile() const { return sourceFile; } - void addSourceText(const char* text, size_t len) { sourceText.append(text, len); } - const std::string& getSourceText() const { return sourceText; } - const std::map& getIncludeText() const { return includeText; } - void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); } - void addProcesses(const std::vector& p) - { - for (int i = 0; i < (int)p.size(); ++i) - processes.addProcess(p[i]); - } - void addProcess(const std::string& process) { processes.addProcess(process); } - void addProcessArgument(const std::string& arg) { processes.addArgument(arg); } - const std::vector& getProcesses() const { return processes.getProcesses(); } - unsigned long long getUniqueId() const { return uniqueId; } - void setUniqueId(unsigned long long id) { uniqueId = id; } - - // Certain explicit conversions are allowed conditionally - bool getArithemeticInt8Enabled() const { - return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8); - } - bool getArithemeticInt16Enabled() const { - return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || - numericFeatures.contains(TNumericFeatures::gpu_shader_int16) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16); - } - - bool getArithemeticFloat16Enabled() const { - return numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) || - numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) || - numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16); - } - void updateNumericFeature(TNumericFeatures::feature f, bool on) - { on ? numericFeatures.insert(f) : numericFeatures.erase(f); } - -protected: - TIntermSymbol* addSymbol(long long Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); - void error(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount); - void warn(TInfoSink& infoSink, const char*, EShLanguage unitStage = EShLangCount); - void mergeCallGraphs(TInfoSink&, TIntermediate&); - void mergeModes(TInfoSink&, TIntermediate&); - void mergeTrees(TInfoSink&, TIntermediate&); - void seedIdMap(TIdMaps& idMaps, long long& IdShift); - void remapIds(const TIdMaps& idMaps, long long idShift, TIntermediate&); - void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); - void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects, EShLanguage); - void mergeBlockDefinitions(TInfoSink&, TIntermSymbol* block, TIntermSymbol* unitBlock, TIntermediate* unitRoot); - void mergeImplicitArraySizes(TType&, const TType&); - void mergeErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, EShLanguage); - void checkCallGraphCycles(TInfoSink&); - void checkCallGraphBodies(TInfoSink&, bool keepUncalled); - void inOutLocationCheck(TInfoSink&); - void sharedBlockCheck(TInfoSink&); - bool userOutputUsed() const; - bool isSpecializationOperation(const TIntermOperator&) const; - bool isNonuniformPropagating(TOperator) const; - bool promoteUnary(TIntermUnary&); - bool promoteBinary(TIntermBinary&); - void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); - bool promoteAggregate(TIntermAggregate&); - void pushSelector(TIntermSequence&, const TVectorSelector&, const TSourceLoc&); - void pushSelector(TIntermSequence&, const TMatrixSelector&, const TSourceLoc&); - bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); - void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root); - bool isConversionAllowed(TOperator op, TIntermTyped* node) const; - std::tuple getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const; - - static const char* getResourceName(TResourceType); - - const EShLanguage language; // stage, known at construction time - std::string entryPointName; - std::string entryPointMangledName; - typedef std::list TGraph; - TGraph callGraph; - - EProfile profile; // source profile - int version; // source version - SpvVersion spvVersion; - TIntermNode* treeRoot; - std::set requestedExtensions; // cumulation of all enabled or required extensions; not connected to what subset of the shader used them - MustBeAssigned resources; - int numEntryPoints; - int numErrors; - int numPushConstants; - bool recursive; - bool invertY; - bool dxPositionW; - bool enhancedMsgs; - bool debugInfo; - bool useStorageBuffer; - bool invariantAll; - bool nanMinMaxClamp; // true if desiring min/max/clamp to favor non-NaN over NaN - bool depthReplacing; - bool stencilReplacing; - int localSize[3]; - bool localSizeNotDefault[3]; - int localSizeSpecId[3]; - unsigned long long uniqueId; - - std::string globalUniformBlockName; - std::string atomicCounterBlockName; - unsigned int globalUniformBlockSet; - unsigned int globalUniformBlockBinding; - unsigned int atomicCounterBlockSet; - -public: - const char* const implicitThisName; - const char* const implicitCounterName; -protected: - EShSource source; // source language, known a bit later - bool useVulkanMemoryModel; - int invocations; - int vertices; - TLayoutGeometry inputPrimitive; - TLayoutGeometry outputPrimitive; - bool pixelCenterInteger; - bool originUpperLeft; - bool texCoordBuiltinRedeclared; - TVertexSpacing vertexSpacing; - TVertexOrder vertexOrder; - TInterlockOrdering interlockOrdering; - bool pointMode; - bool earlyFragmentTests; - bool postDepthCoverage; - bool earlyAndLateFragmentTestsAMD; - bool nonCoherentColorAttachmentReadEXT; - bool nonCoherentDepthAttachmentReadEXT; - bool nonCoherentStencilAttachmentReadEXT; - TLayoutDepth depthLayout; - TLayoutStencil stencilLayout; - bool hlslFunctionality1; - int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift - bool xfbMode; - std::vector xfbBuffers; // all the data we need to track per xfb buffer - bool multiStream; - bool layoutOverrideCoverage; - bool geoPassthroughEXT; - int numShaderRecordBlocks; - ComputeDerivativeMode computeDerivativeMode; - int primitives; - int numTaskNVBlocks; - bool layoutPrimitiveCulling; - int numTaskEXTPayloads; - - // Base shift values - std::array shiftBinding; - - // Per-descriptor-set shift values - std::array, EResCount> shiftBindingForSet; - - std::vector resourceSetBinding; - bool autoMapBindings; - bool autoMapLocations; - bool flattenUniformArrays; - bool useUnknownFormat; - bool hlslOffsets; - bool hlslIoMapping; - bool useVariablePointers; - - std::set semanticNameSet; - - EShTextureSamplerTransformMode textureSamplerTransformMode; - - bool needToLegalize; - bool binaryDoubleOutput; - bool subgroupUniformControlFlow; - bool usePhysicalStorageBuffer; - - TSpirvRequirement* spirvRequirement; - TSpirvExecutionMode* spirvExecutionMode; - std::map bindlessTextureModeCaller; - std::map bindlessImageModeCaller; - std::unordered_map uniformLocationOverrides; - int uniformLocationBase; - TNumericFeatures numericFeatures; - std::unordered_map blockBackingOverrides; - - std::unordered_set usedConstantId; // specialization constant ids used - std::vector usedAtomics; // sets of bindings used by atomic counters - std::vector usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers - std::vector usedIoRT[4]; // sets of used location, one for rayPayload/rayPayloadIN, - // one for callableData/callableDataIn, one for hitObjectAttributeNV and - // one for shaderrecordhitobjectNV - // set of names of statically read/written I/O that might need extra checking - std::set ioAccessed; - - // source code of shader, useful as part of debug information - std::string sourceFile; - std::string sourceText; - - // Included text. First string is a name, second is the included text - std::map includeText; - - // for OpModuleProcessed, or equivalent - TProcesses processes; - -private: - void operator=(TIntermediate&); // prevent assignments -}; - -} // end namespace glslang - -#endif // _LOCAL_INTERMEDIATE_INCLUDED_ diff --git a/3rdparty/glslang/glslang/MachineIndependent/parseConst.cpp b/3rdparty/glslang/glslang/MachineIndependent/parseConst.cpp deleted file mode 100644 index 83509723..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/parseConst.cpp +++ /dev/null @@ -1,213 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// Traverse a tree of constants to create a single folded constant. -// It should only be used when the whole tree is known to be constant. -// - -#include "ParseHelper.h" - -namespace glslang { - -class TConstTraverser : public TIntermTraverser { -public: - TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t) - : unionArray(cUnion), type(t), - constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false), - matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull; } - - virtual void visitConstantUnion(TIntermConstantUnion* node); - virtual bool visitAggregate(TVisit, TIntermAggregate* node); - - int index; - TConstUnionArray unionArray; - TOperator tOp; - const TType& type; - TOperator constructorType; - bool singleConstantParam; - bool error; - int size; // size of the constructor ( 4 for vec4) - bool isMatrix; - int matrixCols; - int matrixRows; - -protected: - TConstTraverser(TConstTraverser&); - TConstTraverser& operator=(TConstTraverser&); -}; - -bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node) -{ - if (! node->isConstructor() && node->getOp() != EOpComma) { - error = true; - - return false; - } - - bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion(); - if (flag) { - singleConstantParam = true; - constructorType = node->getOp(); - size = node->getType().computeNumComponents(); - - if (node->getType().isMatrix()) { - isMatrix = true; - matrixCols = node->getType().getMatrixCols(); - matrixRows = node->getType().getMatrixRows(); - } - } - - for (TIntermSequence::iterator p = node->getSequence().begin(); - p != node->getSequence().end(); p++) { - - if (node->getOp() == EOpComma) - index = 0; - - (*p)->traverse(this); - } - if (flag) - { - singleConstantParam = false; - constructorType = EOpNull; - size = 0; - isMatrix = false; - matrixCols = 0; - matrixRows = 0; - } - - return false; -} - -void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) -{ - TConstUnionArray leftUnionArray(unionArray); - int instanceSize = type.computeNumComponents(); - - if (index >= instanceSize) - return; - - if (! singleConstantParam) { - int rightUnionSize = node->getType().computeNumComponents(); - - const TConstUnionArray& rightUnionArray = node->getConstArray(); - for (int i = 0; i < rightUnionSize; i++) { - if (index >= instanceSize) - return; - leftUnionArray[index] = rightUnionArray[i]; - - index++; - } - } else { - int endIndex = index + size; - const TConstUnionArray& rightUnionArray = node->getConstArray(); - if (! isMatrix) { - int count = 0; - int nodeComps = node->getType().computeNumComponents(); - for (int i = index; i < endIndex; i++) { - if (i >= instanceSize) - return; - - leftUnionArray[i] = rightUnionArray[count]; - - (index)++; - - if (nodeComps > 1) - count++; - } - } else { - // constructing a matrix, but from what? - if (node->isMatrix()) { - // Matrix from a matrix; this has the outer matrix, node is the argument matrix. - // Traverse the outer, potentially bigger matrix, fill in missing pieces with the - // identity matrix. - for (int c = 0; c < matrixCols; ++c) { - for (int r = 0; r < matrixRows; ++r) { - int targetOffset = index + c * matrixRows + r; - if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) { - int srcOffset = c * node->getType().getMatrixRows() + r; - leftUnionArray[targetOffset] = rightUnionArray[srcOffset]; - } else if (r == c) - leftUnionArray[targetOffset].setDConst(1.0); - else - leftUnionArray[targetOffset].setDConst(0.0); - } - } - } else { - // matrix from vector or scalar - int nodeComps = node->getType().computeNumComponents(); - if (nodeComps == 1) { - for (int c = 0; c < matrixCols; ++c) { - for (int r = 0; r < matrixRows; ++r) { - if (r == c) - leftUnionArray[index] = rightUnionArray[0]; - else - leftUnionArray[index].setDConst(0.0); - index++; - } - } - } else { - int count = 0; - for (int i = index; i < endIndex; i++) { - if (i >= instanceSize) - return; - - // construct the matrix in column-major order, from - // the components provided, in order - leftUnionArray[i] = rightUnionArray[count]; - - index++; - count++; - } - } - } - } - } -} - -bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam) -{ - if (root == nullptr) - return false; - - TConstTraverser it(unionArray, singleConstantParam, constructorType, t); - - root->traverse(&it); - if (it.error) - return true; - else - return false; -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/parseVersions.h b/3rdparty/glslang/glslang/MachineIndependent/parseVersions.h deleted file mode 100644 index 63841c40..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/parseVersions.h +++ /dev/null @@ -1,181 +0,0 @@ -// -// Copyright (C) 2015-2018 Google, Inc. -// Copyright (C) 2017 ARM Limited. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// This is implemented in Versions.cpp - -#ifndef _PARSE_VERSIONS_INCLUDED_ -#define _PARSE_VERSIONS_INCLUDED_ - -#include "../Public/ShaderLang.h" -#include "../Include/InfoSink.h" -#include "Scan.h" - -#include - -namespace glslang { - -// -// Base class for parse helpers. -// This just has version-related information and checking. -// This class should be sufficient for preprocessing. -// -class TParseVersions { -public: - TParseVersions(TIntermediate& interm, int version, EProfile profile, - const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink, - bool forwardCompatible, EShMessages messages) - : - forwardCompatible(forwardCompatible), - profile(profile), - infoSink(infoSink), version(version), - language(language), - spvVersion(spvVersion), - intermediate(interm), messages(messages), numErrors(0), currentScanner(nullptr) { } - virtual ~TParseVersions() { } - void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc); - void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc); - - bool forwardCompatible; // true if errors are to be given for use of deprecated features - EProfile profile; // the declared profile in the shader (core by default) - bool isEsProfile() const { return profile == EEsProfile; } - void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc); - void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions, - const char* const extensions[], const char* featureDesc); - void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension, - const char* featureDesc); - virtual void initializeExtensionBehavior(); - virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc); - virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc); - virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], - const char* featureDesc); - virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[], - const char* featureDesc); - virtual TExtensionBehavior getExtensionBehavior(const char*); - virtual bool extensionTurnedOn(const char* const extension); - virtual bool extensionsTurnedOn(int numExtensions, const char* const extensions[]); - virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior); - virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior); - virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], - const char* featureDesc); - virtual void checkExtensionStage(const TSourceLoc&, const char* const extension); - virtual void extensionRequires(const TSourceLoc&, const char* const extension, const char* behavior); - virtual void fullIntegerCheck(const TSourceLoc&, const char* op); - - virtual void unimplemented(const TSourceLoc&, const char* featureDesc); - virtual void doubleCheck(const TSourceLoc&, const char* op); - virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false); - virtual void float16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); - virtual bool float16Arithmetic(); - virtual void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); - virtual void int16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); - virtual bool int16Arithmetic(); - virtual void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); - virtual void int8ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false); - virtual bool int8Arithmetic(); - virtual void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc); - virtual void float16OpaqueCheck(const TSourceLoc&, const char* op, bool builtIn = false); - virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false); - virtual void explicitInt8Check(const TSourceLoc&, const char* op, bool builtIn = false); - virtual void explicitInt16Check(const TSourceLoc&, const char* op, bool builtIn = false); - virtual void explicitInt32Check(const TSourceLoc&, const char* op, bool builtIn = false); - virtual void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false); - virtual void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false); - virtual void fcoopmatCheckNV(const TSourceLoc&, const char* op, bool builtIn = false); - virtual void intcoopmatCheckNV(const TSourceLoc&, const char *op, bool builtIn = false); - virtual void coopmatCheck(const TSourceLoc&, const char* op, bool builtIn = false); - bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; } - bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; } - bool isForwardCompatible() const { return forwardCompatible; } - - virtual void spvRemoved(const TSourceLoc&, const char* op); - virtual void vulkanRemoved(const TSourceLoc&, const char* op); - virtual void requireVulkan(const TSourceLoc&, const char* op); - virtual void requireSpv(const TSourceLoc&, const char* op); - virtual void requireSpv(const TSourceLoc&, const char *op, unsigned int version); - - virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) = 0; - virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) = 0; - virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) = 0; - virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...) = 0; - - void addError() { ++numErrors; } - int getNumErrors() const { return numErrors; } - - void setScanner(TInputScanner* scanner) { currentScanner = scanner; } - TInputScanner* getScanner() const { return currentScanner; } - const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); } - void setCurrentLine(int line) { currentScanner->setLine(line); } - void setCurrentColumn(int col) { currentScanner->setColumn(col); } - void setCurrentSourceName(const char* name) { currentScanner->setFile(name); } - void setCurrentString(int string) { currentScanner->setString(string); } - - void getPreamble(std::string&); -#ifdef ENABLE_HLSL - bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; } - bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; } - bool hlslDX9Compatible() const { return (messages & EShMsgHlslDX9Compatible) != 0; } -#else - bool isReadingHLSL() const { return false; } -#endif - - TInfoSink& infoSink; - - // compilation mode - int version; // version, updated by #version in the shader - EShLanguage language; // really the stage - SpvVersion spvVersion; - TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree - -protected: - TMap extensionBehavior; // for each extension string, what its current behavior is - TMap extensionMinSpv; // for each extension string, store minimum spirv required - TVector spvUnsupportedExt; // for extensions reserved for spv usage. - EShMessages messages; // errors/warnings/rule-sets - int numErrors; // number of compile-time errors encountered - TInputScanner* currentScanner; - -private: - explicit TParseVersions(const TParseVersions&); - TParseVersions& operator=(const TParseVersions&); -}; - -} // end namespace glslang - -#endif // _PARSE_VERSIONS_INCLUDED_ diff --git a/3rdparty/glslang/glslang/MachineIndependent/pch.h b/3rdparty/glslang/glslang/MachineIndependent/pch.h deleted file mode 100644 index 6ea3761e..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/pch.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _PCH_H -#define _PCH_H -// -// Copyright (C) 2018 The Khronos Group Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -#include -#include -#include -#include -#include -#include -#include -#include -#include "SymbolTable.h" -#include "ParseHelper.h" -#include "Scan.h" -#include "ScanContext.h" - -#endif /* _PCH_H */ diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp deleted file mode 100644 index 16b9d243..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp +++ /dev/null @@ -1,1346 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ - -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include -#include -#include -#include -#include - -#include "PpContext.h" -#include "PpTokens.h" - -namespace glslang { - -// Handle #define -int TPpContext::CPPdefine(TPpToken* ppToken) -{ - MacroSymbol mac; - - // get the macro name - int token = scanToken(ppToken); - if (token != PpAtomIdentifier) { - parseContext.ppError(ppToken->loc, "must be followed by macro name", "#define", ""); - return token; - } - if (ppToken->loc.string >= 0) { - // We are in user code; check for reserved name use: - parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#define"); - } - - // save the macro name - const int defAtom = atomStrings.getAddAtom(ppToken->name); - TSourceLoc defineLoc = ppToken->loc; // because ppToken might go to the next line before we report errors - - // gather parameters to the macro, between (...) - token = scanToken(ppToken); - if (token == '(' && !ppToken->space) { - mac.functionLike = 1; - do { - token = scanToken(ppToken); - if (mac.args.size() == 0 && token == ')') - break; - if (token != PpAtomIdentifier) { - parseContext.ppError(ppToken->loc, "bad argument", "#define", ""); - - return token; - } - const int argAtom = atomStrings.getAddAtom(ppToken->name); - - // check for duplication of parameter name - bool duplicate = false; - for (size_t a = 0; a < mac.args.size(); ++a) { - if (mac.args[a] == argAtom) { - parseContext.ppError(ppToken->loc, "duplicate macro parameter", "#define", ""); - duplicate = true; - break; - } - } - if (! duplicate) - mac.args.push_back(argAtom); - token = scanToken(ppToken); - } while (token == ','); - if (token != ')') { - parseContext.ppError(ppToken->loc, "missing parenthesis", "#define", ""); - - return token; - } - - token = scanToken(ppToken); - } else if (token != '\n' && token != EndOfInput && !ppToken->space) { - parseContext.ppWarn(ppToken->loc, "missing space after macro name", "#define", ""); - - return token; - } - - // record the definition of the macro - while (token != '\n' && token != EndOfInput) { - mac.body.putToken(token, ppToken); - token = scanToken(ppToken); - if (token != '\n' && ppToken->space) - mac.body.putToken(' ', ppToken); - } - - // check for duplicate definition - MacroSymbol* existing = lookupMacroDef(defAtom); - if (existing != nullptr) { - if (! existing->undef) { - // Already defined -- need to make sure they are identical: - // "Two replacement lists are identical if and only if the - // preprocessing tokens in both have the same number, - // ordering, spelling, and white-space separation, where all - // white-space separations are considered identical." - if (existing->functionLike != mac.functionLike) { - parseContext.ppError(defineLoc, "Macro redefined; function-like versus object-like:", "#define", - atomStrings.getString(defAtom)); - } else if (existing->args.size() != mac.args.size()) { - parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", - atomStrings.getString(defAtom)); - } else { - if (existing->args != mac.args) { - parseContext.ppError(defineLoc, "Macro redefined; different argument names:", "#define", - atomStrings.getString(defAtom)); - } - // set up to compare the two - existing->body.reset(); - mac.body.reset(); - int newToken; - bool firstToken = true; - do { - int oldToken; - TPpToken oldPpToken; - TPpToken newPpToken; - oldToken = existing->body.getToken(parseContext, &oldPpToken); - newToken = mac.body.getToken(parseContext, &newPpToken); - // for the first token, preceding spaces don't matter - if (firstToken) { - newPpToken.space = oldPpToken.space; - firstToken = false; - } - if (oldToken != newToken || oldPpToken != newPpToken) { - parseContext.ppError(defineLoc, "Macro redefined; different substitutions:", "#define", - atomStrings.getString(defAtom)); - break; - } - } while (newToken != EndOfInput); - } - } - *existing = mac; - } else - addMacroDef(defAtom, mac); - - return '\n'; -} - -// Handle #undef -int TPpContext::CPPundef(TPpToken* ppToken) -{ - int token = scanToken(ppToken); - if (token != PpAtomIdentifier) { - parseContext.ppError(ppToken->loc, "must be followed by macro name", "#undef", ""); - - return token; - } - - parseContext.reservedPpErrorCheck(ppToken->loc, ppToken->name, "#undef"); - - MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name)); - if (macro != nullptr) - macro->undef = 1; - token = scanToken(ppToken); - if (token != '\n') - parseContext.ppError(ppToken->loc, "can only be followed by a single macro name", "#undef", ""); - - return token; -} - -// Handle #else -/* Skip forward to appropriate spot. This is used both -** to skip to a #endif after seeing an #else, AND to skip to a #else, -** #elif, or #endif after a #if/#ifdef/#ifndef/#elif test was false. -*/ -int TPpContext::CPPelse(int matchelse, TPpToken* ppToken) -{ - int depth = 0; - int token = scanToken(ppToken); - - while (token != EndOfInput) { - if (token != '#') { - while (token != '\n' && token != EndOfInput) - token = scanToken(ppToken); - - if (token == EndOfInput) - return token; - - token = scanToken(ppToken); - continue; - } - - if ((token = scanToken(ppToken)) != PpAtomIdentifier) - continue; - - int nextAtom = atomStrings.getAtom(ppToken->name); - if (nextAtom == PpAtomIf || nextAtom == PpAtomIfdef || nextAtom == PpAtomIfndef) { - depth++; - if (ifdepth >= maxIfNesting || elsetracker >= maxIfNesting) { - parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if/#ifdef/#ifndef", ""); - return EndOfInput; - } else { - ifdepth++; - elsetracker++; - } - } else if (nextAtom == PpAtomEndif) { - token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken)); - elseSeen[elsetracker] = false; - --elsetracker; - if (depth == 0) { - // found the #endif we are looking for - if (ifdepth > 0) - --ifdepth; - break; - } - --depth; - --ifdepth; - } else if (matchelse && depth == 0) { - if (nextAtom == PpAtomElse) { - elseSeen[elsetracker] = true; - token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken)); - // found the #else we are looking for - break; - } else if (nextAtom == PpAtomElif) { - if (elseSeen[elsetracker]) - parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); - /* we decrement ifdepth here, because CPPif will increment - * it and we really want to leave it alone */ - if (ifdepth > 0) { - --ifdepth; - elseSeen[elsetracker] = false; - --elsetracker; - } - - return CPPif(ppToken); - } - } else if (nextAtom == PpAtomElse) { - if (elseSeen[elsetracker]) - parseContext.ppError(ppToken->loc, "#else after #else", "#else", ""); - else - elseSeen[elsetracker] = true; - token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken)); - } else if (nextAtom == PpAtomElif) { - if (elseSeen[elsetracker]) - parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); - } - } - - return token; -} - -// Call when there should be no more tokens left on a line. -int TPpContext::extraTokenCheck(int contextAtom, TPpToken* ppToken, int token) -{ - if (token != '\n' && token != EndOfInput) { - static const char* message = "unexpected tokens following directive"; - - const char* label; - if (contextAtom == PpAtomElse) - label = "#else"; - else if (contextAtom == PpAtomElif) - label = "#elif"; - else if (contextAtom == PpAtomEndif) - label = "#endif"; - else if (contextAtom == PpAtomIf) - label = "#if"; - else if (contextAtom == PpAtomLine) - label = "#line"; - else - label = ""; - - if (parseContext.relaxedErrors()) - parseContext.ppWarn(ppToken->loc, message, label, ""); - else - parseContext.ppError(ppToken->loc, message, label, ""); - - while (token != '\n' && token != EndOfInput) - token = scanToken(ppToken); - } - - return token; -} - -enum eval_prec { - MIN_PRECEDENCE, - COND, LOGOR, LOGAND, OR, XOR, AND, EQUAL, RELATION, SHIFT, ADD, MUL, UNARY, - MAX_PRECEDENCE -}; - -namespace { - - int op_logor(int a, int b) { return a || b; } - int op_logand(int a, int b) { return a && b; } - int op_or(int a, int b) { return a | b; } - int op_xor(int a, int b) { return a ^ b; } - int op_and(int a, int b) { return a & b; } - int op_eq(int a, int b) { return a == b; } - int op_ne(int a, int b) { return a != b; } - int op_ge(int a, int b) { return a >= b; } - int op_le(int a, int b) { return a <= b; } - int op_gt(int a, int b) { return a > b; } - int op_lt(int a, int b) { return a < b; } - int op_shl(int a, int b) { return a << b; } - int op_shr(int a, int b) { return a >> b; } - int op_add(int a, int b) { return a + b; } - int op_sub(int a, int b) { return a - b; } - int op_mul(int a, int b) { return a * b; } - int op_div(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a / b; } - int op_mod(int a, int b) { return a == INT_MIN && b == -1 ? 0 : a % b; } - int op_pos(int a) { return a; } - int op_neg(int a) { return -a; } - int op_cmpl(int a) { return ~a; } - int op_not(int a) { return !a; } - -struct TBinop { - int token, precedence, (*op)(int, int); -} binop[] = { - { PpAtomOr, LOGOR, op_logor }, - { PpAtomAnd, LOGAND, op_logand }, - { '|', OR, op_or }, - { '^', XOR, op_xor }, - { '&', AND, op_and }, - { PpAtomEQ, EQUAL, op_eq }, - { PpAtomNE, EQUAL, op_ne }, - { '>', RELATION, op_gt }, - { PpAtomGE, RELATION, op_ge }, - { '<', RELATION, op_lt }, - { PpAtomLE, RELATION, op_le }, - { PpAtomLeft, SHIFT, op_shl }, - { PpAtomRight, SHIFT, op_shr }, - { '+', ADD, op_add }, - { '-', ADD, op_sub }, - { '*', MUL, op_mul }, - { '/', MUL, op_div }, - { '%', MUL, op_mod }, -}; - -struct TUnop { - int token, (*op)(int); -} unop[] = { - { '+', op_pos }, - { '-', op_neg }, - { '~', op_cmpl }, - { '!', op_not }, -}; - -} // anonymous namespace - -#define NUM_ELEMENTS(A) (sizeof(A) / sizeof(A[0])) - -int TPpContext::eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken* ppToken) -{ - TSourceLoc loc = ppToken->loc; // because we sometimes read the newline before reporting the error - if (token == PpAtomIdentifier) { - if (strcmp("defined", ppToken->name) == 0) { - if (! parseContext.isReadingHLSL() && isMacroInput()) { - if (parseContext.relaxedErrors()) - parseContext.ppWarn(ppToken->loc, "nonportable when expanded from macros for preprocessor expression", - "defined", ""); - else - parseContext.ppError(ppToken->loc, "cannot use in preprocessor expression when expanded from macros", - "defined", ""); - } - bool needclose = 0; - token = scanToken(ppToken); - if (token == '(') { - needclose = true; - token = scanToken(ppToken); - } - if (token != PpAtomIdentifier) { - parseContext.ppError(loc, "incorrect directive, expected identifier", "preprocessor evaluation", ""); - err = true; - res = 0; - - return token; - } - - MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name)); - res = macro != nullptr ? !macro->undef : 0; - token = scanToken(ppToken); - if (needclose) { - if (token != ')') { - parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", ""); - err = true; - res = 0; - - return token; - } - token = scanToken(ppToken); - } - } else { - token = tokenPaste(token, *ppToken); - token = evalToToken(token, shortCircuit, res, err, ppToken); - return eval(token, precedence, shortCircuit, res, err, ppToken); - } - } else if (token == PpAtomConstInt) { - res = ppToken->ival; - token = scanToken(ppToken); - } else if (token == '(') { - token = scanToken(ppToken); - token = eval(token, MIN_PRECEDENCE, shortCircuit, res, err, ppToken); - if (! err) { - if (token != ')') { - parseContext.ppError(loc, "expected ')'", "preprocessor evaluation", ""); - err = true; - res = 0; - - return token; - } - token = scanToken(ppToken); - } - } else { - int op = NUM_ELEMENTS(unop) - 1; - for (; op >= 0; op--) { - if (unop[op].token == token) - break; - } - if (op >= 0) { - token = scanToken(ppToken); - token = eval(token, UNARY, shortCircuit, res, err, ppToken); - res = unop[op].op(res); - } else { - parseContext.ppError(loc, "bad expression", "preprocessor evaluation", ""); - err = true; - res = 0; - - return token; - } - } - - token = evalToToken(token, shortCircuit, res, err, ppToken); - - // Perform evaluation of binary operation, if there is one, otherwise we are done. - while (! err) { - if (token == ')' || token == '\n') - break; - int op; - for (op = NUM_ELEMENTS(binop) - 1; op >= 0; op--) { - if (binop[op].token == token) - break; - } - if (op < 0 || binop[op].precedence <= precedence) - break; - int leftSide = res; - - // Setup short-circuiting, needed for ES, unless already in a short circuit. - // (Once in a short-circuit, can't turn off again, until that whole subexpression is done. - if (! shortCircuit) { - if ((token == PpAtomOr && leftSide == 1) || - (token == PpAtomAnd && leftSide == 0)) - shortCircuit = true; - } - - token = scanToken(ppToken); - token = eval(token, binop[op].precedence, shortCircuit, res, err, ppToken); - - if (binop[op].op == op_div || binop[op].op == op_mod) { - if (res == 0) { - parseContext.ppError(loc, "division by 0", "preprocessor evaluation", ""); - res = 1; - } - } - res = binop[op].op(leftSide, res); - } - - return token; -} - -// Expand macros, skipping empty expansions, to get to the first real token in those expansions. -int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken* ppToken) -{ - while (token == PpAtomIdentifier && strcmp("defined", ppToken->name) != 0) { - switch (MacroExpand(ppToken, true, false)) { - case MacroExpandNotStarted: - case MacroExpandError: - parseContext.ppError(ppToken->loc, "can't evaluate expression", "preprocessor evaluation", ""); - err = true; - res = 0; - break; - case MacroExpandStarted: - break; - case MacroExpandUndef: - if (! shortCircuit && parseContext.isEsProfile()) { - const char* message = "undefined macro in expression not allowed in es profile"; - if (parseContext.relaxedErrors()) - parseContext.ppWarn(ppToken->loc, message, "preprocessor evaluation", ppToken->name); - else - parseContext.ppError(ppToken->loc, message, "preprocessor evaluation", ppToken->name); - } - break; - } - token = scanToken(ppToken); - if (err) - break; - } - - return token; -} - -// Handle #if -int TPpContext::CPPif(TPpToken* ppToken) -{ - int token = scanToken(ppToken); - if (ifdepth >= maxIfNesting || elsetracker >= maxIfNesting) { - parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if", ""); - return EndOfInput; - } else { - elsetracker++; - ifdepth++; - } - int res = 0; - bool err = false; - token = eval(token, MIN_PRECEDENCE, false, res, err, ppToken); - token = extraTokenCheck(PpAtomIf, ppToken, token); - if (!res && !err) - token = CPPelse(1, ppToken); - - return token; -} - -// Handle #ifdef -int TPpContext::CPPifdef(int defined, TPpToken* ppToken) -{ - int token = scanToken(ppToken); - if (ifdepth > maxIfNesting || elsetracker > maxIfNesting) { - parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#ifdef", ""); - return EndOfInput; - } else { - elsetracker++; - ifdepth++; - } - - if (token != PpAtomIdentifier) { - if (defined) - parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifdef", ""); - else - parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifndef", ""); - } else { - MacroSymbol* macro = lookupMacroDef(atomStrings.getAtom(ppToken->name)); - token = scanToken(ppToken); - if (token != '\n') { - parseContext.ppError(ppToken->loc, "unexpected tokens following #ifdef directive - expected a newline", "#ifdef", ""); - while (token != '\n' && token != EndOfInput) - token = scanToken(ppToken); - } - if (((macro != nullptr && !macro->undef) ? 1 : 0) != defined) - token = CPPelse(1, ppToken); - } - - return token; -} - -// Handle #include ... -// TODO: Handle macro expansions for the header name -int TPpContext::CPPinclude(TPpToken* ppToken) -{ - const TSourceLoc directiveLoc = ppToken->loc; - bool startWithLocalSearch = true; // to additionally include the extra "" paths - int token; - - // Find the first non-whitespace char after #include - int ch = getChar(); - while (ch == ' ' || ch == '\t') { - ch = getChar(); - } - if (ch == '<') { - // style - startWithLocalSearch = false; - token = scanHeaderName(ppToken, '>'); - } else if (ch == '"') { - // "header-name" style - token = scanHeaderName(ppToken, '"'); - } else { - // unexpected, get the full token to generate the error - ungetChar(); - token = scanToken(ppToken); - } - - if (token != PpAtomConstString) { - parseContext.ppError(directiveLoc, "must be followed by a header name", "#include", ""); - return token; - } - - // Make a copy of the name because it will be overwritten by the next token scan. - const std::string filename = ppToken->name; - - // See if the directive was well formed - token = scanToken(ppToken); - if (token != '\n') { - if (token == EndOfInput) - parseContext.ppError(ppToken->loc, "expected newline after header name:", "#include", "%s", filename.c_str()); - else - parseContext.ppError(ppToken->loc, "extra content after header name:", "#include", "%s", filename.c_str()); - return token; - } - - // Process well-formed directive - - // Find the inclusion, first look in "Local" ("") paths, if requested, - // otherwise, only search the "System" (<>) paths. - TShader::Includer::IncludeResult* res = nullptr; - if (startWithLocalSearch) - res = includer.includeLocal(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1); - if (res == nullptr || res->headerName.empty()) { - includer.releaseInclude(res); - res = includer.includeSystem(filename.c_str(), currentSourceFile.c_str(), includeStack.size() + 1); - } - - // Process the results - if (res != nullptr && !res->headerName.empty()) { - if (res->headerData != nullptr && res->headerLength > 0) { - // path for processing one or more tokens from an included header, hand off 'res' - const bool forNextLine = parseContext.lineDirectiveShouldSetNextLine(); - std::ostringstream prologue; - std::ostringstream epilogue; - prologue << "#line " << forNextLine << " " << "\"" << res->headerName << "\"\n"; - epilogue << (res->headerData[res->headerLength - 1] == '\n'? "" : "\n") << - "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n"; - pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), this)); - parseContext.intermediate.addIncludeText(res->headerName.c_str(), res->headerData, res->headerLength); - // There's no "current" location anymore. - parseContext.setCurrentColumn(0); - } else { - // things are okay, but there is nothing to process - includer.releaseInclude(res); - } - } else { - // error path, clean up - std::string message = - res != nullptr ? std::string(res->headerData, res->headerLength) - : std::string("Could not process include directive"); - parseContext.ppError(directiveLoc, message.c_str(), "#include", "for header name: %s", filename.c_str()); - includer.releaseInclude(res); - } - - return token; -} - -// Handle #line -int TPpContext::CPPline(TPpToken* ppToken) -{ - // "#line must have, after macro substitution, one of the following forms: - // "#line line - // "#line line source-string-number" - - int token = scanToken(ppToken); - const TSourceLoc directiveLoc = ppToken->loc; - if (token == '\n') { - parseContext.ppError(ppToken->loc, "must by followed by an integral literal", "#line", ""); - return token; - } - - int lineRes = 0; // Line number after macro expansion. - int lineToken = 0; - bool hasFile = false; - int fileRes = 0; // Source file number after macro expansion. - const char* sourceName = nullptr; // Optional source file name. - bool lineErr = false; - bool fileErr = false; - disableEscapeSequences = true; - token = eval(token, MIN_PRECEDENCE, false, lineRes, lineErr, ppToken); - disableEscapeSequences = false; - if (! lineErr) { - lineToken = lineRes; - if (token == '\n') - ++lineRes; - - if (parseContext.lineDirectiveShouldSetNextLine()) - --lineRes; - parseContext.setCurrentLine(lineRes); - - if (token != '\n') { - if (token == PpAtomConstString) { - parseContext.ppRequireExtensions(directiveLoc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based #line"); - // We need to save a copy of the string instead of pointing - // to the name field of the token since the name field - // will likely be overwritten by the next token scan. - sourceName = atomStrings.getString(atomStrings.getAddAtom(ppToken->name)); - parseContext.setCurrentSourceName(sourceName); - hasFile = true; - token = scanToken(ppToken); - } else { - token = eval(token, MIN_PRECEDENCE, false, fileRes, fileErr, ppToken); - if (! fileErr) { - parseContext.setCurrentString(fileRes); - hasFile = true; - } - } - } - } - if (!fileErr && !lineErr) { - parseContext.notifyLineDirective(directiveLoc.line, lineToken, hasFile, fileRes, sourceName); - } - token = extraTokenCheck(PpAtomLine, ppToken, token); - - return token; -} - -// Handle #error -int TPpContext::CPPerror(TPpToken* ppToken) -{ - disableEscapeSequences = true; - int token = scanToken(ppToken); - disableEscapeSequences = false; - std::string message; - TSourceLoc loc = ppToken->loc; - - while (token != '\n' && token != EndOfInput) { - if (token == PpAtomConstInt16 || token == PpAtomConstUint16 || - token == PpAtomConstInt || token == PpAtomConstUint || - token == PpAtomConstInt64 || token == PpAtomConstUint64 || - token == PpAtomConstFloat16 || - token == PpAtomConstFloat || token == PpAtomConstDouble) { - message.append(ppToken->name); - } else if (token == PpAtomIdentifier || token == PpAtomConstString) { - message.append(ppToken->name); - } else { - message.append(atomStrings.getString(token)); - } - message.append(" "); - token = scanToken(ppToken); - } - parseContext.notifyErrorDirective(loc.line, message.c_str()); - // store this msg into the shader's information log..set the Compile Error flag!!!! - parseContext.ppError(loc, message.c_str(), "#error", ""); - - return '\n'; -} - -// Handle #pragma -int TPpContext::CPPpragma(TPpToken* ppToken) -{ - char SrcStrName[2]; - TVector tokens; - - TSourceLoc loc = ppToken->loc; // because we go to the next line before processing - int token = scanToken(ppToken); - while (token != '\n' && token != EndOfInput) { - switch (token) { - case PpAtomIdentifier: - case PpAtomConstInt: - case PpAtomConstUint: - case PpAtomConstInt64: - case PpAtomConstUint64: - case PpAtomConstInt16: - case PpAtomConstUint16: - case PpAtomConstFloat: - case PpAtomConstDouble: - case PpAtomConstFloat16: - tokens.push_back(ppToken->name); - break; - default: - SrcStrName[0] = (char)token; - SrcStrName[1] = '\0'; - tokens.push_back(SrcStrName); - } - token = scanToken(ppToken); - } - - if (token == EndOfInput) - parseContext.ppError(loc, "directive must end with a newline", "#pragma", ""); - else - parseContext.handlePragma(loc, tokens); - - return token; -} - -// #version: This is just for error checking: the version and profile are decided before preprocessing starts -int TPpContext::CPPversion(TPpToken* ppToken) -{ - int token = scanToken(ppToken); - - if (errorOnVersion || versionSeen) { - if (parseContext.isReadingHLSL()) - parseContext.ppError(ppToken->loc, "invalid preprocessor command", "#version", ""); - else - parseContext.ppError(ppToken->loc, "must occur first in shader", "#version", ""); - } - versionSeen = true; - - if (token == '\n') { - parseContext.ppError(ppToken->loc, "must be followed by version number", "#version", ""); - - return token; - } - - if (token != PpAtomConstInt) - parseContext.ppError(ppToken->loc, "must be followed by version number", "#version", ""); - - ppToken->ival = atoi(ppToken->name); - int versionNumber = ppToken->ival; - int line = ppToken->loc.line; - token = scanToken(ppToken); - - if (token == '\n') { - parseContext.notifyVersion(line, versionNumber, nullptr); - return token; - } else { - int profileAtom = atomStrings.getAtom(ppToken->name); - if (profileAtom != PpAtomCore && - profileAtom != PpAtomCompatibility && - profileAtom != PpAtomEs) - parseContext.ppError(ppToken->loc, "bad profile name; use es, core, or compatibility", "#version", ""); - parseContext.notifyVersion(line, versionNumber, ppToken->name); - token = scanToken(ppToken); - - if (token == '\n') - return token; - else - parseContext.ppError(ppToken->loc, "bad tokens following profile -- expected newline", "#version", ""); - } - - return token; -} - -// Handle #extension -int TPpContext::CPPextension(TPpToken* ppToken) -{ - int line = ppToken->loc.line; - int token = scanToken(ppToken); - char extensionName[MaxTokenLength + 1]; - - if (token=='\n') { - parseContext.ppError(ppToken->loc, "extension name not specified", "#extension", ""); - return token; - } - - if (token != PpAtomIdentifier) - parseContext.ppError(ppToken->loc, "extension name expected", "#extension", ""); - - snprintf(extensionName, sizeof(extensionName), "%s", ppToken->name); - - token = scanToken(ppToken); - if (token != ':') { - parseContext.ppError(ppToken->loc, "':' missing after extension name", "#extension", ""); - return token; - } - - token = scanToken(ppToken); - if (token != PpAtomIdentifier) { - parseContext.ppError(ppToken->loc, "behavior for extension not specified", "#extension", ""); - return token; - } - - parseContext.updateExtensionBehavior(line, extensionName, ppToken->name); - parseContext.notifyExtensionDirective(line, extensionName, ppToken->name); - - token = scanToken(ppToken); - if (token == '\n') - return token; - else - parseContext.ppError(ppToken->loc, "extra tokens -- expected newline", "#extension",""); - - return token; -} - -int TPpContext::readCPPline(TPpToken* ppToken) -{ - int token = scanToken(ppToken); - - if (token == PpAtomIdentifier) { - switch (atomStrings.getAtom(ppToken->name)) { - case PpAtomDefine: - token = CPPdefine(ppToken); - break; - case PpAtomElse: - if (elseSeen[elsetracker]) - parseContext.ppError(ppToken->loc, "#else after #else", "#else", ""); - elseSeen[elsetracker] = true; - if (ifdepth == 0) - parseContext.ppError(ppToken->loc, "mismatched statements", "#else", ""); - token = extraTokenCheck(PpAtomElse, ppToken, scanToken(ppToken)); - token = CPPelse(0, ppToken); - break; - case PpAtomElif: - if (ifdepth == 0) - parseContext.ppError(ppToken->loc, "mismatched statements", "#elif", ""); - if (elseSeen[elsetracker]) - parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", ""); - // this token is really a dont care, but we still need to eat the tokens - token = scanToken(ppToken); - while (token != '\n' && token != EndOfInput) - token = scanToken(ppToken); - token = CPPelse(0, ppToken); - break; - case PpAtomEndif: - if (ifdepth == 0) - parseContext.ppError(ppToken->loc, "mismatched statements", "#endif", ""); - else { - elseSeen[elsetracker] = false; - --elsetracker; - --ifdepth; - } - token = extraTokenCheck(PpAtomEndif, ppToken, scanToken(ppToken)); - break; - case PpAtomIf: - token = CPPif(ppToken); - break; - case PpAtomIfdef: - token = CPPifdef(1, ppToken); - break; - case PpAtomIfndef: - token = CPPifdef(0, ppToken); - break; - case PpAtomLine: - token = CPPline(ppToken); - break; - case PpAtomInclude: - if(!parseContext.isReadingHLSL()) { - parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_include_directive, "#include"); - } - token = CPPinclude(ppToken); - break; - case PpAtomPragma: - token = CPPpragma(ppToken); - break; - case PpAtomUndef: - token = CPPundef(ppToken); - break; - case PpAtomError: - token = CPPerror(ppToken); - break; - case PpAtomVersion: - token = CPPversion(ppToken); - break; - case PpAtomExtension: - token = CPPextension(ppToken); - break; - default: - parseContext.ppError(ppToken->loc, "invalid directive:", "#", ppToken->name); - break; - } - } else if (token != '\n' && token != EndOfInput) - parseContext.ppError(ppToken->loc, "invalid directive", "#", ""); - - while (token != '\n' && token != EndOfInput) - token = scanToken(ppToken); - - return token; -} - -// Context-dependent parsing of a #include . -// Assumes no macro expansions etc. are being done; the name is just on the current input. -// Always creates a name and returns PpAtomicConstString, unless we run out of input. -int TPpContext::scanHeaderName(TPpToken* ppToken, char delimit) -{ - bool tooLong = false; - - if (inputStack.empty()) - return EndOfInput; - - int len = 0; - ppToken->name[0] = '\0'; - do { - int ch = inputStack.back()->getch(); - - // done yet? - if (ch == delimit) { - ppToken->name[len] = '\0'; - if (tooLong) - parseContext.ppError(ppToken->loc, "header name too long", "", ""); - return PpAtomConstString; - } else if (ch == EndOfInput) - return EndOfInput; - - // found a character to expand the name with - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - else - tooLong = true; - } while (true); -} - -// Macro-expand a macro argument 'arg' to create 'expandedArg'. -// Does not replace 'arg'. -// Returns nullptr if no expanded argument is created. -TPpContext::TokenStream* TPpContext::PrescanMacroArg(TokenStream& arg, TPpToken* ppToken, bool newLineOkay) -{ - // expand the argument - TokenStream* expandedArg = new TokenStream; - pushInput(new tMarkerInput(this)); - pushTokenStreamInput(arg); - int token; - while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput) { - token = tokenPaste(token, *ppToken); - if (token == PpAtomIdentifier) { - switch (MacroExpand(ppToken, false, newLineOkay)) { - case MacroExpandNotStarted: - break; - case MacroExpandError: - // toss the rest of the pushed-input argument by scanning until tMarkerInput - while ((token = scanToken(ppToken)) != tMarkerInput::marker && token != EndOfInput) - ; - break; - case MacroExpandStarted: - case MacroExpandUndef: - continue; - } - } - if (token == tMarkerInput::marker || token == EndOfInput) - break; - expandedArg->putToken(token, ppToken); - } - - if (token != tMarkerInput::marker) { - // Error, or MacroExpand ate the marker, so had bad input, recover - delete expandedArg; - expandedArg = nullptr; - } - - return expandedArg; -} - -// -// Return the next token for a macro expansion, handling macro arguments, -// whose semantics are dependent on being adjacent to ##. -// -int TPpContext::tMacroInput::scan(TPpToken* ppToken) -{ - int token; - do { - token = mac->body.getToken(pp->parseContext, ppToken); - } while (token == ' '); // handle white space in macro - - // Hash operators basically turn off a round of macro substitution - // (the round done on the argument before the round done on the RHS of the - // macro definition): - // - // "A parameter in the replacement list, unless preceded by a # or ## - // preprocessing token or followed by a ## preprocessing token (see below), - // is replaced by the corresponding argument after all macros contained - // therein have been expanded." - // - // "If, in the replacement list, a parameter is immediately preceded or - // followed by a ## preprocessing token, the parameter is replaced by the - // corresponding argument's preprocessing token sequence." - - bool pasting = false; - if (postpaste) { - // don't expand next token - pasting = true; - postpaste = false; - } - - if (prepaste) { - // already know we should be on a ##, verify - assert(token == PpAtomPaste); - prepaste = false; - postpaste = true; - } - - // see if are preceding a ## - if (mac->body.peekUntokenizedPasting()) { - prepaste = true; - pasting = true; - } - - - // TODO: preprocessor: properly handle whitespace (or lack of it) between tokens when expanding - if (token == PpAtomIdentifier) { - int i; - for (i = (int)mac->args.size() - 1; i >= 0; i--) - if (strcmp(pp->atomStrings.getString(mac->args[i]), ppToken->name) == 0) - break; - if (i >= 0) { - TokenStream* arg = expandedArgs[i]; - bool expanded = !!arg && !pasting; - // HLSL does expand macros before concatenation - if (arg == nullptr || (pasting && !pp->parseContext.isReadingHLSL()) ) { - arg = args[i]; - } - pp->pushTokenStreamInput(*arg, prepaste, expanded); - - return pp->scanToken(ppToken); - } - } - - if (token == EndOfInput) - mac->busy = 0; - - return token; -} - -// return a textual zero, for scanning a macro that was never defined -int TPpContext::tZeroInput::scan(TPpToken* ppToken) -{ - if (done) - return EndOfInput; - - ppToken->name[0] = '0'; - ppToken->name[1] = 0; - ppToken->ival = 0; - ppToken->space = false; - done = true; - - return PpAtomConstInt; -} - -// -// Check a token to see if it is a macro that should be expanded: -// - If it is, and defined, push a tInput that will produce the appropriate -// expansion and return MacroExpandStarted. -// - If it is, but undefined, and expandUndef is requested, push a tInput -// that will expand to 0 and return MacroExpandUndef. -// - Otherwise, there is no expansion, and there are two cases: -// * It might be okay there is no expansion, and no specific error was -// detected. Returns MacroExpandNotStarted. -// * The expansion was started, but could not be completed, due to an error -// that cannot be recovered from. Returns MacroExpandError. -// -MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay) -{ - ppToken->space = false; - int macroAtom = atomStrings.getAtom(ppToken->name); - if (ppToken->fullyExpanded) - return MacroExpandNotStarted; - - switch (macroAtom) { - case PpAtomLineMacro: - // Arguments which are macro have been replaced in the first stage. - if (ppToken->ival == 0) - ppToken->ival = parseContext.getCurrentLoc().line; - snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival); - UngetToken(PpAtomConstInt, ppToken); - return MacroExpandStarted; - - case PpAtomFileMacro: { - if (parseContext.getCurrentLoc().name) - parseContext.ppRequireExtensions(ppToken->loc, 1, &E_GL_GOOGLE_cpp_style_line_directive, "filename-based __FILE__"); - ppToken->ival = parseContext.getCurrentLoc().string; - snprintf(ppToken->name, sizeof(ppToken->name), "%s", ppToken->loc.getStringNameOrNum().c_str()); - UngetToken(PpAtomConstInt, ppToken); - return MacroExpandStarted; - } - - case PpAtomVersionMacro: - ppToken->ival = parseContext.version; - snprintf(ppToken->name, sizeof(ppToken->name), "%d", ppToken->ival); - UngetToken(PpAtomConstInt, ppToken); - return MacroExpandStarted; - - default: - break; - } - - MacroSymbol* macro = macroAtom == 0 ? nullptr : lookupMacroDef(macroAtom); - - // no recursive expansions - if (macro != nullptr && macro->busy) { - ppToken->fullyExpanded = true; - return MacroExpandNotStarted; - } - - // not expanding undefined macros - if ((macro == nullptr || macro->undef) && ! expandUndef) - return MacroExpandNotStarted; - - // 0 is the value of an undefined macro - if ((macro == nullptr || macro->undef) && expandUndef) { - pushInput(new tZeroInput(this)); - return MacroExpandUndef; - } - - tMacroInput *in = new tMacroInput(this); - - TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error - in->mac = macro; - if (macro->functionLike) { - // We don't know yet if this will be a successful call of a - // function-like macro; need to look for a '(', but without trashing - // the passed in ppToken, until we know we are no longer speculative. - TPpToken parenToken; - int token = scanToken(&parenToken); - if (newLineOkay) { - while (token == '\n') - token = scanToken(&parenToken); - } - if (token != '(') { - // Function-like macro called with object-like syntax: okay, don't expand. - // (We ate exactly one token that might not be white space; put it back. - UngetToken(token, &parenToken); - delete in; - return MacroExpandNotStarted; - } - in->args.resize(in->mac->args.size()); - for (size_t i = 0; i < in->mac->args.size(); i++) - in->args[i] = new TokenStream; - in->expandedArgs.resize(in->mac->args.size()); - for (size_t i = 0; i < in->mac->args.size(); i++) - in->expandedArgs[i] = nullptr; - size_t arg = 0; - bool tokenRecorded = false; - do { - TVector nestStack; - while (true) { - token = scanToken(ppToken); - if (token == EndOfInput || token == tMarkerInput::marker) { - parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom)); - delete in; - return MacroExpandError; - } - if (token == '\n') { - if (! newLineOkay) { - parseContext.ppError(loc, "End of line in macro substitution:", "macro expansion", atomStrings.getString(macroAtom)); - delete in; - return MacroExpandError; - } - continue; - } - if (token == '#') { - parseContext.ppError(ppToken->loc, "unexpected '#'", "macro expansion", atomStrings.getString(macroAtom)); - delete in; - return MacroExpandError; - } - if (in->mac->args.size() == 0 && token != ')') - break; - if (nestStack.size() == 0 && (token == ',' || token == ')')) - break; - if (token == '(') - nestStack.push_back(')'); - else if (token == '{' && parseContext.isReadingHLSL()) - nestStack.push_back('}'); - else if (nestStack.size() > 0 && token == nestStack.back()) - nestStack.pop_back(); - - //Macro replacement list is expanded in the last stage. - if (atomStrings.getAtom(ppToken->name) == PpAtomLineMacro) - ppToken->ival = parseContext.getCurrentLoc().line; - - in->args[arg]->putToken(token, ppToken); - tokenRecorded = true; - } - // end of single argument scan - - if (token == ')') { - // closing paren of call - if (in->mac->args.size() == 1 && !tokenRecorded) - break; - arg++; - break; - } - arg++; - } while (arg < in->mac->args.size()); - // end of all arguments scan - - if (arg < in->mac->args.size()) - parseContext.ppError(loc, "Too few args in Macro", "macro expansion", atomStrings.getString(macroAtom)); - else if (token != ')') { - // Error recover code; find end of call, if possible - int depth = 0; - while (token != EndOfInput && (depth > 0 || token != ')')) { - if (token == ')' || token == '}') - depth--; - token = scanToken(ppToken); - if (token == '(' || token == '{') - depth++; - } - - if (token == EndOfInput) { - parseContext.ppError(loc, "End of input in macro", "macro expansion", atomStrings.getString(macroAtom)); - delete in; - return MacroExpandError; - } - parseContext.ppError(loc, "Too many args in macro", "macro expansion", atomStrings.getString(macroAtom)); - } - - // We need both expanded and non-expanded forms of the argument, for whether or - // not token pasting will be applied later when the argument is consumed next to ##. - for (size_t i = 0; i < in->mac->args.size(); i++) - in->expandedArgs[i] = PrescanMacroArg(*in->args[i], ppToken, newLineOkay); - } - - pushInput(in); - macro->busy = 1; - macro->body.reset(); - - return MacroExpandStarted; -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp deleted file mode 100644 index 06c2333e..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp +++ /dev/null @@ -1,181 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ - -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include -#include -#include - -#include "PpContext.h" -#include "PpTokens.h" - -namespace { - -using namespace glslang; - -const struct { - int val; - const char* str; -} tokens[] = { - - { PPAtomAddAssign, "+=" }, - { PPAtomSubAssign, "-=" }, - { PPAtomMulAssign, "*=" }, - { PPAtomDivAssign, "/=" }, - { PPAtomModAssign, "%=" }, - - { PpAtomRight, ">>" }, - { PpAtomLeft, "<<" }, - { PpAtomAnd, "&&" }, - { PpAtomOr, "||" }, - { PpAtomXor, "^^" }, - - { PpAtomRightAssign, ">>=" }, - { PpAtomLeftAssign, "<<=" }, - { PpAtomAndAssign, "&=" }, - { PpAtomOrAssign, "|=" }, - { PpAtomXorAssign, "^=" }, - - { PpAtomEQ, "==" }, - { PpAtomNE, "!=" }, - { PpAtomGE, ">=" }, - { PpAtomLE, "<=" }, - - { PpAtomDecrement, "--" }, - { PpAtomIncrement, "++" }, - - { PpAtomColonColon, "::" }, - - { PpAtomDefine, "define" }, - { PpAtomUndef, "undef" }, - { PpAtomIf, "if" }, - { PpAtomElif, "elif" }, - { PpAtomElse, "else" }, - { PpAtomEndif, "endif" }, - { PpAtomIfdef, "ifdef" }, - { PpAtomIfndef, "ifndef" }, - { PpAtomLine, "line" }, - { PpAtomPragma, "pragma" }, - { PpAtomError, "error" }, - - { PpAtomVersion, "version" }, - { PpAtomCore, "core" }, - { PpAtomCompatibility, "compatibility" }, - { PpAtomEs, "es" }, - { PpAtomExtension, "extension" }, - - { PpAtomLineMacro, "__LINE__" }, - { PpAtomFileMacro, "__FILE__" }, - { PpAtomVersionMacro, "__VERSION__" }, - - { PpAtomInclude, "include" }, -}; - -} // end anonymous namespace - -namespace glslang { - -// -// Initialize the atom table. -// -TStringAtomMap::TStringAtomMap() -{ - badToken.assign(""); - - // Add single character tokens to the atom table: - const char* s = "~!%^&*()-+=|,.<>/?;:[]{}#\\"; - char t[2]; - - t[1] = '\0'; - while (*s) { - t[0] = *s; - addAtomFixed(t, s[0]); - s++; - } - - // Add multiple character scanner tokens : - for (size_t ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++) - addAtomFixed(tokens[ii].str, tokens[ii].val); - - nextAtom = PpAtomLast; -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp deleted file mode 100644 index 70f51197..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ - -#include -#include - -#include "PpContext.h" - -namespace glslang { - -TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) : - preamble(nullptr), strings(nullptr), previous_token('\n'), parseContext(pc), includer(inclr), inComment(false), - rootFileName(rootFileName), - currentSourceFile(rootFileName), - disableEscapeSequences(false) -{ - ifdepth = 0; - for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++) - elseSeen[elsetracker] = false; - elsetracker = 0; - - strtodStream.imbue(std::locale::classic()); -} - -TPpContext::~TPpContext() -{ - delete [] preamble; - - // free up the inputStack - while (! inputStack.empty()) - popInput(); -} - -void TPpContext::setInput(TInputScanner& input, bool versionWillBeError) -{ - assert(inputStack.size() == 0); - - pushInput(new tStringInput(this, input)); - - errorOnVersion = versionWillBeError; - versionSeen = false; -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h deleted file mode 100644 index 1ec30491..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpContext.h +++ /dev/null @@ -1,739 +0,0 @@ -// -// Copyright (C) 2013 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ - -#ifndef PPCONTEXT_H -#define PPCONTEXT_H - -#include -#include -#include - -#include "../ParseHelper.h" -#include "PpTokens.h" - -namespace glslang { - -class TPpToken { -public: - TPpToken() { clear(); } - void clear() - { - space = false; - i64val = 0; - loc.init(); - name[0] = 0; - fullyExpanded = false; - } - - // Used for comparing macro definitions, so checks what is relevant for that. - bool operator==(const TPpToken& right) const - { - return space == right.space && - ival == right.ival && dval == right.dval && i64val == right.i64val && - strncmp(name, right.name, MaxTokenLength) == 0; - } - bool operator!=(const TPpToken& right) const { return ! operator==(right); } - - TSourceLoc loc; - // True if a space (for white space or a removed comment) should also be - // recognized, in front of the token returned: - bool space; - - bool fullyExpanded; - // Numeric value of the token: - union { - int ival; - double dval; - long long i64val; - }; - // Text string of the token: - char name[MaxTokenLength + 1]; -}; - -class TStringAtomMap { -// -// Implementation is in PpAtom.cpp -// -// Maintain a bi-directional mapping between relevant preprocessor strings and -// "atoms" which a unique integers (small, contiguous, not hash-like) per string. -// -public: - TStringAtomMap(); - - // Map string -> atom. - // Return 0 if no existing string. - int getAtom(const char* s) const - { - auto it = atomMap.find(s); - return it == atomMap.end() ? 0 : it->second; - } - - // Map a new or existing string -> atom, inventing a new atom if necessary. - int getAddAtom(const char* s) - { - int atom = getAtom(s); - if (atom == 0) { - atom = nextAtom++; - addAtomFixed(s, atom); - } - return atom; - } - - // Map atom -> string. - const char* getString(int atom) const { return stringMap[atom]->c_str(); } - -protected: - TStringAtomMap(TStringAtomMap&); - TStringAtomMap& operator=(TStringAtomMap&); - - TUnorderedMap atomMap; - TVector stringMap; // these point into the TString in atomMap - int nextAtom; - - // Bad source characters can lead to bad atoms, so gracefully handle those by - // pre-filling the table with them (to avoid if tests later). - TString badToken; - - // Add bi-directional mappings: - // - string -> atom - // - atom -> string - void addAtomFixed(const char* s, int atom) - { - auto it = atomMap.insert(std::pair(s, atom)).first; - if (stringMap.size() < (size_t)atom + 1) - stringMap.resize(atom + 100, &badToken); - stringMap[atom] = &it->first; - } -}; - -class TInputScanner; - -enum MacroExpandResult { - MacroExpandNotStarted, // macro not expanded, which might not be an error - MacroExpandError, // a clear error occurred while expanding, no expansion - MacroExpandStarted, // macro expansion process has started - MacroExpandUndef // macro is undefined and will be expanded -}; - -// This class is the result of turning a huge pile of C code communicating through globals -// into a class. This was done to allowing instancing to attain thread safety. -// Don't expect too much in terms of OO design. -class TPpContext { -public: - TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&); - virtual ~TPpContext(); - - void setPreamble(const char* preamble, size_t length); - - int tokenize(TPpToken& ppToken); - int tokenPaste(int token, TPpToken&); - - class tInput { - public: - tInput(TPpContext* p) : done(false), pp(p) { } - virtual ~tInput() { } - - virtual int scan(TPpToken*) = 0; - virtual int getch() = 0; - virtual void ungetch() = 0; - virtual bool peekPasting() { return false; } // true when about to see ## - virtual bool peekContinuedPasting(int) { return false; } // true when non-spaced tokens can paste - virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define) - virtual bool isMacroInput() { return false; } - virtual bool isStringInput() { return false; } - - // Will be called when we start reading tokens from this instance - virtual void notifyActivated() {} - // Will be called when we do not read tokens from this instance anymore - virtual void notifyDeleted() {} - protected: - bool done; - TPpContext* pp; - }; - - void setInput(TInputScanner& input, bool versionWillBeError); - - void pushInput(tInput* in) - { - inputStack.push_back(in); - in->notifyActivated(); - } - void popInput() - { - inputStack.back()->notifyDeleted(); - delete inputStack.back(); - inputStack.pop_back(); - } - - // - // From PpTokens.cpp - // - - // Capture the needed parts of a token stream for macro recording/playback. - class TokenStream { - public: - // Manage a stream of these 'Token', which capture the relevant parts - // of a TPpToken, plus its atom. - class Token { - public: - Token(int atom, const TPpToken& ppToken) : - atom(atom), - space(ppToken.space), - i64val(ppToken.i64val), - name(ppToken.name) { } - int get(TPpToken& ppToken) - { - ppToken.clear(); - ppToken.space = space; - ppToken.i64val = i64val; - snprintf(ppToken.name, sizeof(ppToken.name), "%s", name.c_str()); - return atom; - } - bool isAtom(int a) const { return atom == a; } - int getAtom() const { return atom; } - bool nonSpaced() const { return !space; } - protected: - Token() {} - int atom; - bool space; // did a space precede the token? - long long i64val; - TString name; - }; - - TokenStream() : currentPos(0) { } - - void putToken(int token, TPpToken* ppToken); - bool peekToken(int atom) { return !atEnd() && stream[currentPos].isAtom(atom); } - bool peekContinuedPasting(int atom) - { - // This is basically necessary because, for example, the PP - // tokenizer only accepts valid numeric-literals plus suffixes, so - // separates numeric-literals plus bad suffix into two tokens, which - // should get both pasted together as one token when token pasting. - // - // The following code is a bit more generalized than the above example. - if (!atEnd() && atom == PpAtomIdentifier && stream[currentPos].nonSpaced()) { - switch(stream[currentPos].getAtom()) { - case PpAtomConstInt: - case PpAtomConstUint: - case PpAtomConstInt64: - case PpAtomConstUint64: - case PpAtomConstInt16: - case PpAtomConstUint16: - case PpAtomConstFloat: - case PpAtomConstDouble: - case PpAtomConstFloat16: - case PpAtomConstString: - case PpAtomIdentifier: - return true; - default: - break; - } - } - - return false; - } - int getToken(TParseContextBase&, TPpToken*); - bool atEnd() { return currentPos >= stream.size(); } - bool peekTokenizedPasting(bool lastTokenPastes); - bool peekUntokenizedPasting(); - void reset() { currentPos = 0; } - - protected: - TVector stream; - size_t currentPos; - }; - - // - // From Pp.cpp - // - - struct MacroSymbol { - MacroSymbol() : functionLike(0), busy(0), undef(0) { } - TVector args; - TokenStream body; - unsigned functionLike : 1; // 0 means object-like, 1 means function-like - unsigned busy : 1; - unsigned undef : 1; - }; - - typedef TMap TSymbolMap; - TSymbolMap macroDefs; // map atoms to macro definitions - MacroSymbol* lookupMacroDef(int atom) - { - auto existingMacroIt = macroDefs.find(atom); - return (existingMacroIt == macroDefs.end()) ? nullptr : &(existingMacroIt->second); - } - void addMacroDef(int atom, MacroSymbol& macroDef) { macroDefs[atom] = macroDef; } - -protected: - TPpContext(TPpContext&); - TPpContext& operator=(TPpContext&); - - TStringAtomMap atomStrings; - char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble - int preambleLength; - char** strings; // official strings of shader, starting a string 0 line 1 - size_t* lengths; - int numStrings; // how many official strings there are - int currentString; // which string we're currently parsing (-1 for preamble) - - // Scanner data: - int previous_token; - TParseContextBase& parseContext; - std::vector lastLineTokens; - std::vector lastLineTokenLocs; - // Get the next token from *stack* of input sources, popping input sources - // that are out of tokens, down until an input source is found that has a token. - // Return EndOfInput when there are no more tokens to be found by doing this. - int scanToken(TPpToken* ppToken) - { - int token = EndOfInput; - - while (! inputStack.empty()) { - token = inputStack.back()->scan(ppToken); - if (token != EndOfInput || inputStack.empty()) - break; - popInput(); - } - if (!inputStack.empty() && inputStack.back()->isStringInput()) { - if (token == '\n') { - bool seenNumSign = false; - for (int i = 0; i < (int)lastLineTokens.size() - 1;) { - int curPos = i; - int curToken = lastLineTokens[i++]; - if (curToken == '#' && lastLineTokens[i] == '#') { - curToken = PpAtomPaste; - i++; - } - if (curToken == '#') { - if (seenNumSign) { - parseContext.ppError(lastLineTokenLocs[curPos], "(#) can be preceded in its line only by spaces or horizontal tabs", "#", ""); - } else { - seenNumSign = true; - } - } - } - lastLineTokens.clear(); - lastLineTokenLocs.clear(); - } else { - lastLineTokens.push_back(token); - lastLineTokenLocs.push_back(ppToken->loc); - } - } - return token; - } - int getChar() { return inputStack.back()->getch(); } - void ungetChar() { inputStack.back()->ungetch(); } - bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); } - bool peekContinuedPasting(int a) - { - return !inputStack.empty() && inputStack.back()->peekContinuedPasting(a); - } - bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); } - bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); } - - static const int maxIfNesting = 65; - - int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor) - bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth - int elsetracker; // #if-#else and #endif constructs...Counter. - - class tMacroInput : public tInput { - public: - tMacroInput(TPpContext* pp) : tInput(pp), prepaste(false), postpaste(false) { } - virtual ~tMacroInput() - { - for (size_t i = 0; i < args.size(); ++i) - delete args[i]; - for (size_t i = 0; i < expandedArgs.size(); ++i) - delete expandedArgs[i]; - } - - virtual int scan(TPpToken*) override; - virtual int getch() override { assert(0); return EndOfInput; } - virtual void ungetch() override { assert(0); } - bool peekPasting() override { return prepaste; } - bool peekContinuedPasting(int a) override { return mac->body.peekContinuedPasting(a); } - bool endOfReplacementList() override { return mac->body.atEnd(); } - bool isMacroInput() override { return true; } - - MacroSymbol *mac; - TVector args; - TVector expandedArgs; - - protected: - bool prepaste; // true if we are just before ## - bool postpaste; // true if we are right after ## - }; - - class tMarkerInput : public tInput { - public: - tMarkerInput(TPpContext* pp) : tInput(pp) { } - virtual int scan(TPpToken*) override - { - if (done) - return EndOfInput; - done = true; - - return marker; - } - virtual int getch() override { assert(0); return EndOfInput; } - virtual void ungetch() override { assert(0); } - static const int marker = -3; - }; - - class tZeroInput : public tInput { - public: - tZeroInput(TPpContext* pp) : tInput(pp) { } - virtual int scan(TPpToken*) override; - virtual int getch() override { assert(0); return EndOfInput; } - virtual void ungetch() override { assert(0); } - }; - - std::vector inputStack; - bool errorOnVersion; - bool versionSeen; - - // - // from Pp.cpp - // - - // Used to obtain #include content. - TShader::Includer& includer; - - int CPPdefine(TPpToken * ppToken); - int CPPundef(TPpToken * ppToken); - int CPPelse(int matchelse, TPpToken * ppToken); - int extraTokenCheck(int atom, TPpToken* ppToken, int token); - int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); - int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken); - int CPPif (TPpToken * ppToken); - int CPPifdef(int defined, TPpToken * ppToken); - int CPPinclude(TPpToken * ppToken); - int CPPline(TPpToken * ppToken); - int CPPerror(TPpToken * ppToken); - int CPPpragma(TPpToken * ppToken); - int CPPversion(TPpToken * ppToken); - int CPPextension(TPpToken * ppToken); - int readCPPline(TPpToken * ppToken); - int scanHeaderName(TPpToken* ppToken, char delimit); - TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay); - MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay); - - // - // From PpTokens.cpp - // - void pushTokenStreamInput(TokenStream&, bool pasting = false, bool expanded = false); - void UngetToken(int token, TPpToken*); - - class tTokenInput : public tInput { - public: - tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting, bool expanded) : - tInput(pp), - tokens(t), - lastTokenPastes(prepasting), - preExpanded(expanded) { } - virtual int scan(TPpToken *ppToken) override { - int token = tokens->getToken(pp->parseContext, ppToken); - ppToken->fullyExpanded = preExpanded; - if (tokens->atEnd() && token == PpAtomIdentifier) { - int macroAtom = pp->atomStrings.getAtom(ppToken->name); - MacroSymbol* macro = macroAtom == 0 ? nullptr : pp->lookupMacroDef(macroAtom); - if (macro && macro->functionLike) - ppToken->fullyExpanded = false; - } - return token; - } - virtual int getch() override { assert(0); return EndOfInput; } - virtual void ungetch() override { assert(0); } - virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); } - bool peekContinuedPasting(int a) override { return tokens->peekContinuedPasting(a); } - protected: - TokenStream* tokens; - bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token - bool preExpanded; - }; - - class tUngotTokenInput : public tInput { - public: - tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { } - virtual int scan(TPpToken *) override; - virtual int getch() override { assert(0); return EndOfInput; } - virtual void ungetch() override { assert(0); } - protected: - int token; - TPpToken lval; - }; - - // - // From PpScanner.cpp - // - class tStringInput : public tInput { - public: - tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { } - virtual int scan(TPpToken*) override; - bool isStringInput() override { return true; } - // Scanner used to get source stream characters. - // - Escaped newlines are handled here, invisibly to the caller. - // - All forms of newline are handled, and turned into just a '\n'. - int getch() override - { - int ch = input->get(); - - if (ch == '\\') { - // Move past escaped newlines, as many as sequentially exist - do { - if (input->peek() == '\r' || input->peek() == '\n') { - bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment); - if (! allowed && pp->inComment) - return '\\'; - - // escape one newline now - ch = input->get(); - int nextch = input->get(); - if (ch == '\r' && nextch == '\n') - ch = input->get(); - else - ch = nextch; - } else - return '\\'; - } while (ch == '\\'); - } - - // handle any non-escaped newline - if (ch == '\r' || ch == '\n') { - if (ch == '\r' && input->peek() == '\n') - input->get(); - return '\n'; - } - - return ch; - } - - // Scanner used to backup the source stream characters. Newlines are - // handled here, invisibly to the caller, meaning have to undo exactly - // what getch() above does (e.g., don't leave things in the middle of a - // sequence of escaped newlines). - void ungetch() override - { - input->unget(); - - do { - int ch = input->peek(); - if (ch == '\r' || ch == '\n') { - if (ch == '\n') { - // correct for two-character newline - input->unget(); - if (input->peek() != '\r') - input->get(); - } - // now in front of a complete newline, move past an escape character - input->unget(); - if (input->peek() == '\\') - input->unget(); - else { - input->get(); - break; - } - } else - break; - } while (true); - } - - protected: - TInputScanner* input; - }; - - // Holds a reference to included file data, as well as a - // prologue and an epilogue string. This can be scanned using the tInput - // interface and acts as a single source string. - class TokenizableIncludeFile : public tInput { - public: - // Copies prologue and epilogue. The includedFile must remain valid - // until this TokenizableIncludeFile is no longer used. - TokenizableIncludeFile(const TSourceLoc& startLoc, - const std::string& prologue, - TShader::Includer::IncludeResult* includedFile, - const std::string& epilogue, - TPpContext* pp) - : tInput(pp), - prologue_(prologue), - epilogue_(epilogue), - includedFile_(includedFile), - scanner(3, strings, lengths, nullptr, 0, 0, true), - prevScanner(nullptr), - stringInput(pp, scanner) - { - strings[0] = prologue_.data(); - strings[1] = includedFile_->headerData; - strings[2] = epilogue_.data(); - - lengths[0] = prologue_.size(); - lengths[1] = includedFile_->headerLength; - lengths[2] = epilogue_.size(); - - scanner.setLine(startLoc.line); - scanner.setString(startLoc.string); - - scanner.setFile(startLoc.getFilenameStr(), 0); - scanner.setFile(startLoc.getFilenameStr(), 1); - scanner.setFile(startLoc.getFilenameStr(), 2); - } - - // tInput methods: - int scan(TPpToken* t) override { return stringInput.scan(t); } - int getch() override { return stringInput.getch(); } - void ungetch() override { stringInput.ungetch(); } - - void notifyActivated() override - { - prevScanner = pp->parseContext.getScanner(); - pp->parseContext.setScanner(&scanner); - pp->push_include(includedFile_); - } - - void notifyDeleted() override - { - pp->parseContext.setScanner(prevScanner); - pp->pop_include(); - } - - private: - TokenizableIncludeFile& operator=(const TokenizableIncludeFile&); - - // Stores the prologue for this string. - const std::string prologue_; - - // Stores the epilogue for this string. - const std::string epilogue_; - - // Points to the IncludeResult that this TokenizableIncludeFile represents. - TShader::Includer::IncludeResult* includedFile_; - - // Will point to prologue_, includedFile_->headerData and epilogue_ - // This is passed to scanner constructor. - // These do not own the storage and it must remain valid until this - // object has been destroyed. - const char* strings[3]; - // Length of str_, passed to scanner constructor. - size_t lengths[3]; - // Scans over str_. - TInputScanner scanner; - // The previous effective scanner before the scanner in this instance - // has been activated. - TInputScanner* prevScanner; - // Delegate object implementing the tInput interface. - tStringInput stringInput; - }; - - int ScanFromString(char* s); - void missingEndifCheck(); - int lFloatConst(int len, int ch, TPpToken* ppToken); - int characterLiteral(TPpToken* ppToken); - - void push_include(TShader::Includer::IncludeResult* result) - { - currentSourceFile = result->headerName; - includeStack.push(result); - } - - void pop_include() - { - TShader::Includer::IncludeResult* include = includeStack.top(); - includeStack.pop(); - includer.releaseInclude(include); - if (includeStack.empty()) { - currentSourceFile = rootFileName; - } else { - currentSourceFile = includeStack.top()->headerName; - } - } - - bool inComment; - std::string rootFileName; - std::stack includeStack; - std::string currentSourceFile; - - std::istringstream strtodStream; - bool disableEscapeSequences; -}; - -} // end namespace glslang - -#endif // PPCONTEXT_H diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp deleted file mode 100644 index 34dec207..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp +++ /dev/null @@ -1,1408 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// Copyright (C) 2017 ARM Limited. -// Copyright (C) 2015-2018 Google, Inc. -// Copyright (c) 2023, Mobica Limited -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ - -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include -#include - -#include "PpContext.h" -#include "PpTokens.h" -#include "../Scan.h" - -namespace glslang { - -/////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////// Floating point constants: ///////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// - -// -// Scan a single- or double-precision floating point constant. -// Assumes that the scanner has seen at least one digit, -// followed by either a decimal '.' or the letter 'e', or a -// precision ending (e.g., F or LF). -// -// This is technically not correct, as the preprocessor should just -// accept the numeric literal along with whatever suffix it has, but -// currently, it stops on seeing a bad suffix, treating that as the -// next token. This effects things like token pasting, where it is -// relevant how many tokens something was broken into. -// -// See peekContinuedPasting(). -int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken) -{ - const auto saveName = [&](int ch) { - if (len <= MaxTokenLength) - ppToken->name[len++] = static_cast(ch); - }; - - // find the range of non-zero digits before the decimal point - int startNonZero = 0; - while (startNonZero < len && ppToken->name[startNonZero] == '0') - ++startNonZero; - int endNonZero = len; - while (endNonZero > startNonZero && ppToken->name[endNonZero-1] == '0') - --endNonZero; - int numWholeNumberDigits = endNonZero - startNonZero; - - // accumulate the range's value - bool fastPath = numWholeNumberDigits <= 15; // when the number gets too complex, set to false - unsigned long long wholeNumber = 0; - if (fastPath) { - for (int i = startNonZero; i < endNonZero; ++i) - wholeNumber = wholeNumber * 10 + (ppToken->name[i] - '0'); - } - int decimalShift = len - endNonZero; - - // Decimal point: - bool hasDecimalOrExponent = false; - if (ch == '.') { - hasDecimalOrExponent = true; - saveName(ch); - ch = getChar(); - int firstDecimal = len; - -#ifdef ENABLE_HLSL - // 1.#INF or -1.#INF - if (ch == '#' && (ifdepth > 0 || parseContext.intermediate.getSource() == EShSourceHlsl)) { - if ((len < 2) || - (len == 2 && ppToken->name[0] != '1') || - (len == 3 && ppToken->name[1] != '1' && !(ppToken->name[0] == '-' || ppToken->name[0] == '+')) || - (len > 3)) - parseContext.ppError(ppToken->loc, "unexpected use of", "#", ""); - else { - // we have 1.# or -1.# or +1.#, check for 'INF' - if ((ch = getChar()) != 'I' || - (ch = getChar()) != 'N' || - (ch = getChar()) != 'F') - parseContext.ppError(ppToken->loc, "expected 'INF'", "#", ""); - else { - // we have [+-].#INF, and we are targeting IEEE 754, so wrap it up: - saveName('I'); - saveName('N'); - saveName('F'); - ppToken->name[len] = '\0'; - if (ppToken->name[0] == '-') - ppToken->i64val = 0xfff0000000000000; // -Infinity - else - ppToken->i64val = 0x7ff0000000000000; // +Infinity - return PpAtomConstFloat; - } - } - } -#endif - - // Consume leading-zero digits after the decimal point - while (ch == '0') { - saveName(ch); - ch = getChar(); - } - int startNonZeroDecimal = len; - int endNonZeroDecimal = len; - - // Consume remaining digits, up to the exponent - while (ch >= '0' && ch <= '9') { - saveName(ch); - if (ch != '0') - endNonZeroDecimal = len; - ch = getChar(); - } - - // Compute accumulation up to the last non-zero digit - if (endNonZeroDecimal > startNonZeroDecimal) { - numWholeNumberDigits += endNonZeroDecimal - endNonZero - 1; // don't include the "." - if (numWholeNumberDigits > 15) - fastPath = false; - if (fastPath) { - for (int i = endNonZero; i < endNonZeroDecimal; ++i) { - if (ppToken->name[i] != '.') - wholeNumber = wholeNumber * 10 + (ppToken->name[i] - '0'); - } - } - decimalShift = firstDecimal - endNonZeroDecimal; - } - } - - // Exponent: - bool negativeExponent = false; - double exponentValue = 0.0; - int exponent = 0; - { - if (ch == 'e' || ch == 'E') { - hasDecimalOrExponent = true; - saveName(ch); - ch = getChar(); - if (ch == '+' || ch == '-') { - negativeExponent = ch == '-'; - saveName(ch); - ch = getChar(); - } - if (ch >= '0' && ch <= '9') { - while (ch >= '0' && ch <= '9') { - exponent = exponent * 10 + (ch - '0'); - saveName(ch); - ch = getChar(); - } - } else { - parseContext.ppError(ppToken->loc, "bad character in float exponent", "", ""); - } - } - - // Compensate for location of decimal - if (negativeExponent) - exponent -= decimalShift; - else { - exponent += decimalShift; - if (exponent < 0) { - negativeExponent = true; - exponent = -exponent; - } - } - if (exponent > 22) - fastPath = false; - - if (fastPath) { - // Compute the floating-point value of the exponent - exponentValue = 1.0; - if (exponent > 0) { - double expFactor = 10; - while (exponent > 0) { - if (exponent & 0x1) - exponentValue *= expFactor; - expFactor *= expFactor; - exponent >>= 1; - } - } - } - } - - // Suffix: - bool isDouble = false; - bool isFloat16 = false; - if (ch == 'l' || ch == 'L') { - if (ifdepth == 0 && parseContext.intermediate.getSource() == EShSourceGlsl) - parseContext.doubleCheck(ppToken->loc, "double floating-point suffix"); - if (ifdepth == 0 && !hasDecimalOrExponent) - parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); - if (parseContext.intermediate.getSource() == EShSourceGlsl) { - int ch2 = getChar(); - if (ch2 != 'f' && ch2 != 'F') { - ungetChar(); - ungetChar(); - } else { - saveName(ch); - saveName(ch2); - isDouble = true; - } - } else if (parseContext.intermediate.getSource() == EShSourceHlsl) { - saveName(ch); - isDouble = true; - } - } else if (ch == 'h' || ch == 'H') { - if (ifdepth == 0 && parseContext.intermediate.getSource() == EShSourceGlsl) - parseContext.float16Check(ppToken->loc, "half floating-point suffix"); - if (ifdepth == 0 && !hasDecimalOrExponent) - parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); - if (parseContext.intermediate.getSource() == EShSourceGlsl) { - int ch2 = getChar(); - if (ch2 != 'f' && ch2 != 'F') { - ungetChar(); - ungetChar(); - } else { - saveName(ch); - saveName(ch2); - isFloat16 = true; - } - } else if (parseContext.intermediate.getSource() == EShSourceHlsl) { - saveName(ch); - isFloat16 = true; - } - } else - if (ch == 'f' || ch == 'F') { - if (ifdepth == 0) - parseContext.profileRequires(ppToken->loc, EEsProfile, 300, nullptr, "floating-point suffix"); - if (ifdepth == 0 && !parseContext.relaxedErrors()) - parseContext.profileRequires(ppToken->loc, ~EEsProfile, 120, nullptr, "floating-point suffix"); - if (ifdepth == 0 && !hasDecimalOrExponent) - parseContext.ppError(ppToken->loc, "float literal needs a decimal point or exponent", "", ""); - saveName(ch); - } else - ungetChar(); - - // Patch up the name and length for overflow - - if (len > MaxTokenLength) { - len = MaxTokenLength; - parseContext.ppError(ppToken->loc, "float literal too long", "", ""); - } - ppToken->name[len] = '\0'; - - // Compute the numerical value - if (fastPath) { - // compute the floating-point value of the exponent - if (exponentValue == 0.0) - ppToken->dval = (double)wholeNumber; - else if (negativeExponent) - ppToken->dval = (double)wholeNumber / exponentValue; - else - ppToken->dval = (double)wholeNumber * exponentValue; - } else { - // slow path - ppToken->dval = 0.0; - - // remove suffix - TString numstr(ppToken->name); - if (numstr.back() == 'f' || numstr.back() == 'F') - numstr.pop_back(); - if (numstr.back() == 'h' || numstr.back() == 'H') - numstr.pop_back(); - if (numstr.back() == 'l' || numstr.back() == 'L') - numstr.pop_back(); - - // use platform library - strtodStream.clear(); - strtodStream.str(numstr.c_str()); - strtodStream >> ppToken->dval; - if (strtodStream.fail()) { - // Assume failure combined with a large exponent was overflow, in - // an attempt to set INF. - if (!negativeExponent && exponent + numWholeNumberDigits > 300) - ppToken->i64val = 0x7ff0000000000000; // +Infinity - // Assume failure combined with a small exponent was overflow. - if (negativeExponent && exponent + numWholeNumberDigits > 300) - ppToken->dval = 0.0; - // Unknown reason for failure. Theory is that either - // - the 0.0 is still there, or - // - something reasonable was written that is better than 0.0 - } - } - - // Return the right token type - if (isDouble) - return PpAtomConstDouble; - else if (isFloat16) - return PpAtomConstFloat16; - else - return PpAtomConstFloat; -} - -// Recognize a character literal. -// -// The first ' has already been accepted, read the rest, through the closing '. -// -// Always returns PpAtomConstInt. -// -int TPpContext::characterLiteral(TPpToken* ppToken) -{ - ppToken->name[0] = 0; - ppToken->ival = 0; - - if (parseContext.intermediate.getSource() != EShSourceHlsl) { - // illegal, except in macro definition, for which case we report the character - return '\''; - } - - int ch = getChar(); - switch (ch) { - case '\'': - // As empty sequence: '' - parseContext.ppError(ppToken->loc, "unexpected", "\'", ""); - return PpAtomConstInt; - case '\\': - // As escape sequence: '\XXX' - switch (ch = getChar()) { - case 'a': - ppToken->ival = 7; - break; - case 'b': - ppToken->ival = 8; - break; - case 't': - ppToken->ival = 9; - break; - case 'n': - ppToken->ival = 10; - break; - case 'v': - ppToken->ival = 11; - break; - case 'f': - ppToken->ival = 12; - break; - case 'r': - ppToken->ival = 13; - break; - case 'x': - case '0': - parseContext.ppError(ppToken->loc, "octal and hex sequences not supported", "\\", ""); - break; - default: - // This catches '\'', '\"', '\?', etc. - // Also, things like '\C' mean the same thing as 'C' - // (after the above cases are filtered out). - ppToken->ival = ch; - break; - } - break; - default: - ppToken->ival = ch; - break; - } - ppToken->name[0] = (char)ppToken->ival; - ppToken->name[1] = '\0'; - ch = getChar(); - if (ch != '\'') { - parseContext.ppError(ppToken->loc, "expected", "\'", ""); - // Look ahead for a closing ' - do { - ch = getChar(); - } while (ch != '\'' && ch != EndOfInput && ch != '\n'); - } - - return PpAtomConstInt; -} - -// -// Scanner used to tokenize source stream. -// -// N.B. Invalid numeric suffixes are not consumed.// -// This is technically not correct, as the preprocessor should just -// accept the numeric literal along with whatever suffix it has, but -// currently, it stops on seeing a bad suffix, treating that as the -// next token. This effects things like token pasting, where it is -// relevant how many tokens something was broken into. -// See peekContinuedPasting(). -// -int TPpContext::tStringInput::scan(TPpToken* ppToken) -{ - int AlreadyComplained = 0; - int len = 0; - int ch = 0; - int ii = 0; - unsigned long long ival = 0; - const auto floatingPointChar = [&](int ch) { return ch == '.' || ch == 'e' || ch == 'E' || - ch == 'f' || ch == 'F' || - ch == 'h' || ch == 'H'; }; - - static const char* const Int64_Extensions[] = { - E_GL_ARB_gpu_shader_int64, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int64 }; - static const int Num_Int64_Extensions = sizeof(Int64_Extensions) / sizeof(Int64_Extensions[0]); - - static const char* const Int16_Extensions[] = { - E_GL_AMD_gpu_shader_int16, - E_GL_EXT_shader_explicit_arithmetic_types, - E_GL_EXT_shader_explicit_arithmetic_types_int16 }; - static const int Num_Int16_Extensions = sizeof(Int16_Extensions) / sizeof(Int16_Extensions[0]); - - ppToken->clear(); - ch = getch(); - for (;;) { - while (ch == ' ' || ch == '\t') { - ppToken->space = true; - ch = getch(); - } - - ppToken->loc = pp->parseContext.getCurrentLoc(); - len = 0; - switch (ch) { - default: - // Single character token, including EndOfInput, '#' and '\' (escaped newlines are handled at a lower level, so this is just a '\' token) - if (ch > PpAtomMaxSingle) - ch = PpAtomBadToken; - return ch; - - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'L': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': - case 'Z': case '_': - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': - case 'z': - do { - if (len < MaxTokenLength) { - ppToken->name[len++] = (char)ch; - ch = getch(); - } else { - if (! AlreadyComplained) { - pp->parseContext.ppError(ppToken->loc, "name too long", "", ""); - AlreadyComplained = 1; - } - ch = getch(); - } - } while ((ch >= 'a' && ch <= 'z') || - (ch >= 'A' && ch <= 'Z') || - (ch >= '0' && ch <= '9') || - ch == '_'); - - // line continuation with no token before or after makes len == 0, and need to start over skipping white space, etc. - if (len == 0) - continue; - - ppToken->name[len] = '\0'; - ungetch(); - return PpAtomIdentifier; - case '0': - ppToken->name[len++] = (char)ch; - ch = getch(); - if (ch == 'x' || ch == 'X') { - // must be hexadecimal - - bool isUnsigned = false; - bool isInt64 = false; - bool isInt16 = false; - ppToken->name[len++] = (char)ch; - ch = getch(); - if ((ch >= '0' && ch <= '9') || - (ch >= 'A' && ch <= 'F') || - (ch >= 'a' && ch <= 'f')) { - - ival = 0; - do { - if (len < MaxTokenLength && ival <= 0x7fffffffffffffffull) { - ppToken->name[len++] = (char)ch; - if (ch >= '0' && ch <= '9') { - ii = ch - '0'; - } else if (ch >= 'A' && ch <= 'F') { - ii = ch - 'A' + 10; - } else if (ch >= 'a' && ch <= 'f') { - ii = ch - 'a' + 10; - } else - pp->parseContext.ppError(ppToken->loc, "bad digit in hexadecimal literal", "", ""); - ival = (ival << 4) | ii; - } else { - if (! AlreadyComplained) { - if(len < MaxTokenLength) - pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too big", "", ""); - else - pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too long", "", ""); - AlreadyComplained = 1; - } - ival = 0xffffffffffffffffull; - } - ch = getch(); - } while ((ch >= '0' && ch <= '9') || - (ch >= 'A' && ch <= 'F') || - (ch >= 'a' && ch <= 'f')); - } else { - pp->parseContext.ppError(ppToken->loc, "bad digit in hexadecimal literal", "", ""); - } - if (ch == 'u' || ch == 'U') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isUnsigned = true; - - int nextCh = getch(); - if (nextCh == 'l' || nextCh == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt64 = true; - } else - ungetch(); - - nextCh = getch(); - if ((nextCh == 's' || nextCh == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt16 = true; - } else - ungetch(); - } else if (ch == 'l' || ch == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt64 = true; - } else if ((ch == 's' || ch == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt16 = true; - } else - ungetch(); - ppToken->name[len] = '\0'; - - if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (pp->ifdepth == 0) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "64-bit hexadecimal literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int64_Extensions, Int64_Extensions, "64-bit hexadecimal literal"); - } - ppToken->i64val = ival; - return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; - } else if (isInt16) { - if (pp->ifdepth == 0) { - if (pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "16-bit hexadecimal literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int16_Extensions, Int16_Extensions, "16-bit hexadecimal literal"); - } - } - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16; - } else { - if (ival > 0xffffffffu && !AlreadyComplained) - pp->parseContext.ppError(ppToken->loc, "hexadecimal literal too big", "", ""); - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint : PpAtomConstInt; - } - } else if ((ch == 'b' || ch == 'B') && pp->parseContext.intermediate.getSource() == EShSourceHlsl) { - // must be binary - bool isUnsigned = false; - bool isInt64 = false; - bool isInt16 = false; - ppToken->name[len++] = (char)ch; - ch = getch(); - - // Check value - if ((ch == '0' || ch == '1')) - { - ival = 0; - do { - if (len < MaxTokenLength && ival <= 0x7fffffffffffffffull) { - ppToken->name[len++] = (char)ch; - if (ch == '0' || ch == '1') { - ii = ch - '0'; - } else { - pp->parseContext.ppError(ppToken->loc, "bad digit in binary literal", "", ""); - } - ival = (ival << 1) | ii; - } - else - { - if (! AlreadyComplained) { - if(len < MaxTokenLength) - pp->parseContext.ppError(ppToken->loc, "binary literal too big", "", ""); - else - pp->parseContext.ppError(ppToken->loc, "binary literal too long", "", ""); - AlreadyComplained = 1; - } - ival = 0xffffffffffffffffull; - } - ch = getch(); - } while (ch == '0' || ch == '1'); - } - else - { - pp->parseContext.ppError(ppToken->loc, "bad digit in binary literal", "", ""); - } - - // check type - if (ch == 'u' || ch == 'U') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isUnsigned = true; - - int nextCh = getch(); - if (nextCh == 'l' || nextCh == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt64 = true; - } else - ungetch(); - - nextCh = getch(); - if ((nextCh == 's' || nextCh == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt16 = true; - } else - ungetch(); - } else if (ch == 'l' || ch == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt64 = true; - } else if ((ch == 's' || ch == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt16 = true; - } else { - ungetch(); - } - ppToken->name[len] = '\0'; - - // Assign value - if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (pp->ifdepth == 0) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "64-bit binary literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int64_Extensions, Int64_Extensions, "64-bit binary literal"); - } - ppToken->i64val = ival; - return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; - } else if (isInt16) { - if (pp->ifdepth == 0) { - if (pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "16-bit binary literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int16_Extensions, Int16_Extensions, "16-bit binary literal"); - } - } - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16; - } else { - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint : PpAtomConstInt; - } - } else { - // could be octal integer or floating point, speculative pursue octal until it must be floating point - - bool isUnsigned = false; - bool isInt64 = false; - bool isInt16 = false; - bool octalOverflow = false; - bool nonOctal = false; - ival = 0; - - // see how much octal-like stuff we can read - while (ch >= '0' && ch <= '7') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - else if (! AlreadyComplained) { - pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); - AlreadyComplained = 1; - } - if (ival <= 0x1fffffffffffffffull) { - ii = ch - '0'; - ival = (ival << 3) | ii; - } else - octalOverflow = true; - ch = getch(); - } - - // could be part of a float... - if (ch == '8' || ch == '9') { - nonOctal = true; - do { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - else if (! AlreadyComplained) { - pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); - AlreadyComplained = 1; - } - ch = getch(); - } while (ch >= '0' && ch <= '9'); - } - if (floatingPointChar(ch)) - return pp->lFloatConst(len, ch, ppToken); - - // wasn't a float, so must be octal... - if (nonOctal) - pp->parseContext.ppError(ppToken->loc, "octal literal digit too large", "", ""); - - if (ch == 'u' || ch == 'U') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isUnsigned = true; - - int nextCh = getch(); - if (nextCh == 'l' || nextCh == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt64 = true; - } else - ungetch(); - - nextCh = getch(); - if ((nextCh == 's' || nextCh == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt16 = true; - } else - ungetch(); - } else if (ch == 'l' || ch == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt64 = true; - } else if ((ch == 's' || ch == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt16 = true; - } else - ungetch(); - ppToken->name[len] = '\0'; - - if (!isInt64 && ival > 0xffffffffu) - octalOverflow = true; - - if (octalOverflow) - pp->parseContext.ppError(ppToken->loc, "octal literal too big", "", ""); - - if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (pp->ifdepth == 0) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "64-bit octal literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int64_Extensions, Int64_Extensions, "64-bit octal literal"); - } - ppToken->i64val = ival; - return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; - } else if (isInt16) { - if (pp->ifdepth == 0) { - if (pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "16-bit octal literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int16_Extensions, Int16_Extensions, "16-bit octal literal"); - } - } - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16; - } else { - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint : PpAtomConstInt; - } - } - break; - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - // can't be hexadecimal or octal, is either decimal or floating point - - do { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - else if (! AlreadyComplained) { - pp->parseContext.ppError(ppToken->loc, "numeric literal too long", "", ""); - AlreadyComplained = 1; - } - ch = getch(); - } while (ch >= '0' && ch <= '9'); - if (floatingPointChar(ch)) - return pp->lFloatConst(len, ch, ppToken); - else { - // Finish handling signed and unsigned integers - int numericLen = len; - bool isUnsigned = false; - bool isInt64 = false; - bool isInt16 = false; - if (ch == 'u' || ch == 'U') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isUnsigned = true; - - int nextCh = getch(); - if (nextCh == 'l' || nextCh == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt64 = true; - } else - ungetch(); - - nextCh = getch(); - if ((nextCh == 's' || nextCh == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)nextCh; - isInt16 = true; - } else - ungetch(); - } else if (ch == 'l' || ch == 'L') { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt64 = true; - } else if ((ch == 's' || ch == 'S') && - pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (len < MaxTokenLength) - ppToken->name[len++] = (char)ch; - isInt16 = true; - } else - ungetch(); - - ppToken->name[len] = '\0'; - ival = 0; - const unsigned oneTenthMaxInt = 0xFFFFFFFFu / 10; - const unsigned remainderMaxInt = 0xFFFFFFFFu - 10 * oneTenthMaxInt; - const unsigned long long oneTenthMaxInt64 = 0xFFFFFFFFFFFFFFFFull / 10; - const unsigned long long remainderMaxInt64 = 0xFFFFFFFFFFFFFFFFull - 10 * oneTenthMaxInt64; - const unsigned short oneTenthMaxInt16 = 0xFFFFu / 10; - const unsigned short remainderMaxInt16 = 0xFFFFu - 10 * oneTenthMaxInt16; - for (int i = 0; i < numericLen; i++) { - ch = ppToken->name[i] - '0'; - bool overflow = false; - if (isInt64) - overflow = (ival > oneTenthMaxInt64 || (ival == oneTenthMaxInt64 && (unsigned long long)ch > remainderMaxInt64)); - else if (isInt16) - overflow = (ival > oneTenthMaxInt16 || (ival == oneTenthMaxInt16 && (unsigned short)ch > remainderMaxInt16)); - else - overflow = (ival > oneTenthMaxInt || (ival == oneTenthMaxInt && (unsigned)ch > remainderMaxInt)); - if (overflow) { - pp->parseContext.ppError(ppToken->loc, "numeric literal too big", "", ""); - ival = 0xFFFFFFFFFFFFFFFFull; - break; - } else - ival = ival * 10 + ch; - } - - if (isInt64 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - if (pp->ifdepth == 0) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "64-bit literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int64_Extensions, Int64_Extensions, "64-bit literal"); - } - ppToken->i64val = ival; - return isUnsigned ? PpAtomConstUint64 : PpAtomConstInt64; - } else if (isInt16) { - if (pp->ifdepth == 0 && pp->parseContext.intermediate.getSource() == EShSourceGlsl) { - pp->parseContext.requireProfile(ppToken->loc, ~EEsProfile, - "16-bit literal"); - pp->parseContext.profileRequires(ppToken->loc, ~EEsProfile, 0, - Num_Int16_Extensions, Int16_Extensions, "16-bit literal"); - } - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint16 : PpAtomConstInt16; - } else { - ppToken->ival = (int)ival; - return isUnsigned ? PpAtomConstUint : PpAtomConstInt; - } - } - break; - case '-': - ch = getch(); - if (ch == '-') { - return PpAtomDecrement; - } else if (ch == '=') { - return PPAtomSubAssign; - } else { - ungetch(); - return '-'; - } - case '+': - ch = getch(); - if (ch == '+') { - return PpAtomIncrement; - } else if (ch == '=') { - return PPAtomAddAssign; - } else { - ungetch(); - return '+'; - } - case '*': - ch = getch(); - if (ch == '=') { - return PPAtomMulAssign; - } else { - ungetch(); - return '*'; - } - case '%': - ch = getch(); - if (ch == '=') { - return PPAtomModAssign; - } else { - ungetch(); - return '%'; - } - case '^': - ch = getch(); - if (ch == '^') { - return PpAtomXor; - } else { - if (ch == '=') - return PpAtomXorAssign; - else{ - ungetch(); - return '^'; - } - } - - case '=': - ch = getch(); - if (ch == '=') { - return PpAtomEQ; - } else { - ungetch(); - return '='; - } - case '!': - ch = getch(); - if (ch == '=') { - return PpAtomNE; - } else { - ungetch(); - return '!'; - } - case '|': - ch = getch(); - if (ch == '|') { - return PpAtomOr; - } else if (ch == '=') { - return PpAtomOrAssign; - } else { - ungetch(); - return '|'; - } - case '&': - ch = getch(); - if (ch == '&') { - return PpAtomAnd; - } else if (ch == '=') { - return PpAtomAndAssign; - } else { - ungetch(); - return '&'; - } - case '<': - ch = getch(); - if (ch == '<') { - ch = getch(); - if (ch == '=') - return PpAtomLeftAssign; - else { - ungetch(); - return PpAtomLeft; - } - } else if (ch == '=') { - return PpAtomLE; - } else { - ungetch(); - return '<'; - } - case '>': - ch = getch(); - if (ch == '>') { - ch = getch(); - if (ch == '=') - return PpAtomRightAssign; - else { - ungetch(); - return PpAtomRight; - } - } else if (ch == '=') { - return PpAtomGE; - } else { - ungetch(); - return '>'; - } - case '.': - ch = getch(); - if (ch >= '0' && ch <= '9') { - ungetch(); - return pp->lFloatConst(0, '.', ppToken); - } else { - ungetch(); - return '.'; - } - case '/': - ch = getch(); - if (ch == '/') { - pp->inComment = true; - do { - ch = getch(); - } while (ch != '\n' && ch != EndOfInput); - ppToken->space = true; - pp->inComment = false; - - return ch; - } else if (ch == '*') { - ch = getch(); - do { - while (ch != '*') { - if (ch == EndOfInput) { - pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", ""); - return ch; - } - ch = getch(); - } - ch = getch(); - if (ch == EndOfInput) { - pp->parseContext.ppError(ppToken->loc, "End of input in comment", "comment", ""); - return ch; - } - } while (ch != '/'); - ppToken->space = true; - // loop again to get the next token... - break; - } else if (ch == '=') { - return PPAtomDivAssign; - } else { - ungetch(); - return '/'; - } - break; - case '\'': - return pp->characterLiteral(ppToken); - case '"': - // #include uses scanHeaderName() to ignore these escape sequences. - ch = getch(); - while (ch != '"' && ch != '\n' && ch != EndOfInput) { - if (len < MaxTokenLength) { - if (ch == '\\' && !pp->disableEscapeSequences) { - int nextCh = getch(); - switch (nextCh) { - case '\'': ch = 0x27; break; - case '"': ch = 0x22; break; - case '?': ch = 0x3f; break; - case '\\': ch = 0x5c; break; - case 'a': ch = 0x07; break; - case 'b': ch = 0x08; break; - case 'f': ch = 0x0c; break; - case 'n': ch = 0x0a; break; - case 'r': ch = 0x0d; break; - case 't': ch = 0x09; break; - case 'v': ch = 0x0b; break; - case 'x': - // Hex value, arbitrary number of characters. Terminated by the first - // non-hex digit - { - int numDigits = 0; - ch = 0; - while (true) { - nextCh = getch(); - if (nextCh >= '0' && nextCh <= '9') - nextCh -= '0'; - else if (nextCh >= 'A' && nextCh <= 'F') - nextCh -= 'A' - 10; - else if (nextCh >= 'a' && nextCh <= 'f') - nextCh -= 'a' - 10; - else { - ungetch(); - break; - } - numDigits++; - ch = ch * 0x10 + nextCh; - } - if (numDigits == 0) { - pp->parseContext.ppError(ppToken->loc, "Expected hex value in escape sequence", "string", ""); - } - break; - } - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - // Octal value, up to three octal digits - { - int numDigits = 1; - ch = nextCh - '0'; - while (numDigits < 3) { - nextCh = getch(); - if (nextCh >= '0' && nextCh <= '7') - nextCh -= '0'; - else { - ungetch(); - break; - } - numDigits++; - ch = ch * 8 + nextCh; - } - break; - } - default: - pp->parseContext.ppError(ppToken->loc, "Invalid escape sequence", "string", ""); - break; - } - } - ppToken->name[len] = (char)ch; - len++; - ch = getch(); - } else - break; - }; - ppToken->name[len] = '\0'; - if (ch != '"') { - ungetch(); - pp->parseContext.ppError(ppToken->loc, "End of line in string", "string", ""); - } - return PpAtomConstString; - case ':': - ch = getch(); - if (ch == ':') - return PpAtomColonColon; - ungetch(); - return ':'; - } - - ch = getch(); - } -} - -// -// The main functional entry point into the preprocessor, which will -// scan the source strings to figure out and return the next processing token. -// -// Return the token, or EndOfInput when no more tokens. -// -int TPpContext::tokenize(TPpToken& ppToken) -{ - for(;;) { - int token = scanToken(&ppToken); - - // Handle token-pasting logic - token = tokenPaste(token, ppToken); - - if (token == EndOfInput) { - missingEndifCheck(); - return EndOfInput; - } - if (token == '#') { - if (previous_token == '\n') { - token = readCPPline(&ppToken); - if (token == EndOfInput) { - missingEndifCheck(); - return EndOfInput; - } - continue; - } else { - parseContext.ppError(ppToken.loc, "preprocessor directive cannot be preceded by another token", "#", ""); - return EndOfInput; - } - } - previous_token = token; - - if (token == '\n') - continue; - - // expand macros - if (token == PpAtomIdentifier) { - switch (MacroExpand(&ppToken, false, true)) { - case MacroExpandNotStarted: - break; - case MacroExpandError: - return EndOfInput; - case MacroExpandStarted: - case MacroExpandUndef: - continue; - } - } - - switch (token) { - case PpAtomIdentifier: - case PpAtomConstInt: - case PpAtomConstUint: - case PpAtomConstFloat: - case PpAtomConstInt64: - case PpAtomConstUint64: - case PpAtomConstInt16: - case PpAtomConstUint16: - case PpAtomConstDouble: - case PpAtomConstFloat16: - if (ppToken.name[0] == '\0') - continue; - break; - case PpAtomConstString: - // HLSL allows string literals. - // GLSL allows string literals with GL_EXT_debug_printf. - if (ifdepth == 0 && parseContext.intermediate.getSource() != EShSourceHlsl) { - const char* const string_literal_EXTs[] = { E_GL_EXT_debug_printf, E_GL_EXT_spirv_intrinsics }; - parseContext.requireExtensions(ppToken.loc, 2, string_literal_EXTs, "string literal"); - if (!parseContext.extensionTurnedOn(E_GL_EXT_debug_printf) && - !parseContext.extensionTurnedOn(E_GL_EXT_spirv_intrinsics)) - continue; - } - break; - case '\'': - parseContext.ppError(ppToken.loc, "character literals not supported", "\'", ""); - continue; - default: - snprintf(ppToken.name, sizeof(ppToken.name), "%s", atomStrings.getString(token)); - break; - } - - return token; - } -} - -// -// Do all token-pasting related combining of two pasted tokens when getting a -// stream of tokens from a replacement list. Degenerates to no processing if a -// replacement list is not the source of the token stream. -// -int TPpContext::tokenPaste(int token, TPpToken& ppToken) -{ - // starting with ## is illegal, skip to next token - if (token == PpAtomPaste) { - parseContext.ppError(ppToken.loc, "unexpected location", "##", ""); - return scanToken(&ppToken); - } - - int resultToken = token; // "foo" pasted with "35" is an identifier, not a number - - // ## can be chained, process all in the chain at once - while (peekPasting()) { - TPpToken pastedPpToken; - - // next token has to be ## - token = scanToken(&pastedPpToken); - assert(token == PpAtomPaste); - - // This covers end of macro expansion - if (endOfReplacementList()) { - parseContext.ppError(ppToken.loc, "unexpected location; end of replacement list", "##", ""); - break; - } - - // Get the token(s) after the ##. - // Because of "space" semantics, and prior tokenization, what - // appeared a single token, e.g. "3A", might have been tokenized - // into two tokens "3" and "A", but the "A" will have 'space' set to - // false. Accumulate all of these to recreate the original lexical - // appearing token. - do { - token = scanToken(&pastedPpToken); - - // This covers end of argument expansion - if (token == tMarkerInput::marker) { - parseContext.ppError(ppToken.loc, "unexpected location; end of argument", "##", ""); - return resultToken; - } - - // get the token text - switch (resultToken) { - case PpAtomIdentifier: - // already have the correct text in token.names - break; - case '=': - case '!': - case '-': - case '~': - case '+': - case '*': - case '/': - case '%': - case '<': - case '>': - case '|': - case '^': - case '&': - case PpAtomRight: - case PpAtomLeft: - case PpAtomAnd: - case PpAtomOr: - case PpAtomXor: - snprintf(ppToken.name, sizeof(ppToken.name), "%s", atomStrings.getString(resultToken)); - snprintf(pastedPpToken.name, sizeof(pastedPpToken.name), "%s", atomStrings.getString(token)); - break; - default: - parseContext.ppError(ppToken.loc, "not supported for these tokens", "##", ""); - return resultToken; - } - - // combine the tokens - if (strlen(ppToken.name) + strlen(pastedPpToken.name) > MaxTokenLength) { - parseContext.ppError(ppToken.loc, "combined tokens are too long", "##", ""); - return resultToken; - } - snprintf(&ppToken.name[0] + strlen(ppToken.name), sizeof(ppToken.name) - strlen(ppToken.name), - "%s", pastedPpToken.name); - - // correct the kind of token we are making, if needed (identifiers stay identifiers) - if (resultToken != PpAtomIdentifier) { - int newToken = atomStrings.getAtom(ppToken.name); - if (newToken > 0) - resultToken = newToken; - else - parseContext.ppError(ppToken.loc, "combined token is invalid", "##", ""); - } - } while (peekContinuedPasting(resultToken)); - } - - return resultToken; -} - -// Checks if we've seen balanced #if...#endif -void TPpContext::missingEndifCheck() -{ - if (ifdepth > 0) - parseContext.ppError(parseContext.getCurrentLoc(), "missing #endif", "", ""); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp deleted file mode 100644 index e6ee64cf..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ - -// -// For recording and playing back the stream of tokens in a macro definition. -// - -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif - -#include -#include -#include -#include - -#include "PpContext.h" -#include "PpTokens.h" - -namespace glslang { - -// Add a token (including backing string) to the end of a macro -// token stream, for later playback. -void TPpContext::TokenStream::putToken(int atom, TPpToken* ppToken) -{ - TokenStream::Token streamToken(atom, *ppToken); - stream.push_back(streamToken); -} - -// Read the next token from a macro token stream. -int TPpContext::TokenStream::getToken(TParseContextBase& parseContext, TPpToken *ppToken) -{ - if (atEnd()) - return EndOfInput; - - int atom = stream[currentPos++].get(*ppToken); - ppToken->loc = parseContext.getCurrentLoc(); - - // Check for ##, unless the current # is the last character - if (atom == '#') { - if (peekToken('#')) { - parseContext.requireProfile(ppToken->loc, ~EEsProfile, "token pasting (##)"); - parseContext.profileRequires(ppToken->loc, ~EEsProfile, 130, nullptr, "token pasting (##)"); - currentPos++; - atom = PpAtomPaste; - } - } - - return atom; -} - -// We are pasting if -// 1. we are preceding a pasting operator within this stream -// or -// 2. the entire macro is preceding a pasting operator (lastTokenPastes) -// and we are also on the last token -bool TPpContext::TokenStream::peekTokenizedPasting(bool lastTokenPastes) -{ - // 1. preceding ##? - - size_t savePos = currentPos; - // skip white space - while (peekToken(' ')) - ++currentPos; - if (peekToken(PpAtomPaste)) { - currentPos = savePos; - return true; - } - - // 2. last token and we've been told after this there will be a ## - - if (! lastTokenPastes) - return false; - // Getting here means the last token will be pasted, after this - - // Are we at the last non-whitespace token? - savePos = currentPos; - bool moreTokens = false; - do { - if (atEnd()) - break; - if (!peekToken(' ')) { - moreTokens = true; - break; - } - ++currentPos; - } while (true); - currentPos = savePos; - - return !moreTokens; -} - -// See if the next non-white-space tokens are two consecutive # -bool TPpContext::TokenStream::peekUntokenizedPasting() -{ - // don't return early, have to restore this - size_t savePos = currentPos; - - // skip white-space - while (peekToken(' ')) - ++currentPos; - - // check for ## - bool pasting = false; - if (peekToken('#')) { - ++currentPos; - if (peekToken('#')) - pasting = true; - } - - currentPos = savePos; - - return pasting; -} - -void TPpContext::pushTokenStreamInput(TokenStream& ts, bool prepasting, bool expanded) -{ - pushInput(new tTokenInput(this, &ts, prepasting, expanded)); - ts.reset(); -} - -int TPpContext::tUngotTokenInput::scan(TPpToken* ppToken) -{ - if (done) - return EndOfInput; - - int ret = token; - *ppToken = lval; - done = true; - - return ret; -} - -void TPpContext::UngetToken(int token, TPpToken* ppToken) -{ - pushInput(new tUngotTokenInput(this, token, ppToken)); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h b/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h deleted file mode 100644 index 7b0f8155..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/preprocessor/PpTokens.h +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -/****************************************************************************\ -Copyright (c) 2002, NVIDIA Corporation. - -NVIDIA Corporation("NVIDIA") supplies this software to you in -consideration of your agreement to the following terms, and your use, -installation, modification or redistribution of this NVIDIA software -constitutes acceptance of these terms. If you do not agree with these -terms, please do not use, install, modify or redistribute this NVIDIA -software. - -In consideration of your agreement to abide by the following terms, and -subject to these terms, NVIDIA grants you a personal, non-exclusive -license, under NVIDIA's copyrights in this original NVIDIA software (the -"NVIDIA Software"), to use, reproduce, modify and redistribute the -NVIDIA Software, with or without modifications, in source and/or binary -forms; provided that if you redistribute the NVIDIA Software, you must -retain the copyright notice of NVIDIA, this notice and the following -text and disclaimers in all such redistributions of the NVIDIA Software. -Neither the name, trademarks, service marks nor logos of NVIDIA -Corporation may be used to endorse or promote products derived from the -NVIDIA Software without specific prior written permission from NVIDIA. -Except as expressly stated in this notice, no other rights or licenses -express or implied, are granted by NVIDIA herein, including but not -limited to any patent rights that may be infringed by your derivative -works or by other works in which the NVIDIA Software may be -incorporated. No hardware is licensed hereunder. - -THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT -WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, -INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE, -NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR -ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER -PRODUCTS. - -IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, -INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF -USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY -OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE -NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, -TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF -NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -\****************************************************************************/ - -#ifndef PARSER_H -#define PARSER_H - -namespace glslang { - -// Multi-character tokens -enum EFixedAtoms { - // single character tokens get their own char value as their token; start here for multi-character tokens - PpAtomMaxSingle = 127, - - // replace bad character tokens with this, to avoid accidental aliasing with the below - PpAtomBadToken, - - // Operators - - PPAtomAddAssign, - PPAtomSubAssign, - PPAtomMulAssign, - PPAtomDivAssign, - PPAtomModAssign, - - PpAtomRight, - PpAtomLeft, - - PpAtomRightAssign, - PpAtomLeftAssign, - PpAtomAndAssign, - PpAtomOrAssign, - PpAtomXorAssign, - - PpAtomAnd, - PpAtomOr, - PpAtomXor, - - PpAtomEQ, - PpAtomNE, - PpAtomGE, - PpAtomLE, - - PpAtomDecrement, - PpAtomIncrement, - - PpAtomColonColon, - - PpAtomPaste, - - // Constants - - PpAtomConstInt, - PpAtomConstUint, - PpAtomConstInt64, - PpAtomConstUint64, - PpAtomConstInt16, - PpAtomConstUint16, - PpAtomConstFloat, - PpAtomConstDouble, - PpAtomConstFloat16, - PpAtomConstString, - - // Identifiers - PpAtomIdentifier, - - // preprocessor "keywords" - - PpAtomDefine, - PpAtomUndef, - - PpAtomIf, - PpAtomIfdef, - PpAtomIfndef, - PpAtomElse, - PpAtomElif, - PpAtomEndif, - - PpAtomLine, - PpAtomPragma, - PpAtomError, - - // #version ... - PpAtomVersion, - PpAtomCore, - PpAtomCompatibility, - PpAtomEs, - - // #extension - PpAtomExtension, - - // __LINE__, __FILE__, __VERSION__ - - PpAtomLineMacro, - PpAtomFileMacro, - PpAtomVersionMacro, - - // #include - PpAtomInclude, - - PpAtomLast, -}; - -} // end namespace glslang - -#endif /* not PARSER_H */ diff --git a/3rdparty/glslang/glslang/MachineIndependent/propagateNoContraction.cpp b/3rdparty/glslang/glslang/MachineIndependent/propagateNoContraction.cpp deleted file mode 100644 index 7b5cd03f..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/propagateNoContraction.cpp +++ /dev/null @@ -1,866 +0,0 @@ -// -// Copyright (C) 2015-2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Visit the nodes in the glslang intermediate tree representation to -// propagate the 'noContraction' qualifier. -// - -#include "propagateNoContraction.h" - -#include -#include -#include -#include -#include - -#include "localintermediate.h" -namespace { - -// Use a string to hold the access chain information, as in most cases the -// access chain is short and may contain only one element, which is the symbol -// ID. -// Example: struct {float a; float b;} s; -// Object s.a will be represented with: /0 -// Object s.b will be represented with: /1 -// Object s will be represented with: -// For members of vector, matrix and arrays, they will be represented with the -// same symbol ID of their container symbol objects. This is because their -// preciseness is always the same as their container symbol objects. -typedef std::string ObjectAccessChain; - -// The delimiter used in the ObjectAccessChain string to separate symbol ID and -// different level of struct indices. -const char ObjectAccesschainDelimiter = '/'; - -// Mapping from Symbol IDs of symbol nodes, to their defining operation -// nodes. -typedef std::unordered_multimap NodeMapping; -// Mapping from object nodes to their access chain info string. -typedef std::unordered_map AccessChainMapping; - -// Set of object IDs. -typedef std::unordered_set ObjectAccesschainSet; -// Set of return branch nodes. -typedef std::unordered_set ReturnBranchNodeSet; - -// A helper function to tell whether a node is 'noContraction'. Returns true if -// the node has 'noContraction' qualifier, otherwise false. -bool isPreciseObjectNode(glslang::TIntermTyped* node) -{ - return node->getType().getQualifier().isNoContraction(); -} - -// Returns true if the opcode is a dereferencing one. -bool isDereferenceOperation(glslang::TOperator op) -{ - switch (op) { - case glslang::EOpIndexDirect: - case glslang::EOpIndexDirectStruct: - case glslang::EOpIndexIndirect: - case glslang::EOpVectorSwizzle: - case glslang::EOpMatrixSwizzle: - return true; - default: - return false; - } -} - -// Returns true if the opcode leads to an assignment operation. -bool isAssignOperation(glslang::TOperator op) -{ - switch (op) { - case glslang::EOpAssign: - case glslang::EOpAddAssign: - case glslang::EOpSubAssign: - case glslang::EOpMulAssign: - case glslang::EOpVectorTimesMatrixAssign: - case glslang::EOpVectorTimesScalarAssign: - case glslang::EOpMatrixTimesScalarAssign: - case glslang::EOpMatrixTimesMatrixAssign: - case glslang::EOpDivAssign: - case glslang::EOpModAssign: - case glslang::EOpAndAssign: - case glslang::EOpLeftShiftAssign: - case glslang::EOpRightShiftAssign: - case glslang::EOpInclusiveOrAssign: - case glslang::EOpExclusiveOrAssign: - - case glslang::EOpPostIncrement: - case glslang::EOpPostDecrement: - case glslang::EOpPreIncrement: - case glslang::EOpPreDecrement: - return true; - default: - return false; - } -} - -// A helper function to get the unsigned int from a given constant union node. -// Note the node should only hold a uint scalar. -unsigned getStructIndexFromConstantUnion(glslang::TIntermTyped* node) -{ - assert(node->getAsConstantUnion() && node->getAsConstantUnion()->isScalar()); - unsigned struct_dereference_index = node->getAsConstantUnion()->getConstArray()[0].getUConst(); - return struct_dereference_index; -} - -// A helper function to generate symbol_label. -ObjectAccessChain generateSymbolLabel(glslang::TIntermSymbol* node) -{ - ObjectAccessChain symbol_id = - std::to_string(node->getId()) + "(" + node->getName().c_str() + ")"; - return symbol_id; -} - -// Returns true if the operation is an arithmetic operation and valid for -// the 'NoContraction' decoration. -bool isArithmeticOperation(glslang::TOperator op) -{ - switch (op) { - case glslang::EOpAddAssign: - case glslang::EOpSubAssign: - case glslang::EOpMulAssign: - case glslang::EOpVectorTimesMatrixAssign: - case glslang::EOpVectorTimesScalarAssign: - case glslang::EOpMatrixTimesScalarAssign: - case glslang::EOpMatrixTimesMatrixAssign: - case glslang::EOpDivAssign: - case glslang::EOpModAssign: - - case glslang::EOpNegative: - - case glslang::EOpAdd: - case glslang::EOpSub: - case glslang::EOpMul: - case glslang::EOpDiv: - case glslang::EOpMod: - - case glslang::EOpVectorTimesScalar: - case glslang::EOpVectorTimesMatrix: - case glslang::EOpMatrixTimesVector: - case glslang::EOpMatrixTimesScalar: - case glslang::EOpMatrixTimesMatrix: - - case glslang::EOpDot: - - case glslang::EOpPostIncrement: - case glslang::EOpPostDecrement: - case glslang::EOpPreIncrement: - case glslang::EOpPreDecrement: - return true; - default: - return false; - } -} - -// A helper class to help manage the populating_initial_no_contraction_ flag. -template class StateSettingGuard { -public: - StateSettingGuard(T* state_ptr, T new_state_value) - : state_ptr_(state_ptr), previous_state_(*state_ptr) - { - *state_ptr = new_state_value; - } - StateSettingGuard(T* state_ptr) : state_ptr_(state_ptr), previous_state_(*state_ptr) {} - void setState(T new_state_value) { *state_ptr_ = new_state_value; } - ~StateSettingGuard() { *state_ptr_ = previous_state_; } - -private: - T* state_ptr_; - T previous_state_; -}; - -// A helper function to get the front element from a given ObjectAccessChain -ObjectAccessChain getFrontElement(const ObjectAccessChain& chain) -{ - size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter); - return pos_delimiter == std::string::npos ? chain : chain.substr(0, pos_delimiter); -} - -// A helper function to get the access chain starting from the second element. -ObjectAccessChain subAccessChainFromSecondElement(const ObjectAccessChain& chain) -{ - size_t pos_delimiter = chain.find(ObjectAccesschainDelimiter); - return pos_delimiter == std::string::npos ? "" : chain.substr(pos_delimiter + 1); -} - -// A helper function to get the access chain after removing a given prefix. -ObjectAccessChain getSubAccessChainAfterPrefix(const ObjectAccessChain& chain, - const ObjectAccessChain& prefix) -{ - size_t pos = chain.find(prefix); - if (pos != 0) - return chain; - return chain.substr(prefix.length() + sizeof(ObjectAccesschainDelimiter)); -} - -// -// A traverser which traverses the whole AST and populates: -// 1) A mapping from symbol nodes' IDs to their defining operation nodes. -// 2) A set of access chains of the initial precise object nodes. -// -class TSymbolDefinitionCollectingTraverser : public glslang::TIntermTraverser { -public: - TSymbolDefinitionCollectingTraverser(NodeMapping* symbol_definition_mapping, - AccessChainMapping* accesschain_mapping, - ObjectAccesschainSet* precise_objects, - ReturnBranchNodeSet* precise_return_nodes); - - bool visitUnary(glslang::TVisit, glslang::TIntermUnary*) override; - bool visitBinary(glslang::TVisit, glslang::TIntermBinary*) override; - void visitSymbol(glslang::TIntermSymbol*) override; - bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate*) override; - bool visitBranch(glslang::TVisit, glslang::TIntermBranch*) override; - -protected: - TSymbolDefinitionCollectingTraverser& operator=(const TSymbolDefinitionCollectingTraverser&); - - // The mapping from symbol node IDs to their defining nodes. This should be - // populated along traversing the AST. - NodeMapping& symbol_definition_mapping_; - // The set of symbol node IDs for precise symbol nodes, the ones marked as - // 'noContraction'. - ObjectAccesschainSet& precise_objects_; - // The set of precise return nodes. - ReturnBranchNodeSet& precise_return_nodes_; - // A temporary cache of the symbol node whose defining node is to be found - // currently along traversing the AST. - ObjectAccessChain current_object_; - // A map from object node to its access chain. This traverser stores - // the built access chains into this map for each object node it has - // visited. - AccessChainMapping& accesschain_mapping_; - // The pointer to the Function Definition node, so we can get the - // preciseness of the return expression from it when we traverse the - // return branch node. - glslang::TIntermAggregate* current_function_definition_node_; -}; - -TSymbolDefinitionCollectingTraverser::TSymbolDefinitionCollectingTraverser( - NodeMapping* symbol_definition_mapping, AccessChainMapping* accesschain_mapping, - ObjectAccesschainSet* precise_objects, - std::unordered_set* precise_return_nodes) - : TIntermTraverser(true, false, false), symbol_definition_mapping_(*symbol_definition_mapping), - precise_objects_(*precise_objects), precise_return_nodes_(*precise_return_nodes), - current_object_(), accesschain_mapping_(*accesschain_mapping), - current_function_definition_node_(nullptr) {} - -// Visits a symbol node, set the current_object_ to the -// current node symbol ID, and record a mapping from this node to the current -// current_object_, which is the just obtained symbol -// ID. -void TSymbolDefinitionCollectingTraverser::visitSymbol(glslang::TIntermSymbol* node) -{ - current_object_ = generateSymbolLabel(node); - accesschain_mapping_[node] = current_object_; -} - -// Visits an aggregate node, traverses all of its children. -bool TSymbolDefinitionCollectingTraverser::visitAggregate(glslang::TVisit, - glslang::TIntermAggregate* node) -{ - // This aggregate node might be a function definition node, in which case we need to - // cache this node, so we can get the preciseness information of the return value - // of this function later. - StateSettingGuard current_function_definition_node_setting_guard( - ¤t_function_definition_node_); - if (node->getOp() == glslang::EOpFunction) { - // This is function definition node, we need to cache this node so that we can - // get the preciseness of the return value later. - current_function_definition_node_setting_guard.setState(node); - } - // Traverse the items in the sequence. - glslang::TIntermSequence& seq = node->getSequence(); - for (int i = 0; i < (int)seq.size(); ++i) { - current_object_.clear(); - seq[i]->traverse(this); - } - return false; -} - -bool TSymbolDefinitionCollectingTraverser::visitBranch(glslang::TVisit, - glslang::TIntermBranch* node) -{ - if (node->getFlowOp() == glslang::EOpReturn && node->getExpression() && - current_function_definition_node_ && - current_function_definition_node_->getType().getQualifier().noContraction) { - // This node is a return node with an expression, and its function has a - // precise return value. We need to find the involved objects in its - // expression and add them to the set of initial precise objects. - precise_return_nodes_.insert(node); - node->getExpression()->traverse(this); - } - return false; -} - -// Visits a unary node. This might be an implicit assignment like i++, i--. etc. -bool TSymbolDefinitionCollectingTraverser::visitUnary(glslang::TVisit /* visit */, - glslang::TIntermUnary* node) -{ - current_object_.clear(); - node->getOperand()->traverse(this); - if (isAssignOperation(node->getOp())) { - // We should always be able to get an access chain of the operand node. - assert(!current_object_.empty()); - - // If the operand node object is 'precise', we collect its access chain - // for the initial set of 'precise' objects. - if (isPreciseObjectNode(node->getOperand())) { - // The operand node is an 'precise' object node, add its - // access chain to the set of 'precise' objects. This is to collect - // the initial set of 'precise' objects. - precise_objects_.insert(current_object_); - } - // Gets the symbol ID from the object's access chain. - ObjectAccessChain id_symbol = getFrontElement(current_object_); - // Add a mapping from the symbol ID to this assignment operation node. - symbol_definition_mapping_.insert(std::make_pair(id_symbol, node)); - } - // A unary node is not a dereference node, so we clear the access chain which - // is under construction. - current_object_.clear(); - return false; -} - -// Visits a binary node and updates the mapping from symbol IDs to the definition -// nodes. Also collects the access chains for the initial precise objects. -bool TSymbolDefinitionCollectingTraverser::visitBinary(glslang::TVisit /* visit */, - glslang::TIntermBinary* node) -{ - // Traverses the left node to build the access chain info for the object. - current_object_.clear(); - node->getLeft()->traverse(this); - - if (isAssignOperation(node->getOp())) { - // We should always be able to get an access chain for the left node. - assert(!current_object_.empty()); - - // If the left node object is 'precise', it is an initial precise object - // specified in the shader source. Adds it to the initial work list to - // process later. - if (isPreciseObjectNode(node->getLeft())) { - // The left node is an 'precise' object node, add its access chain to - // the set of 'precise' objects. This is to collect the initial set - // of 'precise' objects. - precise_objects_.insert(current_object_); - } - // Gets the symbol ID from the object access chain, which should be the - // first element recorded in the access chain. - ObjectAccessChain id_symbol = getFrontElement(current_object_); - // Adds a mapping from the symbol ID to this assignment operation node. - symbol_definition_mapping_.insert(std::make_pair(id_symbol, node)); - - // Traverses the right node, there may be other 'assignment' - // operations in the right. - current_object_.clear(); - node->getRight()->traverse(this); - - } else if (isDereferenceOperation(node->getOp())) { - // The left node (parent node) is a struct type object. We need to - // record the access chain information of the current node into its - // object id. - if (node->getOp() == glslang::EOpIndexDirectStruct) { - unsigned struct_dereference_index = getStructIndexFromConstantUnion(node->getRight()); - current_object_.push_back(ObjectAccesschainDelimiter); - current_object_.append(std::to_string(struct_dereference_index)); - } - accesschain_mapping_[node] = current_object_; - - // For a dereference node, there is no need to traverse the right child - // node as the right node should always be an integer type object. - - } else { - // For other binary nodes, still traverse the right node. - current_object_.clear(); - node->getRight()->traverse(this); - } - return false; -} - -// Traverses the AST and returns a tuple of four members: -// 1) a mapping from symbol IDs to the definition nodes (aka. assignment nodes) of these symbols. -// 2) a mapping from object nodes in the AST to the access chains of these objects. -// 3) a set of access chains of precise objects. -// 4) a set of return nodes with precise expressions. -std::tuple -getSymbolToDefinitionMappingAndPreciseSymbolIDs(const glslang::TIntermediate& intermediate) -{ - auto result_tuple = std::make_tuple(NodeMapping(), AccessChainMapping(), ObjectAccesschainSet(), - ReturnBranchNodeSet()); - - TIntermNode* root = intermediate.getTreeRoot(); - if (root == nullptr) - return result_tuple; - - NodeMapping& symbol_definition_mapping = std::get<0>(result_tuple); - AccessChainMapping& accesschain_mapping = std::get<1>(result_tuple); - ObjectAccesschainSet& precise_objects = std::get<2>(result_tuple); - ReturnBranchNodeSet& precise_return_nodes = std::get<3>(result_tuple); - - // Traverses the AST and populate the results. - TSymbolDefinitionCollectingTraverser collector(&symbol_definition_mapping, &accesschain_mapping, - &precise_objects, &precise_return_nodes); - root->traverse(&collector); - - return result_tuple; -} - -// -// A traverser that determine whether the left node (or operand node for unary -// node) of an assignment node is 'precise', containing 'precise' or not, -// according to the access chain a given precise object which share the same -// symbol as the left node. -// -// Post-orderly traverses the left node subtree of an binary assignment node and: -// -// 1) Propagates the 'precise' from the left object nodes to this object node. -// -// 2) Builds object access chain along the traversal, and also compares with -// the access chain of the given 'precise' object along with the traversal to -// tell if the node to be defined is 'precise' or not. -// -class TNoContractionAssigneeCheckingTraverser : public glslang::TIntermTraverser { - - enum DecisionStatus { - // The object node to be assigned to may contain 'precise' objects and also not 'precise' objects. - Mixed = 0, - // The object node to be assigned to is either a 'precise' object or a struct objects whose members are all 'precise'. - Precise = 1, - // The object node to be assigned to is not a 'precise' object. - NotPreicse = 2, - }; - -public: - TNoContractionAssigneeCheckingTraverser(const AccessChainMapping& accesschain_mapping) - : TIntermTraverser(true, false, false), accesschain_mapping_(accesschain_mapping), - precise_object_(nullptr) {} - - // Checks the preciseness of a given assignment node with a precise object - // represented as access chain. The precise object shares the same symbol - // with the assignee of the given assignment node. Return a tuple of two: - // - // 1) The preciseness of the assignee node of this assignment node. True - // if the assignee contains 'precise' objects or is 'precise', false if - // the assignee is not 'precise' according to the access chain of the given - // precise object. - // - // 2) The incremental access chain from the assignee node to its nested - // 'precise' object, according to the access chain of the given precise - // object. This incremental access chain can be empty, which means the - // assignee is 'precise'. Otherwise it shows the path to the nested - // precise object. - std::tuple - getPrecisenessAndRemainedAccessChain(glslang::TIntermOperator* node, - const ObjectAccessChain& precise_object) - { - assert(isAssignOperation(node->getOp())); - precise_object_ = &precise_object; - ObjectAccessChain assignee_object; - if (glslang::TIntermBinary* BN = node->getAsBinaryNode()) { - // This is a binary assignment node, we need to check the - // preciseness of the left node. - assert(accesschain_mapping_.count(BN->getLeft())); - // The left node (assignee node) is an object node, traverse the - // node to let the 'precise' of nesting objects being transfered to - // nested objects. - BN->getLeft()->traverse(this); - // After traversing the left node, if the left node is 'precise', - // we can conclude this assignment should propagate 'precise'. - if (isPreciseObjectNode(BN->getLeft())) { - return make_tuple(true, ObjectAccessChain()); - } - // If the preciseness of the left node (assignee node) can not - // be determined by now, we need to compare the access chain string - // of the assignee object with the given precise object. - assignee_object = accesschain_mapping_.at(BN->getLeft()); - - } else if (glslang::TIntermUnary* UN = node->getAsUnaryNode()) { - // This is a unary assignment node, we need to check the - // preciseness of the operand node. For unary assignment node, the - // operand node should always be an object node. - assert(accesschain_mapping_.count(UN->getOperand())); - // Traverse the operand node to let the 'precise' being propagated - // from lower nodes to upper nodes. - UN->getOperand()->traverse(this); - // After traversing the operand node, if the operand node is - // 'precise', this assignment should propagate 'precise'. - if (isPreciseObjectNode(UN->getOperand())) { - return make_tuple(true, ObjectAccessChain()); - } - // If the preciseness of the operand node (assignee node) can not - // be determined by now, we need to compare the access chain string - // of the assignee object with the given precise object. - assignee_object = accesschain_mapping_.at(UN->getOperand()); - } else { - // Not a binary or unary node, should not happen. - assert(false); - } - - // Compare the access chain string of the assignee node with the given - // precise object to determine if this assignment should propagate - // 'precise'. - if (assignee_object.find(precise_object) == 0) { - // The access chain string of the given precise object is a prefix - // of assignee's access chain string. The assignee should be - // 'precise'. - return make_tuple(true, ObjectAccessChain()); - } else if (precise_object.find(assignee_object) == 0) { - // The assignee's access chain string is a prefix of the given - // precise object, the assignee object contains 'precise' object, - // and we need to pass the remained access chain to the object nodes - // in the right. - return make_tuple(true, getSubAccessChainAfterPrefix(precise_object, assignee_object)); - } else { - // The access chain strings do not match, the assignee object can - // not be labeled as 'precise' according to the given precise - // object. - return make_tuple(false, ObjectAccessChain()); - } - } - -protected: - TNoContractionAssigneeCheckingTraverser& operator=(const TNoContractionAssigneeCheckingTraverser&); - - bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override; - void visitSymbol(glslang::TIntermSymbol* node) override; - - // A map from object nodes to their access chain string (used as object ID). - const AccessChainMapping& accesschain_mapping_; - // A given precise object, represented in it access chain string. This - // precise object is used to be compared with the assignee node to tell if - // the assignee node is 'precise', contains 'precise' object or not - // 'precise'. - const ObjectAccessChain* precise_object_; -}; - -// Visits a binary node. If the node is an object node, it must be a dereference -// node. In such cases, if the left node is 'precise', this node should also be -// 'precise'. -bool TNoContractionAssigneeCheckingTraverser::visitBinary(glslang::TVisit, - glslang::TIntermBinary* node) -{ - // Traverses the left so that we transfer the 'precise' from nesting object - // to its nested object. - node->getLeft()->traverse(this); - // If this binary node is an object node, we should have it in the - // accesschain_mapping_. - if (accesschain_mapping_.count(node)) { - // A binary object node must be a dereference node. - assert(isDereferenceOperation(node->getOp())); - // If the left node is 'precise', this node should also be precise, - // otherwise, compare with the given precise_object_. If the - // access chain of this node matches with the given precise_object_, - // this node should be marked as 'precise'. - if (isPreciseObjectNode(node->getLeft())) { - node->getWritableType().getQualifier().noContraction = true; - } else if (accesschain_mapping_.at(node) == *precise_object_) { - node->getWritableType().getQualifier().noContraction = true; - } - } - return false; -} - -// Visits a symbol node, if the symbol node ID (its access chain string) matches -// with the given precise object, this node should be 'precise'. -void TNoContractionAssigneeCheckingTraverser::visitSymbol(glslang::TIntermSymbol* node) -{ - // A symbol node should always be an object node, and should have been added - // to the map from object nodes to their access chain strings. - assert(accesschain_mapping_.count(node)); - if (accesschain_mapping_.at(node) == *precise_object_) { - node->getWritableType().getQualifier().noContraction = true; - } -} - -// -// A traverser that only traverses the right side of binary assignment nodes -// and the operand node of unary assignment nodes. -// -// 1) Marks arithmetic operations as 'NoContraction'. -// -// 2) Find the object which should be marked as 'precise' in the right and -// update the 'precise' object work list. -// -class TNoContractionPropagator : public glslang::TIntermTraverser { -public: - TNoContractionPropagator(ObjectAccesschainSet* precise_objects, - const AccessChainMapping& accesschain_mapping) - : TIntermTraverser(true, false, false), - precise_objects_(*precise_objects), added_precise_object_ids_(), - remained_accesschain_(), accesschain_mapping_(accesschain_mapping) {} - - // Propagates 'precise' in the right nodes of a given assignment node with - // access chain record from the assignee node to a 'precise' object it - // contains. - void - propagateNoContractionInOneExpression(glslang::TIntermTyped* defining_node, - const ObjectAccessChain& assignee_remained_accesschain) - { - remained_accesschain_ = assignee_remained_accesschain; - if (glslang::TIntermBinary* BN = defining_node->getAsBinaryNode()) { - assert(isAssignOperation(BN->getOp())); - BN->getRight()->traverse(this); - if (isArithmeticOperation(BN->getOp())) { - BN->getWritableType().getQualifier().noContraction = true; - } - } else if (glslang::TIntermUnary* UN = defining_node->getAsUnaryNode()) { - assert(isAssignOperation(UN->getOp())); - UN->getOperand()->traverse(this); - if (isArithmeticOperation(UN->getOp())) { - UN->getWritableType().getQualifier().noContraction = true; - } - } - } - - // Propagates 'precise' in a given precise return node. - void propagateNoContractionInReturnNode(glslang::TIntermBranch* return_node) - { - remained_accesschain_ = ""; - assert(return_node->getFlowOp() == glslang::EOpReturn && return_node->getExpression()); - return_node->getExpression()->traverse(this); - } - -protected: - TNoContractionPropagator& operator=(const TNoContractionPropagator&); - - // Visits an aggregate node. The node can be a initializer list, in which - // case we need to find the 'precise' or 'precise' containing object node - // with the access chain record. In other cases, just need to traverse all - // the children nodes. - bool visitAggregate(glslang::TVisit, glslang::TIntermAggregate* node) override - { - if (!remained_accesschain_.empty() && node->getOp() == glslang::EOpConstructStruct) { - // This is a struct initializer node, and the remained - // access chain is not empty, we need to refer to the - // assignee_remained_access_chain_ to find the nested - // 'precise' object. And we don't need to visit other nodes in this - // aggregate node. - - // Gets the struct dereference index that leads to 'precise' object. - ObjectAccessChain precise_accesschain_index_str = - getFrontElement(remained_accesschain_); - unsigned precise_accesschain_index = (unsigned)strtoul(precise_accesschain_index_str.c_str(), nullptr, 10); - // Gets the node pointed by the access chain index extracted before. - glslang::TIntermTyped* potential_precise_node = - node->getSequence()[precise_accesschain_index]->getAsTyped(); - assert(potential_precise_node); - // Pop the front access chain index from the path, and visit the nested node. - { - ObjectAccessChain next_level_accesschain = - subAccessChainFromSecondElement(remained_accesschain_); - StateSettingGuard setup_remained_accesschain_for_next_level( - &remained_accesschain_, next_level_accesschain); - potential_precise_node->traverse(this); - } - return false; - } - return true; - } - - // Visits a binary node. A binary node can be an object node, e.g. a dereference node. - // As only the top object nodes in the right side of an assignment needs to be visited - // and added to 'precise' work list, this traverser won't visit the children nodes of - // an object node. If the binary node does not represent an object node, it should - // go on to traverse its children nodes and if it is an arithmetic operation node, this - // operation should be marked as 'noContraction'. - bool visitBinary(glslang::TVisit, glslang::TIntermBinary* node) override - { - if (isDereferenceOperation(node->getOp())) { - // This binary node is an object node. Need to update the precise - // object set with the access chain of this node + remained - // access chain . - ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node); - if (remained_accesschain_.empty()) { - node->getWritableType().getQualifier().noContraction = true; - } else { - new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_; - } - // Cache the access chain as added precise object, so we won't add the - // same object to the work list again. - if (!added_precise_object_ids_.count(new_precise_accesschain)) { - precise_objects_.insert(new_precise_accesschain); - added_precise_object_ids_.insert(new_precise_accesschain); - } - // Only the upper-most object nodes should be visited, so do not - // visit children of this object node. - return false; - } - // If this is an arithmetic operation, marks this node as 'noContraction'. - if (isArithmeticOperation(node->getOp()) && node->getBasicType() != glslang::EbtInt) { - node->getWritableType().getQualifier().noContraction = true; - } - // As this node is not an object node, need to traverse the children nodes. - return true; - } - - // Visits a unary node. A unary node can not be an object node. If the operation - // is an arithmetic operation, need to mark this node as 'noContraction'. - bool visitUnary(glslang::TVisit /* visit */, glslang::TIntermUnary* node) override - { - // If this is an arithmetic operation, marks this with 'noContraction' - if (isArithmeticOperation(node->getOp())) { - node->getWritableType().getQualifier().noContraction = true; - } - return true; - } - - // Visits a symbol node. A symbol node is always an object node. So we - // should always be able to find its in our collected mapping from object - // nodes to access chains. As an object node, a symbol node can be either - // 'precise' or containing 'precise' objects according to unused - // access chain information we have when we visit this node. - void visitSymbol(glslang::TIntermSymbol* node) override - { - // Symbol nodes are object nodes and should always have an - // access chain collected before matches with it. - assert(accesschain_mapping_.count(node)); - ObjectAccessChain new_precise_accesschain = accesschain_mapping_.at(node); - // If the unused access chain is empty, this symbol node should be - // marked as 'precise'. Otherwise, the unused access chain should be - // appended to the symbol ID to build a new access chain which points to - // the nested 'precise' object in this symbol object. - if (remained_accesschain_.empty()) { - node->getWritableType().getQualifier().noContraction = true; - } else { - new_precise_accesschain += ObjectAccesschainDelimiter + remained_accesschain_; - } - // Add the new 'precise' access chain to the work list and make sure we - // don't visit it again. - if (!added_precise_object_ids_.count(new_precise_accesschain)) { - precise_objects_.insert(new_precise_accesschain); - added_precise_object_ids_.insert(new_precise_accesschain); - } - } - - // A set of precise objects, represented as access chains. - ObjectAccesschainSet& precise_objects_; - // Visited symbol nodes, should not revisit these nodes. - ObjectAccesschainSet added_precise_object_ids_; - // The left node of an assignment operation might be an parent of 'precise' objects. - // This means the left node might not be an 'precise' object node, but it may contains - // 'precise' qualifier which should be propagated to the corresponding child node in - // the right. So we need the path from the left node to its nested 'precise' node to - // tell us how to find the corresponding 'precise' node in the right. - ObjectAccessChain remained_accesschain_; - // A map from node pointers to their access chains. - const AccessChainMapping& accesschain_mapping_; -}; -} - -namespace glslang { - -void PropagateNoContraction(const glslang::TIntermediate& intermediate) -{ - // First, traverses the AST, records symbols with their defining operations - // and collects the initial set of precise symbols (symbol nodes that marked - // as 'noContraction') and precise return nodes. - auto mappings_and_precise_objects = - getSymbolToDefinitionMappingAndPreciseSymbolIDs(intermediate); - - // The mapping of symbol node IDs to their defining nodes. This enables us - // to get the defining node directly from a given symbol ID without - // traversing the tree again. - NodeMapping& symbol_definition_mapping = std::get<0>(mappings_and_precise_objects); - - // The mapping of object nodes to their access chains recorded. - AccessChainMapping& accesschain_mapping = std::get<1>(mappings_and_precise_objects); - - // The initial set of 'precise' objects which are represented as the - // access chain toward them. - ObjectAccesschainSet& precise_object_accesschains = std::get<2>(mappings_and_precise_objects); - - // The set of 'precise' return nodes. - ReturnBranchNodeSet& precise_return_nodes = std::get<3>(mappings_and_precise_objects); - - // Second, uses the initial set of precise objects as a work list, pops an - // access chain, extract the symbol ID from it. Then: - // 1) Check the assignee object, see if it is 'precise' object node or - // contains 'precise' object. Obtain the incremental access chain from the - // assignee node to its nested 'precise' node (if any). - // 2) If the assignee object node is 'precise' or it contains 'precise' - // objects, traverses the right side of the assignment operation - // expression to mark arithmetic operations as 'noContration' and update - // 'precise' access chain work list with new found object nodes. - // Repeat above steps until the work list is empty. - TNoContractionAssigneeCheckingTraverser checker(accesschain_mapping); - TNoContractionPropagator propagator(&precise_object_accesschains, accesschain_mapping); - - // We have two initial precise work lists to handle: - // 1) precise return nodes - // 2) precise object access chains - // We should process the precise return nodes first and the involved - // objects in the return expression should be added to the precise object - // access chain set. - while (!precise_return_nodes.empty()) { - glslang::TIntermBranch* precise_return_node = *precise_return_nodes.begin(); - propagator.propagateNoContractionInReturnNode(precise_return_node); - precise_return_nodes.erase(precise_return_node); - } - - while (!precise_object_accesschains.empty()) { - // Get the access chain of a precise object from the work list. - ObjectAccessChain precise_object_accesschain = *precise_object_accesschains.begin(); - // Get the symbol id from the access chain. - ObjectAccessChain symbol_id = getFrontElement(precise_object_accesschain); - // Get all the defining nodes of that symbol ID. - std::pair range = - symbol_definition_mapping.equal_range(symbol_id); - // Visits all the assignment nodes of that symbol ID and - // 1) Check if the assignee node is 'precise' or contains 'precise' - // objects. - // 2) Propagate the 'precise' to the top layer object nodes - // in the right side of the assignment operation, update the 'precise' - // work list with new access chains representing the new 'precise' - // objects, and mark arithmetic operations as 'noContraction'. - for (NodeMapping::iterator defining_node_iter = range.first; - defining_node_iter != range.second; defining_node_iter++) { - TIntermOperator* defining_node = defining_node_iter->second; - // Check the assignee node. - auto checker_result = checker.getPrecisenessAndRemainedAccessChain( - defining_node, precise_object_accesschain); - bool& contain_precise = std::get<0>(checker_result); - ObjectAccessChain& remained_accesschain = std::get<1>(checker_result); - // If the assignee node is 'precise' or contains 'precise', propagate the - // 'precise' to the right. Otherwise just skip this assignment node. - if (contain_precise) { - propagator.propagateNoContractionInOneExpression(defining_node, - remained_accesschain); - } - } - // Remove the last processed 'precise' object from the work list. - precise_object_accesschains.erase(precise_object_accesschain); - } -} -} diff --git a/3rdparty/glslang/glslang/MachineIndependent/propagateNoContraction.h b/3rdparty/glslang/glslang/MachineIndependent/propagateNoContraction.h deleted file mode 100644 index 8521ad7d..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/propagateNoContraction.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright (C) 2015-2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -// -// Visit the nodes in the glslang intermediate tree representation to -// propagate 'noContraction' qualifier. -// - -#pragma once - -#include "../Include/intermediate.h" - -namespace glslang { - -// Propagates the 'precise' qualifier for objects (objects marked with -// 'noContraction' qualifier) from the shader source specified 'precise' -// variables to all the involved objects, and add 'noContraction' qualifier for -// the involved arithmetic operations. -// Note that the same qualifier: 'noContraction' is used in both object nodes -// and arithmetic operation nodes, but has different meaning. For object nodes, -// 'noContraction' means the object is 'precise'; and for arithmetic operation -// nodes, it means the operation should not be contracted. -void PropagateNoContraction(const glslang::TIntermediate& intermediate); -}; diff --git a/3rdparty/glslang/glslang/MachineIndependent/reflection.cpp b/3rdparty/glslang/glslang/MachineIndependent/reflection.cpp deleted file mode 100644 index 6c7d3a2c..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/reflection.cpp +++ /dev/null @@ -1,1270 +0,0 @@ -// -// Copyright (C) 2013-2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../Include/Common.h" -#include "reflection.h" -#include "LiveTraverser.h" -#include "localintermediate.h" - -#include "gl_types.h" - -// -// Grow the reflection database through a friend traverser class of TReflection and a -// collection of functions to do a liveness traversal that note what uniforms are used -// in semantically non-dead code. -// -// Can be used multiple times, once per stage, to grow a program reflection. -// -// High-level algorithm for one stage: -// -// 1. Put the entry point on the list of live functions. -// -// 2. Traverse any live function, while skipping if-tests with a compile-time constant -// condition of false, and while adding any encountered function calls to the live -// function list. -// -// Repeat until the live function list is empty. -// -// 3. Add any encountered uniform variables and blocks to the reflection database. -// -// Can be attempted with a failed link, but will return false if recursion had been detected, or -// there wasn't exactly one entry point. -// - -namespace glslang { - -// -// The traverser: mostly pass through, except -// - processing binary nodes to see if they are dereferences of an aggregates to track -// - processing symbol nodes to see if they are non-aggregate objects to track -// -// This ignores semantically dead code by using TLiveTraverser. -// -// This is in the glslang namespace directly so it can be a friend of TReflection. -// - -class TReflectionTraverser : public TIntermTraverser { -public: - TReflectionTraverser(const TIntermediate& i, TReflection& r) : - TIntermTraverser(), intermediate(i), reflection(r), updateStageMasks(true) { } - - virtual bool visitBinary(TVisit, TIntermBinary* node); - virtual void visitSymbol(TIntermSymbol* base); - - // Add a simple reference to a uniform variable to the uniform database, no dereference involved. - // However, no dereference doesn't mean simple... it could be a complex aggregate. - void addUniform(const TIntermSymbol& base) - { - if (processedDerefs.find(&base) == processedDerefs.end()) { - processedDerefs.insert(&base); - - int blockIndex = -1; - int offset = -1; - TList derefs; - TString baseName = base.getName(); - - if (base.getType().getBasicType() == EbtBlock) { - offset = 0; - bool anonymous = IsAnonymous(baseName); - const TString& blockName = base.getType().getTypeName(); - - if (!anonymous) - baseName = blockName; - else - baseName = ""; - - blockIndex = addBlockName(blockName, base.getType(), intermediate.getBlockSize(base.getType())); - } - - // Use a degenerate (empty) set of dereferences to immediately put as at the end of - // the dereference change expected by blowUpActiveAggregate. - blowUpActiveAggregate(base.getType(), baseName, derefs, derefs.end(), offset, blockIndex, 0, -1, 0, - base.getQualifier().storage, updateStageMasks); - } - } - - void addPipeIOVariable(const TIntermSymbol& base) - { - if (processedDerefs.find(&base) == processedDerefs.end()) { - processedDerefs.insert(&base); - - const TString &name = base.getName(); - const TType &type = base.getType(); - const bool input = base.getQualifier().isPipeInput(); - - TReflection::TMapIndexToReflection &ioItems = - input ? reflection.indexToPipeInput : reflection.indexToPipeOutput; - - - TReflection::TNameToIndex &ioMapper = - input ? reflection.pipeInNameToIndex : reflection.pipeOutNameToIndex; - - if (reflection.options & EShReflectionUnwrapIOBlocks) { - bool anonymous = IsAnonymous(name); - - TString baseName; - if (type.getBasicType() == EbtBlock) { - baseName = anonymous ? TString() : type.getTypeName(); - } else { - baseName = anonymous ? TString() : name; - } - - // by convention if this is an arrayed block we ignore the array in the reflection - if (type.isArray() && type.getBasicType() == EbtBlock) { - blowUpIOAggregate(input, baseName, TType(type, 0)); - } else { - blowUpIOAggregate(input, baseName, type); - } - } else { - TReflection::TNameToIndex::const_iterator it = ioMapper.find(name.c_str()); - if (it == ioMapper.end()) { - // seperate pipe i/o params from uniforms and blocks - // in is only for input in first stage as out is only for last stage. check traverse in call stack. - ioMapper[name.c_str()] = static_cast(ioItems.size()); - ioItems.push_back( - TObjectReflection(name.c_str(), type, 0, mapToGlType(type), mapToGlArraySize(type), 0)); - EShLanguageMask& stages = ioItems.back().stages; - stages = static_cast(stages | 1 << intermediate.getStage()); - } else { - EShLanguageMask& stages = ioItems[it->second].stages; - stages = static_cast(stages | 1 << intermediate.getStage()); - } - } - } - } - - // Lookup or calculate the offset of all block members at once, using the recursively - // defined block offset rules. - void getOffsets(const TType& type, TVector& offsets) - { - const TTypeList& memberList = *type.getStruct(); - int memberSize = 0; - int offset = 0; - - for (size_t m = 0; m < offsets.size(); ++m) { - // if the user supplied an offset, snap to it now - if (memberList[m].type->getQualifier().hasOffset()) - offset = memberList[m].type->getQualifier().layoutOffset; - - // calculate the offset of the next member and align the current offset to this member - intermediate.updateOffset(type, *memberList[m].type, offset, memberSize); - - // save the offset of this member - offsets[m] = offset; - - // update for the next member - offset += memberSize; - } - } - - // Calculate the stride of an array type - int getArrayStride(const TType& baseType, const TType& type) - { - int dummySize; - int stride; - - // consider blocks to have 0 stride, so that all offsets are relative to the start of their block - if (type.getBasicType() == EbtBlock) - return 0; - - TLayoutMatrix subMatrixLayout = type.getQualifier().layoutMatrix; - intermediate.getMemberAlignment(type, dummySize, stride, - baseType.getQualifier().layoutPacking, - subMatrixLayout != ElmNone - ? subMatrixLayout == ElmRowMajor - : baseType.getQualifier().layoutMatrix == ElmRowMajor); - - return stride; - } - - // count the total number of leaf members from iterating out of a block type - int countAggregateMembers(const TType& parentType) - { - if (! parentType.isStruct()) - return 1; - - const bool strictArraySuffix = (reflection.options & EShReflectionStrictArraySuffix); - - bool blockParent = (parentType.getBasicType() == EbtBlock && parentType.getQualifier().storage == EvqBuffer); - - const TTypeList &memberList = *parentType.getStruct(); - - int ret = 0; - - for (size_t i = 0; i < memberList.size(); i++) - { - const TType &memberType = *memberList[i].type; - int numMembers = countAggregateMembers(memberType); - // for sized arrays of structs, apply logic to expand out the same as we would below in - // blowUpActiveAggregate - if (memberType.isArray() && ! memberType.getArraySizes()->hasUnsized() && memberType.isStruct()) { - if (! strictArraySuffix || ! blockParent) - numMembers *= memberType.getArraySizes()->getCumulativeSize(); - } - ret += numMembers; - } - - return ret; - } - - // Traverse the provided deref chain, including the base, and - // - build a full reflection-granularity name, array size, etc. entry out of it, if it goes down to that granularity - // - recursively expand any variable array index in the middle of that traversal - // - recursively expand what's left at the end if the deref chain did not reach down to reflection granularity - // - // arraySize tracks, just for the final dereference in the chain, if there was a specific known size. - // A value of 0 for arraySize will mean to use the full array's size. - void blowUpActiveAggregate(const TType& baseType, const TString& baseName, const TList& derefs, - TList::const_iterator deref, int offset, int blockIndex, int arraySize, - int topLevelArraySize, int topLevelArrayStride, TStorageQualifier baseStorage, bool active) - { - // when strictArraySuffix is enabled, we closely follow the rules from ARB_program_interface_query. - // Broadly: - // * arrays-of-structs always have a [x] suffix. - // * with array-of-struct variables in the root of a buffer block, only ever return [0]. - // * otherwise, array suffixes are added whenever we iterate, even if that means expanding out an array. - const bool strictArraySuffix = (reflection.options & EShReflectionStrictArraySuffix); - - // is this variable inside a buffer block. This flag is set back to false after we iterate inside the first array element. - bool blockParent = (baseType.getBasicType() == EbtBlock && baseType.getQualifier().storage == EvqBuffer); - - // process the part of the dereference chain that was explicit in the shader - TString name = baseName; - const TType* terminalType = &baseType; - for (; deref != derefs.end(); ++deref) { - TIntermBinary* visitNode = *deref; - terminalType = &visitNode->getType(); - int index; - switch (visitNode->getOp()) { - case EOpIndexIndirect: { - int stride = getArrayStride(baseType, visitNode->getLeft()->getType()); - - if (topLevelArrayStride == 0) - topLevelArrayStride = stride; - - // Visit all the indices of this array, and for each one add on the remaining dereferencing - for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) { - TString newBaseName = name; - if (terminalType->getBasicType() == EbtBlock) {} - else if (strictArraySuffix && blockParent) - newBaseName.append(TString("[0]")); - else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) - newBaseName.append(TString("[") + String(i) + "]"); - TList::const_iterator nextDeref = deref; - ++nextDeref; - blowUpActiveAggregate(*terminalType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize, - topLevelArraySize, topLevelArrayStride, baseStorage, active); - - if (offset >= 0) - offset += stride; - } - - // it was all completed in the recursive calls above - return; - } - case EOpIndexDirect: { - int stride = getArrayStride(baseType, visitNode->getLeft()->getType()); - - index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (terminalType->getBasicType() == EbtBlock) {} - else if (strictArraySuffix && blockParent) - name.append(TString("[0]")); - else if (strictArraySuffix || baseType.getBasicType() != EbtBlock) { - name.append(TString("[") + String(index) + "]"); - - if (offset >= 0) - offset += stride * index; - } - - if (topLevelArrayStride == 0) - topLevelArrayStride = stride; - - // expand top-level arrays in blocks with [0] suffix - if (topLevelArrayStride != 0 && visitNode->getLeft()->getType().isArray()) { - blockParent = false; - } - break; - } - case EOpIndexDirectStruct: - index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); - if (offset >= 0) - offset += intermediate.getOffset(visitNode->getLeft()->getType(), index); - if (name.size() > 0) - name.append("."); - name.append((*visitNode->getLeft()->getType().getStruct())[index].type->getFieldName()); - - // expand non top-level arrays with [x] suffix - if (visitNode->getLeft()->getType().getBasicType() != EbtBlock && terminalType->isArray()) - { - blockParent = false; - } - break; - default: - break; - } - } - - // if the terminalType is still too coarse a granularity, this is still an aggregate to expand, expand it... - if (! isReflectionGranularity(*terminalType)) { - // the base offset of this node, that children are relative to - int baseOffset = offset; - - if (terminalType->isArray()) { - // Visit all the indices of this array, and for each one, - // fully explode the remaining aggregate to dereference - - int stride = 0; - if (offset >= 0) - stride = getArrayStride(baseType, *terminalType); - - int arrayIterateSize = std::max(terminalType->getOuterArraySize(), 1); - - // for top-level arrays in blocks, only expand [0] to avoid explosion of items - if ((strictArraySuffix && blockParent) || - ((topLevelArraySize == arrayIterateSize) && (topLevelArrayStride == 0))) { - arrayIterateSize = 1; - } - - if (topLevelArrayStride == 0) - topLevelArrayStride = stride; - - for (int i = 0; i < arrayIterateSize; ++i) { - TString newBaseName = name; - if (terminalType->getBasicType() != EbtBlock) - newBaseName.append(TString("[") + String(i) + "]"); - TType derefType(*terminalType, 0); - if (offset >= 0) - offset = baseOffset + stride * i; - - blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0, - topLevelArraySize, topLevelArrayStride, baseStorage, active); - } - } else { - // Visit all members of this aggregate, and for each one, - // fully explode the remaining aggregate to dereference - const TTypeList& typeList = *terminalType->getStruct(); - - TVector memberOffsets; - - if (baseOffset >= 0) { - memberOffsets.resize(typeList.size()); - getOffsets(*terminalType, memberOffsets); - } - - for (int i = 0; i < (int)typeList.size(); ++i) { - TString newBaseName = name; - if (newBaseName.size() > 0) - newBaseName.append("."); - newBaseName.append(typeList[i].type->getFieldName()); - TType derefType(*terminalType, i); - if (offset >= 0) - offset = baseOffset + memberOffsets[i]; - - int arrayStride = topLevelArrayStride; - if (terminalType->getBasicType() == EbtBlock && terminalType->getQualifier().storage == EvqBuffer && - derefType.isArray()) { - arrayStride = getArrayStride(baseType, derefType); - } - - if (topLevelArraySize == -1 && arrayStride == 0 && blockParent) - topLevelArraySize = 1; - - if (strictArraySuffix && blockParent) { - // if this member is an array, store the top-level array stride but start the explosion from - // the inner struct type. - if (derefType.isArray() && derefType.isStruct()) { - newBaseName.append("[0]"); - auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0); - blowUpActiveAggregate(TType(derefType, 0), newBaseName, derefs, derefs.end(), memberOffsets[i], - blockIndex, 0, dimSize, arrayStride, terminalType->getQualifier().storage, false); - } - else if (derefType.isArray()) { - auto dimSize = derefType.isUnsizedArray() ? 0 : derefType.getArraySizes()->getDimSize(0); - blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex, - 0, dimSize, 0, terminalType->getQualifier().storage, false); - } - else { - blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), memberOffsets[i], blockIndex, - 0, 1, 0, terminalType->getQualifier().storage, false); - } - } else { - blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0, - topLevelArraySize, arrayStride, baseStorage, active); - } - } - } - - // it was all completed in the recursive calls above - return; - } - - if ((reflection.options & EShReflectionBasicArraySuffix) && terminalType->isArray()) { - name.append(TString("[0]")); - } - - // Finally, add a full string to the reflection database, and update the array size if necessary. - // If the dereferenced entity to record is an array, compute the size and update the maximum size. - - // there might not be a final array dereference, it could have been copied as an array object - if (arraySize == 0) - arraySize = mapToGlArraySize(*terminalType); - - TReflection::TMapIndexToReflection& variables = reflection.GetVariableMapForStorage(baseStorage); - - TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str()); - if (it == reflection.nameToIndex.end()) { - int uniformIndex = (int)variables.size(); - reflection.nameToIndex[name.c_str()] = uniformIndex; - variables.push_back(TObjectReflection(name.c_str(), *terminalType, offset, mapToGlType(*terminalType), - arraySize, blockIndex)); - if (terminalType->isArray()) { - variables.back().arrayStride = getArrayStride(baseType, *terminalType); - if (topLevelArrayStride == 0) - topLevelArrayStride = variables.back().arrayStride; - } - - if ((reflection.options & EShReflectionSeparateBuffers) && terminalType->isAtomic()) - reflection.atomicCounterUniformIndices.push_back(uniformIndex); - - variables.back().topLevelArraySize = topLevelArraySize; - variables.back().topLevelArrayStride = topLevelArrayStride; - - if ((reflection.options & EShReflectionAllBlockVariables) && active) { - EShLanguageMask& stages = variables.back().stages; - stages = static_cast(stages | 1 << intermediate.getStage()); - } - } else { - if (arraySize > 1) { - int& reflectedArraySize = variables[it->second].size; - reflectedArraySize = std::max(arraySize, reflectedArraySize); - } - - if ((reflection.options & EShReflectionAllBlockVariables) && active) { - EShLanguageMask& stages = variables[it->second].stages; - stages = static_cast(stages | 1 << intermediate.getStage()); - } - } - } - - // similar to blowUpActiveAggregate, but with simpler rules and no dereferences to follow. - void blowUpIOAggregate(bool input, const TString &baseName, const TType &type) - { - TString name = baseName; - - // if the type is still too coarse a granularity, this is still an aggregate to expand, expand it... - if (! isReflectionGranularity(type)) { - if (type.isArray()) { - // Visit all the indices of this array, and for each one, - // fully explode the remaining aggregate to dereference - for (int i = 0; i < std::max(type.getOuterArraySize(), 1); ++i) { - TString newBaseName = name; - newBaseName.append(TString("[") + String(i) + "]"); - TType derefType(type, 0); - - blowUpIOAggregate(input, newBaseName, derefType); - } - } else { - // Visit all members of this aggregate, and for each one, - // fully explode the remaining aggregate to dereference - const TTypeList& typeList = *type.getStruct(); - - for (int i = 0; i < (int)typeList.size(); ++i) { - TString newBaseName = name; - if (newBaseName.size() > 0) - newBaseName.append("."); - newBaseName.append(typeList[i].type->getFieldName()); - TType derefType(type, i); - - blowUpIOAggregate(input, newBaseName, derefType); - } - } - - // it was all completed in the recursive calls above - return; - } - - if ((reflection.options & EShReflectionBasicArraySuffix) && type.isArray()) { - name.append(TString("[0]")); - } - - TReflection::TMapIndexToReflection &ioItems = - input ? reflection.indexToPipeInput : reflection.indexToPipeOutput; - - std::string namespacedName = input ? "in " : "out "; - namespacedName += name.c_str(); - - TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(namespacedName); - if (it == reflection.nameToIndex.end()) { - reflection.nameToIndex[namespacedName] = (int)ioItems.size(); - ioItems.push_back( - TObjectReflection(name.c_str(), type, 0, mapToGlType(type), mapToGlArraySize(type), 0)); - - EShLanguageMask& stages = ioItems.back().stages; - stages = static_cast(stages | 1 << intermediate.getStage()); - } else { - EShLanguageMask& stages = ioItems[it->second].stages; - stages = static_cast(stages | 1 << intermediate.getStage()); - } - } - - // Add a uniform dereference where blocks/struct/arrays are involved in the access. - // Handles the situation where the left node is at the correct or too coarse a - // granularity for reflection. (That is, further dereferences up the tree will be - // skipped.) Earlier dereferences, down the tree, will be handled - // at the same time, and logged to prevent reprocessing as the tree is traversed. - // - // Note: Other things like the following must be caught elsewhere: - // - a simple non-array, non-struct variable (no dereference even conceivable) - // - an aggregrate consumed en masse, without a dereference - // - // So, this code is for cases like - // - a struct/block dereferencing a member (whether the member is array or not) - // - an array of struct - // - structs/arrays containing the above - // - void addDereferencedUniform(TIntermBinary* topNode) - { - // See if too fine-grained to process (wait to get further down the tree) - const TType& leftType = topNode->getLeft()->getType(); - if ((leftType.isVector() || leftType.isMatrix()) && ! leftType.isArray()) - return; - - // We have an array or structure or block dereference, see if it's a uniform - // based dereference (if not, skip it). - TIntermSymbol* base = findBase(topNode); - if (! base || ! base->getQualifier().isUniformOrBuffer()) - return; - - // See if we've already processed this (e.g., in the middle of something - // we did earlier), and if so skip it - if (processedDerefs.find(topNode) != processedDerefs.end()) - return; - - // Process this uniform dereference - - int offset = -1; - int blockIndex = -1; - bool anonymous = false; - - // See if we need to record the block itself - bool block = base->getBasicType() == EbtBlock; - if (block) { - offset = 0; - anonymous = IsAnonymous(base->getName()); - - const TString& blockName = base->getType().getTypeName(); - TString baseName; - - if (! anonymous) - baseName = blockName; - - blockIndex = addBlockName(blockName, base->getType(), intermediate.getBlockSize(base->getType())); - - if (reflection.options & EShReflectionAllBlockVariables) { - // Use a degenerate (empty) set of dereferences to immediately put as at the end of - // the dereference change expected by blowUpActiveAggregate. - TList derefs; - - // otherwise - if we're not using strict array suffix rules, or this isn't a block so we are - // expanding root arrays anyway, just start the iteration from the base block type. - blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.end(), 0, blockIndex, 0, -1, 0, - base->getQualifier().storage, false); - } - } - - // Process the dereference chain, backward, accumulating the pieces for later forward traversal. - // If the topNode is a reflection-granularity-array dereference, don't include that last dereference. - TList derefs; - for (TIntermBinary* visitNode = topNode; visitNode; visitNode = visitNode->getLeft()->getAsBinaryNode()) { - if (isReflectionGranularity(visitNode->getLeft()->getType())) - continue; - - derefs.push_front(visitNode); - processedDerefs.insert(visitNode); - } - processedDerefs.insert(base); - - // See if we have a specific array size to stick to while enumerating the explosion of the aggregate - int arraySize = 0; - if (isReflectionGranularity(topNode->getLeft()->getType()) && topNode->getLeft()->isArray()) { - if (topNode->getOp() == EOpIndexDirect) - arraySize = topNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst() + 1; - } - - // Put the dereference chain together, forward - TString baseName; - if (! anonymous) { - if (block) - baseName = base->getType().getTypeName(); - else - baseName = base->getName(); - } - blowUpActiveAggregate(base->getType(), baseName, derefs, derefs.begin(), offset, blockIndex, arraySize, -1, 0, - base->getQualifier().storage, true); - } - - int addBlockName(const TString& name, const TType& type, int size) - { - int blockIndex = 0; - if (type.isArray()) { - TType derefType(type, 0); - for (int e = 0; e < type.getOuterArraySize(); ++e) { - int memberBlockIndex = addBlockName(name + "[" + String(e) + "]", derefType, size); - if (e == 0) - blockIndex = memberBlockIndex; - } - } else { - TReflection::TMapIndexToReflection& blocks = reflection.GetBlockMapForStorage(type.getQualifier().storage); - - TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str()); - if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) { - blockIndex = (int)blocks.size(); - reflection.nameToIndex[name.c_str()] = blockIndex; - blocks.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, blockIndex)); - - blocks.back().numMembers = countAggregateMembers(type); - - if (updateStageMasks) { - EShLanguageMask& stages = blocks.back().stages; - stages = static_cast(stages | 1 << intermediate.getStage()); - } - } - else { - blockIndex = it->second; - if (updateStageMasks) { - EShLanguageMask& stages = blocks[blockIndex].stages; - stages = static_cast(stages | 1 << intermediate.getStage()); - } - } - } - - return blockIndex; - } - - // Are we at a level in a dereference chain at which individual active uniform queries are made? - bool isReflectionGranularity(const TType& type) - { - return type.getBasicType() != EbtBlock && type.getBasicType() != EbtStruct && !type.isArrayOfArrays(); - } - - // For a binary operation indexing into an aggregate, chase down the base of the aggregate. - // Return nullptr if the topology does not fit this situation. - TIntermSymbol* findBase(const TIntermBinary* node) - { - TIntermSymbol *base = node->getLeft()->getAsSymbolNode(); - if (base) - return base; - TIntermBinary* left = node->getLeft()->getAsBinaryNode(); - if (! left) - return nullptr; - - return findBase(left); - } - - // - // Translate a glslang sampler type into the GL API #define number. - // - int mapSamplerToGlType(TSampler sampler) - { - if (! sampler.image) { - // a sampler... - switch (sampler.type) { - case EbtFloat: - switch ((int)sampler.dim) { - case Esd1D: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_SAMPLER_1D_ARRAY : GL_SAMPLER_1D; - case true: return sampler.arrayed ? GL_SAMPLER_1D_ARRAY_SHADOW : GL_SAMPLER_1D_SHADOW; - } - case Esd2D: - switch ((int)sampler.ms) { - case false: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_SAMPLER_2D_ARRAY : GL_SAMPLER_2D; - case true: return sampler.arrayed ? GL_SAMPLER_2D_ARRAY_SHADOW : GL_SAMPLER_2D_SHADOW; - } - case true: return sampler.arrayed ? GL_SAMPLER_2D_MULTISAMPLE_ARRAY : GL_SAMPLER_2D_MULTISAMPLE; - } - case Esd3D: - return GL_SAMPLER_3D; - case EsdCube: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_SAMPLER_CUBE_MAP_ARRAY : GL_SAMPLER_CUBE; - case true: return sampler.arrayed ? GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW : GL_SAMPLER_CUBE_SHADOW; - } - case EsdRect: - return sampler.shadow ? GL_SAMPLER_2D_RECT_SHADOW : GL_SAMPLER_2D_RECT; - case EsdBuffer: - return GL_SAMPLER_BUFFER; - } - case EbtFloat16: - switch ((int)sampler.dim) { - case Esd1D: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_1D_ARRAY_AMD : GL_FLOAT16_SAMPLER_1D_AMD; - case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_1D_SHADOW_AMD; - } - case Esd2D: - switch ((int)sampler.ms) { - case false: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_ARRAY_AMD : GL_FLOAT16_SAMPLER_2D_AMD; - case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_2D_SHADOW_AMD; - } - case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD : GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD; - } - case Esd3D: - return GL_FLOAT16_SAMPLER_3D_AMD; - case EsdCube: - switch ((int)sampler.shadow) { - case false: return sampler.arrayed ? GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD : GL_FLOAT16_SAMPLER_CUBE_AMD; - case true: return sampler.arrayed ? GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD : GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD; - } - case EsdRect: - return sampler.shadow ? GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD : GL_FLOAT16_SAMPLER_2D_RECT_AMD; - case EsdBuffer: - return GL_FLOAT16_SAMPLER_BUFFER_AMD; - } - case EbtInt: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_INT_SAMPLER_1D_ARRAY : GL_INT_SAMPLER_1D; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_INT_SAMPLER_2D_ARRAY : GL_INT_SAMPLER_2D; - case true: return sampler.arrayed ? GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY - : GL_INT_SAMPLER_2D_MULTISAMPLE; - } - case Esd3D: - return GL_INT_SAMPLER_3D; - case EsdCube: - return sampler.arrayed ? GL_INT_SAMPLER_CUBE_MAP_ARRAY : GL_INT_SAMPLER_CUBE; - case EsdRect: - return GL_INT_SAMPLER_2D_RECT; - case EsdBuffer: - return GL_INT_SAMPLER_BUFFER; - } - case EbtUint: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_1D_ARRAY : GL_UNSIGNED_INT_SAMPLER_1D; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_ARRAY : GL_UNSIGNED_INT_SAMPLER_2D; - case true: return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY - : GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE; - } - case Esd3D: - return GL_UNSIGNED_INT_SAMPLER_3D; - case EsdCube: - return sampler.arrayed ? GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY : GL_UNSIGNED_INT_SAMPLER_CUBE; - case EsdRect: - return GL_UNSIGNED_INT_SAMPLER_2D_RECT; - case EsdBuffer: - return GL_UNSIGNED_INT_SAMPLER_BUFFER; - } - default: - return 0; - } - } else { - // an image... - switch (sampler.type) { - case EbtFloat: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_IMAGE_1D_ARRAY : GL_IMAGE_1D; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_IMAGE_2D_ARRAY : GL_IMAGE_2D; - case true: return sampler.arrayed ? GL_IMAGE_2D_MULTISAMPLE_ARRAY : GL_IMAGE_2D_MULTISAMPLE; - } - case Esd3D: - return GL_IMAGE_3D; - case EsdCube: - return sampler.arrayed ? GL_IMAGE_CUBE_MAP_ARRAY : GL_IMAGE_CUBE; - case EsdRect: - return GL_IMAGE_2D_RECT; - case EsdBuffer: - return GL_IMAGE_BUFFER; - } - case EbtFloat16: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_FLOAT16_IMAGE_1D_ARRAY_AMD : GL_FLOAT16_IMAGE_1D_AMD; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_FLOAT16_IMAGE_2D_ARRAY_AMD : GL_FLOAT16_IMAGE_2D_AMD; - case true: return sampler.arrayed ? GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD : GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD; - } - case Esd3D: - return GL_FLOAT16_IMAGE_3D_AMD; - case EsdCube: - return sampler.arrayed ? GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD : GL_FLOAT16_IMAGE_CUBE_AMD; - case EsdRect: - return GL_FLOAT16_IMAGE_2D_RECT_AMD; - case EsdBuffer: - return GL_FLOAT16_IMAGE_BUFFER_AMD; - } - case EbtInt: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_INT_IMAGE_1D_ARRAY : GL_INT_IMAGE_1D; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_INT_IMAGE_2D_ARRAY : GL_INT_IMAGE_2D; - case true: return sampler.arrayed ? GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY : GL_INT_IMAGE_2D_MULTISAMPLE; - } - case Esd3D: - return GL_INT_IMAGE_3D; - case EsdCube: - return sampler.arrayed ? GL_INT_IMAGE_CUBE_MAP_ARRAY : GL_INT_IMAGE_CUBE; - case EsdRect: - return GL_INT_IMAGE_2D_RECT; - case EsdBuffer: - return GL_INT_IMAGE_BUFFER; - } - case EbtUint: - switch ((int)sampler.dim) { - case Esd1D: - return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_1D_ARRAY : GL_UNSIGNED_INT_IMAGE_1D; - case Esd2D: - switch ((int)sampler.ms) { - case false: return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_ARRAY : GL_UNSIGNED_INT_IMAGE_2D; - case true: return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY - : GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE; - } - case Esd3D: - return GL_UNSIGNED_INT_IMAGE_3D; - case EsdCube: - return sampler.arrayed ? GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY : GL_UNSIGNED_INT_IMAGE_CUBE; - case EsdRect: - return GL_UNSIGNED_INT_IMAGE_2D_RECT; - case EsdBuffer: - return GL_UNSIGNED_INT_IMAGE_BUFFER; - } - default: - return 0; - } - } - } - - // - // Translate a glslang type into the GL API #define number. - // Ignores arrayness. - // - int mapToGlType(const TType& type) - { - switch (type.getBasicType()) { - case EbtSampler: - return mapSamplerToGlType(type.getSampler()); - case EbtStruct: - case EbtBlock: - case EbtVoid: - return 0; - default: - break; - } - - if (type.isVector()) { - int offset = type.getVectorSize() - 2; - switch (type.getBasicType()) { - case EbtFloat: return GL_FLOAT_VEC2 + offset; - case EbtDouble: return GL_DOUBLE_VEC2 + offset; - case EbtFloat16: return GL_FLOAT16_VEC2_NV + offset; - case EbtInt: return GL_INT_VEC2 + offset; - case EbtUint: return GL_UNSIGNED_INT_VEC2 + offset; - case EbtInt64: return GL_INT64_VEC2_ARB + offset; - case EbtUint64: return GL_UNSIGNED_INT64_VEC2_ARB + offset; - case EbtBool: return GL_BOOL_VEC2 + offset; - case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER + offset; - default: return 0; - } - } - if (type.isMatrix()) { - switch (type.getBasicType()) { - case EbtFloat: - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT_MAT2; - case 3: return GL_FLOAT_MAT2x3; - case 4: return GL_FLOAT_MAT2x4; - default: return 0; - } - case 3: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT_MAT3x2; - case 3: return GL_FLOAT_MAT3; - case 4: return GL_FLOAT_MAT3x4; - default: return 0; - } - case 4: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT_MAT4x2; - case 3: return GL_FLOAT_MAT4x3; - case 4: return GL_FLOAT_MAT4; - default: return 0; - } - } - case EbtDouble: - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: return GL_DOUBLE_MAT2; - case 3: return GL_DOUBLE_MAT2x3; - case 4: return GL_DOUBLE_MAT2x4; - default: return 0; - } - case 3: - switch (type.getMatrixRows()) { - case 2: return GL_DOUBLE_MAT3x2; - case 3: return GL_DOUBLE_MAT3; - case 4: return GL_DOUBLE_MAT3x4; - default: return 0; - } - case 4: - switch (type.getMatrixRows()) { - case 2: return GL_DOUBLE_MAT4x2; - case 3: return GL_DOUBLE_MAT4x3; - case 4: return GL_DOUBLE_MAT4; - default: return 0; - } - } - case EbtFloat16: - switch (type.getMatrixCols()) { - case 2: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT16_MAT2_AMD; - case 3: return GL_FLOAT16_MAT2x3_AMD; - case 4: return GL_FLOAT16_MAT2x4_AMD; - default: return 0; - } - case 3: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT16_MAT3x2_AMD; - case 3: return GL_FLOAT16_MAT3_AMD; - case 4: return GL_FLOAT16_MAT3x4_AMD; - default: return 0; - } - case 4: - switch (type.getMatrixRows()) { - case 2: return GL_FLOAT16_MAT4x2_AMD; - case 3: return GL_FLOAT16_MAT4x3_AMD; - case 4: return GL_FLOAT16_MAT4_AMD; - default: return 0; - } - } - default: - return 0; - } - } - if (type.getVectorSize() == 1) { - switch (type.getBasicType()) { - case EbtFloat: return GL_FLOAT; - case EbtDouble: return GL_DOUBLE; - case EbtFloat16: return GL_FLOAT16_NV; - case EbtInt: return GL_INT; - case EbtUint: return GL_UNSIGNED_INT; - case EbtInt64: return GL_INT64_ARB; - case EbtUint64: return GL_UNSIGNED_INT64_ARB; - case EbtBool: return GL_BOOL; - case EbtAtomicUint: return GL_UNSIGNED_INT_ATOMIC_COUNTER; - default: return 0; - } - } - - return 0; - } - - int mapToGlArraySize(const TType& type) - { - return type.isArray() ? type.getOuterArraySize() : 1; - } - - const TIntermediate& intermediate; - TReflection& reflection; - std::set processedDerefs; - bool updateStageMasks; - -protected: - TReflectionTraverser(TReflectionTraverser&); - TReflectionTraverser& operator=(TReflectionTraverser&); -}; - -// -// Implement the traversal functions of interest. -// - -// To catch dereferenced aggregates that must be reflected. -// This catches them at the highest level possible in the tree. -bool TReflectionTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node) -{ - switch (node->getOp()) { - case EOpIndexDirect: - case EOpIndexIndirect: - case EOpIndexDirectStruct: - addDereferencedUniform(node); - break; - default: - break; - } - - // still need to visit everything below, which could contain sub-expressions - // containing different uniforms - return true; -} - -// To reflect non-dereferenced objects. -void TReflectionTraverser::visitSymbol(TIntermSymbol* base) -{ - if (base->getQualifier().storage == EvqUniform) { - if (base->getBasicType() == EbtBlock) { - if (reflection.options & EShReflectionSharedStd140UBO) { - addUniform(*base); - } - } else { - addUniform(*base); - } - } - - // #TODO add std140/layout active rules for ssbo, same with ubo. - // Storage buffer blocks will be collected and expanding in this part. - if((reflection.options & EShReflectionSharedStd140SSBO) && - (base->getQualifier().storage == EvqBuffer && base->getBasicType() == EbtBlock && - (base->getQualifier().layoutPacking == ElpStd140 || base->getQualifier().layoutPacking == ElpShared))) - addUniform(*base); - - if ((intermediate.getStage() == reflection.firstStage && base->getQualifier().isPipeInput()) || - (intermediate.getStage() == reflection.lastStage && base->getQualifier().isPipeOutput())) - addPipeIOVariable(*base); -} - -// -// Implement TObjectReflection methods. -// - -TObjectReflection::TObjectReflection(const std::string &pName, const TType &pType, int pOffset, int pGLDefineType, - int pSize, int pIndex) - : name(pName), offset(pOffset), glDefineType(pGLDefineType), size(pSize), index(pIndex), counterIndex(-1), - numMembers(-1), arrayStride(0), topLevelArrayStride(0), stages(EShLanguageMask(0)), type(pType.clone()) -{ -} - -int TObjectReflection::getBinding() const -{ - if (type == nullptr || !type->getQualifier().hasBinding()) - return -1; - return type->getQualifier().layoutBinding; -} - -void TObjectReflection::dump() const -{ - printf("%s: offset %d, type %x, size %d, index %d, binding %d, stages %d", name.c_str(), offset, glDefineType, size, - index, getBinding(), stages); - - if (counterIndex != -1) - printf(", counter %d", counterIndex); - - if (numMembers != -1) - printf(", numMembers %d", numMembers); - - if (arrayStride != 0) - printf(", arrayStride %d", arrayStride); - - if (topLevelArrayStride != 0) - printf(", topLevelArrayStride %d", topLevelArrayStride); - - printf("\n"); -} - -// -// Implement TReflection methods. -// - -// Track any required attribute reflection, such as compute shader numthreads. -// -void TReflection::buildAttributeReflection(EShLanguage stage, const TIntermediate& intermediate) -{ - if (stage == EShLangCompute) { - // Remember thread dimensions - for (int dim=0; dim<3; ++dim) - localSize[dim] = intermediate.getLocalSize(dim); - } -} - -// build counter block index associations for buffers -void TReflection::buildCounterIndices(const TIntermediate& intermediate) -{ -#ifdef ENABLE_HLSL - // search for ones that have counters - for (int i = 0; i < int(indexToUniformBlock.size()); ++i) { - const TString counterName(intermediate.addCounterBufferName(indexToUniformBlock[i].name).c_str()); - const int index = getIndex(counterName); - - if (index >= 0) - indexToUniformBlock[i].counterIndex = index; - } -#else - (void)intermediate; -#endif -} - -// build Shader Stages mask for all uniforms -void TReflection::buildUniformStageMask(const TIntermediate& intermediate) -{ - if (options & EShReflectionAllBlockVariables) - return; - - for (int i = 0; i < int(indexToUniform.size()); ++i) { - indexToUniform[i].stages = static_cast(indexToUniform[i].stages | 1 << intermediate.getStage()); - } - - for (int i = 0; i < int(indexToBufferVariable.size()); ++i) { - indexToBufferVariable[i].stages = - static_cast(indexToBufferVariable[i].stages | 1 << intermediate.getStage()); - } -} - -// Merge live symbols from 'intermediate' into the existing reflection database. -// -// Returns false if the input is too malformed to do this. -bool TReflection::addStage(EShLanguage stage, const TIntermediate& intermediate) -{ - if (intermediate.getTreeRoot() == nullptr || - intermediate.getNumEntryPoints() != 1 || - intermediate.isRecursive()) - return false; - - buildAttributeReflection(stage, intermediate); - - TReflectionTraverser it(intermediate, *this); - - for (auto& sequnence : intermediate.getTreeRoot()->getAsAggregate()->getSequence()) { - if (sequnence->getAsAggregate() != nullptr) { - if (sequnence->getAsAggregate()->getOp() == glslang::EOpLinkerObjects) { - it.updateStageMasks = false; - TIntermAggregate* linkerObjects = sequnence->getAsAggregate(); - for (auto& sequnence : linkerObjects->getSequence()) { - auto pNode = sequnence->getAsSymbolNode(); - if (pNode != nullptr) { - if ((pNode->getQualifier().storage == EvqUniform && - (options & EShReflectionSharedStd140UBO)) || - (pNode->getQualifier().storage == EvqBuffer && - (options & EShReflectionSharedStd140SSBO))) { - // collect std140 and shared uniform block form AST - if ((pNode->getBasicType() == EbtBlock) && - ((pNode->getQualifier().layoutPacking == ElpStd140) || - (pNode->getQualifier().layoutPacking == ElpShared))) { - pNode->traverse(&it); - } - } - else if ((options & EShReflectionAllIOVariables) && - (pNode->getQualifier().isPipeInput() || pNode->getQualifier().isPipeOutput())) - { - pNode->traverse(&it); - } - } - } - } else { - // This traverser will travers all function in AST. - // If we want reflect uncalled function, we need set linke message EShMsgKeepUncalled. - // When EShMsgKeepUncalled been set to true, all function will be keep in AST, even it is a uncalled function. - // This will keep some uniform variables in reflection, if those uniform variables is used in these uncalled function. - // - // If we just want reflect only live node, we can use a default link message or set EShMsgKeepUncalled false. - // When linke message not been set EShMsgKeepUncalled, linker won't keep uncalled function in AST. - // So, travers all function node can equivalent to travers live function. - it.updateStageMasks = true; - sequnence->getAsAggregate()->traverse(&it); - } - } - } - it.updateStageMasks = true; - - buildCounterIndices(intermediate); - buildUniformStageMask(intermediate); - - return true; -} - -void TReflection::dump() -{ - printf("Uniform reflection:\n"); - for (size_t i = 0; i < indexToUniform.size(); ++i) - indexToUniform[i].dump(); - printf("\n"); - - printf("Uniform block reflection:\n"); - for (size_t i = 0; i < indexToUniformBlock.size(); ++i) - indexToUniformBlock[i].dump(); - printf("\n"); - - printf("Buffer variable reflection:\n"); - for (size_t i = 0; i < indexToBufferVariable.size(); ++i) - indexToBufferVariable[i].dump(); - printf("\n"); - - printf("Buffer block reflection:\n"); - for (size_t i = 0; i < indexToBufferBlock.size(); ++i) - indexToBufferBlock[i].dump(); - printf("\n"); - - printf("Pipeline input reflection:\n"); - for (size_t i = 0; i < indexToPipeInput.size(); ++i) - indexToPipeInput[i].dump(); - printf("\n"); - - printf("Pipeline output reflection:\n"); - for (size_t i = 0; i < indexToPipeOutput.size(); ++i) - indexToPipeOutput[i].dump(); - printf("\n"); - - if (getLocalSize(0) > 1) { - static const char* axis[] = { "X", "Y", "Z" }; - - for (int dim=0; dim<3; ++dim) - if (getLocalSize(dim) > 1) - printf("Local size %s: %u\n", axis[dim], getLocalSize(dim)); - - printf("\n"); - } - - // printf("Live names\n"); - // for (TNameToIndex::const_iterator it = nameToIndex.begin(); it != nameToIndex.end(); ++it) - // printf("%s: %d\n", it->first.c_str(), it->second); - // printf("\n"); -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/MachineIndependent/reflection.h b/3rdparty/glslang/glslang/MachineIndependent/reflection.h deleted file mode 100644 index 221d93f8..00000000 --- a/3rdparty/glslang/glslang/MachineIndependent/reflection.h +++ /dev/null @@ -1,219 +0,0 @@ -// -// Copyright (C) 2013-2016 LunarG, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef _REFLECTION_INCLUDED -#define _REFLECTION_INCLUDED - -#include "../Public/ShaderLang.h" -#include "../Include/Types.h" - -#include -#include - -// -// A reflection database and its interface, consistent with the OpenGL API reflection queries. -// - -namespace glslang { - -class TIntermediate; -class TIntermAggregate; -class TReflectionTraverser; - -// The full reflection database -class TReflection { -public: - TReflection(EShReflectionOptions opts, EShLanguage first, EShLanguage last) - : options(opts), firstStage(first), lastStage(last), badReflection(TObjectReflection::badReflection()) - { - for (int dim=0; dim<3; ++dim) - localSize[dim] = 0; - } - - virtual ~TReflection() {} - - // grow the reflection stage by stage - bool addStage(EShLanguage, const TIntermediate&); - - // for mapping a uniform index to a uniform object's description - int getNumUniforms() { return (int)indexToUniform.size(); } - const TObjectReflection& getUniform(int i) const - { - if (i >= 0 && i < (int)indexToUniform.size()) - return indexToUniform[i]; - else - return badReflection; - } - - // for mapping a block index to the block's description - int getNumUniformBlocks() const { return (int)indexToUniformBlock.size(); } - const TObjectReflection& getUniformBlock(int i) const - { - if (i >= 0 && i < (int)indexToUniformBlock.size()) - return indexToUniformBlock[i]; - else - return badReflection; - } - - // for mapping an pipeline input index to the input's description - int getNumPipeInputs() { return (int)indexToPipeInput.size(); } - const TObjectReflection& getPipeInput(int i) const - { - if (i >= 0 && i < (int)indexToPipeInput.size()) - return indexToPipeInput[i]; - else - return badReflection; - } - - // for mapping an pipeline output index to the output's description - int getNumPipeOutputs() { return (int)indexToPipeOutput.size(); } - const TObjectReflection& getPipeOutput(int i) const - { - if (i >= 0 && i < (int)indexToPipeOutput.size()) - return indexToPipeOutput[i]; - else - return badReflection; - } - - // for mapping from an atomic counter to the uniform index - int getNumAtomicCounters() const { return (int)atomicCounterUniformIndices.size(); } - const TObjectReflection& getAtomicCounter(int i) const - { - if (i >= 0 && i < (int)atomicCounterUniformIndices.size()) - return getUniform(atomicCounterUniformIndices[i]); - else - return badReflection; - } - - // for mapping a buffer variable index to a buffer variable object's description - int getNumBufferVariables() { return (int)indexToBufferVariable.size(); } - const TObjectReflection& getBufferVariable(int i) const - { - if (i >= 0 && i < (int)indexToBufferVariable.size()) - return indexToBufferVariable[i]; - else - return badReflection; - } - - // for mapping a storage block index to the storage block's description - int getNumStorageBuffers() const { return (int)indexToBufferBlock.size(); } - const TObjectReflection& getStorageBufferBlock(int i) const - { - if (i >= 0 && i < (int)indexToBufferBlock.size()) - return indexToBufferBlock[i]; - else - return badReflection; - } - - // for mapping any name to its index (block names, uniform names and input/output names) - int getIndex(const char* name) const - { - TNameToIndex::const_iterator it = nameToIndex.find(name); - if (it == nameToIndex.end()) - return -1; - else - return it->second; - } - - // see getIndex(const char*) - int getIndex(const TString& name) const { return getIndex(name.c_str()); } - - - // for mapping any name to its index (only pipe input/output names) - int getPipeIOIndex(const char* name, const bool inOrOut) const - { - TNameToIndex::const_iterator it = inOrOut ? pipeInNameToIndex.find(name) : pipeOutNameToIndex.find(name); - if (it == (inOrOut ? pipeInNameToIndex.end() : pipeOutNameToIndex.end())) - return -1; - else - return it->second; - } - - // see gePipeIOIndex(const char*, const bool) - int getPipeIOIndex(const TString& name, const bool inOrOut) const { return getPipeIOIndex(name.c_str(), inOrOut); } - - // Thread local size - unsigned getLocalSize(int dim) const { return dim <= 2 ? localSize[dim] : 0; } - - void dump(); - -protected: - friend class glslang::TReflectionTraverser; - - void buildCounterIndices(const TIntermediate&); - void buildUniformStageMask(const TIntermediate& intermediate); - void buildAttributeReflection(EShLanguage, const TIntermediate&); - - // Need a TString hash: typedef std::unordered_map TNameToIndex; - typedef std::map TNameToIndex; - typedef std::vector TMapIndexToReflection; - typedef std::vector TIndices; - - TMapIndexToReflection& GetBlockMapForStorage(TStorageQualifier storage) - { - if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) - return indexToBufferBlock; - return indexToUniformBlock; - } - TMapIndexToReflection& GetVariableMapForStorage(TStorageQualifier storage) - { - if ((options & EShReflectionSeparateBuffers) && storage == EvqBuffer) - return indexToBufferVariable; - return indexToUniform; - } - - EShReflectionOptions options; - - EShLanguage firstStage; - EShLanguage lastStage; - - TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this - TNameToIndex nameToIndex; // maps names to indexes; can hold all types of data: uniform/buffer and which function names have been processed - TNameToIndex pipeInNameToIndex; // maps pipe in names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. - TNameToIndex pipeOutNameToIndex; // maps pipe out names to indexes, this is a fix to seperate pipe I/O from uniforms and buffers. - TMapIndexToReflection indexToUniform; - TMapIndexToReflection indexToUniformBlock; - TMapIndexToReflection indexToBufferVariable; - TMapIndexToReflection indexToBufferBlock; - TMapIndexToReflection indexToPipeInput; - TMapIndexToReflection indexToPipeOutput; - TIndices atomicCounterUniformIndices; - - unsigned int localSize[3]; -}; - -} // end namespace glslang - -#endif // _REFLECTION_INCLUDED diff --git a/3rdparty/glslang/glslang/OSDependent/Unix/CMakeLists.txt b/3rdparty/glslang/glslang/OSDependent/Unix/CMakeLists.txt deleted file mode 100644 index ec35da30..00000000 --- a/3rdparty/glslang/glslang/OSDependent/Unix/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (C) 2020 The Khronos Group Inc. -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# Neither the name of The Khronos Group Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -add_library(OSDependent STATIC ossource.cpp ../osinclude.h) -set_property(TARGET OSDependent PROPERTY FOLDER glslang) -set_property(TARGET OSDependent PROPERTY POSITION_INDEPENDENT_CODE ON) - -# Link pthread -set(THREADS_PREFER_PTHREAD_FLAG ON) -find_package(Threads REQUIRED) -target_link_libraries(OSDependent Threads::Threads) - -if(PROJECT_IS_TOP_LEVEL AND NOT BUILD_SHARED_LIBS) - install(TARGETS OSDependent EXPORT glslang-targets) - - # Backward compatibility - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/OSDependentTargets.cmake" " - message(WARNING \"Using `OSDependentTargets.cmake` is deprecated: use `find_package(glslang)` to find glslang CMake targets.\") - - if (NOT TARGET glslang::OSDependent) - include(\"${CMAKE_INSTALL_FULL_LIBDIR}/cmake/${PROJECT_NAME}/glslang-targets.cmake\") - endif() - - add_library(OSDependent ALIAS glslang::OSDependent) - ") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/OSDependentTargets.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) -endif() diff --git a/3rdparty/glslang/glslang/OSDependent/Unix/ossource.cpp b/3rdparty/glslang/glslang/OSDependent/Unix/ossource.cpp deleted file mode 100644 index fbb51f7b..00000000 --- a/3rdparty/glslang/glslang/OSDependent/Unix/ossource.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -// -// This file contains the Linux-specific functions -// -#include "../osinclude.h" - -#include - -#if !defined(__Fuchsia__) -#include -#endif - -namespace glslang { - -// #define DUMP_COUNTERS - -void OS_DumpMemoryCounters() -{ -#ifdef DUMP_COUNTERS - struct rusage usage; - - if (getrusage(RUSAGE_SELF, &usage) == 0) - printf("Working set size: %ld\n", usage.ru_maxrss * 1024); -#else - printf("Recompile with DUMP_COUNTERS defined to see counters.\n"); -#endif -} - -} // end namespace glslang diff --git a/3rdparty/glslang/glslang/OSDependent/Web/CMakeLists.txt b/3rdparty/glslang/glslang/OSDependent/Web/CMakeLists.txt deleted file mode 100644 index 5d174960..00000000 --- a/3rdparty/glslang/glslang/OSDependent/Web/CMakeLists.txt +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright (C) 2020 The Khronos Group Inc. -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# Neither the name of The Khronos Group Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -if(ENABLE_GLSLANG_JS) - add_executable(glslang.js "glslang.js.cpp") - glslang_set_link_args(glslang.js) - target_link_libraries(glslang.js glslang SPIRV) - - # Link library names that start with "-" are treated as link flags. - # "-Os" should be OK in MSVC; don't use /Os because CMake won't - # treat it as a link flag. - target_link_libraries(glslang.js "-Os") - - if(EMSCRIPTEN) - set_target_properties(glslang.js PROPERTIES - OUTPUT_NAME "glslang" - SUFFIX ".js") - em_link_pre_js(glslang.js "${CMAKE_CURRENT_SOURCE_DIR}/glslang.pre.js") - - target_link_libraries(glslang.js "--llvm-lto 1") - target_link_libraries(glslang.js "--closure 1") - target_link_libraries(glslang.js "-s MODULARIZE=1") - target_link_libraries(glslang.js "-s ALLOW_MEMORY_GROWTH=1") - target_link_libraries(glslang.js "-s FILESYSTEM=0") - - # We use ccall in glslang.pre.js, so make sure it's exposed - target_link_libraries(glslang.js "-s EXPORTED_RUNTIME_METHODS=ccall") - - if(ENABLE_EMSCRIPTEN_SINGLE_FILE) - target_link_libraries(glslang.js "-s SINGLE_FILE=1") - endif() - - if(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE) - target_link_libraries(glslang.js "-s ENVIRONMENT=node -s BINARYEN_ASYNC_COMPILATION=0") - else() - target_link_libraries(glslang.js "-s ENVIRONMENT=web,worker") - endif() - - if(NOT ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE) - if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.18") - add_custom_command(TARGET glslang.js POST_BUILD - COMMAND ${CMAKE_COMMAND} -E cat ${CMAKE_CURRENT_SOURCE_DIR}/glslang.after.js >> ${CMAKE_CURRENT_BINARY_DIR}/glslang.js - ) - else() - if (MINGW) - message(FATAL_ERROR "Must use at least CMake 3.18") - endif() - - if (CMAKE_HOST_SYSTEM MATCHES "Windows.*") - # There are several ways we could append one file to another on Windows, but unfortunately 'cat' is not one of them - # (there is no 'cat' command in cmd). Also, since this will ultimately run in cmd and not pwsh, we need to ensure - # Windows path separators are used. - file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/glslang.js" glslang_js_path) - file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/glslang.after.js" glslang_after_js_path) - add_custom_command(TARGET glslang.js POST_BUILD - COMMAND type "${glslang_after_js_path}" >> "${glslang_js_path}") - else() - add_custom_command(TARGET glslang.js POST_BUILD - COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/glslang.after.js >> ${CMAKE_CURRENT_BINARY_DIR}/glslang.js) - endif() - endif() - endif() - endif() -endif() \ No newline at end of file diff --git a/3rdparty/glslang/glslang/OSDependent/Web/glslang.after.js b/3rdparty/glslang/glslang/OSDependent/Web/glslang.after.js deleted file mode 100644 index c2cfc35a..00000000 --- a/3rdparty/glslang/glslang/OSDependent/Web/glslang.after.js +++ /dev/null @@ -1,26 +0,0 @@ -export default (() => { - const initialize = () => { - return new Promise(resolve => { - Module({ - locateFile() { - const i = import.meta.url.lastIndexOf('/') - return import.meta.url.substring(0, i) + '/glslang.wasm'; - }, - onRuntimeInitialized() { - resolve({ - compileGLSLZeroCopy: this.compileGLSLZeroCopy, - compileGLSL: this.compileGLSL, - }); - }, - }); - }); - }; - - let instance; - return () => { - if (!instance) { - instance = initialize(); - } - return instance; - }; -})(); diff --git a/3rdparty/glslang/glslang/OSDependent/Web/glslang.js.cpp b/3rdparty/glslang/glslang/OSDependent/Web/glslang.js.cpp deleted file mode 100644 index c820da6a..00000000 --- a/3rdparty/glslang/glslang/OSDependent/Web/glslang.js.cpp +++ /dev/null @@ -1,296 +0,0 @@ -// -// Copyright (C) 2019 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include -#include -#include - -#ifdef __EMSCRIPTEN__ -#include -#endif - -#include "../../../SPIRV/GlslangToSpv.h" -#include "../../../glslang/Public/ShaderLang.h" - -#ifndef __EMSCRIPTEN__ -#define EMSCRIPTEN_KEEPALIVE -#endif - -const TBuiltInResource DefaultTBuiltInResource = { - /* .MaxLights = */ 32, - /* .MaxClipPlanes = */ 6, - /* .MaxTextureUnits = */ 32, - /* .MaxTextureCoords = */ 32, - /* .MaxVertexAttribs = */ 64, - /* .MaxVertexUniformComponents = */ 4096, - /* .MaxVaryingFloats = */ 64, - /* .MaxVertexTextureImageUnits = */ 32, - /* .MaxCombinedTextureImageUnits = */ 80, - /* .MaxTextureImageUnits = */ 32, - /* .MaxFragmentUniformComponents = */ 4096, - /* .MaxDrawBuffers = */ 32, - /* .MaxVertexUniformVectors = */ 128, - /* .MaxVaryingVectors = */ 8, - /* .MaxFragmentUniformVectors = */ 16, - /* .MaxVertexOutputVectors = */ 16, - /* .MaxFragmentInputVectors = */ 15, - /* .MinProgramTexelOffset = */ -8, - /* .MaxProgramTexelOffset = */ 7, - /* .MaxClipDistances = */ 8, - /* .MaxComputeWorkGroupCountX = */ 65535, - /* .MaxComputeWorkGroupCountY = */ 65535, - /* .MaxComputeWorkGroupCountZ = */ 65535, - /* .MaxComputeWorkGroupSizeX = */ 1024, - /* .MaxComputeWorkGroupSizeY = */ 1024, - /* .MaxComputeWorkGroupSizeZ = */ 64, - /* .MaxComputeUniformComponents = */ 1024, - /* .MaxComputeTextureImageUnits = */ 16, - /* .MaxComputeImageUniforms = */ 8, - /* .MaxComputeAtomicCounters = */ 8, - /* .MaxComputeAtomicCounterBuffers = */ 1, - /* .MaxVaryingComponents = */ 60, - /* .MaxVertexOutputComponents = */ 64, - /* .MaxGeometryInputComponents = */ 64, - /* .MaxGeometryOutputComponents = */ 128, - /* .MaxFragmentInputComponents = */ 128, - /* .MaxImageUnits = */ 8, - /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, - /* .MaxCombinedShaderOutputResources = */ 8, - /* .MaxImageSamples = */ 0, - /* .MaxVertexImageUniforms = */ 0, - /* .MaxTessControlImageUniforms = */ 0, - /* .MaxTessEvaluationImageUniforms = */ 0, - /* .MaxGeometryImageUniforms = */ 0, - /* .MaxFragmentImageUniforms = */ 8, - /* .MaxCombinedImageUniforms = */ 8, - /* .MaxGeometryTextureImageUnits = */ 16, - /* .MaxGeometryOutputVertices = */ 256, - /* .MaxGeometryTotalOutputComponents = */ 1024, - /* .MaxGeometryUniformComponents = */ 1024, - /* .MaxGeometryVaryingComponents = */ 64, - /* .MaxTessControlInputComponents = */ 128, - /* .MaxTessControlOutputComponents = */ 128, - /* .MaxTessControlTextureImageUnits = */ 16, - /* .MaxTessControlUniformComponents = */ 1024, - /* .MaxTessControlTotalOutputComponents = */ 4096, - /* .MaxTessEvaluationInputComponents = */ 128, - /* .MaxTessEvaluationOutputComponents = */ 128, - /* .MaxTessEvaluationTextureImageUnits = */ 16, - /* .MaxTessEvaluationUniformComponents = */ 1024, - /* .MaxTessPatchComponents = */ 120, - /* .MaxPatchVertices = */ 32, - /* .MaxTessGenLevel = */ 64, - /* .MaxViewports = */ 16, - /* .MaxVertexAtomicCounters = */ 0, - /* .MaxTessControlAtomicCounters = */ 0, - /* .MaxTessEvaluationAtomicCounters = */ 0, - /* .MaxGeometryAtomicCounters = */ 0, - /* .MaxFragmentAtomicCounters = */ 8, - /* .MaxCombinedAtomicCounters = */ 8, - /* .MaxAtomicCounterBindings = */ 1, - /* .MaxVertexAtomicCounterBuffers = */ 0, - /* .MaxTessControlAtomicCounterBuffers = */ 0, - /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, - /* .MaxGeometryAtomicCounterBuffers = */ 0, - /* .MaxFragmentAtomicCounterBuffers = */ 1, - /* .MaxCombinedAtomicCounterBuffers = */ 1, - /* .MaxAtomicCounterBufferSize = */ 16384, - /* .MaxTransformFeedbackBuffers = */ 4, - /* .MaxTransformFeedbackInterleavedComponents = */ 64, - /* .MaxCullDistances = */ 8, - /* .MaxCombinedClipAndCullDistances = */ 8, - /* .MaxSamples = */ 4, - /* .maxMeshOutputVerticesNV = */ 256, - /* .maxMeshOutputPrimitivesNV = */ 512, - /* .maxMeshWorkGroupSizeX_NV = */ 32, - /* .maxMeshWorkGroupSizeY_NV = */ 1, - /* .maxMeshWorkGroupSizeZ_NV = */ 1, - /* .maxTaskWorkGroupSizeX_NV = */ 32, - /* .maxTaskWorkGroupSizeY_NV = */ 1, - /* .maxTaskWorkGroupSizeZ_NV = */ 1, - /* .maxMeshViewCountNV = */ 4, - /* .maxMeshOutputVerticesEXT = */ 256, - /* .maxMeshOutputPrimitivesEXT = */ 512, - /* .maxMeshWorkGroupSizeX_EXT = */ 32, - /* .maxMeshWorkGroupSizeY_EXT = */ 1, - /* .maxMeshWorkGroupSizeZ_EXT = */ 1, - /* .maxTaskWorkGroupSizeX_EXT = */ 32, - /* .maxTaskWorkGroupSizeY_EXT = */ 1, - /* .maxTaskWorkGroupSizeZ_EXT = */ 1, - /* .maxMeshViewCountEXT = */ 4, - /* .maxDualSourceDrawBuffersEXT = */ 1, - - /* .limits = */ { - /* .nonInductiveForLoops = */ 1, - /* .whileLoops = */ 1, - /* .doWhileLoops = */ 1, - /* .generalUniformIndexing = */ 1, - /* .generalAttributeMatrixVectorIndexing = */ 1, - /* .generalVaryingIndexing = */ 1, - /* .generalSamplerIndexing = */ 1, - /* .generalVariableIndexing = */ 1, - /* .generalConstantMatrixVectorIndexing = */ 1, - }}; - -static bool initialized = false; - -extern "C" { - -/* - * Takes in a GLSL shader as a string and converts it to SPIR-V in binary form. - * - * |glsl| Null-terminated string containing the shader to be converted. - * |stage_int| Magic number indicating the type of shader being processed. -* Legal values are as follows: - * Vertex = 0 - * Fragment = 4 - * Compute = 5 - * |gen_debug| Flag to indicate if debug information should be generated. - * |spirv| Output parameter for a pointer to the resulting SPIR-V data. - * |spirv_len| Output parameter for the length of the output binary buffer. - * - * Returns a void* pointer which, if not null, must be destroyed by - * destroy_output_buffer.o. (This is not the same pointer returned in |spirv|.) - * If null, the compilation failed. - */ -EMSCRIPTEN_KEEPALIVE -void* convert_glsl_to_spirv(const char* glsl, - int stage_int, - bool gen_debug, - glslang::EShTargetLanguageVersion spirv_version, - uint32_t** spirv, - size_t* spirv_len) -{ - if (glsl == nullptr) { - fprintf(stderr, "Input pointer null\n"); - return nullptr; - } - if (spirv == nullptr || spirv_len == nullptr) { - fprintf(stderr, "Output pointer null\n"); - return nullptr; - } - *spirv = nullptr; - *spirv_len = 0; - - if (stage_int != 0 && stage_int != 4 && stage_int != 5) { - fprintf(stderr, "Invalid shader stage\n"); - return nullptr; - } - EShLanguage stage = static_cast(stage_int); - switch (spirv_version) { - case glslang::EShTargetSpv_1_0: - case glslang::EShTargetSpv_1_1: - case glslang::EShTargetSpv_1_2: - case glslang::EShTargetSpv_1_3: - case glslang::EShTargetSpv_1_4: - case glslang::EShTargetSpv_1_5: - break; - default: - fprintf(stderr, "Invalid SPIR-V version number\n"); - return nullptr; - } - - if (!initialized) { - glslang::InitializeProcess(); - initialized = true; - } - - glslang::TShader shader(stage); - shader.setStrings(&glsl, 1); - shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100); - shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0); - shader.setEnvTarget(glslang::EShTargetSpv, spirv_version); - if (!shader.parse(&DefaultTBuiltInResource, 100, true, EShMsgDefault)) { - fprintf(stderr, "Parse failed\n"); - fprintf(stderr, "%s\n", shader.getInfoLog()); - return nullptr; - } - - glslang::TProgram program; - program.addShader(&shader); - if (!program.link(EShMsgDefault)) { - fprintf(stderr, "Link failed\n"); - fprintf(stderr, "%s\n", program.getInfoLog()); - return nullptr; - } - - glslang::SpvOptions spvOptions; - spvOptions.generateDebugInfo = gen_debug; - spvOptions.optimizeSize = false; - spvOptions.disassemble = false; - spvOptions.validate = false; - - std::vector* output = new std::vector; - glslang::GlslangToSpv(*program.getIntermediate(stage), *output, nullptr, &spvOptions); - - *spirv_len = output->size(); - *spirv = output->data(); - return output; -} - -/* - * Destroys a buffer created by convert_glsl_to_spirv - */ -EMSCRIPTEN_KEEPALIVE -void destroy_output_buffer(void* p) -{ - delete static_cast*>(p); -} - -} // extern "C" - -/* - * For non-Emscripten builds we supply a generic main, so that the glslang.js - * build target can generate an executable with a trivial use case instead of - * generating a WASM binary. This is done so that there is a target that can be - * built and output analyzed using desktop tools, since WASM binaries are - * specific to the Emscripten toolchain. - */ -#ifndef __EMSCRIPTEN__ -int main() { - const char* input = R"(#version 310 es - -void main() { })"; - - uint32_t* output; - size_t output_len; - - void* id = convert_glsl_to_spirv(input, 4, false, glslang::EShTargetSpv_1_0, &output, &output_len); - assert(output != nullptr); - assert(output_len != 0); - destroy_output_buffer(id); - return 0; -} -#endif // ifndef __EMSCRIPTEN__ diff --git a/3rdparty/glslang/glslang/OSDependent/Web/glslang.pre.js b/3rdparty/glslang/glslang/OSDependent/Web/glslang.pre.js deleted file mode 100644 index 390390e9..00000000 --- a/3rdparty/glslang/glslang/OSDependent/Web/glslang.pre.js +++ /dev/null @@ -1,56 +0,0 @@ -Module['compileGLSLZeroCopy'] = function(glsl, shader_stage, gen_debug, spirv_version) { - gen_debug = !!gen_debug; - - var shader_stage_int; // EShLanguage - switch (shader_stage) { - case 'vertex': shader_stage_int = 0; break; - case 'fragment': shader_stage_int = 4; break; - case 'compute': shader_stage_int = 5; break; - default: - throw new Error("shader_stage must be 'vertex', 'fragment', or 'compute'."); - } - - spirv_version = spirv_version || '1.0'; - var spirv_version_int; // EShTargetLanguageVersion - switch (spirv_version) { - case '1.0': spirv_version_int = (1 << 16) | (0 << 8); break; - case '1.1': spirv_version_int = (1 << 16) | (1 << 8); break; - case '1.2': spirv_version_int = (1 << 16) | (2 << 8); break; - case '1.3': spirv_version_int = (1 << 16) | (3 << 8); break; - case '1.4': spirv_version_int = (1 << 16) | (4 << 8); break; - case '1.5': spirv_version_int = (1 << 16) | (5 << 8); break; - default: - throw new Error("spirv_version must be '1.0' ~ '1.5'."); - } - - var p_output = Module['_malloc'](4); - var p_output_len = Module['_malloc'](4); - var id = Module['ccall']('convert_glsl_to_spirv', - 'number', - ['string', 'number', 'boolean', 'number', 'number', 'number'], - [glsl, shader_stage_int, gen_debug, spirv_version_int, p_output, p_output_len]); - var output = getValue(p_output, 'i32'); - var output_len = getValue(p_output_len, 'i32'); - Module['_free'](p_output); - Module['_free'](p_output_len); - - if (id === 0) { - throw new Error('GLSL compilation failed'); - } - - var ret = {}; - var outputIndexU32 = output / 4; - ret['data'] = Module['HEAPU32'].subarray(outputIndexU32, outputIndexU32 + output_len); - ret['free'] = function() { - Module['_destroy_output_buffer'](id); - }; - - return ret; -}; - -Module['compileGLSL'] = function(glsl, shader_stage, gen_debug, spirv_version) { - var compiled = Module['compileGLSLZeroCopy'](glsl, shader_stage, gen_debug, spirv_version); - var ret = compiled['data'].slice() - compiled['free'](); - return ret; -}; diff --git a/3rdparty/glslang/glslang/OSDependent/Windows/CMakeLists.txt b/3rdparty/glslang/glslang/OSDependent/Windows/CMakeLists.txt deleted file mode 100644 index b8af046c..00000000 --- a/3rdparty/glslang/glslang/OSDependent/Windows/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) 2020 The Khronos Group Inc. -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# Neither the name of The Khronos Group Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -add_library(OSDependent STATIC) - -target_sources(OSDependent PRIVATE - ../osinclude.h - ossource.cpp -) - -set_property(TARGET OSDependent PROPERTY FOLDER glslang) -set_property(TARGET OSDependent PROPERTY POSITION_INDEPENDENT_CODE ON) - -# MinGW GCC complains about function pointer casts to void*. -# Turn that off with -fpermissive. -if(MINGW AND ${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") - target_compile_options(OSDependent PRIVATE -fpermissive) -endif() - -if(WIN32) - source_group("Source" FILES ${SOURCES}) -endif() - -if(PROJECT_IS_TOP_LEVEL) - install(TARGETS OSDependent EXPORT glslang-targets) - - # Backward compatibility - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/OSDependentTargets.cmake" " - message(WARNING \"Using `OSDependentTargets.cmake` is deprecated: use `find_package(glslang)` to find glslang CMake targets.\") - - if (NOT TARGET glslang::OSDependent) - include(\"${CMAKE_INSTALL_FULL_LIBDIR}/cmake/${PROJECT_NAME}/glslang-targets.cmake\") - endif() - - add_library(OSDependent ALIAS glslang::OSDependent) - ") - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/OSDependentTargets.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) -endif() diff --git a/3rdparty/glslang/glslang/OSDependent/Windows/ossource.cpp b/3rdparty/glslang/glslang/OSDependent/Windows/ossource.cpp deleted file mode 100644 index d7f89f71..00000000 --- a/3rdparty/glslang/glslang/OSDependent/Windows/ossource.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#include "../osinclude.h" - -#define STRICT -#define VC_EXTRALEAN 1 -#include -#include -#include -#include - -// -// This file contains the Window-OS-specific functions -// - -#if !(defined(_WIN32) || defined(_WIN64)) -#error Trying to build a windows specific file in a non windows build. -#endif - -namespace glslang { - -//#define DUMP_COUNTERS - -void OS_DumpMemoryCounters() -{ -#ifdef DUMP_COUNTERS - PROCESS_MEMORY_COUNTERS counters; - GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)); - printf("Working set size: %d\n", counters.WorkingSetSize); -#else - printf("Recompile with DUMP_COUNTERS defined to see counters.\n"); -#endif -} - -} // namespace glslang diff --git a/3rdparty/glslang/glslang/OSDependent/osinclude.h b/3rdparty/glslang/glslang/OSDependent/osinclude.h deleted file mode 100644 index 0d677e4a..00000000 --- a/3rdparty/glslang/glslang/OSDependent/osinclude.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// - -#ifndef __OSINCLUDE_H -#define __OSINCLUDE_H - -namespace glslang { - -void OS_DumpMemoryCounters(); - -} // end namespace glslang - -#endif // __OSINCLUDE_H diff --git a/3rdparty/glslang/glslang/Public/ResourceLimits.h b/3rdparty/glslang/glslang/Public/ResourceLimits.h deleted file mode 100644 index f70be817..00000000 --- a/3rdparty/glslang/glslang/Public/ResourceLimits.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#ifndef _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_ -#define _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_ - -#include - -#include "../Include/ResourceLimits.h" - -// Return pointer to user-writable Resource to pass through API in -// future-proof way. -extern TBuiltInResource* GetResources(); - -// These are the default resources for TBuiltInResources, used for both -// - parsing this string for the case where the user didn't supply one, -// - dumping out a template for user construction of a config file. -extern const TBuiltInResource* GetDefaultResources(); - -// Returns the DefaultTBuiltInResource as a human-readable string. -std::string GetDefaultTBuiltInResourceString(); - -// Decodes the resource limits from |config| to |resources|. -void DecodeResourceLimits(TBuiltInResource* resources, char* config); - -#endif // _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Public/ShaderLang.h b/3rdparty/glslang/glslang/Public/ShaderLang.h deleted file mode 100644 index e0ec47f8..00000000 --- a/3rdparty/glslang/glslang/Public/ShaderLang.h +++ /dev/null @@ -1,979 +0,0 @@ -// -// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. -// Copyright (C) 2013-2016 LunarG, Inc. -// Copyright (C) 2015-2018 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of 3Dlabs Inc. Ltd. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. -// -#ifndef _COMPILER_INTERFACE_INCLUDED_ -#define _COMPILER_INTERFACE_INCLUDED_ - -#include "../Include/ResourceLimits.h" -#include "../MachineIndependent/Versions.h" - -#include -#include - -#ifdef _WIN32 - #define C_DECL __cdecl -#else - #define C_DECL -#endif - -#ifdef GLSLANG_IS_SHARED_LIBRARY - #ifdef _WIN32 - #ifdef GLSLANG_EXPORTING - #define GLSLANG_EXPORT __declspec(dllexport) - #else - #define GLSLANG_EXPORT __declspec(dllimport) - #endif - #elif __GNUC__ >= 4 - #define GLSLANG_EXPORT __attribute__((visibility("default"))) - #endif -#endif // GLSLANG_IS_SHARED_LIBRARY - -#ifndef GLSLANG_EXPORT -#define GLSLANG_EXPORT -#endif - -// -// This is the platform independent interface between an OGL driver -// and the shading language compiler/linker. -// - -#ifdef __cplusplus - extern "C" { -#endif - -// -// Call before doing any other compiler/linker operations. -// -// (Call once per process, not once per thread.) -// -GLSLANG_EXPORT int ShInitialize(); - -// -// Call this at process shutdown to clean up memory. -// -GLSLANG_EXPORT int ShFinalize(); - -// -// Types of languages the compiler can consume. -// -typedef enum { - EShLangVertex, - EShLangTessControl, - EShLangTessEvaluation, - EShLangGeometry, - EShLangFragment, - EShLangCompute, - EShLangRayGen, - EShLangRayGenNV = EShLangRayGen, - EShLangIntersect, - EShLangIntersectNV = EShLangIntersect, - EShLangAnyHit, - EShLangAnyHitNV = EShLangAnyHit, - EShLangClosestHit, - EShLangClosestHitNV = EShLangClosestHit, - EShLangMiss, - EShLangMissNV = EShLangMiss, - EShLangCallable, - EShLangCallableNV = EShLangCallable, - EShLangTask, - EShLangTaskNV = EShLangTask, - EShLangMesh, - EShLangMeshNV = EShLangMesh, - LAST_ELEMENT_MARKER(EShLangCount), -} EShLanguage; // would be better as stage, but this is ancient now - -typedef enum : unsigned { - EShLangVertexMask = (1 << EShLangVertex), - EShLangTessControlMask = (1 << EShLangTessControl), - EShLangTessEvaluationMask = (1 << EShLangTessEvaluation), - EShLangGeometryMask = (1 << EShLangGeometry), - EShLangFragmentMask = (1 << EShLangFragment), - EShLangComputeMask = (1 << EShLangCompute), - EShLangRayGenMask = (1 << EShLangRayGen), - EShLangRayGenNVMask = EShLangRayGenMask, - EShLangIntersectMask = (1 << EShLangIntersect), - EShLangIntersectNVMask = EShLangIntersectMask, - EShLangAnyHitMask = (1 << EShLangAnyHit), - EShLangAnyHitNVMask = EShLangAnyHitMask, - EShLangClosestHitMask = (1 << EShLangClosestHit), - EShLangClosestHitNVMask = EShLangClosestHitMask, - EShLangMissMask = (1 << EShLangMiss), - EShLangMissNVMask = EShLangMissMask, - EShLangCallableMask = (1 << EShLangCallable), - EShLangCallableNVMask = EShLangCallableMask, - EShLangTaskMask = (1 << EShLangTask), - EShLangTaskNVMask = EShLangTaskMask, - EShLangMeshMask = (1 << EShLangMesh), - EShLangMeshNVMask = EShLangMeshMask, - LAST_ELEMENT_MARKER(EShLanguageMaskCount), -} EShLanguageMask; - -namespace glslang { - -class TType; - -typedef enum { - EShSourceNone, - EShSourceGlsl, // GLSL, includes ESSL (OpenGL ES GLSL) - EShSourceHlsl, // HLSL - LAST_ELEMENT_MARKER(EShSourceCount), -} EShSource; // if EShLanguage were EShStage, this could be EShLanguage instead - -typedef enum { - EShClientNone, // use when there is no client, e.g. for validation - EShClientVulkan, // as GLSL dialect, specifies KHR_vulkan_glsl extension - EShClientOpenGL, // as GLSL dialect, specifies ARB_gl_spirv extension - LAST_ELEMENT_MARKER(EShClientCount), -} EShClient; - -typedef enum { - EShTargetNone, - EShTargetSpv, // SPIR-V (preferred spelling) - EshTargetSpv = EShTargetSpv, // legacy spelling - LAST_ELEMENT_MARKER(EShTargetCount), -} EShTargetLanguage; - -typedef enum { - EShTargetVulkan_1_0 = (1 << 22), // Vulkan 1.0 - EShTargetVulkan_1_1 = (1 << 22) | (1 << 12), // Vulkan 1.1 - EShTargetVulkan_1_2 = (1 << 22) | (2 << 12), // Vulkan 1.2 - EShTargetVulkan_1_3 = (1 << 22) | (3 << 12), // Vulkan 1.3 - EShTargetOpenGL_450 = 450, // OpenGL - LAST_ELEMENT_MARKER(EShTargetClientVersionCount = 5), -} EShTargetClientVersion; - -typedef EShTargetClientVersion EshTargetClientVersion; - -typedef enum { - EShTargetSpv_1_0 = (1 << 16), // SPIR-V 1.0 - EShTargetSpv_1_1 = (1 << 16) | (1 << 8), // SPIR-V 1.1 - EShTargetSpv_1_2 = (1 << 16) | (2 << 8), // SPIR-V 1.2 - EShTargetSpv_1_3 = (1 << 16) | (3 << 8), // SPIR-V 1.3 - EShTargetSpv_1_4 = (1 << 16) | (4 << 8), // SPIR-V 1.4 - EShTargetSpv_1_5 = (1 << 16) | (5 << 8), // SPIR-V 1.5 - EShTargetSpv_1_6 = (1 << 16) | (6 << 8), // SPIR-V 1.6 - LAST_ELEMENT_MARKER(EShTargetLanguageVersionCount = 7), -} EShTargetLanguageVersion; - -struct TInputLanguage { - EShSource languageFamily; // redundant information with other input, this one overrides when not EShSourceNone - EShLanguage stage; // redundant information with other input, this one overrides when not EShSourceNone - EShClient dialect; - int dialectVersion; // version of client's language definition, not the client (when not EShClientNone) - bool vulkanRulesRelaxed; -}; - -struct TClient { - EShClient client; - EShTargetClientVersion version; // version of client itself (not the client's input dialect) -}; - -struct TTarget { - EShTargetLanguage language; - EShTargetLanguageVersion version; // version to target, if SPIR-V, defined by "word 1" of the SPIR-V header - bool hlslFunctionality1; // can target hlsl_functionality1 extension(s) -}; - -// All source/client/target versions and settings. -// Can override previous methods of setting, when items are set here. -// Expected to grow, as more are added, rather than growing parameter lists. -struct TEnvironment { - TInputLanguage input; // definition of the input language - TClient client; // what client is the overall compilation being done for? - TTarget target; // what to generate -}; - -GLSLANG_EXPORT const char* StageName(EShLanguage); - -} // end namespace glslang - -// -// Types of output the linker will create. -// -typedef enum { - EShExVertexFragment, - EShExFragment -} EShExecutable; - -// -// Optimization level for the compiler. -// -typedef enum { - EShOptNoGeneration, - EShOptNone, - EShOptSimple, // Optimizations that can be done quickly - EShOptFull, // Optimizations that will take more time - LAST_ELEMENT_MARKER(EshOptLevelCount), -} EShOptimizationLevel; - -// -// Texture and Sampler transformation mode. -// -typedef enum { - EShTexSampTransKeep, // keep textures and samplers as is (default) - EShTexSampTransUpgradeTextureRemoveSampler, // change texture w/o embeded sampler into sampled texture and throw away all samplers - LAST_ELEMENT_MARKER(EShTexSampTransCount), -} EShTextureSamplerTransformMode; - -// -// Message choices for what errors and warnings are given. -// -enum EShMessages : unsigned { - EShMsgDefault = 0, // default is to give all required errors and extra warnings - EShMsgRelaxedErrors = (1 << 0), // be liberal in accepting input - EShMsgSuppressWarnings = (1 << 1), // suppress all warnings, except those required by the specification - EShMsgAST = (1 << 2), // print the AST intermediate representation - EShMsgSpvRules = (1 << 3), // issue messages for SPIR-V generation - EShMsgVulkanRules = (1 << 4), // issue messages for Vulkan-requirements of GLSL for SPIR-V - EShMsgOnlyPreprocessor = (1 << 5), // only print out errors produced by the preprocessor - EShMsgReadHlsl = (1 << 6), // use HLSL parsing rules and semantics - EShMsgCascadingErrors = (1 << 7), // get cascading errors; risks error-recovery issues, instead of an early exit - EShMsgKeepUncalled = (1 << 8), // for testing, don't eliminate uncalled functions - EShMsgHlslOffsets = (1 << 9), // allow block offsets to follow HLSL rules instead of GLSL rules - EShMsgDebugInfo = (1 << 10), // save debug information - EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL - EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages - EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (for samplers and semantics) - EShMsgBuiltinSymbolTable = (1 << 14), // print the builtin symbol table - EShMsgEnhanced = (1 << 15), // enhanced message readability - LAST_ELEMENT_MARKER(EShMsgCount), -}; - -// -// Options for building reflection -// -typedef enum { - EShReflectionDefault = 0, // default is original behaviour before options were added - EShReflectionStrictArraySuffix = (1 << 0), // reflection will follow stricter rules for array-of-structs suffixes - EShReflectionBasicArraySuffix = (1 << 1), // arrays of basic types will be appended with [0] as in GL reflection - EShReflectionIntermediateIO = (1 << 2), // reflect inputs and outputs to program, even with no vertex shader - EShReflectionSeparateBuffers = (1 << 3), // buffer variables and buffer blocks are reflected separately - EShReflectionAllBlockVariables = (1 << 4), // reflect all variables in blocks, even if they are inactive - EShReflectionUnwrapIOBlocks = (1 << 5), // unwrap input/output blocks the same as with uniform blocks - EShReflectionAllIOVariables = (1 << 6), // reflect all input/output variables, even if they are inactive - EShReflectionSharedStd140SSBO = (1 << 7), // Apply std140/shared rules for ubo to ssbo - EShReflectionSharedStd140UBO = (1 << 8), // Apply std140/shared rules for ubo to ssbo - LAST_ELEMENT_MARKER(EShReflectionCount), -} EShReflectionOptions; - -// -// Build a table for bindings. This can be used for locating -// attributes, uniforms, globals, etc., as needed. -// -typedef struct { - const char* name; - int binding; -} ShBinding; - -typedef struct { - int numBindings; - ShBinding* bindings; // array of bindings -} ShBindingTable; - -// -// ShHandle held by but opaque to the driver. It is allocated, -// managed, and de-allocated by the compiler/linker. Its contents -// are defined by and used by the compiler and linker. For example, -// symbol table information and object code passed from the compiler -// to the linker can be stored where ShHandle points. -// -// If handle creation fails, 0 will be returned. -// -typedef void* ShHandle; - -// -// Driver calls these to create and destroy compiler/linker -// objects. -// -GLSLANG_EXPORT ShHandle ShConstructCompiler(const EShLanguage, int /*debugOptions unused*/); // one per shader -GLSLANG_EXPORT ShHandle ShConstructLinker(const EShExecutable, int /*debugOptions unused*/); // one per shader pair -GLSLANG_EXPORT ShHandle ShConstructUniformMap(); // one per uniform namespace (currently entire program object) -GLSLANG_EXPORT void ShDestruct(ShHandle); - -// -// The return value of ShCompile is boolean, non-zero indicating -// success. -// -// The info-log should be written by ShCompile into -// ShHandle, so it can answer future queries. -// -GLSLANG_EXPORT int ShCompile(const ShHandle, const char* const shaderStrings[], const int numStrings, - const int* lengths, const EShOptimizationLevel, const TBuiltInResource* resources, - int, // debugOptions unused - int defaultVersion = 110, // use 100 for ES environment, overridden by #version in shader - bool forwardCompatible = false, // give errors for use of deprecated features - EShMessages messages = EShMsgDefault // warnings and errors -); - -GLSLANG_EXPORT int ShLinkExt( - const ShHandle, // linker object - const ShHandle h[], // compiler objects to link together - const int numHandles); - -// -// ShSetEncrpytionMethod is a place-holder for specifying -// how source code is encrypted. -// -GLSLANG_EXPORT void ShSetEncryptionMethod(ShHandle); - -// -// All the following return 0 if the information is not -// available in the object passed down, or the object is bad. -// -GLSLANG_EXPORT const char* ShGetInfoLog(const ShHandle); -GLSLANG_EXPORT const void* ShGetExecutable(const ShHandle); -GLSLANG_EXPORT int ShSetVirtualAttributeBindings(const ShHandle, const ShBindingTable*); // to detect user aliasing -GLSLANG_EXPORT int ShSetFixedAttributeBindings(const ShHandle, const ShBindingTable*); // to force any physical mappings -// -// Tell the linker to never assign a vertex attribute to this list of physical attributes -// -GLSLANG_EXPORT int ShExcludeAttributes(const ShHandle, int *attributes, int count); - -// -// Returns the location ID of the named uniform. -// Returns -1 if error. -// -GLSLANG_EXPORT int ShGetUniformLocation(const ShHandle uniformMap, const char* name); - -#ifdef __cplusplus - } // end extern "C" -#endif - -//////////////////////////////////////////////////////////////////////////////////////////// -// -// Deferred-Lowering C++ Interface -// ----------------------------------- -// -// Below is a new alternate C++ interface, which deprecates the above -// opaque handle-based interface. -// -// The below is further designed to handle multiple compilation units per stage, where -// the intermediate results, including the parse tree, are preserved until link time, -// rather than the above interface which is designed to have each compilation unit -// lowered at compile time. In the above model, linking occurs on the lowered results, -// whereas in this model intra-stage linking can occur at the parse tree -// (treeRoot in TIntermediate) level, and then a full stage can be lowered. -// - -#include -#include -#include - -class TCompiler; -class TInfoSink; - -namespace glslang { - -struct Version { - int major; - int minor; - int patch; - const char* flavor; -}; - -GLSLANG_EXPORT Version GetVersion(); -GLSLANG_EXPORT const char* GetEsslVersionString(); -GLSLANG_EXPORT const char* GetGlslVersionString(); -GLSLANG_EXPORT int GetKhronosToolId(); - -class TIntermediate; -class TProgram; -class TPoolAllocator; - -// Call this exactly once per process before using anything else -GLSLANG_EXPORT bool InitializeProcess(); - -// Call once per process to tear down everything -GLSLANG_EXPORT void FinalizeProcess(); - -// Resource type for IO resolver -enum TResourceType { - EResSampler, - EResTexture, - EResImage, - EResUbo, - EResSsbo, - EResUav, - EResCount -}; - -enum TBlockStorageClass -{ - EbsUniform = 0, - EbsStorageBuffer, - EbsPushConstant, - EbsNone, // not a uniform or buffer variable - EbsCount, -}; - -// Make one TShader per shader that you will link into a program. Then -// - provide the shader through setStrings() or setStringsWithLengths() -// - optionally call setEnv*(), see below for more detail -// - optionally use setPreamble() to set a special shader string that will be -// processed before all others but won't affect the validity of #version -// - optionally call addProcesses() for each setting/transform, -// see comment for class TProcesses -// - call parse(): source language and target environment must be selected -// either by correct setting of EShMessages sent to parse(), or by -// explicitly calling setEnv*() -// - query the info logs -// -// N.B.: Does not yet support having the same TShader instance being linked into -// multiple programs. -// -// N.B.: Destruct a linked program *before* destructing the shaders linked into it. -// -class TShader { -public: - GLSLANG_EXPORT explicit TShader(EShLanguage); - GLSLANG_EXPORT virtual ~TShader(); - GLSLANG_EXPORT void setStrings(const char* const* s, int n); - GLSLANG_EXPORT void setStringsWithLengths( - const char* const* s, const int* l, int n); - GLSLANG_EXPORT void setStringsWithLengthsAndNames( - const char* const* s, const int* l, const char* const* names, int n); - void setPreamble(const char* s) { preamble = s; } - GLSLANG_EXPORT void setEntryPoint(const char* entryPoint); - GLSLANG_EXPORT void setSourceEntryPoint(const char* sourceEntryPointName); - GLSLANG_EXPORT void addProcesses(const std::vector&); - GLSLANG_EXPORT void setUniqueId(unsigned long long id); - GLSLANG_EXPORT void setOverrideVersion(int version); - GLSLANG_EXPORT void setDebugInfo(bool debugInfo); - - // IO resolver binding data: see comments in ShaderLang.cpp - GLSLANG_EXPORT void setShiftBinding(TResourceType res, unsigned int base); - GLSLANG_EXPORT void setShiftSamplerBinding(unsigned int base); // DEPRECATED: use setShiftBinding - GLSLANG_EXPORT void setShiftTextureBinding(unsigned int base); // DEPRECATED: use setShiftBinding - GLSLANG_EXPORT void setShiftImageBinding(unsigned int base); // DEPRECATED: use setShiftBinding - GLSLANG_EXPORT void setShiftUboBinding(unsigned int base); // DEPRECATED: use setShiftBinding - GLSLANG_EXPORT void setShiftUavBinding(unsigned int base); // DEPRECATED: use setShiftBinding - GLSLANG_EXPORT void setShiftCbufferBinding(unsigned int base); // synonym for setShiftUboBinding - GLSLANG_EXPORT void setShiftSsboBinding(unsigned int base); // DEPRECATED: use setShiftBinding - GLSLANG_EXPORT void setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set); - GLSLANG_EXPORT void setResourceSetBinding(const std::vector& base); - GLSLANG_EXPORT void setAutoMapBindings(bool map); - GLSLANG_EXPORT void setAutoMapLocations(bool map); - GLSLANG_EXPORT void addUniformLocationOverride(const char* name, int loc); - GLSLANG_EXPORT void setUniformLocationBase(int base); - GLSLANG_EXPORT void setInvertY(bool invert); - GLSLANG_EXPORT void setDxPositionW(bool dxPosW); - GLSLANG_EXPORT void setEnhancedMsgs(); -#ifdef ENABLE_HLSL - GLSLANG_EXPORT void setHlslIoMapping(bool hlslIoMap); - GLSLANG_EXPORT void setFlattenUniformArrays(bool flatten); -#endif - GLSLANG_EXPORT void setNoStorageFormat(bool useUnknownFormat); - GLSLANG_EXPORT void setNanMinMaxClamp(bool nanMinMaxClamp); - GLSLANG_EXPORT void setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode); - GLSLANG_EXPORT void addBlockStorageOverride(const char* nameStr, glslang::TBlockStorageClass backing); - - GLSLANG_EXPORT void setGlobalUniformBlockName(const char* name); - GLSLANG_EXPORT void setAtomicCounterBlockName(const char* name); - GLSLANG_EXPORT void setGlobalUniformSet(unsigned int set); - GLSLANG_EXPORT void setGlobalUniformBinding(unsigned int binding); - GLSLANG_EXPORT void setAtomicCounterBlockSet(unsigned int set); - GLSLANG_EXPORT void setAtomicCounterBlockBinding(unsigned int binding); - - // For setting up the environment (cleared to nothingness in the constructor). - // These must be called so that parsing is done for the right source language and - // target environment, either indirectly through TranslateEnvironment() based on - // EShMessages et. al., or directly by the user. - // - // setEnvInput: The input source language and stage. If generating code for a - // specific client, the input client semantics to use and the - // version of that client's input semantics to use, otherwise - // use EShClientNone and version of 0, e.g. for validation mode. - // Note 'version' does not describe the target environment, - // just the version of the source dialect to compile under. - // For example, to choose the Vulkan dialect of GLSL defined by - // version 100 of the KHR_vulkan_glsl extension: lang = EShSourceGlsl, - // dialect = EShClientVulkan, and version = 100. - // - // See the definitions of TEnvironment, EShSource, EShLanguage, - // and EShClient for choices and more detail. - // - // setEnvClient: The client that will be hosting the execution, and its version. - // Note 'version' is not the version of the languages involved, but - // the version of the client environment. - // Use EShClientNone and version of 0 if there is no client, e.g. - // for validation mode. - // - // See EShTargetClientVersion for choices. - // - // setEnvTarget: The language to translate to when generating code, and that - // language's version. - // Use EShTargetNone and version of 0 if there is no client, e.g. - // for validation mode. - // - void setEnvInput(EShSource lang, EShLanguage envStage, EShClient client, int version) - { - environment.input.languageFamily = lang; - environment.input.stage = envStage; - environment.input.dialect = client; - environment.input.dialectVersion = version; - } - void setEnvClient(EShClient client, EShTargetClientVersion version) - { - environment.client.client = client; - environment.client.version = version; - } - void setEnvTarget(EShTargetLanguage lang, EShTargetLanguageVersion version) - { - environment.target.language = lang; - environment.target.version = version; - } - - void getStrings(const char* const* &s, int& n) { s = strings; n = numStrings; } - -#ifdef ENABLE_HLSL - void setEnvTargetHlslFunctionality1() { environment.target.hlslFunctionality1 = true; } - bool getEnvTargetHlslFunctionality1() const { return environment.target.hlslFunctionality1; } -#else - bool getEnvTargetHlslFunctionality1() const { return false; } -#endif - - void setEnvInputVulkanRulesRelaxed() { environment.input.vulkanRulesRelaxed = true; } - bool getEnvInputVulkanRulesRelaxed() const { return environment.input.vulkanRulesRelaxed; } - - void setCompileOnly() { compileOnly = true; } - bool getCompileOnly() const { return compileOnly; } - - // Interface to #include handlers. - // - // To support #include, a client of Glslang does the following: - // 1. Call setStringsWithNames to set the source strings and associated - // names. For example, the names could be the names of the files - // containing the shader sources. - // 2. Call parse with an Includer. - // - // When the Glslang parser encounters an #include directive, it calls - // the Includer's include method with the requested include name - // together with the current string name. The returned IncludeResult - // contains the fully resolved name of the included source, together - // with the source text that should replace the #include directive - // in the source stream. After parsing that source, Glslang will - // release the IncludeResult object. - class Includer { - public: - // An IncludeResult contains the resolved name and content of a source - // inclusion. - struct IncludeResult { - IncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength, void* userData) : - headerName(headerName), headerData(headerData), headerLength(headerLength), userData(userData) { } - // For a successful inclusion, the fully resolved name of the requested - // include. For example, in a file system-based includer, full resolution - // should convert a relative path name into an absolute path name. - // For a failed inclusion, this is an empty string. - const std::string headerName; - // The content and byte length of the requested inclusion. The - // Includer producing this IncludeResult retains ownership of the - // storage. - // For a failed inclusion, the header - // field points to a string containing error details. - const char* const headerData; - const size_t headerLength; - // Include resolver's context. - void* userData; - protected: - IncludeResult& operator=(const IncludeResult&); - IncludeResult(); - }; - - // For both include methods below: - // - // Resolves an inclusion request by name, current source name, - // and include depth. - // On success, returns an IncludeResult containing the resolved name - // and content of the include. - // On failure, returns a nullptr, or an IncludeResult - // with an empty string for the headerName and error details in the - // header field. - // The Includer retains ownership of the contents - // of the returned IncludeResult value, and those contents must - // remain valid until the releaseInclude method is called on that - // IncludeResult object. - // - // Note "local" vs. "system" is not an "either/or": "local" is an - // extra thing to do over "system". Both might get called, as per - // the C++ specification. - - // For the "system" or <>-style includes; search the "system" paths. - virtual IncludeResult* includeSystem(const char* /*headerName*/, - const char* /*includerName*/, - size_t /*inclusionDepth*/) { return nullptr; } - - // For the "local"-only aspect of a "" include. Should not search in the - // "system" paths, because on returning a failure, the parser will - // call includeSystem() to look in the "system" locations. - virtual IncludeResult* includeLocal(const char* /*headerName*/, - const char* /*includerName*/, - size_t /*inclusionDepth*/) { return nullptr; } - - // Signals that the parser will no longer use the contents of the - // specified IncludeResult. - virtual void releaseInclude(IncludeResult*) = 0; - virtual ~Includer() {} - }; - - // Fail all Includer searches - class ForbidIncluder : public Includer { - public: - virtual void releaseInclude(IncludeResult*) override { } - }; - - GLSLANG_EXPORT bool parse( - const TBuiltInResource*, int defaultVersion, EProfile defaultProfile, - bool forceDefaultVersionAndProfile, bool forwardCompatible, - EShMessages, Includer&); - - bool parse(const TBuiltInResource* res, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages messages) - { - TShader::ForbidIncluder includer; - return parse(res, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, includer); - } - - // Equivalent to parse() without a default profile and without forcing defaults. - bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages) - { - return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages); - } - - bool parse(const TBuiltInResource* builtInResources, int defaultVersion, bool forwardCompatible, EShMessages messages, - Includer& includer) - { - return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer); - } - - // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string - // is not an officially supported or fully working path. - GLSLANG_EXPORT bool preprocess( - const TBuiltInResource* builtInResources, int defaultVersion, - EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages message, std::string* outputString, - Includer& includer); - - GLSLANG_EXPORT const char* getInfoLog(); - GLSLANG_EXPORT const char* getInfoDebugLog(); - EShLanguage getStage() const { return stage; } - TIntermediate* getIntermediate() const { return intermediate; } - -protected: - TPoolAllocator* pool; - EShLanguage stage; - TCompiler* compiler; - TIntermediate* intermediate; - TInfoSink* infoSink; - // strings and lengths follow the standard for glShaderSource: - // strings is an array of numStrings pointers to string data. - // lengths can be null, but if not it is an array of numStrings - // integers containing the length of the associated strings. - // if lengths is null or lengths[n] < 0 the associated strings[n] is - // assumed to be null-terminated. - // stringNames is the optional names for all the strings. If stringNames - // is null, then none of the strings has name. If a certain element in - // stringNames is null, then the corresponding string does not have name. - const char* const* strings; // explicit code to compile, see previous comment - const int* lengths; - const char* const* stringNames; - int numStrings; // size of the above arrays - const char* preamble; // string of implicit code to compile before the explicitly provided code - - // a function in the source string can be renamed FROM this TO the name given in setEntryPoint. - std::string sourceEntryPointName; - - // overrides #version in shader source or default version if #version isn't present - int overrideVersion; - - TEnvironment environment; - - // Indicates this shader is meant to be used without linking - bool compileOnly = false; - - friend class TProgram; - -private: - TShader& operator=(TShader&); -}; - -// -// A reflection database and its interface, consistent with the OpenGL API reflection queries. -// - -// Data needed for just a single object at the granularity exchanged by the reflection API -class TObjectReflection { -public: - GLSLANG_EXPORT TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex); - - const TType* getType() const { return type; } - GLSLANG_EXPORT int getBinding() const; - GLSLANG_EXPORT void dump() const; - static TObjectReflection badReflection() { return TObjectReflection(); } - - std::string name; - int offset; - int glDefineType; - int size; // data size in bytes for a block, array size for a (non-block) object that's an array - int index; - int counterIndex; - int numMembers; - int arrayStride; // stride of an array variable - int topLevelArraySize; // size of the top-level variable in a storage buffer member - int topLevelArrayStride; // stride of the top-level variable in a storage buffer member - EShLanguageMask stages; - -protected: - TObjectReflection() - : offset(-1), glDefineType(-1), size(-1), index(-1), counterIndex(-1), numMembers(-1), arrayStride(0), - topLevelArrayStride(0), stages(EShLanguageMask(0)), type(nullptr) - { - } - - const TType* type; -}; - -class TReflection; -class TIoMapper; -struct TVarEntryInfo; - -// Allows to customize the binding layout after linking. -// All used uniform variables will invoke at least validateBinding. -// If validateBinding returned true then the other resolveBinding, -// resolveSet, and resolveLocation are invoked to resolve the binding -// and descriptor set index respectively. -// -// Invocations happen in a particular order: -// 1) all shader inputs -// 2) all shader outputs -// 3) all uniforms with binding and set already defined -// 4) all uniforms with binding but no set defined -// 5) all uniforms with set but no binding defined -// 6) all uniforms with no binding and no set defined -// -// mapIO will use this resolver in two phases. The first -// phase is a notification phase, calling the corresponging -// notifiy callbacks, this phase ends with a call to endNotifications. -// Phase two starts directly after the call to endNotifications -// and calls all other callbacks to validate and to get the -// bindings, sets, locations, component and color indices. -// -// NOTE: that still limit checks are applied to bindings and sets -// and may result in an error. -class TIoMapResolver -{ -public: - virtual ~TIoMapResolver() {} - - // Should return true if the resulting/current binding would be okay. - // Basic idea is to do aliasing binding checks with this. - virtual bool validateBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; - // Should return a value >= 0 if the current binding should be overridden. - // Return -1 if the current binding (including no binding) should be kept. - virtual int resolveBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; - // Should return a value >= 0 if the current set should be overridden. - // Return -1 if the current set (including no set) should be kept. - virtual int resolveSet(EShLanguage stage, TVarEntryInfo& ent) = 0; - // Should return a value >= 0 if the current location should be overridden. - // Return -1 if the current location (including no location) should be kept. - virtual int resolveUniformLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; - // Should return true if the resulting/current setup would be okay. - // Basic idea is to do aliasing checks and reject invalid semantic names. - virtual bool validateInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; - // Should return a value >= 0 if the current location should be overridden. - // Return -1 if the current location (including no location) should be kept. - virtual int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) = 0; - // Should return a value >= 0 if the current component index should be overridden. - // Return -1 if the current component index (including no index) should be kept. - virtual int resolveInOutComponent(EShLanguage stage, TVarEntryInfo& ent) = 0; - // Should return a value >= 0 if the current color index should be overridden. - // Return -1 if the current color index (including no index) should be kept. - virtual int resolveInOutIndex(EShLanguage stage, TVarEntryInfo& ent) = 0; - // Notification of a uniform variable - virtual void notifyBinding(EShLanguage stage, TVarEntryInfo& ent) = 0; - // Notification of a in or out variable - virtual void notifyInOut(EShLanguage stage, TVarEntryInfo& ent) = 0; - // Called by mapIO when it starts its notify pass for the given stage - virtual void beginNotifications(EShLanguage stage) = 0; - // Called by mapIO when it has finished the notify pass - virtual void endNotifications(EShLanguage stage) = 0; - // Called by mipIO when it starts its resolve pass for the given stage - virtual void beginResolve(EShLanguage stage) = 0; - // Called by mapIO when it has finished the resolve pass - virtual void endResolve(EShLanguage stage) = 0; - // Called by mapIO when it starts its symbol collect for teh given stage - virtual void beginCollect(EShLanguage stage) = 0; - // Called by mapIO when it has finished the symbol collect - virtual void endCollect(EShLanguage stage) = 0; - // Called by TSlotCollector to resolve storage locations or bindings - virtual void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; - // Called by TSlotCollector to resolve resource locations or bindings - virtual void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) = 0; - // Called by mapIO.addStage to set shader stage mask to mark a stage be added to this pipeline - virtual void addStage(EShLanguage stage, TIntermediate& stageIntermediate) = 0; -}; - -// Make one TProgram per set of shaders that will get linked together. Add all -// the shaders that are to be linked together. After calling shader.parse() -// for all shaders, call link(). -// -// N.B.: Destruct a linked program *before* destructing the shaders linked into it. -// -class TProgram { -public: - GLSLANG_EXPORT TProgram(); - GLSLANG_EXPORT virtual ~TProgram(); - void addShader(TShader* shader) { stages[shader->stage].push_back(shader); } - std::list& getShaders(EShLanguage stage) { return stages[stage]; } - // Link Validation interface - GLSLANG_EXPORT bool link(EShMessages); - GLSLANG_EXPORT const char* getInfoLog(); - GLSLANG_EXPORT const char* getInfoDebugLog(); - - TIntermediate* getIntermediate(EShLanguage stage) const { return intermediate[stage]; } - - // Reflection Interface - - // call first, to do liveness analysis, index mapping, etc.; returns false on failure - GLSLANG_EXPORT bool buildReflection(int opts = EShReflectionDefault); - GLSLANG_EXPORT unsigned getLocalSize(int dim) const; // return dim'th local size - GLSLANG_EXPORT int getReflectionIndex(const char *name) const; - GLSLANG_EXPORT int getReflectionPipeIOIndex(const char* name, const bool inOrOut) const; - GLSLANG_EXPORT int getNumUniformVariables() const; - GLSLANG_EXPORT const TObjectReflection& getUniform(int index) const; - GLSLANG_EXPORT int getNumUniformBlocks() const; - GLSLANG_EXPORT const TObjectReflection& getUniformBlock(int index) const; - GLSLANG_EXPORT int getNumPipeInputs() const; - GLSLANG_EXPORT const TObjectReflection& getPipeInput(int index) const; - GLSLANG_EXPORT int getNumPipeOutputs() const; - GLSLANG_EXPORT const TObjectReflection& getPipeOutput(int index) const; - GLSLANG_EXPORT int getNumBufferVariables() const; - GLSLANG_EXPORT const TObjectReflection& getBufferVariable(int index) const; - GLSLANG_EXPORT int getNumBufferBlocks() const; - GLSLANG_EXPORT const TObjectReflection& getBufferBlock(int index) const; - GLSLANG_EXPORT int getNumAtomicCounters() const; - GLSLANG_EXPORT const TObjectReflection& getAtomicCounter(int index) const; - - // Legacy Reflection Interface - expressed in terms of above interface - - // can be used for glGetProgramiv(GL_ACTIVE_UNIFORMS) - int getNumLiveUniformVariables() const { return getNumUniformVariables(); } - - // can be used for glGetProgramiv(GL_ACTIVE_UNIFORM_BLOCKS) - int getNumLiveUniformBlocks() const { return getNumUniformBlocks(); } - - // can be used for glGetProgramiv(GL_ACTIVE_ATTRIBUTES) - int getNumLiveAttributes() const { return getNumPipeInputs(); } - - // can be used for glGetUniformIndices() - int getUniformIndex(const char *name) const { return getReflectionIndex(name); } - - int getPipeIOIndex(const char *name, const bool inOrOut) const - { return getReflectionPipeIOIndex(name, inOrOut); } - - // can be used for "name" part of glGetActiveUniform() - const char *getUniformName(int index) const { return getUniform(index).name.c_str(); } - - // returns the binding number - int getUniformBinding(int index) const { return getUniform(index).getBinding(); } - - // returns Shaders Stages where a Uniform is present - EShLanguageMask getUniformStages(int index) const { return getUniform(index).stages; } - - // can be used for glGetActiveUniformsiv(GL_UNIFORM_BLOCK_INDEX) - int getUniformBlockIndex(int index) const { return getUniform(index).index; } - - // can be used for glGetActiveUniformsiv(GL_UNIFORM_TYPE) - int getUniformType(int index) const { return getUniform(index).glDefineType; } - - // can be used for glGetActiveUniformsiv(GL_UNIFORM_OFFSET) - int getUniformBufferOffset(int index) const { return getUniform(index).offset; } - - // can be used for glGetActiveUniformsiv(GL_UNIFORM_SIZE) - int getUniformArraySize(int index) const { return getUniform(index).size; } - - // returns a TType* - const TType *getUniformTType(int index) const { return getUniform(index).getType(); } - - // can be used for glGetActiveUniformBlockName() - const char *getUniformBlockName(int index) const { return getUniformBlock(index).name.c_str(); } - - // can be used for glGetActiveUniformBlockiv(UNIFORM_BLOCK_DATA_SIZE) - int getUniformBlockSize(int index) const { return getUniformBlock(index).size; } - - // returns the block binding number - int getUniformBlockBinding(int index) const { return getUniformBlock(index).getBinding(); } - - // returns block index of associated counter. - int getUniformBlockCounterIndex(int index) const { return getUniformBlock(index).counterIndex; } - - // returns a TType* - const TType *getUniformBlockTType(int index) const { return getUniformBlock(index).getType(); } - - // can be used for glGetActiveAttrib() - const char *getAttributeName(int index) const { return getPipeInput(index).name.c_str(); } - - // can be used for glGetActiveAttrib() - int getAttributeType(int index) const { return getPipeInput(index).glDefineType; } - - // returns a TType* - const TType *getAttributeTType(int index) const { return getPipeInput(index).getType(); } - - GLSLANG_EXPORT void dumpReflection(); - // I/O mapping: apply base offsets and map live unbound variables - // If resolver is not provided it uses the previous approach - // and respects auto assignment and offsets. - GLSLANG_EXPORT bool mapIO(TIoMapResolver* pResolver = nullptr, TIoMapper* pIoMapper = nullptr); - -protected: - GLSLANG_EXPORT bool linkStage(EShLanguage, EShMessages); - GLSLANG_EXPORT bool crossStageCheck(EShMessages); - - TPoolAllocator* pool; - std::list stages[EShLangCount]; - TIntermediate* intermediate[EShLangCount]; - bool newedIntermediate[EShLangCount]; // track which intermediate were "new" versus reusing a singleton unit in a stage - TInfoSink* infoSink; - TReflection* reflection; - bool linked; - -private: - TProgram(TProgram&); - TProgram& operator=(TProgram&); -}; - -} // end namespace glslang - -#endif // _COMPILER_INTERFACE_INCLUDED_ diff --git a/3rdparty/glslang/glslang/Public/resource_limits_c.h b/3rdparty/glslang/glslang/Public/resource_limits_c.h deleted file mode 100644 index 05aa8eb0..00000000 --- a/3rdparty/glslang/glslang/Public/resource_limits_c.h +++ /dev/null @@ -1,57 +0,0 @@ -/** -BSD 2-Clause License - -Copyright (c) 2020, Travis Fort -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**/ - -#ifndef _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_ -#define _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_ - -#include "../Include/glslang_c_interface.h" - -#ifdef __cplusplus -extern "C" { -#endif - -// Returns a struct that can be use to create custom resource values. -glslang_resource_t* glslang_resource(void); - -// These are the default resources for TBuiltInResources, used for both -// - parsing this string for the case where the user didn't supply one, -// - dumping out a template for user construction of a config file. -const glslang_resource_t* glslang_default_resource(void); - -// Returns the DefaultTBuiltInResource as a human-readable string. -// NOTE: User is responsible for freeing this string. -const char* glslang_default_resource_string(); - -// Decodes the resource limits from |config| to |resources|. -void glslang_decode_resource_limits(glslang_resource_t* resources, char* config); - -#ifdef __cplusplus -} -#endif - -#endif // _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_ diff --git a/3rdparty/glslang/glslang/ResourceLimits/ResourceLimits.cpp b/3rdparty/glslang/glslang/ResourceLimits/ResourceLimits.cpp deleted file mode 100644 index 0e9d1b54..00000000 --- a/3rdparty/glslang/glslang/ResourceLimits/ResourceLimits.cpp +++ /dev/null @@ -1,542 +0,0 @@ -// -// Copyright (C) 2016 Google, Inc. -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// -// Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -#include -#include -#include -#include - -#include "glslang/Public/ResourceLimits.h" - -TBuiltInResource Resources; - -const TBuiltInResource DefaultTBuiltInResource = { - /* .MaxLights = */ 32, - /* .MaxClipPlanes = */ 6, - /* .MaxTextureUnits = */ 32, - /* .MaxTextureCoords = */ 32, - /* .MaxVertexAttribs = */ 64, - /* .MaxVertexUniformComponents = */ 4096, - /* .MaxVaryingFloats = */ 64, - /* .MaxVertexTextureImageUnits = */ 32, - /* .MaxCombinedTextureImageUnits = */ 80, - /* .MaxTextureImageUnits = */ 32, - /* .MaxFragmentUniformComponents = */ 4096, - /* .MaxDrawBuffers = */ 32, - /* .MaxVertexUniformVectors = */ 128, - /* .MaxVaryingVectors = */ 8, - /* .MaxFragmentUniformVectors = */ 16, - /* .MaxVertexOutputVectors = */ 16, - /* .MaxFragmentInputVectors = */ 15, - /* .MinProgramTexelOffset = */ -8, - /* .MaxProgramTexelOffset = */ 7, - /* .MaxClipDistances = */ 8, - /* .MaxComputeWorkGroupCountX = */ 65535, - /* .MaxComputeWorkGroupCountY = */ 65535, - /* .MaxComputeWorkGroupCountZ = */ 65535, - /* .MaxComputeWorkGroupSizeX = */ 1024, - /* .MaxComputeWorkGroupSizeY = */ 1024, - /* .MaxComputeWorkGroupSizeZ = */ 64, - /* .MaxComputeUniformComponents = */ 1024, - /* .MaxComputeTextureImageUnits = */ 16, - /* .MaxComputeImageUniforms = */ 8, - /* .MaxComputeAtomicCounters = */ 8, - /* .MaxComputeAtomicCounterBuffers = */ 1, - /* .MaxVaryingComponents = */ 60, - /* .MaxVertexOutputComponents = */ 64, - /* .MaxGeometryInputComponents = */ 64, - /* .MaxGeometryOutputComponents = */ 128, - /* .MaxFragmentInputComponents = */ 128, - /* .MaxImageUnits = */ 8, - /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, - /* .MaxCombinedShaderOutputResources = */ 8, - /* .MaxImageSamples = */ 0, - /* .MaxVertexImageUniforms = */ 0, - /* .MaxTessControlImageUniforms = */ 0, - /* .MaxTessEvaluationImageUniforms = */ 0, - /* .MaxGeometryImageUniforms = */ 0, - /* .MaxFragmentImageUniforms = */ 8, - /* .MaxCombinedImageUniforms = */ 8, - /* .MaxGeometryTextureImageUnits = */ 16, - /* .MaxGeometryOutputVertices = */ 256, - /* .MaxGeometryTotalOutputComponents = */ 1024, - /* .MaxGeometryUniformComponents = */ 1024, - /* .MaxGeometryVaryingComponents = */ 64, - /* .MaxTessControlInputComponents = */ 128, - /* .MaxTessControlOutputComponents = */ 128, - /* .MaxTessControlTextureImageUnits = */ 16, - /* .MaxTessControlUniformComponents = */ 1024, - /* .MaxTessControlTotalOutputComponents = */ 4096, - /* .MaxTessEvaluationInputComponents = */ 128, - /* .MaxTessEvaluationOutputComponents = */ 128, - /* .MaxTessEvaluationTextureImageUnits = */ 16, - /* .MaxTessEvaluationUniformComponents = */ 1024, - /* .MaxTessPatchComponents = */ 120, - /* .MaxPatchVertices = */ 32, - /* .MaxTessGenLevel = */ 64, - /* .MaxViewports = */ 16, - /* .MaxVertexAtomicCounters = */ 0, - /* .MaxTessControlAtomicCounters = */ 0, - /* .MaxTessEvaluationAtomicCounters = */ 0, - /* .MaxGeometryAtomicCounters = */ 0, - /* .MaxFragmentAtomicCounters = */ 8, - /* .MaxCombinedAtomicCounters = */ 8, - /* .MaxAtomicCounterBindings = */ 1, - /* .MaxVertexAtomicCounterBuffers = */ 0, - /* .MaxTessControlAtomicCounterBuffers = */ 0, - /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, - /* .MaxGeometryAtomicCounterBuffers = */ 0, - /* .MaxFragmentAtomicCounterBuffers = */ 1, - /* .MaxCombinedAtomicCounterBuffers = */ 1, - /* .MaxAtomicCounterBufferSize = */ 16384, - /* .MaxTransformFeedbackBuffers = */ 4, - /* .MaxTransformFeedbackInterleavedComponents = */ 64, - /* .MaxCullDistances = */ 8, - /* .MaxCombinedClipAndCullDistances = */ 8, - /* .MaxSamples = */ 4, - /* .maxMeshOutputVerticesNV = */ 256, - /* .maxMeshOutputPrimitivesNV = */ 512, - /* .maxMeshWorkGroupSizeX_NV = */ 32, - /* .maxMeshWorkGroupSizeY_NV = */ 1, - /* .maxMeshWorkGroupSizeZ_NV = */ 1, - /* .maxTaskWorkGroupSizeX_NV = */ 32, - /* .maxTaskWorkGroupSizeY_NV = */ 1, - /* .maxTaskWorkGroupSizeZ_NV = */ 1, - /* .maxMeshViewCountNV = */ 4, - /* .maxMeshOutputVerticesEXT = */ 256, - /* .maxMeshOutputPrimitivesEXT = */ 256, - /* .maxMeshWorkGroupSizeX_EXT = */ 128, - /* .maxMeshWorkGroupSizeY_EXT = */ 128, - /* .maxMeshWorkGroupSizeZ_EXT = */ 128, - /* .maxTaskWorkGroupSizeX_EXT = */ 128, - /* .maxTaskWorkGroupSizeY_EXT = */ 128, - /* .maxTaskWorkGroupSizeZ_EXT = */ 128, - /* .maxMeshViewCountEXT = */ 4, - /* .maxDualSourceDrawBuffersEXT = */ 1, - - /* .limits = */ { - /* .nonInductiveForLoops = */ 1, - /* .whileLoops = */ 1, - /* .doWhileLoops = */ 1, - /* .generalUniformIndexing = */ 1, - /* .generalAttributeMatrixVectorIndexing = */ 1, - /* .generalVaryingIndexing = */ 1, - /* .generalSamplerIndexing = */ 1, - /* .generalVariableIndexing = */ 1, - /* .generalConstantMatrixVectorIndexing = */ 1, - }}; - -std::string GetDefaultTBuiltInResourceString() -{ - std::ostringstream ostream; - - ostream << "MaxLights " << DefaultTBuiltInResource.maxLights << "\n" - << "MaxClipPlanes " << DefaultTBuiltInResource.maxClipPlanes << "\n" - << "MaxTextureUnits " << DefaultTBuiltInResource.maxTextureUnits << "\n" - << "MaxTextureCoords " << DefaultTBuiltInResource.maxTextureCoords << "\n" - << "MaxVertexAttribs " << DefaultTBuiltInResource.maxVertexAttribs << "\n" - << "MaxVertexUniformComponents " << DefaultTBuiltInResource.maxVertexUniformComponents << "\n" - << "MaxVaryingFloats " << DefaultTBuiltInResource.maxVaryingFloats << "\n" - << "MaxVertexTextureImageUnits " << DefaultTBuiltInResource.maxVertexTextureImageUnits << "\n" - << "MaxCombinedTextureImageUnits " << DefaultTBuiltInResource.maxCombinedTextureImageUnits << "\n" - << "MaxTextureImageUnits " << DefaultTBuiltInResource.maxTextureImageUnits << "\n" - << "MaxFragmentUniformComponents " << DefaultTBuiltInResource.maxFragmentUniformComponents << "\n" - << "MaxDrawBuffers " << DefaultTBuiltInResource.maxDrawBuffers << "\n" - << "MaxVertexUniformVectors " << DefaultTBuiltInResource.maxVertexUniformVectors << "\n" - << "MaxVaryingVectors " << DefaultTBuiltInResource.maxVaryingVectors << "\n" - << "MaxFragmentUniformVectors " << DefaultTBuiltInResource.maxFragmentUniformVectors << "\n" - << "MaxVertexOutputVectors " << DefaultTBuiltInResource.maxVertexOutputVectors << "\n" - << "MaxFragmentInputVectors " << DefaultTBuiltInResource.maxFragmentInputVectors << "\n" - << "MinProgramTexelOffset " << DefaultTBuiltInResource.minProgramTexelOffset << "\n" - << "MaxProgramTexelOffset " << DefaultTBuiltInResource.maxProgramTexelOffset << "\n" - << "MaxClipDistances " << DefaultTBuiltInResource.maxClipDistances << "\n" - << "MaxComputeWorkGroupCountX " << DefaultTBuiltInResource.maxComputeWorkGroupCountX << "\n" - << "MaxComputeWorkGroupCountY " << DefaultTBuiltInResource.maxComputeWorkGroupCountY << "\n" - << "MaxComputeWorkGroupCountZ " << DefaultTBuiltInResource.maxComputeWorkGroupCountZ << "\n" - << "MaxComputeWorkGroupSizeX " << DefaultTBuiltInResource.maxComputeWorkGroupSizeX << "\n" - << "MaxComputeWorkGroupSizeY " << DefaultTBuiltInResource.maxComputeWorkGroupSizeY << "\n" - << "MaxComputeWorkGroupSizeZ " << DefaultTBuiltInResource.maxComputeWorkGroupSizeZ << "\n" - << "MaxComputeUniformComponents " << DefaultTBuiltInResource.maxComputeUniformComponents << "\n" - << "MaxComputeTextureImageUnits " << DefaultTBuiltInResource.maxComputeTextureImageUnits << "\n" - << "MaxComputeImageUniforms " << DefaultTBuiltInResource.maxComputeImageUniforms << "\n" - << "MaxComputeAtomicCounters " << DefaultTBuiltInResource.maxComputeAtomicCounters << "\n" - << "MaxComputeAtomicCounterBuffers " << DefaultTBuiltInResource.maxComputeAtomicCounterBuffers << "\n" - << "MaxVaryingComponents " << DefaultTBuiltInResource.maxVaryingComponents << "\n" - << "MaxVertexOutputComponents " << DefaultTBuiltInResource.maxVertexOutputComponents << "\n" - << "MaxGeometryInputComponents " << DefaultTBuiltInResource.maxGeometryInputComponents << "\n" - << "MaxGeometryOutputComponents " << DefaultTBuiltInResource.maxGeometryOutputComponents << "\n" - << "MaxFragmentInputComponents " << DefaultTBuiltInResource.maxFragmentInputComponents << "\n" - << "MaxImageUnits " << DefaultTBuiltInResource.maxImageUnits << "\n" - << "MaxCombinedImageUnitsAndFragmentOutputs " << DefaultTBuiltInResource.maxCombinedImageUnitsAndFragmentOutputs << "\n" - << "MaxCombinedShaderOutputResources " << DefaultTBuiltInResource.maxCombinedShaderOutputResources << "\n" - << "MaxImageSamples " << DefaultTBuiltInResource.maxImageSamples << "\n" - << "MaxVertexImageUniforms " << DefaultTBuiltInResource.maxVertexImageUniforms << "\n" - << "MaxTessControlImageUniforms " << DefaultTBuiltInResource.maxTessControlImageUniforms << "\n" - << "MaxTessEvaluationImageUniforms " << DefaultTBuiltInResource.maxTessEvaluationImageUniforms << "\n" - << "MaxGeometryImageUniforms " << DefaultTBuiltInResource.maxGeometryImageUniforms << "\n" - << "MaxFragmentImageUniforms " << DefaultTBuiltInResource.maxFragmentImageUniforms << "\n" - << "MaxCombinedImageUniforms " << DefaultTBuiltInResource.maxCombinedImageUniforms << "\n" - << "MaxGeometryTextureImageUnits " << DefaultTBuiltInResource.maxGeometryTextureImageUnits << "\n" - << "MaxGeometryOutputVertices " << DefaultTBuiltInResource.maxGeometryOutputVertices << "\n" - << "MaxGeometryTotalOutputComponents " << DefaultTBuiltInResource.maxGeometryTotalOutputComponents << "\n" - << "MaxGeometryUniformComponents " << DefaultTBuiltInResource.maxGeometryUniformComponents << "\n" - << "MaxGeometryVaryingComponents " << DefaultTBuiltInResource.maxGeometryVaryingComponents << "\n" - << "MaxTessControlInputComponents " << DefaultTBuiltInResource.maxTessControlInputComponents << "\n" - << "MaxTessControlOutputComponents " << DefaultTBuiltInResource.maxTessControlOutputComponents << "\n" - << "MaxTessControlTextureImageUnits " << DefaultTBuiltInResource.maxTessControlTextureImageUnits << "\n" - << "MaxTessControlUniformComponents " << DefaultTBuiltInResource.maxTessControlUniformComponents << "\n" - << "MaxTessControlTotalOutputComponents " << DefaultTBuiltInResource.maxTessControlTotalOutputComponents << "\n" - << "MaxTessEvaluationInputComponents " << DefaultTBuiltInResource.maxTessEvaluationInputComponents << "\n" - << "MaxTessEvaluationOutputComponents " << DefaultTBuiltInResource.maxTessEvaluationOutputComponents << "\n" - << "MaxTessEvaluationTextureImageUnits " << DefaultTBuiltInResource.maxTessEvaluationTextureImageUnits << "\n" - << "MaxTessEvaluationUniformComponents " << DefaultTBuiltInResource.maxTessEvaluationUniformComponents << "\n" - << "MaxTessPatchComponents " << DefaultTBuiltInResource.maxTessPatchComponents << "\n" - << "MaxPatchVertices " << DefaultTBuiltInResource.maxPatchVertices << "\n" - << "MaxTessGenLevel " << DefaultTBuiltInResource.maxTessGenLevel << "\n" - << "MaxViewports " << DefaultTBuiltInResource.maxViewports << "\n" - << "MaxVertexAtomicCounters " << DefaultTBuiltInResource.maxVertexAtomicCounters << "\n" - << "MaxTessControlAtomicCounters " << DefaultTBuiltInResource.maxTessControlAtomicCounters << "\n" - << "MaxTessEvaluationAtomicCounters " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounters << "\n" - << "MaxGeometryAtomicCounters " << DefaultTBuiltInResource.maxGeometryAtomicCounters << "\n" - << "MaxFragmentAtomicCounters " << DefaultTBuiltInResource.maxFragmentAtomicCounters << "\n" - << "MaxCombinedAtomicCounters " << DefaultTBuiltInResource.maxCombinedAtomicCounters << "\n" - << "MaxAtomicCounterBindings " << DefaultTBuiltInResource.maxAtomicCounterBindings << "\n" - << "MaxVertexAtomicCounterBuffers " << DefaultTBuiltInResource.maxVertexAtomicCounterBuffers << "\n" - << "MaxTessControlAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessControlAtomicCounterBuffers << "\n" - << "MaxTessEvaluationAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounterBuffers << "\n" - << "MaxGeometryAtomicCounterBuffers " << DefaultTBuiltInResource.maxGeometryAtomicCounterBuffers << "\n" - << "MaxFragmentAtomicCounterBuffers " << DefaultTBuiltInResource.maxFragmentAtomicCounterBuffers << "\n" - << "MaxCombinedAtomicCounterBuffers " << DefaultTBuiltInResource.maxCombinedAtomicCounterBuffers << "\n" - << "MaxAtomicCounterBufferSize " << DefaultTBuiltInResource.maxAtomicCounterBufferSize << "\n" - << "MaxTransformFeedbackBuffers " << DefaultTBuiltInResource.maxTransformFeedbackBuffers << "\n" - << "MaxTransformFeedbackInterleavedComponents " << DefaultTBuiltInResource.maxTransformFeedbackInterleavedComponents << "\n" - << "MaxCullDistances " << DefaultTBuiltInResource.maxCullDistances << "\n" - << "MaxCombinedClipAndCullDistances " << DefaultTBuiltInResource.maxCombinedClipAndCullDistances << "\n" - << "MaxSamples " << DefaultTBuiltInResource.maxSamples << "\n" - << "MaxMeshOutputVerticesNV " << DefaultTBuiltInResource.maxMeshOutputVerticesNV << "\n" - << "MaxMeshOutputPrimitivesNV " << DefaultTBuiltInResource.maxMeshOutputPrimitivesNV << "\n" - << "MaxMeshWorkGroupSizeX_NV " << DefaultTBuiltInResource.maxMeshWorkGroupSizeX_NV << "\n" - << "MaxMeshWorkGroupSizeY_NV " << DefaultTBuiltInResource.maxMeshWorkGroupSizeY_NV << "\n" - << "MaxMeshWorkGroupSizeZ_NV " << DefaultTBuiltInResource.maxMeshWorkGroupSizeZ_NV << "\n" - << "MaxTaskWorkGroupSizeX_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeX_NV << "\n" - << "MaxTaskWorkGroupSizeY_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeY_NV << "\n" - << "MaxTaskWorkGroupSizeZ_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeZ_NV << "\n" - << "MaxMeshViewCountNV " << DefaultTBuiltInResource.maxMeshViewCountNV << "\n" - << "MaxMeshOutputVerticesEXT " << DefaultTBuiltInResource.maxMeshOutputVerticesEXT << "\n" - << "MaxMeshOutputPrimitivesEXT " << DefaultTBuiltInResource.maxMeshOutputPrimitivesEXT << "\n" - << "MaxMeshWorkGroupSizeX_EXT " << DefaultTBuiltInResource.maxMeshWorkGroupSizeX_EXT << "\n" - << "MaxMeshWorkGroupSizeY_EXT " << DefaultTBuiltInResource.maxMeshWorkGroupSizeY_EXT << "\n" - << "MaxMeshWorkGroupSizeZ_EXT " << DefaultTBuiltInResource.maxMeshWorkGroupSizeZ_EXT << "\n" - << "MaxTaskWorkGroupSizeX_EXT " << DefaultTBuiltInResource.maxTaskWorkGroupSizeX_EXT << "\n" - << "MaxTaskWorkGroupSizeY_EXT " << DefaultTBuiltInResource.maxTaskWorkGroupSizeY_EXT << "\n" - << "MaxTaskWorkGroupSizeZ_EXT " << DefaultTBuiltInResource.maxTaskWorkGroupSizeZ_EXT << "\n" - << "MaxMeshViewCountEXT " << DefaultTBuiltInResource.maxMeshViewCountEXT << "\n" - << "MaxDualSourceDrawBuffersEXT " << DefaultTBuiltInResource.maxDualSourceDrawBuffersEXT << "\n" - << "nonInductiveForLoops " << DefaultTBuiltInResource.limits.nonInductiveForLoops << "\n" - << "whileLoops " << DefaultTBuiltInResource.limits.whileLoops << "\n" - << "doWhileLoops " << DefaultTBuiltInResource.limits.doWhileLoops << "\n" - << "generalUniformIndexing " << DefaultTBuiltInResource.limits.generalUniformIndexing << "\n" - << "generalAttributeMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalAttributeMatrixVectorIndexing << "\n" - << "generalVaryingIndexing " << DefaultTBuiltInResource.limits.generalVaryingIndexing << "\n" - << "generalSamplerIndexing " << DefaultTBuiltInResource.limits.generalSamplerIndexing << "\n" - << "generalVariableIndexing " << DefaultTBuiltInResource.limits.generalVariableIndexing << "\n" - << "generalConstantMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalConstantMatrixVectorIndexing << "\n" - ; - - return ostream.str(); -} - -void DecodeResourceLimits(TBuiltInResource* resources, char* config) -{ - static const char* delims = " \t\n\r"; - - size_t pos = 0; - std::string configStr(config); - - while ((pos = configStr.find_first_not_of(delims, pos)) != std::string::npos) { - const size_t token_s = pos; - const size_t token_e = configStr.find_first_of(delims, token_s); - const size_t value_s = configStr.find_first_not_of(delims, token_e); - const size_t value_e = configStr.find_first_of(delims, value_s); - pos = value_e; - - // Faster to use compare(), but prefering readability. - const std::string tokenStr = configStr.substr(token_s, token_e-token_s); - const std::string valueStr = configStr.substr(value_s, value_e-value_s); - - if (value_s == std::string::npos || ! (valueStr[0] == '-' || isdigit(valueStr[0]))) { - printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n", - valueStr.c_str()); - return; - } - - const int value = std::atoi(valueStr.c_str()); - - if (tokenStr == "MaxLights") - resources->maxLights = value; - else if (tokenStr == "MaxClipPlanes") - resources->maxClipPlanes = value; - else if (tokenStr == "MaxTextureUnits") - resources->maxTextureUnits = value; - else if (tokenStr == "MaxTextureCoords") - resources->maxTextureCoords = value; - else if (tokenStr == "MaxVertexAttribs") - resources->maxVertexAttribs = value; - else if (tokenStr == "MaxVertexUniformComponents") - resources->maxVertexUniformComponents = value; - else if (tokenStr == "MaxVaryingFloats") - resources->maxVaryingFloats = value; - else if (tokenStr == "MaxVertexTextureImageUnits") - resources->maxVertexTextureImageUnits = value; - else if (tokenStr == "MaxCombinedTextureImageUnits") - resources->maxCombinedTextureImageUnits = value; - else if (tokenStr == "MaxTextureImageUnits") - resources->maxTextureImageUnits = value; - else if (tokenStr == "MaxFragmentUniformComponents") - resources->maxFragmentUniformComponents = value; - else if (tokenStr == "MaxDrawBuffers") - resources->maxDrawBuffers = value; - else if (tokenStr == "MaxVertexUniformVectors") - resources->maxVertexUniformVectors = value; - else if (tokenStr == "MaxVaryingVectors") - resources->maxVaryingVectors = value; - else if (tokenStr == "MaxFragmentUniformVectors") - resources->maxFragmentUniformVectors = value; - else if (tokenStr == "MaxVertexOutputVectors") - resources->maxVertexOutputVectors = value; - else if (tokenStr == "MaxFragmentInputVectors") - resources->maxFragmentInputVectors = value; - else if (tokenStr == "MinProgramTexelOffset") - resources->minProgramTexelOffset = value; - else if (tokenStr == "MaxProgramTexelOffset") - resources->maxProgramTexelOffset = value; - else if (tokenStr == "MaxClipDistances") - resources->maxClipDistances = value; - else if (tokenStr == "MaxComputeWorkGroupCountX") - resources->maxComputeWorkGroupCountX = value; - else if (tokenStr == "MaxComputeWorkGroupCountY") - resources->maxComputeWorkGroupCountY = value; - else if (tokenStr == "MaxComputeWorkGroupCountZ") - resources->maxComputeWorkGroupCountZ = value; - else if (tokenStr == "MaxComputeWorkGroupSizeX") - resources->maxComputeWorkGroupSizeX = value; - else if (tokenStr == "MaxComputeWorkGroupSizeY") - resources->maxComputeWorkGroupSizeY = value; - else if (tokenStr == "MaxComputeWorkGroupSizeZ") - resources->maxComputeWorkGroupSizeZ = value; - else if (tokenStr == "MaxComputeUniformComponents") - resources->maxComputeUniformComponents = value; - else if (tokenStr == "MaxComputeTextureImageUnits") - resources->maxComputeTextureImageUnits = value; - else if (tokenStr == "MaxComputeImageUniforms") - resources->maxComputeImageUniforms = value; - else if (tokenStr == "MaxComputeAtomicCounters") - resources->maxComputeAtomicCounters = value; - else if (tokenStr == "MaxComputeAtomicCounterBuffers") - resources->maxComputeAtomicCounterBuffers = value; - else if (tokenStr == "MaxVaryingComponents") - resources->maxVaryingComponents = value; - else if (tokenStr == "MaxVertexOutputComponents") - resources->maxVertexOutputComponents = value; - else if (tokenStr == "MaxGeometryInputComponents") - resources->maxGeometryInputComponents = value; - else if (tokenStr == "MaxGeometryOutputComponents") - resources->maxGeometryOutputComponents = value; - else if (tokenStr == "MaxFragmentInputComponents") - resources->maxFragmentInputComponents = value; - else if (tokenStr == "MaxImageUnits") - resources->maxImageUnits = value; - else if (tokenStr == "MaxCombinedImageUnitsAndFragmentOutputs") - resources->maxCombinedImageUnitsAndFragmentOutputs = value; - else if (tokenStr == "MaxCombinedShaderOutputResources") - resources->maxCombinedShaderOutputResources = value; - else if (tokenStr == "MaxImageSamples") - resources->maxImageSamples = value; - else if (tokenStr == "MaxVertexImageUniforms") - resources->maxVertexImageUniforms = value; - else if (tokenStr == "MaxTessControlImageUniforms") - resources->maxTessControlImageUniforms = value; - else if (tokenStr == "MaxTessEvaluationImageUniforms") - resources->maxTessEvaluationImageUniforms = value; - else if (tokenStr == "MaxGeometryImageUniforms") - resources->maxGeometryImageUniforms = value; - else if (tokenStr == "MaxFragmentImageUniforms") - resources->maxFragmentImageUniforms = value; - else if (tokenStr == "MaxCombinedImageUniforms") - resources->maxCombinedImageUniforms = value; - else if (tokenStr == "MaxGeometryTextureImageUnits") - resources->maxGeometryTextureImageUnits = value; - else if (tokenStr == "MaxGeometryOutputVertices") - resources->maxGeometryOutputVertices = value; - else if (tokenStr == "MaxGeometryTotalOutputComponents") - resources->maxGeometryTotalOutputComponents = value; - else if (tokenStr == "MaxGeometryUniformComponents") - resources->maxGeometryUniformComponents = value; - else if (tokenStr == "MaxGeometryVaryingComponents") - resources->maxGeometryVaryingComponents = value; - else if (tokenStr == "MaxTessControlInputComponents") - resources->maxTessControlInputComponents = value; - else if (tokenStr == "MaxTessControlOutputComponents") - resources->maxTessControlOutputComponents = value; - else if (tokenStr == "MaxTessControlTextureImageUnits") - resources->maxTessControlTextureImageUnits = value; - else if (tokenStr == "MaxTessControlUniformComponents") - resources->maxTessControlUniformComponents = value; - else if (tokenStr == "MaxTessControlTotalOutputComponents") - resources->maxTessControlTotalOutputComponents = value; - else if (tokenStr == "MaxTessEvaluationInputComponents") - resources->maxTessEvaluationInputComponents = value; - else if (tokenStr == "MaxTessEvaluationOutputComponents") - resources->maxTessEvaluationOutputComponents = value; - else if (tokenStr == "MaxTessEvaluationTextureImageUnits") - resources->maxTessEvaluationTextureImageUnits = value; - else if (tokenStr == "MaxTessEvaluationUniformComponents") - resources->maxTessEvaluationUniformComponents = value; - else if (tokenStr == "MaxTessPatchComponents") - resources->maxTessPatchComponents = value; - else if (tokenStr == "MaxPatchVertices") - resources->maxPatchVertices = value; - else if (tokenStr == "MaxTessGenLevel") - resources->maxTessGenLevel = value; - else if (tokenStr == "MaxViewports") - resources->maxViewports = value; - else if (tokenStr == "MaxVertexAtomicCounters") - resources->maxVertexAtomicCounters = value; - else if (tokenStr == "MaxTessControlAtomicCounters") - resources->maxTessControlAtomicCounters = value; - else if (tokenStr == "MaxTessEvaluationAtomicCounters") - resources->maxTessEvaluationAtomicCounters = value; - else if (tokenStr == "MaxGeometryAtomicCounters") - resources->maxGeometryAtomicCounters = value; - else if (tokenStr == "MaxFragmentAtomicCounters") - resources->maxFragmentAtomicCounters = value; - else if (tokenStr == "MaxCombinedAtomicCounters") - resources->maxCombinedAtomicCounters = value; - else if (tokenStr == "MaxAtomicCounterBindings") - resources->maxAtomicCounterBindings = value; - else if (tokenStr == "MaxVertexAtomicCounterBuffers") - resources->maxVertexAtomicCounterBuffers = value; - else if (tokenStr == "MaxTessControlAtomicCounterBuffers") - resources->maxTessControlAtomicCounterBuffers = value; - else if (tokenStr == "MaxTessEvaluationAtomicCounterBuffers") - resources->maxTessEvaluationAtomicCounterBuffers = value; - else if (tokenStr == "MaxGeometryAtomicCounterBuffers") - resources->maxGeometryAtomicCounterBuffers = value; - else if (tokenStr == "MaxFragmentAtomicCounterBuffers") - resources->maxFragmentAtomicCounterBuffers = value; - else if (tokenStr == "MaxCombinedAtomicCounterBuffers") - resources->maxCombinedAtomicCounterBuffers = value; - else if (tokenStr == "MaxAtomicCounterBufferSize") - resources->maxAtomicCounterBufferSize = value; - else if (tokenStr == "MaxTransformFeedbackBuffers") - resources->maxTransformFeedbackBuffers = value; - else if (tokenStr == "MaxTransformFeedbackInterleavedComponents") - resources->maxTransformFeedbackInterleavedComponents = value; - else if (tokenStr == "MaxCullDistances") - resources->maxCullDistances = value; - else if (tokenStr == "MaxCombinedClipAndCullDistances") - resources->maxCombinedClipAndCullDistances = value; - else if (tokenStr == "MaxSamples") - resources->maxSamples = value; - else if (tokenStr == "MaxMeshOutputVerticesNV") - resources->maxMeshOutputVerticesNV = value; - else if (tokenStr == "MaxMeshOutputPrimitivesNV") - resources->maxMeshOutputPrimitivesNV = value; - else if (tokenStr == "MaxMeshWorkGroupSizeX_NV") - resources->maxMeshWorkGroupSizeX_NV = value; - else if (tokenStr == "MaxMeshWorkGroupSizeY_NV") - resources->maxMeshWorkGroupSizeY_NV = value; - else if (tokenStr == "MaxMeshWorkGroupSizeZ_NV") - resources->maxMeshWorkGroupSizeZ_NV = value; - else if (tokenStr == "MaxTaskWorkGroupSizeX_NV") - resources->maxTaskWorkGroupSizeX_NV = value; - else if (tokenStr == "MaxTaskWorkGroupSizeY_NV") - resources->maxTaskWorkGroupSizeY_NV = value; - else if (tokenStr == "MaxTaskWorkGroupSizeZ_NV") - resources->maxTaskWorkGroupSizeZ_NV = value; - else if (tokenStr == "MaxMeshViewCountNV") - resources->maxMeshViewCountNV = value; - else if (tokenStr == "MaxMeshOutputVerticesEXT") - resources->maxMeshOutputVerticesEXT = value; - else if (tokenStr == "MaxMeshOutputPrimitivesEXT") - resources->maxMeshOutputPrimitivesEXT = value; - else if (tokenStr == "MaxMeshWorkGroupSizeX_EXT") - resources->maxMeshWorkGroupSizeX_EXT = value; - else if (tokenStr == "MaxMeshWorkGroupSizeY_EXT") - resources->maxMeshWorkGroupSizeY_EXT = value; - else if (tokenStr == "MaxMeshWorkGroupSizeZ_EXT") - resources->maxMeshWorkGroupSizeZ_EXT = value; - else if (tokenStr == "MaxTaskWorkGroupSizeX_EXT") - resources->maxTaskWorkGroupSizeX_EXT = value; - else if (tokenStr == "MaxTaskWorkGroupSizeY_EXT") - resources->maxTaskWorkGroupSizeY_EXT = value; - else if (tokenStr == "MaxTaskWorkGroupSizeZ_EXT") - resources->maxTaskWorkGroupSizeZ_EXT = value; - else if (tokenStr == "MaxMeshViewCountEXT") - resources->maxMeshViewCountEXT = value; - else if (tokenStr == "MaxDualSourceDrawBuffersEXT") - resources->maxDualSourceDrawBuffersEXT = value; - else if (tokenStr == "nonInductiveForLoops") - resources->limits.nonInductiveForLoops = (value != 0); - else if (tokenStr == "whileLoops") - resources->limits.whileLoops = (value != 0); - else if (tokenStr == "doWhileLoops") - resources->limits.doWhileLoops = (value != 0); - else if (tokenStr == "generalUniformIndexing") - resources->limits.generalUniformIndexing = (value != 0); - else if (tokenStr == "generalAttributeMatrixVectorIndexing") - resources->limits.generalAttributeMatrixVectorIndexing = (value != 0); - else if (tokenStr == "generalVaryingIndexing") - resources->limits.generalVaryingIndexing = (value != 0); - else if (tokenStr == "generalSamplerIndexing") - resources->limits.generalSamplerIndexing = (value != 0); - else if (tokenStr == "generalVariableIndexing") - resources->limits.generalVariableIndexing = (value != 0); - else if (tokenStr == "generalConstantMatrixVectorIndexing") - resources->limits.generalConstantMatrixVectorIndexing = (value != 0); - else - printf("Warning: unrecognized limit (%s) in configuration file.\n", tokenStr.c_str()); - - } -} - -TBuiltInResource* GetResources() -{ - return &Resources; -} - -const TBuiltInResource* GetDefaultResources() -{ - return &DefaultTBuiltInResource; -} diff --git a/3rdparty/glslang/glslang/ResourceLimits/resource_limits_c.cpp b/3rdparty/glslang/glslang/ResourceLimits/resource_limits_c.cpp deleted file mode 100644 index 8909d9ef..00000000 --- a/3rdparty/glslang/glslang/ResourceLimits/resource_limits_c.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/** -BSD 2-Clause License - -Copyright (c) 2020, Travis Fort -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**/ - -#include "glslang/Public/resource_limits_c.h" -#include "glslang/Public/ResourceLimits.h" -#include -#include -#include - -glslang_resource_t* glslang_resource(void) -{ - return reinterpret_cast(GetResources()); -} - -const glslang_resource_t* glslang_default_resource(void) -{ - return reinterpret_cast(GetDefaultResources()); -} - -const char* glslang_default_resource_string() -{ - std::string cpp_str = GetDefaultTBuiltInResourceString(); - char* c_str = (char*)malloc(cpp_str.length() + 1); - strncpy(c_str, cpp_str.c_str(), cpp_str.length() + 1); - return c_str; -} - -void glslang_decode_resource_limits(glslang_resource_t* resources, char* config) -{ - DecodeResourceLimits(reinterpret_cast(resources), config); -} diff --git a/3rdparty/glslang/glslang/updateGrammar b/3rdparty/glslang/glslang/updateGrammar deleted file mode 100644 index a15dc24b..00000000 --- a/3rdparty/glslang/glslang/updateGrammar +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -# Copyright (C) 2020 The Khronos Group Inc. -# -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# -# Neither the name of The Khronos Group Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -bison --defines=MachineIndependent/glslang_tab.cpp.h -t MachineIndependent/glslang.y -o MachineIndependent/glslang_tab.cpp diff --git a/3rdparty/glslang/parse_version.cmake b/3rdparty/glslang/parse_version.cmake deleted file mode 100644 index b9ba4137..00000000 --- a/3rdparty/glslang/parse_version.cmake +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (C) 2020 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 -# -# https://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. - -# parse_version() reads and parses the version string from FILE, assigning the -# version string to ${PROJECT}_VERSION and the parsed version to -# ${PROJECT}_VERSION_MAJOR, ${PROJECT}_VERSION_MINOR, ${PROJECT}_VERSION_PATCH, -# and the optional ${PROJECT}_VERSION_FLAVOR. -# -# The version string take one of the forms: -# .. -# ..- -function(parse_version FILE PROJECT) - configure_file(${FILE} "${CMAKE_CURRENT_BINARY_DIR}/CHANGES.md") # Required to re-run cmake on version change - file(READ ${FILE} CHANGES) - if(${CHANGES} MATCHES "#+ *([0-9]+)\\.([0-9]+)\\.([0-9]+)(-[a-zA-Z0-9]+)?") - set(FLAVOR "") - if(NOT "${CMAKE_MATCH_4}" STREQUAL "") - string(SUBSTRING ${CMAKE_MATCH_4} 1 -1 FLAVOR) - endif() - set("${PROJECT}_VERSION_MAJOR" ${CMAKE_MATCH_1} PARENT_SCOPE) - set("${PROJECT}_VERSION_MINOR" ${CMAKE_MATCH_2} PARENT_SCOPE) - set("${PROJECT}_VERSION_PATCH" ${CMAKE_MATCH_3} PARENT_SCOPE) - set("${PROJECT}_VERSION_FLAVOR" ${FLAVOR} PARENT_SCOPE) - set("${PROJECT}_VERSION" - "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}${CMAKE_MATCH_4}" - PARENT_SCOPE) - else() - message(FATAL_ERROR "Unable to parse version from '${FILE}'") - endif() -endfunction() diff --git a/3rdparty/glslang/update_glslang_sources.py b/3rdparty/glslang/update_glslang_sources.py deleted file mode 100644 index 2e02c96e..00000000 --- a/3rdparty/glslang/update_glslang_sources.py +++ /dev/null @@ -1,152 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2017 The Glslang Authors. All rights reserved. -# -# 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. - -"""Get source files for Glslang and its dependencies from public repositories. -""" - -import argparse -import json -import os -import subprocess -import sys - -KNOWN_GOOD_FILE = 'known_good.json' - -SITE_TO_KNOWN_GOOD_FILE = { 'github' : 'known_good.json', - 'gitlab' : 'known_good_khr.json' } - -# Maps a site name to its hostname. -SITE_TO_HOST = { 'github' : 'https://github.com/', - 'gitlab' : 'git@gitlab.khronos.org:' } - -VERBOSE = True - - -def command_output(cmd, directory, fail_ok=False): - """Runs a command in a directory and returns its standard output stream. - - Captures the standard error stream. - - Raises a RuntimeError if the command fails to launch or otherwise fails. - """ - if VERBOSE: - print('In {d}: {cmd}'.format(d=directory, cmd=cmd)) - p = subprocess.Popen(cmd, - cwd=directory, - stdout=subprocess.PIPE) - (stdout, _) = p.communicate() - if p.returncode != 0 and not fail_ok: - raise RuntimeError('Failed to run {} in {}'.format(cmd, directory)) - if VERBOSE: - print(stdout) - return stdout - - -def command_retval(cmd, directory): - """Runs a command in a directory and returns its return value. - - Captures the standard error stream. - """ - p = subprocess.Popen(cmd, - cwd=directory, - stdout=subprocess.PIPE) - p.communicate() - return p.returncode - - -class GoodCommit(object): - """Represents a good commit for a repository.""" - - def __init__(self, json): - """Initializes this good commit object. - - Args: - 'json': A fully populated JSON object describing the commit. - """ - self._json = json - self.name = json['name'] - self.site = json['site'] - self.subrepo = json['subrepo'] - self.subdir = json['subdir'] if ('subdir' in json) else '.' - self.commit = json['commit'] - - def GetUrl(self): - """Returns the URL for the repository.""" - host = SITE_TO_HOST[self.site] - return '{host}{subrepo}'.format( - host=host, - subrepo=self.subrepo) - - def AddRemote(self): - """Add the remote 'known-good' if it does not exist.""" - remotes = command_output(['git', 'remote'], self.subdir).splitlines() - if b'known-good' not in remotes: - command_output(['git', 'remote', 'add', 'known-good', self.GetUrl()], self.subdir) - - def HasCommit(self): - """Check if the repository contains the known-good commit.""" - return 0 == subprocess.call(['git', 'rev-parse', '--verify', '--quiet', - self.commit + "^{commit}"], - cwd=self.subdir) - - def Clone(self): - os.makedirs(self.subdir, exist_ok=True) - command_output(['git', 'clone', self.GetUrl(), '.'], self.subdir) - - def Fetch(self): - command_output(['git', 'fetch', 'known-good'], self.subdir) - - def Checkout(self): - if not os.path.exists(os.path.join(self.subdir,'.git')): - self.Clone() - self.AddRemote() - if not self.HasCommit(): - self.Fetch() - command_output(['git', 'checkout', self.commit], self.subdir) - - -def GetGoodCommits(site): - """Returns the latest list of GoodCommit objects.""" - known_good_file = SITE_TO_KNOWN_GOOD_FILE[site] - with open(known_good_file) as known_good: - return [GoodCommit(c) for c in json.loads(known_good.read())['commits']] - - -def main(): - parser = argparse.ArgumentParser(description='Get Glslang source dependencies at a known-good commit') - parser.add_argument('--dir', dest='dir', default='.', - help="Set target directory for Glslang source root. Default is \'.\'.") - parser.add_argument('--site', dest='site', default='github', - help="Set git server site. Default is github.") - - args = parser.parse_args() - - commits = GetGoodCommits(args.site) - - os.makedirs(args.dir, exist_ok=True) - print('Change directory to {d}'.format(d=args.dir)) - os.chdir(args.dir) - - # Create the subdirectories in sorted order so that parent git repositories - # are created first. - for c in sorted(commits, key=lambda x: x.subdir): - print('Get {n}\n'.format(n=c.name)) - c.Checkout() - sys.exit(0) - - -if __name__ == '__main__': - main() diff --git a/CMakeLists.txt b/CMakeLists.txt index 89fb6205..4d1ebc4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,7 +67,8 @@ set(ENABLE_CTEST FALSE CACHE BOOL "" FORCE) set(SPIRV_CROSS_ENABLE_TESTS OFF CACHE BOOL "" FORCE) # halx99: optimize require https://github.com/KhronosGroup/SPIRV-Tools? -set(ALLOW_EXTERNAL_SPIRV_TOOLS ON CACHE BOOL "" FORCE) +set(ALLOW_EXTERNAL_SPIRV_TOOLS OFF CACHE BOOL "" FORCE) +find_program(PWSH_COMMAND NAMES pwsh powershell NO_PACKAGE_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH NO_CMAKE_FIND_ROOT_PATH REQUIRED) add_subdirectory(3rdparty/glslang) add_subdirectory(3rdparty/spirv-cross) add_subdirectory(3rdparty/sx) diff --git a/src/glslcc.cpp b/src/glslcc.cpp index a1fd8711..048ed189 100644 --- a/src/glslcc.cpp +++ b/src/glslcc.cpp @@ -106,7 +106,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 9 -#define VERSION_SUB 3 +#define VERSION_SUB 4 static const sx_alloc* g_alloc = sx_alloc_malloc(); static sgs_file* g_sgs = nullptr;