Externals: Update glslang.

This updates glslang to commit 9bb8cfffb0eed010e07132282c41d73064a7a609
which is the current version listed in the known_good.json file for the
version 1.3.212 of the Vulkan-ValidationLayers repo.
This commit is contained in:
iwubcode 2022-04-30 00:37:59 -05:00
parent 260d3faba8
commit 6d528a72eb
142 changed files with 26417 additions and 10676 deletions

View File

@ -4,7 +4,7 @@
# build version format # build version format
version: "{build}" version: "{build}"
os: Visual Studio 2013 os: Visual Studio 2015
platform: platform:
- x64 - x64
@ -17,6 +17,20 @@ branches:
only: only:
- master - master
# changes to these files don't need to trigger testing
skip_commits:
files:
- README.md
- README-spirv-remap.txt
- LICENSE.txt
- CODE_OF_CONDUCT.md
- BUILD.*
- WORKSPACE
- kokoro/*
- make-revision
- Android.mk
- _config.yml
# Travis advances the master-tot tag to current top of the tree after # Travis advances the master-tot tag to current top of the tree after
# each push into the master branch, because it relies on that tag to # each push into the master branch, because it relies on that tag to
# upload build artifacts to the master-tot release. This will cause # upload build artifacts to the master-tot release. This will cause
@ -31,8 +45,9 @@ matrix:
# scripts that run after cloning repository # scripts that run after cloning repository
install: install:
- git clone https://github.com/google/googletest.git External/googletest
- C:/Python27/python.exe update_glslang_sources.py - C:/Python27/python.exe update_glslang_sources.py
- set PATH=C:\ninja;C:\Python36;%PATH%
- git clone https://github.com/google/googletest.git External/googletest
build: build:
parallel: true # enable MSBuild parallel builds parallel: true # enable MSBuild parallel builds
@ -40,7 +55,7 @@ build:
build_script: build_script:
- mkdir build && cd build - mkdir build && cd build
- cmake .. -DCMAKE_INSTALL_PREFIX=install - cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_INSTALL_PREFIX=install ..
- cmake --build . --config %CONFIGURATION% --target install - cmake --build . --config %CONFIGURATION% --target install
test_script: test_script:
@ -60,10 +75,13 @@ after_test:
# Zip all glslang artifacts for uploading and deploying # Zip all glslang artifacts for uploading and deploying
- 7z a glslang-master-windows-"%PLATFORM%"-"%CONFIGURATION%".zip - 7z a glslang-master-windows-"%PLATFORM%"-"%CONFIGURATION%".zip
bin\glslangValidator.exe bin\glslangValidator.exe
bin\spirv-remap.exe
include\glslang\* include\glslang\*
include\SPIRV\* lib\GenericCodeGen%SUFFIX%.lib
lib\glslang%SUFFIX%.lib lib\glslang%SUFFIX%.lib
lib\glslang-default-resource-limits%SUFFIX%.lib
lib\HLSL%SUFFIX%.lib lib\HLSL%SUFFIX%.lib
lib\MachineIndependent%SUFFIX%.lib
lib\OGLCompiler%SUFFIX%.lib lib\OGLCompiler%SUFFIX%.lib
lib\OSDependent%SUFFIX%.lib lib\OSDependent%SUFFIX%.lib
lib\SPIRV%SUFFIX%.lib lib\SPIRV%SUFFIX%.lib
@ -87,4 +105,4 @@ deploy:
force_update: true force_update: true
on: on:
branch: master branch: master
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015

View File

@ -1,7 +1,8 @@
Language: Cpp Language: Cpp
IndentWidth: 4 IndentWidth: 4
PointerAlignment: Left
BreakBeforeBraces: Custom BreakBeforeBraces: Custom
BraceWrapping: { AfterFunction: true, AfterControlStatement: true } BraceWrapping: { AfterFunction: true, AfterControlStatement: false }
IndentCaseLabels: false IndentCaseLabels: false
ReflowComments: false ReflowComments: false
ColumnLimit: 120 ColumnLimit: 120

View File

@ -8,10 +8,10 @@
*.txt text *.txt text
# source code can be native and normalized, but simpler if lf everywhere; will try that way # source code can be native and normalized, but simpler if lf everywhere; will try that way
*.h text eof=lf *.h text eol=lf
*.c text eof=lf *.c text eol=lf
*.cpp text eof=lf *.cpp text eol=lf
*.y text eof=lf *.y text eol=lf
*.out text eof=lf *.out text eol=lf
*.conf text eof=lf *.conf text eol=lf
*.err text eof=lf *.err text eol=lf

View File

@ -2,9 +2,19 @@
*.a *.a
*.so *.so
*.exe *.exe
.vscode/
tags tags
TAGS TAGS
bazel-*
build/ build/
Test/localResults/ Test/localResults/
External/googletest External/googletest
External/spirv-tools External/spirv-tools
out/
# GN generated files
.cipd/
*.gclient_entries
third_party/
buildtools/
tools/

View File

@ -48,25 +48,41 @@ install:
- if [[ "$TRAVIS_OS_NAME" == "linux" && "$CC" == "clang" ]]; then - if [[ "$TRAVIS_OS_NAME" == "linux" && "$CC" == "clang" ]]; then
export CC=clang-3.6 CXX=clang++-3.6; export CC=clang-3.6 CXX=clang++-3.6;
fi fi
# Download Android NDK and Android CMake toolchain file. # Download a recent Android NDK and use its android.toolchain.cmake file.
- if [[ "$BUILD_NDK" == "ON" ]]; then - if [[ "$BUILD_NDK" == "ON" ]]; then
git clone --depth=1 https://github.com/urho3d/android-ndk.git $HOME/android-ndk;
export ANDROID_NDK=$HOME/android-ndk; export ANDROID_NDK=$HOME/android-ndk;
git clone --depth=1 https://github.com/taka-no-me/android-cmake.git $HOME/android-cmake; git init $ANDROID_NDK;
export TOOLCHAIN_PATH=$HOME/android-cmake/android.toolchain.cmake; pushd $ANDROID_NDK;
git remote add dneto0 https://github.com/dneto0/android-ndk.git;
git fetch --depth=1 dneto0 r17b-strip;
git checkout FETCH_HEAD;
popd;
export TOOLCHAIN_PATH=$ANDROID_NDK/build/cmake/android.toolchain.cmake;
fi fi
before_script: before_script:
- git clone --depth=1 https://github.com/google/googletest.git External/googletest # check out pre-breakage version of googletest; can be deleted when
# issue 3128 is fixed
# git clone --depth=1 https://github.com/google/googletest.git External/googletest
- mkdir -p External/googletest
- cd External/googletest
- git init
- git remote add origin https://github.com/google/googletest.git
- git fetch --depth 1 origin 0c400f67fcf305869c5fb113dd296eca266c9725
- git reset --hard FETCH_HEAD
- cd ../..
# get spirv-tools and spirv-headers
- ./update_glslang_sources.py - ./update_glslang_sources.py
script: script:
- mkdir build && cd build - mkdir build && cd build
# For Android, do release building using NDK without testing. # For Android, do release building using NDK without testing.
# Use android-14, the oldest native API level supporeted by NDK r17b.
# We can use newer API levels if we want.
# For Linux and macOS, do debug/release building with testing. # For Linux and macOS, do debug/release building with testing.
- if [[ "$BUILD_NDK" == "ON" ]]; then - if [[ "$BUILD_NDK" == "ON" ]]; then
cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_PATH} cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_PATH}
-DANDROID_NATIVE_API_LEVEL=android-12 -DANDROID_NATIVE_API_LEVEL=android-14
-DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_TYPE=Release
-DANDROID_ABI="armeabi-v7a with NEON" -DANDROID_ABI="armeabi-v7a with NEON"
-DBUILD_TESTING=OFF ..; -DBUILD_TESTING=OFF ..;
@ -93,9 +109,11 @@ after_success:
zip ${TARBALL} zip ${TARBALL}
bin/glslangValidator bin/glslangValidator
include/glslang/* include/glslang/*
include/SPIRV/* lib/libGenericCodeGen${SUFFIX}.a
lib/libglslang${SUFFIX}.a lib/libglslang${SUFFIX}.a
lib/libglslang-default-resource-limits${SUFFIX}.a
lib/libHLSL${SUFFIX}.a lib/libHLSL${SUFFIX}.a
lib/libMachineIndependent${SUFFIX}.a
lib/libOGLCompiler${SUFFIX}.a lib/libOGLCompiler${SUFFIX}.a
lib/libOSDependent${SUFFIX}.a lib/libOSDependent${SUFFIX}.a
lib/libSPIRV${SUFFIX}.a lib/libSPIRV${SUFFIX}.a

View File

@ -1,6 +1,13 @@
set(SRCS set(SRCS
glslang/GenericCodeGen/CodeGen.cpp glslang/GenericCodeGen/CodeGen.cpp
glslang/GenericCodeGen/Link.cpp glslang/GenericCodeGen/Link.cpp
#glslang/HLSL/hlslAttributes.cpp
#glslang/HLSL/hlslGrammar.cpp
#glslang/HLSL/hlslOpMap.cpp
#glslang/HLSL/hlslParseables.cpp
#glslang/HLSL/hlslParseHelper.cpp
#glslang/HLSL/hlslScanContext.cpp
#glslang/HLSL/hlslTokenStream.cpp
glslang/MachineIndependent/attribute.cpp glslang/MachineIndependent/attribute.cpp
glslang/MachineIndependent/Constant.cpp glslang/MachineIndependent/Constant.cpp
glslang/MachineIndependent/glslang_tab.cpp glslang/MachineIndependent/glslang_tab.cpp
@ -26,6 +33,7 @@ set(SRCS
glslang/MachineIndependent/RemoveTree.cpp glslang/MachineIndependent/RemoveTree.cpp
glslang/MachineIndependent/Scan.cpp glslang/MachineIndependent/Scan.cpp
glslang/MachineIndependent/ShaderLang.cpp glslang/MachineIndependent/ShaderLang.cpp
glslang/MachineIndependent/SpirvIntrinsics.cpp
glslang/MachineIndependent/SymbolTable.cpp glslang/MachineIndependent/SymbolTable.cpp
glslang/MachineIndependent/Versions.cpp glslang/MachineIndependent/Versions.cpp
OGLCompilersDLL/InitializeDll.cpp OGLCompilersDLL/InitializeDll.cpp
@ -37,6 +45,7 @@ set(SRCS
SPIRV/SpvBuilder.cpp SPIRV/SpvBuilder.cpp
SPIRV/SpvPostProcess.cpp SPIRV/SpvPostProcess.cpp
SPIRV/SPVRemapper.cpp SPIRV/SPVRemapper.cpp
SPIRV/SpvTools.cpp
StandAlone/ResourceLimits.cpp StandAlone/ResourceLimits.cpp
) )

View File

@ -1,9 +1,48 @@
# 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.
# increase to 3.1 once all major distributions # increase to 3.1 once all major distributions
# include a version of CMake >= 3.1 # include a version of CMake >= 3.1
cmake_minimum_required(VERSION 2.8.12) cmake_minimum_required(VERSION 2.8.12)
if (POLICY CMP0048) if (POLICY CMP0048)
cmake_policy(SET CMP0048 NEW) cmake_policy(SET CMP0048 NEW)
endif() endif()
if(POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()
project(glslang LANGUAGES CXX)
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# Enable compile commands database # Enable compile commands database
@ -24,6 +63,14 @@ if(BUILD_SHARED_LIBS)
set(LIB_TYPE SHARED) set(LIB_TYPE SHARED)
endif() 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()
option(SKIP_GLSLANG_INSTALL "Skip installation" ${SKIP_GLSLANG_INSTALL}) option(SKIP_GLSLANG_INSTALL "Skip installation" ${SKIP_GLSLANG_INSTALL})
if(NOT ${SKIP_GLSLANG_INSTALL}) if(NOT ${SKIP_GLSLANG_INSTALL})
set(ENABLE_GLSLANG_INSTALL ON) set(ENABLE_GLSLANG_INSTALL ON)
@ -32,13 +79,32 @@ option(ENABLE_SPVREMAPPER "Enables building of SPVRemapper" ON)
option(ENABLE_GLSLANG_BINARIES "Builds glslangValidator and spirv-remap" ON) option(ENABLE_GLSLANG_BINARIES "Builds glslangValidator and spirv-remap" ON)
option(ENABLE_GLSLANG_WEB "Reduces glslang to minimum needed for web use" OFF) option(ENABLE_GLSLANG_JS
option(ENABLE_GLSLANG_WEB_DEVEL "For ENABLE_GLSLANG_WEB builds, enables compilation error messages" OFF) "If using Emscripten, build glslang.js. Otherwise, builds a sample executable for binary-size testing." OFF)
option(ENABLE_EMSCRIPTEN_SINGLE_FILE "If using Emscripten, enables SINGLE_FILE build" OFF) CMAKE_DEPENDENT_OPTION(ENABLE_GLSLANG_WEBMIN
option(ENABLE_EMSCRIPTEN_ENVIRONMENT_NODE "If using Emscripten, builds to run on Node instead of Web" OFF) "Reduces glslang to minimum needed for web use"
OFF "ENABLE_GLSLANG_JS"
OFF)
CMAKE_DEPENDENT_OPTION(ENABLE_GLSLANG_WEBMIN_DEVEL
"For ENABLE_GLSLANG_WEBMIN builds, enables compilation error messages"
OFF "ENABLE_GLSLANG_WEBMIN"
OFF)
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)
CMAKE_DEPENDENT_OPTION(ENABLE_HLSL "Enables HLSL input support" ON "NOT ENABLE_GLSLANG_WEB" OFF) CMAKE_DEPENDENT_OPTION(ENABLE_HLSL
"Enables HLSL input support"
ON "NOT ENABLE_GLSLANG_WEBMIN"
OFF)
option(ENABLE_RTTI "Enables RTTI" OFF)
option(ENABLE_EXCEPTIONS "Enables Exceptions" OFF)
option(ENABLE_OPT "Enables spirv-opt capability if present" ON) option(ENABLE_OPT "Enables spirv-opt capability if present" ON)
option(ENABLE_PCH "Enables Precompiled header" ON) option(ENABLE_PCH "Enables Precompiled header" ON)
option(ENABLE_CTEST "Enables testing" ON) option(ENABLE_CTEST "Enables testing" ON)
@ -55,20 +121,6 @@ if(USE_CCACHE)
endif(CCACHE_FOUND) endif(CCACHE_FOUND)
endif() endif()
# Precompiled header macro. Parameters are source file list and filename for pch cpp file.
macro(glslang_pch SRCS PCHCPP)
if(MSVC AND CMAKE_GENERATOR MATCHES "^Visual Studio" AND ENABLE_PCH)
set(PCH_NAME "$(IntDir)\\pch.pch")
# make source files use/depend on PCH_NAME
set_source_files_properties(${${SRCS}} PROPERTIES COMPILE_FLAGS "/Yupch.h /FIpch.h /Fp${PCH_NAME} /Zm300" OBJECT_DEPENDS "${PCH_NAME}")
# make PCHCPP file compile and generate PCH_NAME
set_source_files_properties(${PCHCPP} PROPERTIES COMPILE_FLAGS "/Ycpch.h /Fp${PCH_NAME} /Zm300" OBJECT_OUTPUTS "${PCH_NAME}")
list(APPEND ${SRCS} "${PCHCPP}")
endif()
endmacro(glslang_pch)
project(glslang)
if(ENABLE_CTEST) if(ENABLE_CTEST)
include(CTest) include(CTest)
endif() endif()
@ -77,16 +129,17 @@ if(ENABLE_HLSL)
add_definitions(-DENABLE_HLSL) add_definitions(-DENABLE_HLSL)
endif(ENABLE_HLSL) endif(ENABLE_HLSL)
if(ENABLE_GLSLANG_WEB) if(ENABLE_GLSLANG_WEBMIN)
add_definitions(-DGLSLANG_WEB) add_definitions(-DGLSLANG_WEB)
if(ENABLE_GLSLANG_WEB_DEVEL) if(ENABLE_GLSLANG_WEBMIN_DEVEL)
add_definitions(-DGLSLANG_WEB_DEVEL) add_definitions(-DGLSLANG_WEB_DEVEL)
endif(ENABLE_GLSLANG_WEB_DEVEL) endif(ENABLE_GLSLANG_WEBMIN_DEVEL)
endif(ENABLE_GLSLANG_WEB) endif(ENABLE_GLSLANG_WEBMIN)
if(WIN32) if(WIN32)
set(CMAKE_DEBUG_POSTFIX "d") set(CMAKE_DEBUG_POSTFIX "d")
if(MSVC) option(OVERRIDE_MSVCCRT "Overrides runtime of MSVC " ON)
if(MSVC AND OVERRIDE_MSVCCRT)
include(ChooseMSVCCRT.cmake) include(ChooseMSVCCRT.cmake)
endif(MSVC) endif(MSVC)
add_definitions(-DGLSLANG_OSINCLUDE_WIN32) add_definitions(-DGLSLANG_OSINCLUDE_WIN32)
@ -100,45 +153,73 @@ if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
add_compile_options(-Wall -Wmaybe-uninitialized -Wuninitialized -Wunused -Wunused-local-typedefs 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) -Wunused-parameter -Wunused-value -Wunused-variable -Wunused-but-set-parameter -Wunused-but-set-variable -fno-exceptions)
add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over. add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over.
add_compile_options(-fno-rtti) if(NOT ENABLE_RTTI)
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") 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_VERSION VERSION_LESS "3.13")
# Error if there's symbols that are not found at link time.
# add_link_options() was added in CMake 3.13 - if using an earlier
# version don't set this - it should be caught by presubmits anyway.
add_link_options("-Wl,--no-undefined")
endif()
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC)
add_compile_options(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs add_compile_options(-Wall -Wuninitialized -Wunused -Wunused-local-typedefs
-Wunused-parameter -Wunused-value -Wunused-variable) -Wunused-parameter -Wunused-value -Wunused-variable)
add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over. add_compile_options(-Wno-reorder) # disable this from -Wall, since it happens all over.
add_compile_options(-fno-rtti) if(NOT ENABLE_RTTI)
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") add_compile_options(-fno-rtti)
add_compile_options(/GR-) # Disable RTTI endif()
if(NOT ENABLE_EXCEPTIONS)
add_compile_options(-fno-exceptions)
endif()
if(NOT CMAKE_VERSION VERSION_LESS "3.13")
# Error if there's symbols that are not found at link time.
# add_link_options() was added in CMake 3.13 - if using an earlier
# version don't set this - it should be caught by presubmits anyway.
add_link_options("-Wl,-undefined,error")
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() endif()
if(EMSCRIPTEN) if(ENABLE_GLSLANG_JS)
add_compile_options(-Os -fno-exceptions) if(MSVC)
add_compile_options("SHELL: -s WASM=1") add_compile_options(/Os /GR-)
add_compile_options("SHELL: -s WASM_OBJECT_FILES=0") else()
add_link_options(-Os) add_compile_options(-Os -fno-rtti -fno-exceptions)
add_link_options("SHELL: -s FILESYSTEM=0") if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" AND NOT MSVC)
add_link_options("SHELL: --llvm-lto 1") add_compile_options(-Wno-unused-parameter)
add_link_options("SHELL: --closure 1") add_compile_options(-Wno-unused-variable -Wno-unused-const-variable)
add_link_options("SHELL: -s ALLOW_MEMORY_GROWTH=1")
if(ENABLE_EMSCRIPTEN_SINGLE_FILE)
add_link_options("SHELL: -s SINGLE_FILE=1")
endif(ENABLE_EMSCRIPTEN_SINGLE_FILE)
else()
if(ENABLE_GLSLANG_WEB)
if(MSVC)
add_compile_options(/Os /GR-)
else()
add_compile_options(-Os -fno-exceptions)
add_link_options(-Os)
endif() endif()
endif(ENABLE_GLSLANG_WEB) endif()
endif(EMSCRIPTEN) endif(ENABLE_GLSLANG_JS)
# Request C++11 # Request C++11
if(${CMAKE_VERSION} VERSION_LESS 3.1) if(${CMAKE_VERSION} VERSION_LESS 3.1)
# CMake versions before 3.1 do not understand CMAKE_CXX_STANDARD # CMake versions before 3.1 do not understand CMAKE_CXX_STANDARD
# remove this block once CMake >=3.1 has fixated in the ecosystem # remove this block once CMake >=3.1 has fixated in the ecosystem
add_compile_options(-std=c++11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
else() else()
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -154,13 +235,76 @@ function(glslang_set_link_args TARGET)
endif() endif()
endfunction(glslang_set_link_args) endfunction(glslang_set_link_args)
# CMake needs to find the right version of python, right from the beginning, if(NOT COMMAND find_host_package)
# otherwise, it will find the wrong version and fail later macro(find_host_package)
if(BUILD_EXTERNAL AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/External) find_package(${ARGN})
find_package(PythonInterp 3 REQUIRED) endmacro()
endif()
# We depend on these for later projects, so they should come first. # Root directory for build-time generated include files
add_subdirectory(External) 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 $<BUILD_INTERFACE:${GLSLANG_GENERATED_INCLUDEDIR}>)
endfunction()
# glslang_only_export_explicit_symbols() makes the symbol visibility hidden by
# default for <target> when building shared libraries, and sets the
# GLSLANG_IS_SHARED_LIBRARY define, and GLSLANG_EXPORTING to 1 when specifically
# building <target>.
function(glslang_only_export_explicit_symbols target)
if(BUILD_SHARED_LIBS)
target_compile_definitions(${target} PUBLIC "GLSLANG_IS_SHARED_LIBRARY=1")
if(WIN32)
target_compile_definitions(${target} PRIVATE "GLSLANG_EXPORTING=1")
else()
target_compile_options(${target} PRIVATE "-fvisibility=hidden")
endif()
endif()
endfunction()
# glslang_pch() adds precompiled header rules to <target> for the pre-compiled
# header file <pch>. As target_precompile_headers() was added in CMake 3.16,
# this is a no-op if called on earlier versions of CMake.
if(NOT CMAKE_VERSION VERSION_LESS "3.16" AND ENABLE_PCH)
function(glslang_pch target pch)
target_precompile_headers(${target} PRIVATE ${pch})
endfunction()
else()
function(glslang_pch target pch)
endfunction()
if(ENABLE_PCH)
message("Your CMake version is ${CMAKE_VERSION}. Update to at least 3.16 to enable precompiled headers to speed up incremental builds")
endif()
endif()
if(BUILD_EXTERNAL AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/External)
find_host_package(PythonInterp 3 REQUIRED)
# We depend on these for later projects, so they should come first.
add_subdirectory(External)
endif() endif()
if(NOT TARGET SPIRV-Tools-opt) if(NOT TARGET SPIRV-Tools-opt)
@ -190,7 +334,7 @@ if(ENABLE_CTEST)
add_subdirectory(gtests) add_subdirectory(gtests)
endif() endif()
if(BUILD_TESTING) if(ENABLE_CTEST AND BUILD_TESTING)
# glslang-testsuite runs a bash script on Windows. # glslang-testsuite runs a bash script on Windows.
# Make sure to use '-o igncr' flag to ignore carriage returns (\r). # Make sure to use '-o igncr' flag to ignore carriage returns (\r).
set(IGNORE_CR_FLAG "") set(IGNORE_CR_FLAG "")
@ -211,4 +355,4 @@ if(BUILD_TESTING)
add_test(NAME glslang-testsuite add_test(NAME glslang-testsuite
COMMAND bash ${IGNORE_CR_FLAG} runtests ${RESULTS_PATH} ${VALIDATOR_PATH} ${REMAP_PATH} COMMAND bash ${IGNORE_CR_FLAG} runtests ${RESULTS_PATH} ${VALIDATOR_PATH} ${REMAP_PATH}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Test/) WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/Test/)
endif(BUILD_TESTING) endif()

View File

@ -1,3 +1,36 @@
# 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.
# The macro choose_msvc_crt() takes a list of possible # The macro choose_msvc_crt() takes a list of possible
# C runtimes to choose from, in the form of compiler flags, # C runtimes to choose from, in the form of compiler flags,
# to present to the user. (MTd for /MTd, etc) # to present to the user. (MTd for /MTd, etc)

View File

@ -1,3 +1,36 @@
# 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. # Suppress all warnings from external projects.
set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS -w) set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS -w)

View File

@ -1,6 +1,6 @@
Here, glslang proper means core GLSL parsing, HLSL parsing, and SPIR-V code Here, glslang proper means core GLSL parsing, HLSL parsing, and SPIR-V code
generation. Glslang proper requires use of two licenses, one that covers generation. Glslang proper requires use of a number of licenses, one that covers
non-preprocessing and an additional one that covers preprocessing. preprocessing and others that covers non-preprocessing.
Bison was removed long ago. You can build glslang from the source grammar, Bison was removed long ago. You can build glslang from the source grammar,
using tools of your choice, without using bison or any bison files. using tools of your choice, without using bison or any bison files.
@ -23,6 +23,10 @@ Other parts, outside of glslang proper, include:
The core of glslang-proper, minus the preprocessor is licenced as follows: The core of glslang-proper, minus the preprocessor is licenced as follows:
--------------------------------------------------------------------------------
3-Clause BSD License
--------------------------------------------------------------------------------
// //
// Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) <various other dates and companies> // Copyright (C) <various other dates and companies>
@ -59,9 +63,887 @@ The core of glslang-proper, minus the preprocessor is licenced as follows:
// POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
// //
--------------------------------------------------------------------------------
2-Clause BSD License
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
The preprocessor has the core license stated above, plus an additional licence: Copyright 2020 The Khronos Group Inc
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.
--------------------------------------------------------------------------------
The MIT License
--------------------------------------------------------------------------------
Copyright 2020 The Khronos Group Inc
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 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 Software.
THE SOFTWARE IS 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 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
APACHE LICENSE, VERSION 2.0
--------------------------------------------------------------------------------
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
--------------------------------------------------------------------------------
GPL 3 with special bison exception
--------------------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
Bison Exception
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.
END OF TERMS AND CONDITIONS
--------------------------------------------------------------------------------
================================================================================
--------------------------------------------------------------------------------
The preprocessor has the core licenses stated above, plus additional licences:
/****************************************************************************\ /****************************************************************************\
Copyright (c) 2002, NVIDIA Corporation. Copyright (c) 2002, NVIDIA Corporation.
@ -106,3 +988,29 @@ NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\****************************************************************************/ \****************************************************************************/
/*
** 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.
*/

View File

@ -1,3 +1,36 @@
# 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 InitializeDll.cpp InitializeDll.h) set(SOURCES InitializeDll.cpp InitializeDll.h)
add_library(OGLCompiler STATIC ${SOURCES}) add_library(OGLCompiler STATIC ${SOURCES})

View File

@ -1,44 +1,77 @@
# News
1. 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.
2. The versioning scheme is being improved, and you might notice some differences. This is currently WIP, but will be coming soon. See, for example, PR #2277.
3. If you get a new **compilation error due to a missing header**, it might be caused by this planned removal:
**SPIRV Folder, 1-May, 2020.** Glslang, when installed through CMake,
will install a `SPIRV` folder into `${CMAKE_INSTALL_INCLUDEDIR}`.
This `SPIRV` folder is being moved to `glslang/SPIRV`.
During the transition the `SPIRV` folder will be installed into both locations.
The old install of `SPIRV/` will be removed as a CMake install target no sooner than May 1, 2020.
See issue #1964.
If people are only using this location to get spirv.hpp, I recommend they get that from [SPIRV-Headers](https://github.com/KhronosGroup/SPIRV-Headers) instead.
[![appveyor status](https://ci.appveyor.com/api/projects/status/q6fi9cb0qnhkla68/branch/master?svg=true)](https://ci.appveyor.com/project/Khronoswebmaster/glslang/branch/master)
![Continuous Deployment](https://github.com/KhronosGroup/glslang/actions/workflows/continuous_deployment.yml/badge.svg)
# 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
`glslangValidator` 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: Also see the Khronos landing page for glslang as a reference front end:
https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/ https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/
The above page includes where to get binaries, and is kept up to date The above page, while not kept up to date, includes additional information regarding glslang as a reference validator.
regarding the feature level of glslang.
glslang # How to Use Glslang
=======
[![Build Status](https://travis-ci.org/KhronosGroup/glslang.svg?branch=master)](https://travis-ci.org/KhronosGroup/glslang) ## Execution of Standalone Wrapper
[![Build status](https://ci.appveyor.com/api/projects/status/q6fi9cb0qnhkla68/branch/master?svg=true)](https://ci.appveyor.com/project/Khronoswebmaster/glslang/branch/master)
An OpenGL and OpenGL ES shader front end and validator.
There are several components:
1. A GLSL/ESSL front-end for reference validation and translation of GLSL/ESSL into an AST.
2. An HLSL front-end for translation of a broad generic HLL into the AST. See [issue 362](https://github.com/KhronosGroup/glslang/issues/362) and [issue 701](https://github.com/KhronosGroup/glslang/issues/701) for current status.
3. A SPIR-V back end for translating the AST to SPIR-V.
4. A standalone wrapper, `glslangValidator`, that can be used as a command-line tool for the above.
How to add a feature protected by a version/extension/stage/profile: See the
comment in `glslang/MachineIndependent/Versions.cpp`.
Tasks waiting to be done are documented as GitHub issues.
Deprecations
------------
1. GLSLang, when installed through CMake, will install a `SPIRV` folder into
`${CMAKE_INSTALL_INCLUDEDIR}`. This `SPIRV` folder is being moved to
`glslang/SPIRV`. During the transition the `SPIRV` folder will be installed into
both locations. The old install of `SPIRV/` will be removed as a CMake install
target no sooner then May 1, 2020. See issue #1964.
Execution of Standalone Wrapper
-------------------------------
To use the standalone binary form, execute `glslangValidator`, and it will print To use the standalone binary form, execute `glslangValidator`, and it will print
a usage statement. Basic operation is to give it a file containing a shader, a usage statement. Basic operation is to give it a file containing a shader,
@ -52,11 +85,18 @@ The applied stage-specific rules are based on the file extension:
* `.frag` for a fragment shader * `.frag` for a fragment shader
* `.comp` for a compute shader * `.comp` for a compute shader
There is also a non-shader extension 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 * `.conf` for a configuration file of limits, see usage statement for example
Building ## Building (CMake)
--------
Instead of building manually, you can also download the binaries for your Instead of building manually, you can also download the binaries for your
platform directly from the [master-tot release][master-tot-release] on GitHub. platform directly from the [master-tot release][master-tot-release] on GitHub.
@ -67,7 +107,7 @@ branch.
### Dependencies ### Dependencies
* A C++11 compiler. * A C++11 compiler.
(For MSVS: 2015 is recommended, 2013 is fully supported/tested, and 2010 support is attempted, but not tested.) (For MSVS: use 2015 or later.)
* [CMake][cmake]: for generating compilation targets. * [CMake][cmake]: for generating compilation targets.
* make: _Linux_, ninja is an alternative, if configured. * 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.) * [Python 3.x][python]: for executing SPIRV-Tools scripts. (Optional if not using SPIRV-Tools and the 'External' subdirectory does not exist.)
@ -79,7 +119,7 @@ branch.
The following steps assume a Bash shell. On Windows, that could be the Git Bash The following steps assume a Bash shell. On Windows, that could be the Git Bash
shell or some other shell of your choosing. shell or some other shell of your choosing.
#### 1) Check-Out this project #### 1) Check-Out this project
```bash ```bash
cd <parent of where you want glslang to be> cd <parent of where you want glslang to be>
@ -93,12 +133,12 @@ cd <the directory glslang was cloned to, "External" will be a subdirectory>
git clone https://github.com/google/googletest.git External/googletest git clone https://github.com/google/googletest.git External/googletest
``` ```
If you want to use googletest with Visual Studio 2013, you also need to check out an older version: TEMPORARY NOTICE: additionally perform the following to avoid a current
breakage in googletest:
```bash ```bash
# to use googletest with Visual Studio 2013
cd External/googletest cd External/googletest
git checkout 440527a61e1c91188195f7de212c63c77e8f0a45 git checkout 0c400f67fcf305869c5fb113dd296eca266c9725
cd ../.. cd ../..
``` ```
@ -127,6 +167,14 @@ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$(pwd)/install" $SOURCE
# "Release" (for CMAKE_BUILD_TYPE) could also be "Debug" or "RelWithDebInfo" # "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_ROOT/prebuilt/linux-x86_64/bin/make -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake
# If on Windows will be -DCMAKE_MAKE_PROGRAM=%ANDROID_NDK_ROOT%\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: For building on Windows:
```bash ```bash
@ -153,6 +201,36 @@ cmake --build . --config Release --target install
If using MSVC, after running CMake to configure, use the If using MSVC, after running CMake to configure, use the
Configuration Manager to check the `INSTALL` project. Configuration Manager to check the `INSTALL` project.
### 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 ### If you need to change the GLSL grammar
The grammar in `glslang/MachineIndependent/glslang.y` has to be recompiled with The grammar in `glslang/MachineIndependent/glslang.y` has to be recompiled with
@ -176,31 +254,45 @@ With no arguments it builds the full grammar, and with a "web" argument,
the web grammar subset (see more about the web subset in the next section). the web grammar subset (see more about the web subset in the next section).
### Building to WASM for the Web and Node ### 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: Use the steps in [Build Steps](#build-steps), with the following notes/exceptions:
* For building the web subset of core glslang: * `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 `-DBUILD_TESTING=OFF -DENABLE_OPT=OFF -DINSTALL_GTEST=OFF`.
* Set `-DENABLE_HLSL=OFF` if HLSL is not needed.
* For a standalone JS/WASM library, turn on `-DENABLE_GLSLANG_JS=ON`.
* For building a minimum-size web subset of core glslang:
+ turn on `-DENABLE_GLSLANG_WEBMIN=ON` (disables HLSL)
+ execute `updateGrammar web` from the glslang subdirectory + execute `updateGrammar web` from the glslang subdirectory
(or if using your own scripts, `m4` needs a `-DGLSLANG_WEB` argument) (or if using your own scripts, `m4` needs a `-DGLSLANG_WEB` argument)
+ set `-DENABLE_HLSL=OFF -DBUILD_TESTING=OFF -DENABLE_OPT=OFF -DINSTALL_GTEST=OFF` + optionally, for GLSL compilation error messages, turn on
+ turn on `-DENABLE_GLSLANG_WEB=ON` `-DENABLE_GLSLANG_WEBMIN_DEVEL=ON`
+ optionally, for GLSL compilation error messages, turn on `-DENABLE_GLSLANG_WEB_DEVEL=ON`
* `emsdk` needs to be present in your executable search path, *PATH* for
Bash-like enivironments
+ [Instructions located
here](https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install)
* Wrap cmake call: `emcmake cmake`
* To get a fully minimized build, make sure to use `brotli` to compress the .js * To get a fully minimized build, make sure to use `brotli` to compress the .js
and .wasm files and .wasm files
Example: Example:
```sh ```sh
emcmake cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GLSLANG_WEB=ON \ emcmake cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GLSLANG_JS=ON \
-DENABLE_HLSL=OFF -DBUILD_TESTING=OFF -DENABLE_OPT=OFF -DINSTALL_GTEST=OFF .. -DENABLE_HLSL=OFF -DBUILD_TESTING=OFF -DENABLE_OPT=OFF -DINSTALL_GTEST=OFF ..
``` ```
Testing ## 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 Right now, there are two test harnesses existing in glslang: one is [Google
Test](gtests/), one is the [`runtests` script](Test/runtests). The former Test](gtests/), one is the [`runtests` script](Test/runtests). The former
@ -272,8 +364,7 @@ You can add your own private list of tests, not tracked publicly, by using
`localtestlist` to list non-tracked tests. This is automatically read `localtestlist` to list non-tracked tests. This is automatically read
by `runtests` and included in the `diff` and `bump` process. by `runtests` and included in the `diff` and `bump` process.
Programmatic Interfaces ## Programmatic Interfaces
-----------------------
Another piece of software can programmatically translate shaders to an AST Another piece of software can programmatically translate shaders to an AST
using one of two different interfaces: using one of two different interfaces:
@ -309,7 +400,7 @@ class TProgram
Reflection queries Reflection queries
``` ```
For just validating (not generating code), subsitute these calls: For just validating (not generating code), substitute these calls:
```cxx ```cxx
setEnvInput(EShSourceHlsl or EShSourceGlsl, stage, EShClientNone, 0); setEnvInput(EShSourceHlsl or EShSourceGlsl, stage, EShClientNone, 0);
@ -327,7 +418,7 @@ 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`. as the `Sh*()` interface, as all the entry points start `Sh`.
The `Sh*()` interface takes a "compiler" call-back object, which it calls after 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 backend on it. 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: The following is a simplified resulting run-time call stack:
@ -338,8 +429,7 @@ ShCompile(shader, compiler) -> compiler(AST) -> <back end>
In practice, `ShCompile()` takes shader strings, default version, and In practice, `ShCompile()` takes shader strings, default version, and
warning/error and other options for controlling compilation. warning/error and other options for controlling compilation.
Basic Internal Operation ## Basic Internal Operation
------------------------
* Initial lexical analysis is done by the preprocessor in * Initial lexical analysis is done by the preprocessor in
`MachineIndependent/Preprocessor`, and then refined by a GLSL scanner `MachineIndependent/Preprocessor`, and then refined by a GLSL scanner
@ -354,7 +444,7 @@ Basic Internal Operation
* The intermediate representation is very high-level, and represented * The intermediate representation is very high-level, and represented
as an in-memory tree. This serves to lose no information from the as an in-memory tree. This serves to lose no information from the
original program, and to have efficient transfer of the result from original program, and to have efficient transfer of the result from
parsing to the back-end. In the AST, constants are propogated and parsing to the back-end. In the AST, constants are propagated and
folded, and a very small amount of dead code is eliminated. folded, and a very small amount of dead code is eliminated.
To aid linking and reflection, the last top-level branch in the AST To aid linking and reflection, the last top-level branch in the AST
@ -386,6 +476,8 @@ Basic Internal Operation
- the object does not come from the pool, and you have to do normal - the object does not come from the pool, and you have to do normal
C++ memory management of what you `new` 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/ [cmake]: https://cmake.org/
[python]: https://www.python.org/ [python]: https://www.python.org/

View File

@ -0,0 +1,110 @@
/**
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"
typedef struct glslang_program_s {
glslang::TProgram* program;
std::vector<unsigned int> 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_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_NV:
return EShLangTaskNV;
case GLSLANG_STAGE_MESH_NV:
return EShLangMeshNV;
default:
break;
}
return EShLangCount;
}
GLSLANG_EXPORT void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage)
{
spv::SpvBuildLogger logger;
glslang::SpvOptions spvOptions;
spvOptions.validate = true;
const glslang::TIntermediate* intermediate = program->program->getIntermediate(c_shader_stage(stage));
glslang::GlslangToSpv(*intermediate, program->spirv, &logger, &spvOptions);
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();
}

View File

@ -1,3 +1,36 @@
# 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 set(SOURCES
GlslangToSpv.cpp GlslangToSpv.cpp
InReadableOrder.cpp InReadableOrder.cpp
@ -6,7 +39,8 @@ set(SOURCES
SpvPostProcess.cpp SpvPostProcess.cpp
doc.cpp doc.cpp
SpvTools.cpp SpvTools.cpp
disassemble.cpp) disassemble.cpp
CInterface/spirv_c_interface.cpp)
set(SPVREMAP_SOURCES set(SPVREMAP_SOURCES
SPVRemapper.cpp SPVRemapper.cpp
@ -27,7 +61,8 @@ set(HEADERS
SpvTools.h SpvTools.h
disassemble.h disassemble.h
GLSL.ext.AMD.h GLSL.ext.AMD.h
GLSL.ext.NV.h) GLSL.ext.NV.h
NonSemanticDebugPrintf.h)
set(SPVREMAP_HEADERS set(SPVREMAP_HEADERS
SPVRemapper.h SPVRemapper.h
@ -37,8 +72,10 @@ add_library(SPIRV ${LIB_TYPE} ${SOURCES} ${HEADERS})
set_property(TARGET SPIRV PROPERTY FOLDER glslang) set_property(TARGET SPIRV PROPERTY FOLDER glslang)
set_property(TARGET SPIRV PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET SPIRV PROPERTY POSITION_INDEPENDENT_CODE ON)
target_include_directories(SPIRV PUBLIC target_include_directories(SPIRV PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>) $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
glslang_add_build_info_dependency(SPIRV)
if (ENABLE_SPVREMAPPER) if (ENABLE_SPVREMAPPER)
add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS})
@ -58,25 +95,26 @@ if(ENABLE_OPT)
PRIVATE ${spirv-tools_SOURCE_DIR}/include PRIVATE ${spirv-tools_SOURCE_DIR}/include
PRIVATE ${spirv-tools_SOURCE_DIR}/source PRIVATE ${spirv-tools_SOURCE_DIR}/source
) )
target_link_libraries(SPIRV glslang SPIRV-Tools-opt) target_link_libraries(SPIRV PRIVATE MachineIndependent SPIRV-Tools-opt)
target_include_directories(SPIRV PUBLIC target_include_directories(SPIRV PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../External> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../External>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/External>) $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/External>)
else() else()
target_link_libraries(SPIRV glslang) target_link_libraries(SPIRV PRIVATE MachineIndependent)
endif(ENABLE_OPT) endif()
if(WIN32) if(WIN32)
source_group("Source" FILES ${SOURCES} ${HEADERS}) source_group("Source" FILES ${SOURCES} ${HEADERS})
source_group("Source" FILES ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) source_group("Source" FILES ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS})
endif(WIN32) endif()
if(ENABLE_GLSLANG_INSTALL) if(ENABLE_GLSLANG_INSTALL)
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)
if (ENABLE_SPVREMAPPER) if (ENABLE_SPVREMAPPER)
install(TARGETS SPVRemapper EXPORT SPVRemapperTargets install(TARGETS SPVRemapper EXPORT SPVRemapperTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif() endif()
install(TARGETS SPIRV EXPORT SPIRVTargets install(TARGETS SPIRV EXPORT SPIRVTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
@ -97,6 +135,5 @@ if(ENABLE_GLSLANG_INSTALL)
install(EXPORT SPIRVTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) install(EXPORT SPIRVTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
install(FILES ${HEADERS} ${SPVREMAP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/SPIRV/)
install(FILES ${HEADERS} ${SPVREMAP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/SPIRV/) install(FILES ${HEADERS} ${SPVREMAP_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/SPIRV/)
endif(ENABLE_GLSLANG_INSTALL) endif()

View File

@ -35,5 +35,9 @@ static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shade
static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; 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_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_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";
#endif // #ifndef GLSLextEXT_H #endif // #ifndef GLSLextEXT_H

View File

@ -1,5 +1,6 @@
/* /*
** Copyright (c) 2014-2016 The Khronos Group Inc. ** 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 ** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and/or associated documentation files (the "Materials"), ** of this software and/or associated documentation files (the "Materials"),
@ -44,5 +45,12 @@ static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physi
static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_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_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_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";
#endif // #ifndef GLSLextKHR_H #endif // #ifndef GLSLextKHR_H

View File

@ -69,6 +69,9 @@ const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader";
//SPV_NV_raytracing //SPV_NV_raytracing
const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing"; 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 //SPV_NV_shading_rate
const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate"; const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate";

File diff suppressed because it is too large Load Diff

View File

@ -69,4 +69,4 @@ std::string SpvBuildLogger::getAllMessages() const {
} // end spv namespace } // end spv namespace
#endif #endif

View File

@ -0,0 +1,50 @@
// 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_

View File

@ -297,15 +297,21 @@ namespace spv {
std::string spirvbin_t::literalString(unsigned word) const std::string spirvbin_t::literalString(unsigned word) const
{ {
std::string literal; std::string literal;
const spirword_t * pos = spv.data() + word;
literal.reserve(16); literal.reserve(16);
const char* bytes = reinterpret_cast<const char*>(spv.data() + word); do {
spirword_t word = *pos;
while (bytes && *bytes) for (int i = 0; i < 4; i++) {
literal += *bytes++; char c = word & 0xff;
if (c == '\0')
return literal; return literal;
literal += c;
word >>= 8;
}
pos++;
} while (true);
} }
void spirvbin_t::applyMap() void spirvbin_t::applyMap()
@ -544,6 +550,9 @@ namespace spv {
// Extended instructions: currently, assume everything is an ID. // Extended instructions: currently, assume everything is an ID.
// TODO: add whatever data we need for exceptions to that // TODO: add whatever data we need for exceptions to that
if (opCode == spv::OpExtInst) { 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 word += 2; // instruction set, and instruction from set
numOperands -= 2; numOperands -= 2;
@ -625,6 +634,9 @@ namespace spv {
break; break;
} }
case spv::OperandVariableLiteralStrings:
return nextInst;
// Execution mode might have extra literal operands. Skip them. // Execution mode might have extra literal operands. Skip them.
case spv::OperandExecutionMode: case spv::OperandExecutionMode:
return nextInst; return nextInst;
@ -827,7 +839,15 @@ namespace spv {
[&](spv::Id& id) { [&](spv::Id& id) {
if (thisOpCode != spv::OpNop) { if (thisOpCode != spv::OpNop) {
++idCounter; ++idCounter;
const std::uint32_t hashval = opCounter[thisOpCode] * thisOpCode * 50047 + idCounter + fnId * 117; 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<unsigned int>(opCounter[thisOpCode])
* thisOpCode
* 50047
+ idCounter
+ static_cast<unsigned int>(fnId) * 117;
if (isOldIdUnmapped(id)) if (isOldIdUnmapped(id))
localId(id, nextUnusedId(hashval % softTypeIdLimit + firstMappedID)); localId(id, nextUnusedId(hashval % softTypeIdLimit + firstMappedID));

View File

@ -1,6 +1,7 @@
// //
// Copyright (C) 2014-2015 LunarG, Inc. // Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2015-2018 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -426,6 +427,37 @@ Id Builder::makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols)
return type->getResultId(); return type->getResultId();
} }
Id Builder::makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands)
{
// try to find it
Instruction* type;
for (int t = 0; t < (int)groupedTypes[opcode].size(); ++t) {
type = groupedTypes[opcode][t];
if (static_cast<size_t>(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<Instruction>(type));
module.mapInstruction(type);
return type->getResultId();
}
// TODO: performance: track arrays per stride // TODO: performance: track arrays per stride
// If a stride is supplied (non-zero) make an array. // If a stride is supplied (non-zero) make an array.
@ -496,7 +528,8 @@ Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
return type->getResultId(); return type->getResultId();
} }
Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format) Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled,
ImageFormat format)
{ {
assert(sampled == 1 || sampled == 2); assert(sampled == 1 || sampled == 2);
@ -601,16 +634,31 @@ Id Builder::makeSampledImageType(Id imageType)
} }
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
Id Builder::makeAccelerationStructureNVType() Id Builder::makeAccelerationStructureType()
{ {
Instruction *type; Instruction *type;
if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) { if (groupedTypes[OpTypeAccelerationStructureKHR].size() == 0) {
type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV); type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureKHR);
groupedTypes[OpTypeAccelerationStructureNV].push_back(type); groupedTypes[OpTypeAccelerationStructureKHR].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type)); constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type); module.mapInstruction(type);
} else { } else {
type = groupedTypes[OpTypeAccelerationStructureNV].back(); 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<Instruction>(type));
module.mapInstruction(type);
} else {
type = groupedTypes[OpTypeRayQueryKHR].back();
} }
return type->getResultId(); return type->getResultId();
@ -726,6 +774,26 @@ Id Builder::getContainedTypeId(Id typeId, int member) const
} }
} }
// 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. // Return the immediately contained type of a given composite type.
Id Builder::getContainedTypeId(Id typeId) const Id Builder::getContainedTypeId(Id typeId) const
{ {
@ -852,6 +920,30 @@ bool Builder::isSpecConstantOpCode(Op opcode) const
} }
} }
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<Instruction>(c));
nullConstants.push_back(c);
module.mapInstruction(c);
return c->getResultId();
}
Id Builder::makeBoolConstant(bool b, bool specConstant) Id Builder::makeBoolConstant(bool b, bool specConstant)
{ {
Id typeId = makeBoolType(); Id typeId = makeBoolType();
@ -1166,6 +1258,28 @@ void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int val
executionModes.push_back(std::unique_ptr<Instruction>(instr)); executionModes.push_back(std::unique_ptr<Instruction>(instr));
} }
void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, const std::vector<unsigned>& literals)
{
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<Instruction>(instr));
}
void Builder::addExecutionModeId(Function* entryPoint, ExecutionMode mode, const std::vector<Id>& operandIds)
{
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<Instruction>(instr));
}
void Builder::addName(Id id, const char* string) void Builder::addName(Id id, const char* string)
{ {
Instruction* name = new Instruction(OpName); Instruction* name = new Instruction(OpName);
@ -1204,7 +1318,7 @@ void Builder::addDecoration(Id id, Decoration decoration, const char* s)
if (decoration == spv::DecorationMax) if (decoration == spv::DecorationMax)
return; return;
Instruction* dec = new Instruction(OpDecorateStringGOOGLE); Instruction* dec = new Instruction(OpDecorateString);
dec->addIdOperand(id); dec->addIdOperand(id);
dec->addImmediateOperand(decoration); dec->addImmediateOperand(decoration);
dec->addStringOperand(s); dec->addStringOperand(s);
@ -1212,6 +1326,34 @@ void Builder::addDecoration(Id id, Decoration decoration, const char* s)
decorations.push_back(std::unique_ptr<Instruction>(dec)); decorations.push_back(std::unique_ptr<Instruction>(dec));
} }
void Builder::addDecoration(Id id, Decoration decoration, const std::vector<unsigned>& 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<Instruction>(dec));
}
void Builder::addDecoration(Id id, Decoration decoration, const std::vector<const char*>& 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<Instruction>(dec));
}
void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration) void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
{ {
if (decoration == spv::DecorationMax) if (decoration == spv::DecorationMax)
@ -1225,6 +1367,21 @@ void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
decorations.push_back(std::unique_ptr<Instruction>(dec)); decorations.push_back(std::unique_ptr<Instruction>(dec));
} }
void Builder::addDecorationId(Id id, Decoration decoration, const std::vector<Id>& 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<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num) void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
{ {
if (decoration == spv::DecorationMax) if (decoration == spv::DecorationMax)
@ -1254,6 +1411,36 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
decorations.push_back(std::unique_ptr<Instruction>(dec)); decorations.push_back(std::unique_ptr<Instruction>(dec));
} }
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<unsigned>& 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<Instruction>(dec));
}
void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const std::vector<const char*>& 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<Instruction>(dec));
}
// Comments in header // Comments in header
Function* Builder::makeEntryPoint(const char* entryPoint) Function* Builder::makeEntryPoint(const char* entryPoint)
{ {
@ -1270,7 +1457,8 @@ Function* Builder::makeEntryPoint(const char* entryPoint)
// Comments in header // Comments in header
Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name, Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& decorations, Block **entry) const std::vector<Id>& paramTypes,
const std::vector<std::vector<Decoration>>& decorations, Block **entry)
{ {
// Make the function and initial instructions in it // Make the function and initial instructions in it
Id typeId = makeFunctionType(returnType, paramTypes); Id typeId = makeFunctionType(returnType, paramTypes);
@ -1279,9 +1467,12 @@ Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const
// Set up the precisions // Set up the precisions
setPrecision(function->getId(), precision); setPrecision(function->getId(), precision);
function->setReturnPrecision(precision);
for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) { for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) {
for (int d = 0; d < (int)decorations[p].size(); ++d) for (int d = 0; d < (int)decorations[p].size(); ++d) {
addDecoration(firstParamId + p, decorations[p][d]); addDecoration(firstParamId + p, decorations[p][d]);
function->addParamPrecision(p, decorations[p][d]);
}
} }
// CFG // CFG
@ -1331,14 +1522,14 @@ void Builder::leaveFunction()
} }
// Comments in header // Comments in header
void Builder::makeDiscard() void Builder::makeStatementTerminator(spv::Op opcode, const char *name)
{ {
buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(OpKill))); buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(opcode)));
createAndSetNoPredecessorBlock("post-discard"); createAndSetNoPredecessorBlock(name);
} }
// Comments in header // Comments in header
Id Builder::createVariable(StorageClass storageClass, Id type, const char* name, Id initializer) Id Builder::createVariable(Decoration precision, StorageClass storageClass, Id type, const char* name, Id initializer)
{ {
Id pointerType = makePointer(storageClass, type); Id pointerType = makePointer(storageClass, type);
Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable); Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
@ -1360,6 +1551,7 @@ Id Builder::createVariable(StorageClass storageClass, Id type, const char* name,
if (name) if (name)
addName(inst->getResultId(), name); addName(inst->getResultId(), name);
setPrecision(inst->getResultId(), precision);
return inst->getResultId(); return inst->getResultId();
} }
@ -1373,7 +1565,8 @@ Id Builder::createUndefined(Id type)
} }
// av/vis/nonprivate are unnecessary and illegal for some storage classes. // av/vis/nonprivate are unnecessary and illegal for some storage classes.
spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
const
{ {
switch (sc) { switch (sc) {
case spv::StorageClassUniform: case spv::StorageClassUniform:
@ -1392,7 +1585,8 @@ spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAc
} }
// Comments in header // Comments in header
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope,
unsigned int alignment)
{ {
Instruction* store = new Instruction(OpStore); Instruction* store = new Instruction(OpStore);
store->addIdOperand(lValue); store->addIdOperand(lValue);
@ -1414,7 +1608,8 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce
} }
// Comments in header // Comments in header
Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) 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); Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
load->addIdOperand(lValue); load->addIdOperand(lValue);
@ -1432,6 +1627,7 @@ Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope
} }
buildPoint->addInstruction(std::unique_ptr<Instruction>(load)); buildPoint->addInstruction(std::unique_ptr<Instruction>(load));
setPrecision(load->getResultId(), precision);
return load->getResultId(); return load->getResultId();
} }
@ -1440,16 +1636,7 @@ Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope
Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector<Id>& offsets) Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector<Id>& offsets)
{ {
// Figure out the final resulting type. // Figure out the final resulting type.
spv::Id typeId = getTypeId(base); Id typeId = getResultingAccessChainType();
assert(isPointerType(typeId) && offsets.size() > 0);
typeId = getContainedTypeId(typeId);
for (int i = 0; i < (int)offsets.size(); ++i) {
if (isStructType(typeId)) {
assert(isConstantScalar(offsets[i]));
typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i]));
} else
typeId = getContainedTypeId(typeId, offsets[i]);
}
typeId = makePointer(storageClass, typeId); typeId = makePointer(storageClass, typeId);
// Make the instruction // Make the instruction
@ -1495,7 +1682,8 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
// Generate code for spec constants if in spec constant operation // Generate code for spec constants if in spec constant operation
// generation mode. // generation mode.
if (generatingOpCodeForSpecConst) { if (generatingOpCodeForSpecConst) {
return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), std::vector<Id>(1, index)); return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite),
std::vector<Id>(1, index));
} }
Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract); Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
extract->addIdOperand(composite); extract->addIdOperand(composite);
@ -1697,7 +1885,8 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& opera
return op->getResultId(); return op->getResultId();
} }
Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals) Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands,
const std::vector<unsigned>& literals)
{ {
Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
op->addImmediateOperand((unsigned) opCode); op->addImmediateOperand((unsigned) opCode);
@ -2144,7 +2333,7 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
Op op; Op op;
switch (getMostBasicTypeClass(valueType)) { switch (getMostBasicTypeClass(valueType)) {
case OpTypeFloat: case OpTypeFloat:
op = equal ? OpFOrdEqual : OpFOrdNotEqual; op = equal ? OpFOrdEqual : OpFUnordNotEqual;
break; break;
case OpTypeInt: case OpTypeInt:
default: default:
@ -2187,7 +2376,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
if (constituent == 0) if (constituent == 0)
resultId = subResultId; resultId = subResultId;
else else
resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision); resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId),
precision);
} }
return resultId; return resultId;
@ -2196,7 +2386,8 @@ Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, b
// OpCompositeConstruct // OpCompositeConstruct
Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents) Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
{ {
assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size())); assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 &&
getNumTypeConstituents(typeId) == (int)constituents.size()));
if (generatingOpCodeForSpecConst) { if (generatingOpCodeForSpecConst) {
// Sometime, even in spec-constant-op mode, the constant composite to be // Sometime, even in spec-constant-op mode, the constant composite to be
@ -2394,7 +2585,7 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
int row = 0; int row = 0;
int col = 0; int col = 0;
for (int arg = 0; arg < (int)sources.size(); ++arg) { for (int arg = 0; arg < (int)sources.size() && col < numCols; ++arg) {
Id argComp = sources[arg]; Id argComp = sources[arg];
for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) { for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) {
if (getNumComponents(sources[arg]) > 1) { if (getNumComponents(sources[arg]) > 1) {
@ -2406,6 +2597,10 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
row = 0; row = 0;
col++; col++;
} }
if (col == numCols) {
// If more components are provided than fit the matrix, discard the rest.
break;
}
} }
} }
} }
@ -2609,7 +2804,8 @@ void Builder::clearAccessChain()
} }
// Comments in header // Comments in header
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
{ {
accessChain.coherentFlags |= coherentFlags; accessChain.coherentFlags |= coherentFlags;
accessChain.alignment |= alignment; accessChain.alignment |= alignment;
@ -2635,35 +2831,70 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizz
} }
// Comments in header // Comments in header
void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) void Builder::accessChainStore(Id rvalue, Decoration nonUniform, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{ {
assert(accessChain.isRValue == false); assert(accessChain.isRValue == false);
transferAccessChainSwizzle(true); transferAccessChainSwizzle(true);
Id base = collapseAccessChain();
Id source = rvalue;
// dynamic component should be gone // If a swizzle exists and is not full and is not dynamic, then the swizzle will be broken into individual stores.
assert(accessChain.component == NoResult); 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;
// If swizzle still exists, it is out-of-order or not full, we must load the target vector, Id base = collapseAccessChain();
// extract and insert elements to perform writeMask and/or swizzle. addDecoration(base, nonUniform);
if (accessChain.swizzle.size() > 0) {
Id tempBaseId = createLoad(base); accessChain.indexChain.pop_back();
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle); 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);
// take LSB of alignment Id source = rvalue;
alignment = alignment & ~(alignment & (alignment-1));
if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) { // dynamic component should be gone
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask); 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);
} }
createStore(source, base, memoryAccess, scope, alignment);
} }
// Comments in header // Comments in header
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment) Id Builder::accessChainLoad(Decoration precision, Decoration l_nonUniform,
Decoration r_nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess,
spv::Scope scope, unsigned int alignment)
{ {
Id id; Id id;
@ -2687,17 +2918,19 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
if (constant) { if (constant) {
id = createCompositeExtract(accessChain.base, swizzleBase, indexes); id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
setPrecision(id, precision);
} else { } else {
Id lValue = NoResult; Id lValue = NoResult;
if (spvVersion >= Spv_1_4) { if (spvVersion >= Spv_1_4 && isValidInitializer(accessChain.base)) {
// make a new function variable for this r-value, using an initializer, // 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 // and mark it as NonWritable so that downstream it can be detected as a lookup
// table // table
lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable", lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base),
accessChain.base); "indexable", accessChain.base);
addDecoration(lValue, DecorationNonWritable); addDecoration(lValue, DecorationNonWritable);
} else { } else {
lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable"); lValue = createVariable(NoPrecision, StorageClassFunction, getTypeId(accessChain.base),
"indexable");
// store into it // store into it
createStore(accessChain.base, lValue); createStore(accessChain.base, lValue);
} }
@ -2706,9 +2939,8 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
accessChain.isRValue = false; accessChain.isRValue = false;
// load through the access chain // load through the access chain
id = createLoad(collapseAccessChain()); id = createLoad(collapseAccessChain(), precision);
} }
setPrecision(id, precision);
} else } else
id = accessChain.base; // no precision, it was set when this was defined id = accessChain.base; // no precision, it was set when this was defined
} else { } else {
@ -2721,9 +2953,14 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
} }
// load through the access chain // load through the access chain
id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment); id = collapseAccessChain();
setPrecision(id, precision); // Apply nonuniform both to the access chain and the loaded value.
addDecoration(id, nonUniform); // 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 // Done, unless there are swizzles to do
@ -2744,7 +2981,7 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
if (accessChain.component != NoResult) if (accessChain.component != NoResult)
id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision); id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
addDecoration(id, nonUniform); addDecoration(id, r_nonUniform);
return id; return id;
} }
@ -3075,7 +3312,8 @@ void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
dumpSourceInstructions(iItr->first, *iItr->second, out); dumpSourceInstructions(iItr->first, *iItr->second, out);
} }
void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const void Builder::dumpInstructions(std::vector<unsigned int>& out,
const std::vector<std::unique_ptr<Instruction> >& instructions) const
{ {
for (int i = 0; i < (int)instructions.size(); ++i) { for (int i = 0; i < (int)instructions.size(); ++i) {
instructions[i]->dump(out); instructions[i]->dump(out);

View File

@ -1,7 +1,8 @@
// //
// Copyright (C) 2014-2015 LunarG, Inc. // Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -94,6 +95,7 @@ public:
const char* file_c_str = str.c_str(); const char* file_c_str = str.c_str();
fileString->addStringOperand(file_c_str); fileString->addStringOperand(file_c_str);
strings.push_back(std::unique_ptr<Instruction>(fileString)); strings.push_back(std::unique_ptr<Instruction>(fileString));
module.mapInstruction(fileString);
stringIds[file_c_str] = strId; stringIds[file_c_str] = strId;
return strId; return strId;
} }
@ -179,9 +181,12 @@ public:
Id makeSamplerType(); Id makeSamplerType();
Id makeSampledImageType(Id imageType); Id makeSampledImageType(Id imageType);
Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols); Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
Id makeGenericType(spv::Op opcode, std::vector<spv::IdImmediate>& operands);
// accelerationStructureNV type // accelerationStructureNV type
Id makeAccelerationStructureNVType(); Id makeAccelerationStructureType();
// rayQueryEXT type
Id makeRayQueryType();
// For querying about types. // For querying about types.
Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
@ -196,7 +201,9 @@ public:
Id getContainedTypeId(Id typeId) const; Id getContainedTypeId(Id typeId) const;
Id getContainedTypeId(Id typeId, int) const; Id getContainedTypeId(Id typeId, int) const;
StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); } StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); } ImageFormat getImageTypeFormat(Id typeId) const
{ return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
Id getResultingAccessChainType() const;
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); } bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); } bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
@ -206,12 +213,17 @@ public:
bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); } bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
bool isSampledImage(Id resultId) const { return isSampledImageType(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 isBoolType(Id typeId)
bool isIntType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; } { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
bool isUintType(Id typeId) const { return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; } 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 isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; }
bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; } 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 isScalarType(Id typeId) const
{ return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt ||
getTypeClass(typeId) == OpTypeBool; }
bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; } bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; } bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; }
bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; } bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; }
@ -221,7 +233,8 @@ public:
#else #else
bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; } bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; }
#endif #endif
bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); } bool isAggregateType(Id typeId) const
{ return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
@ -233,9 +246,17 @@ public:
bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); } bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; } bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); } bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); } unsigned int getConstantScalar(Id resultId) const
{ return module.getInstruction(resultId)->getImmediateOperand(0); }
StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); } 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); }
int getScalarTypeWidth(Id typeId) const int getScalarTypeWidth(Id typeId) const
{ {
Id scalarTypeId = getScalarTypeId(typeId); Id scalarTypeId = getScalarTypeId(typeId);
@ -274,15 +295,24 @@ public:
} }
// For making new constants (will return old constant if the requested one was already made). // 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 makeBoolConstant(bool b, bool specConstant = false);
Id makeInt8Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); } Id makeInt8Constant(int i, bool specConstant = false)
Id makeUint8Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(8), u, specConstant); } { return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
Id makeInt16Constant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); } Id makeUint8Constant(unsigned u, bool specConstant = false)
Id makeUint16Constant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(16), u, specConstant); } { return makeIntConstant(makeUintType(8), u, specConstant); }
Id makeIntConstant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); } Id makeInt16Constant(int i, bool specConstant = false)
Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); } { return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); }
Id makeInt64Constant(long long i, bool specConstant = false) { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); } Id makeUint16Constant(unsigned u, bool specConstant = false)
Id makeUint64Constant(unsigned long long u, bool specConstant = false) { return makeInt64Constant(makeUintType(64), u, specConstant); } { 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 makeFloatConstant(float f, bool specConstant = false);
Id makeDoubleConstant(double d, bool specConstant = false); Id makeDoubleConstant(double d, bool specConstant = false);
Id makeFloat16Constant(float f16, bool specConstant = false); Id makeFloat16Constant(float f16, bool specConstant = false);
@ -294,13 +324,20 @@ public:
// Methods for adding information outside the CFG. // Methods for adding information outside the CFG.
Instruction* addEntryPoint(ExecutionModel, Function*, const char* name); 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, int value1 = -1, int value2 = -1, int value3 = -1);
void addExecutionMode(Function*, ExecutionMode mode, const std::vector<unsigned>& literals);
void addExecutionModeId(Function*, ExecutionMode mode, const std::vector<Id>& operandIds);
void addName(Id, const char* name); void addName(Id, const char* name);
void addMemberName(Id, int member, const char* name); void addMemberName(Id, int member, const char* name);
void addDecoration(Id, Decoration, int num = -1); void addDecoration(Id, Decoration, int num = -1);
void addDecoration(Id, Decoration, const char*); void addDecoration(Id, Decoration, const char*);
void addDecoration(Id, Decoration, const std::vector<unsigned>& literals);
void addDecoration(Id, Decoration, const std::vector<const char*>& strings);
void addDecorationId(Id id, Decoration, Id idDecoration); void addDecorationId(Id id, Decoration, Id idDecoration);
void addDecorationId(Id id, Decoration, const std::vector<Id>& operandIds);
void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1); 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 char*);
void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<unsigned>& literals);
void addMemberDecoration(Id, unsigned int member, Decoration, const std::vector<const char*>& strings);
// At the end of what block do the next create*() instructions go? // At the end of what block do the next create*() instructions go?
void setBuildPoint(Block* bp) { buildPoint = bp; } void setBuildPoint(Block* bp) { buildPoint = bp; }
@ -313,8 +350,8 @@ public:
// Make a shader-style function, and create its entry block if entry is non-zero. // Make a shader-style function, and create its entry block if entry is non-zero.
// Return the function, pass back the entry. // Return the function, pass back the entry.
// The returned pointer is only valid for the lifetime of this builder. // The returned pointer is only valid for the lifetime of this builder.
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes, Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name,
const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0); const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& precisions, Block **entry = 0);
// Create a return. An 'implicit' return is one not appearing in the source // 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. // code. In the case of an implicit return, no post-return block is inserted.
@ -323,20 +360,25 @@ public:
// Generate all the code needed to finish up a function. // Generate all the code needed to finish up a function.
void leaveFunction(); void leaveFunction();
// Create a discard. // Create block terminator instruction for certain statements like
void makeDiscard(); // discard, terminate-invocation, terminateRayEXT, or ignoreIntersectionEXT
void makeStatementTerminator(spv::Op opcode, const char *name);
// Create a global or function local or IO variable. // Create a global or function local or IO variable.
Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult); Id createVariable(Decoration precision, StorageClass, Id type, const char* name = nullptr,
Id initializer = NoResult);
// Create an intermediate with an undefined value. // Create an intermediate with an undefined value.
Id createUndefined(Id type); Id createUndefined(Id type);
// Store into an Id and return the l-value // 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); 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 // Load from an Id and return it
Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); 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 // Create an OpAccessChain instruction
Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets); Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
@ -495,7 +537,7 @@ public:
// recursion stack can hold the memory for it. // recursion stack can hold the memory for it.
// //
void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues, void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB); // return argument const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB);
// Add a branch to the innermost switch's merge block. // Add a branch to the innermost switch's merge block.
void addSwitchBreak(); void addSwitchBreak();
@ -512,7 +554,7 @@ public:
Block &head, &body, &merge, &continue_target; Block &head, &body, &merge, &continue_target;
private: private:
LoopBlocks(); LoopBlocks();
LoopBlocks& operator=(const LoopBlocks&); LoopBlocks& operator=(const LoopBlocks&) = delete;
}; };
// Start a new loop and prepare the builder to generate code for it. Until // Start a new loop and prepare the builder to generate code for it. Until
@ -569,10 +611,13 @@ public:
std::vector<Id> indexChain; std::vector<Id> indexChain;
Id instr; // cache the instruction that generates this access chain Id instr; // cache the instruction that generates this access chain
std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number std::vector<unsigned> 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 component; // a dynamic component index, can coexist with a swizzle,
Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present // 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 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. 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. // Accumulate whether anything in the chain of structures has coherent decorations.
struct CoherentFlags { struct CoherentFlags {
@ -583,15 +628,22 @@ public:
CoherentFlags operator |=(const CoherentFlags &other) { return *this; } CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
#else #else
bool isVolatile() const { return volatil; } bool isVolatile() const { return volatil; }
bool isNonUniform() const { return nonUniform; }
bool anyCoherent() const {
return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
subgroupcoherent || shadercallcoherent;
}
unsigned coherent : 1; unsigned coherent : 1;
unsigned devicecoherent : 1; unsigned devicecoherent : 1;
unsigned queuefamilycoherent : 1; unsigned queuefamilycoherent : 1;
unsigned workgroupcoherent : 1; unsigned workgroupcoherent : 1;
unsigned subgroupcoherent : 1; unsigned subgroupcoherent : 1;
unsigned shadercallcoherent : 1;
unsigned nonprivate : 1; unsigned nonprivate : 1;
unsigned volatil : 1; unsigned volatil : 1;
unsigned isImage : 1; unsigned isImage : 1;
unsigned nonUniform : 1;
void clear() { void clear() {
coherent = 0; coherent = 0;
@ -599,9 +651,11 @@ public:
queuefamilycoherent = 0; queuefamilycoherent = 0;
workgroupcoherent = 0; workgroupcoherent = 0;
subgroupcoherent = 0; subgroupcoherent = 0;
shadercallcoherent = 0;
nonprivate = 0; nonprivate = 0;
volatil = 0; volatil = 0;
isImage = 0; isImage = 0;
nonUniform = 0;
} }
CoherentFlags operator |=(const CoherentFlags &other) { CoherentFlags operator |=(const CoherentFlags &other) {
@ -610,9 +664,11 @@ public:
queuefamilycoherent |= other.queuefamilycoherent; queuefamilycoherent |= other.queuefamilycoherent;
workgroupcoherent |= other.workgroupcoherent; workgroupcoherent |= other.workgroupcoherent;
subgroupcoherent |= other.subgroupcoherent; subgroupcoherent |= other.subgroupcoherent;
shadercallcoherent |= other.shadercallcoherent;
nonprivate |= other.nonprivate; nonprivate |= other.nonprivate;
volatil |= other.volatil; volatil |= other.volatil;
isImage |= other.isImage; isImage |= other.isImage;
nonUniform |= other.nonUniform;
return *this; return *this;
} }
#endif #endif
@ -655,11 +711,13 @@ public:
} }
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle // push new swizzle onto the end of any existing swizzle, merging into a single swizzle
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment); void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
// push a dynamic component selection onto the access chain, only applicable with a // push a dynamic component selection onto the access chain, only applicable with a
// non-trivial swizzle or no swizzle // non-trivial swizzle or no swizzle
void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment) void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags,
unsigned int alignment)
{ {
if (accessChain.swizzle.size() != 1) { if (accessChain.swizzle.size() != 1) {
accessChain.component = component; accessChain.component = component;
@ -671,10 +729,19 @@ public:
} }
// use accessChain and swizzle to store value // use accessChain and swizzle to store value
void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); 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 // use accessChain and swizzle to load an r-value
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0); 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 // get the direct pointer for an l-value
Id accessChainGetLValue(); Id accessChainGetLValue();
@ -703,7 +770,8 @@ public:
void createBranch(Block* block); void createBranch(Block* block);
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock); void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control, const std::vector<unsigned int>& operands); void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
const std::vector<unsigned int>& operands);
// Sets to generate opcode for specialization constants. // Sets to generate opcode for specialization constants.
void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; } void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
@ -729,7 +797,8 @@ public:
void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const; void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const;
void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const; void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
void dumpModuleProcesses(std::vector<unsigned int>&) const; void dumpModuleProcesses(std::vector<unsigned int>&) const;
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const; spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
const;
unsigned int spvVersion; // the version of SPIR-V to emit in the header unsigned int spvVersion; // the version of SPIR-V to emit in the header
SourceLanguage source; SourceLanguage source;
@ -764,10 +833,16 @@ public:
std::vector<std::unique_ptr<Instruction> > externals; std::vector<std::unique_ptr<Instruction> > externals;
std::vector<std::unique_ptr<Function> > functions; std::vector<std::unique_ptr<Function> > functions;
// not output, internally used for quick & dirty canonical (unique) creation // not output, internally used for quick & dirty canonical (unique) creation
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants; // map type opcodes to constant inst.
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants; // map struct-id to constant instructions // map type opcodes to constant inst.
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes; // map type opcodes to type instructions std::unordered_map<unsigned int, std::vector<Instruction*>> groupedConstants;
// map struct-id to constant instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedStructConstants;
// map type opcodes to type instructions
std::unordered_map<unsigned int, std::vector<Instruction*>> groupedTypes;
// list of OpConstantNull instructions
std::vector<Instruction*> nullConstants;
// stack of switches // stack of switches
std::stack<Block*> switchMerges; std::stack<Block*> switchMerges;

View File

@ -44,10 +44,8 @@
#include <algorithm> #include <algorithm>
#include "SpvBuilder.h" #include "SpvBuilder.h"
#include "spirv.hpp" #include "spirv.hpp"
#include "GlslangToSpv.h"
#include "SpvBuilder.h"
namespace spv { namespace spv {
#include "GLSL.std.450.h" #include "GLSL.std.450.h"
#include "GLSL.ext.KHR.h" #include "GLSL.ext.KHR.h"
@ -113,8 +111,6 @@ void Builder::postProcessType(const Instruction& inst, Id typeId)
} }
} }
break; break;
case OpAccessChain:
case OpPtrAccessChain:
case OpCopyObject: case OpCopyObject:
break; break;
case OpFConvert: case OpFConvert:
@ -161,26 +157,43 @@ void Builder::postProcessType(const Instruction& inst, Id typeId)
switch (inst.getImmediateOperand(1)) { switch (inst.getImmediateOperand(1)) {
case GLSLstd450Frexp: case GLSLstd450Frexp:
case GLSLstd450FrexpStruct: case GLSLstd450FrexpStruct:
if (getSpvVersion() < glslang::EShTargetSpv_1_3 && containsType(typeId, OpTypeInt, 16)) if (getSpvVersion() < spv::Spv_1_3 && containsType(typeId, OpTypeInt, 16))
addExtension(spv::E_SPV_AMD_gpu_shader_int16); addExtension(spv::E_SPV_AMD_gpu_shader_int16);
break; break;
case GLSLstd450InterpolateAtCentroid: case GLSLstd450InterpolateAtCentroid:
case GLSLstd450InterpolateAtSample: case GLSLstd450InterpolateAtSample:
case GLSLstd450InterpolateAtOffset: case GLSLstd450InterpolateAtOffset:
if (getSpvVersion() < glslang::EShTargetSpv_1_3 && containsType(typeId, OpTypeFloat, 16)) if (getSpvVersion() < spv::Spv_1_3 && containsType(typeId, OpTypeFloat, 16))
addExtension(spv::E_SPV_AMD_gpu_shader_half_float); addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
break; break;
default: default:
break; break;
} }
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: default:
if (basicTypeOp == OpTypeFloat && width == 16) if (basicTypeOp == OpTypeInt) {
addCapability(CapabilityFloat16); if (width == 16)
if (basicTypeOp == OpTypeInt && width == 16) addCapability(CapabilityInt16);
addCapability(CapabilityInt16); else if (width == 8)
if (basicTypeOp == OpTypeInt && width == 8) addCapability(CapabilityInt8);
addCapability(CapabilityInt8); else if (width == 64)
addCapability(CapabilityInt64);
} else if (basicTypeOp == OpTypeFloat) {
if (width == 16)
addCapability(CapabilityFloat16);
else if (width == 64)
addCapability(CapabilityFloat64);
}
break; break;
} }
} }
@ -436,6 +449,38 @@ void Builder::postProcessFeatures() {
} }
} }
} }
// 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<Id> 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);
}
}
} }
#endif #endif

View File

@ -1,6 +1,6 @@
// //
// Copyright (C) 2014-2016 LunarG, Inc. // Copyright (C) 2014-2016 LunarG, Inc.
// Copyright (C) 2018 Google, Inc. // Copyright (C) 2018-2020 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -44,7 +44,6 @@
#include "SpvTools.h" #include "SpvTools.h"
#include "spirv-tools/optimizer.hpp" #include "spirv-tools/optimizer.hpp"
#include "spirv-tools/libspirv.h"
namespace glslang { namespace glslang {
@ -69,6 +68,8 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog
} }
case glslang::EShTargetVulkan_1_2: case glslang::EShTargetVulkan_1_2:
return spv_target_env::SPV_ENV_VULKAN_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: default:
break; break;
} }
@ -80,12 +81,52 @@ spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLog
return spv_target_env::SPV_ENV_UNIVERSAL_1_0; 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. // 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<unsigned int>& spirv) void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& 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<unsigned int>& spirv,
spv_target_env requested_context)
{ {
// disassemble // disassemble
spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3); spv_context context = spvContextCreate(requested_context);
spv_text text; spv_text text;
spv_diagnostic diagnostic = nullptr; spv_diagnostic diagnostic = nullptr;
spvBinaryToText(context, spirv.data(), spirv.size(), spvBinaryToText(context, spirv.data(), spirv.size(),
@ -114,6 +155,8 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
spv_validator_options options = spvValidatorOptionsCreate(); spv_validator_options options = spvValidatorOptionsCreate();
spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets()); spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization); spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization);
spvValidatorOptionsSetScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
spvValidatorOptionsSetWorkgroupScalarBlockLayout(options, intermediate.usingScalarBlockLayout());
spvValidateWithOptions(context, options, &binary, &diagnostic); spvValidateWithOptions(context, options, &binary, &diagnostic);
// report // report
@ -128,52 +171,21 @@ void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<
spvContextDestroy(context); spvContextDestroy(context);
} }
// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of // Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process.
// legalizing HLSL SPIR-V. void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger, const SpvOptions* options)
spv::SpvBuildLogger*, const SpvOptions* options)
{ {
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; spv_target_env target_env = MapToSpirvToolsEnv(intermediate.getSpv(), logger);
spvtools::Optimizer optimizer(target_env); spvtools::Optimizer optimizer(target_env);
optimizer.SetMessageConsumer( optimizer.SetMessageConsumer(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;
});
// If debug (specifically source line info) is being generated, propagate // If debug (specifically source line info) is being generated, propagate
// line information into all SPIR-V instructions. This avoids loss of // line information into all SPIR-V instructions. This avoids loss of
// information when instructions are deleted or moved. Later, remove // information when instructions are deleted or moved. Later, remove
// redundant information to minimize final SPRIR-V size. // redundant information to minimize final SPRIR-V size.
if (options->generateDebugInfo) { if (options->stripDebugInfo) {
optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass()); optimizer.RegisterPass(spvtools::CreateStripDebugInfoPass());
} }
optimizer.RegisterPass(spvtools::CreateWrapOpKillPass()); optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass()); optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
@ -197,17 +209,36 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateVectorDCEPass()); optimizer.RegisterPass(spvtools::CreateVectorDCEPass());
optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass()); optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass());
optimizer.RegisterPass(spvtools::CreateInterpolateFixupPass());
if (options->optimizeSize) { if (options->optimizeSize) {
optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass()); optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass());
optimizer.RegisterPass(spvtools::CreateEliminateDeadInputComponentsPass());
} }
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass()); optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass()); optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
if (options->generateDebugInfo) {
optimizer.RegisterPass(spvtools::CreateRedundantLineInfoElimPass());
}
spvtools::OptimizerOptions spvOptOptions; spvtools::OptimizerOptions spvOptOptions;
spvOptOptions.set_run_validator(false); // The validator may run as a seperate step later on 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);
}
// 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<unsigned int>& 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); optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
} }

View File

@ -41,9 +41,10 @@
#ifndef GLSLANG_SPV_TOOLS_H #ifndef GLSLANG_SPV_TOOLS_H
#define GLSLANG_SPV_TOOLS_H #define GLSLANG_SPV_TOOLS_H
#ifdef ENABLE_OPT #if ENABLE_OPT
#include <vector> #include <vector>
#include <ostream> #include <ostream>
#include "spirv-tools/libspirv.h"
#endif #endif
#include "glslang/MachineIndependent/localintermediate.h" #include "glslang/MachineIndependent/localintermediate.h"
@ -52,28 +53,38 @@
namespace glslang { namespace glslang {
struct SpvOptions { struct SpvOptions {
SpvOptions() : generateDebugInfo(false), disableOptimizer(true), SpvOptions() : generateDebugInfo(false), stripDebugInfo(false), disableOptimizer(true),
optimizeSize(false), disassemble(false), validate(false) { } optimizeSize(false), disassemble(false), validate(false) { }
bool generateDebugInfo; bool generateDebugInfo;
bool stripDebugInfo;
bool disableOptimizer; bool disableOptimizer;
bool optimizeSize; bool optimizeSize;
bool disassemble; bool disassemble;
bool validate; bool validate;
}; };
#ifdef ENABLE_OPT #if ENABLE_OPT
// Use the SPIRV-Tools disassembler to print SPIR-V. // 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<unsigned int>& spirv); void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
// Use the SPIRV-Tools disassembler to print SPIR-V with a provided SPIR-V environment.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv,
spv_target_env requested_context);
// Apply the SPIRV-Tools validator to generated SPIR-V. // Apply the SPIRV-Tools validator to generated SPIR-V.
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, bool prelegalization); spv::SpvBuildLogger*, bool prelegalization);
// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of // Apply the SPIRV-Tools optimizer to generated SPIR-V. HLSL SPIR-V is legalized in the process.
// legalizing HLSL SPIR-V. void SpirvToolsTransform(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, spv::SpvBuildLogger*, const SpvOptions*);
spv::SpvBuildLogger*, const SpvOptions*);
// 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<unsigned int>& spirv, spv::SpvBuildLogger*);
#endif #endif

View File

@ -43,10 +43,10 @@
#include <stack> #include <stack>
#include <sstream> #include <sstream>
#include <cstring> #include <cstring>
#include <utility>
#include "disassemble.h" #include "disassemble.h"
#include "doc.h" #include "doc.h"
#include "SpvTools.h"
namespace spv { namespace spv {
extern "C" { extern "C" {
@ -75,6 +75,7 @@ enum ExtInstSet {
GLSLextAMDInst, GLSLextAMDInst,
GLSLextNVInst, GLSLextNVInst,
OpenCLExtInst, OpenCLExtInst,
NonSemanticDebugPrintfExtInst,
}; };
// Container class for a single instance of a SPIR-V stream, with methods for disassembly. // Container class for a single instance of a SPIR-V stream, with methods for disassembly.
@ -100,6 +101,7 @@ protected:
void outputMask(OperandClass operandClass, unsigned mask); void outputMask(OperandClass operandClass, unsigned mask);
void disassembleImmediates(int numOperands); void disassembleImmediates(int numOperands);
void disassembleIds(int numOperands); void disassembleIds(int numOperands);
std::pair<int, std::string> decodeString();
int disassembleString(); int disassembleString();
void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands); void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
@ -290,31 +292,44 @@ void SpirvStream::disassembleIds(int numOperands)
} }
} }
// return the number of operands consumed by the string // decode string from words at current position (non-consuming)
int SpirvStream::disassembleString() std::pair<int, std::string> SpirvStream::decodeString()
{ {
int startWord = word; std::string res;
int wordPos = word;
out << " \""; char c;
const char* wordString;
bool done = false; bool done = false;
do { do {
unsigned int content = stream[word]; unsigned int content = stream[wordPos];
wordString = (const char*)&content;
for (int charCount = 0; charCount < 4; ++charCount) { for (int charCount = 0; charCount < 4; ++charCount) {
if (*wordString == 0) { c = content & 0xff;
content >>= 8;
if (c == '\0') {
done = true; done = true;
break; break;
} }
out << *(wordString++); res += c;
} }
++word; ++wordPos;
} while (! done); } while(! done);
return std::make_pair(wordPos - word, res);
}
// return the number of operands consumed by the string
int SpirvStream::disassembleString()
{
out << " \"";
std::pair<int, std::string> decoderes = decodeString();
out << decoderes.second;
out << "\""; out << "\"";
return word - startWord; word += decoderes.first;
return decoderes.first;
} }
void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands) void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
@ -331,7 +346,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
nextNestedControl = 0; nextNestedControl = 0;
} }
} else if (opCode == OpExtInstImport) { } else if (opCode == OpExtInstImport) {
idDescriptor[resultId] = (const char*)(&stream[word]); idDescriptor[resultId] = decodeString().second;
} }
else { else {
if (resultId != 0 && idDescriptor[resultId].size() == 0) { if (resultId != 0 && idDescriptor[resultId].size() == 0) {
@ -428,7 +443,7 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
--numOperands; --numOperands;
// Get names for printing "(XXX)" for readability, *after* this id // Get names for printing "(XXX)" for readability, *after* this id
if (opCode == OpName) if (opCode == OpName)
idDescriptor[stream[word - 1]] = (const char*)(&stream[word]); idDescriptor[stream[word - 1]] = decodeString().second;
break; break;
case OperandVariableIds: case OperandVariableIds:
disassembleIds(numOperands); disassembleIds(numOperands);
@ -480,8 +495,12 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
if (opCode == OpExtInst) { if (opCode == OpExtInst) {
ExtInstSet extInstSet = GLSL450Inst; ExtInstSet extInstSet = GLSL450Inst;
const char* name = idDescriptor[stream[word - 2]].c_str(); const char* name = idDescriptor[stream[word - 2]].c_str();
if (0 == memcmp("OpenCL", name, 6)) { if (strcmp("OpenCL.std", name) == 0) {
extInstSet = OpenCLExtInst; extInstSet = OpenCLExtInst;
} else if (strcmp("OpenCL.DebugInfo.100", name) == 0) {
extInstSet = OpenCLExtInst;
} else if (strcmp("NonSemantic.DebugPrintf", name) == 0) {
extInstSet = NonSemanticDebugPrintfExtInst;
} else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 || } 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_trinary_minmax, name) == 0 ||
strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 || strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
@ -505,6 +524,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
} }
else if (extInstSet == GLSLextNVInst) { else if (extInstSet == GLSLextNVInst) {
out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")"; out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
} else if (extInstSet == NonSemanticDebugPrintfExtInst) {
out << "(DebugPrintf)";
} }
} }
break; break;
@ -512,6 +533,10 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
case OperandLiteralString: case OperandLiteralString:
numOperands -= disassembleString(); numOperands -= disassembleString();
break; break;
case OperandVariableLiteralStrings:
while (numOperands > 0)
numOperands -= disassembleString();
return;
case OperandMemoryAccess: case OperandMemoryAccess:
outputMask(OperandMemoryAccess, stream[word++]); outputMask(OperandMemoryAccess, stream[word++]);
--numOperands; --numOperands;

View File

@ -1,5 +1,6 @@
// //
// Copyright (C) 2014-2015 LunarG, Inc. // Copyright (C) 2014-2015 LunarG, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -99,12 +100,12 @@ const char* ExecutionModelString(int model)
default: return "Bad"; default: return "Bad";
case ExecutionModelRayGenerationNV: return "RayGenerationNV"; case ExecutionModelRayGenerationKHR: return "RayGenerationKHR";
case ExecutionModelIntersectionNV: return "IntersectionNV"; case ExecutionModelIntersectionKHR: return "IntersectionKHR";
case ExecutionModelAnyHitNV: return "AnyHitNV"; case ExecutionModelAnyHitKHR: return "AnyHitKHR";
case ExecutionModelClosestHitNV: return "ClosestHitNV"; case ExecutionModelClosestHitKHR: return "ClosestHitKHR";
case ExecutionModelMissNV: return "MissNV"; case ExecutionModelMissKHR: return "MissKHR";
case ExecutionModelCallableNV: return "CallableNV"; case ExecutionModelCallableKHR: return "CallableKHR";
} }
} }
@ -133,7 +134,7 @@ const char* MemoryString(int mem)
} }
} }
const int ExecutionModeCeiling = 33; const int ExecutionModeCeiling = 40;
const char* ExecutionModeString(int mode) const char* ExecutionModeString(int mode)
{ {
@ -172,7 +173,22 @@ const char* ExecutionModeString(int mode)
case 31: return "ContractionOff"; case 31: return "ContractionOff";
case 32: return "Bad"; case 32: return "Bad";
case 4446: return "PostDepthCoverage"; 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 ExecutionModeStencilRefReplacingEXT: return "StencilRefReplacingEXT";
case ExecutionModeSubgroupUniformControlFlowKHR: return "SubgroupUniformControlFlow";
case ExecutionModeOutputLinesNV: return "OutputLinesNV"; case ExecutionModeOutputLinesNV: return "OutputLinesNV";
case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV"; case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV";
@ -187,6 +203,11 @@ const char* ExecutionModeString(int mode)
case ExecutionModeShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT"; case ExecutionModeShadingRateInterlockOrderedEXT: return "ShadingRateInterlockOrderedEXT";
case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT"; case ExecutionModeShadingRateInterlockUnorderedEXT: return "ShadingRateInterlockUnorderedEXT";
case ExecutionModeMaxWorkgroupSizeINTEL: return "MaxWorkgroupSizeINTEL";
case ExecutionModeMaxWorkDimINTEL: return "MaxWorkDimINTEL";
case ExecutionModeNoGlobalOffsetINTEL: return "NoGlobalOffsetINTEL";
case ExecutionModeNumSIMDWorkitemsINTEL: return "NumSIMDWorkitemsINTEL";
case ExecutionModeCeiling: case ExecutionModeCeiling:
default: return "Bad"; default: return "Bad";
} }
@ -209,12 +230,12 @@ const char* StorageClassString(int StorageClass)
case 11: return "Image"; case 11: return "Image";
case 12: return "StorageBuffer"; case 12: return "StorageBuffer";
case StorageClassRayPayloadNV: return "RayPayloadNV"; case StorageClassRayPayloadKHR: return "RayPayloadKHR";
case StorageClassHitAttributeNV: return "HitAttributeNV"; case StorageClassHitAttributeKHR: return "HitAttributeKHR";
case StorageClassIncomingRayPayloadNV: return "IncomingRayPayloadNV"; case StorageClassIncomingRayPayloadKHR: return "IncomingRayPayloadKHR";
case StorageClassShaderRecordBufferNV: return "ShaderRecordBufferNV"; case StorageClassShaderRecordBufferKHR: return "ShaderRecordBufferKHR";
case StorageClassCallableDataNV: return "CallableDataNV"; case StorageClassCallableDataKHR: return "CallableDataKHR";
case StorageClassIncomingCallableDataNV: return "IncomingCallableDataNV"; case StorageClassIncomingCallableDataKHR: return "IncomingCallableDataKHR";
case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT"; case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT";
@ -352,6 +373,8 @@ const char* BuiltInString(int builtIn)
case 4424: return "BaseVertex"; case 4424: return "BaseVertex";
case 4425: return "BaseInstance"; case 4425: return "BaseInstance";
case 4426: return "DrawIndex"; case 4426: return "DrawIndex";
case 4432: return "PrimitiveShadingRateKHR";
case 4444: return "ShadingRateKHR";
case 5014: return "FragStencilRefEXT"; case 5014: return "FragStencilRefEXT";
case 4992: return "BaryCoordNoPerspAMD"; case 4992: return "BaryCoordNoPerspAMD";
@ -361,32 +384,33 @@ const char* BuiltInString(int builtIn)
case 4996: return "BaryCoordSmoothCentroidAMD"; case 4996: return "BaryCoordSmoothCentroidAMD";
case 4997: return "BaryCoordSmoothSampleAMD"; case 4997: return "BaryCoordSmoothSampleAMD";
case 4998: return "BaryCoordPullModelAMD"; case 4998: return "BaryCoordPullModelAMD";
case BuiltInLaunchIdNV: return "LaunchIdNV"; case BuiltInLaunchIdKHR: return "LaunchIdKHR";
case BuiltInLaunchSizeNV: return "LaunchSizeNV"; case BuiltInLaunchSizeKHR: return "LaunchSizeKHR";
case BuiltInWorldRayOriginNV: return "WorldRayOriginNV"; case BuiltInWorldRayOriginKHR: return "WorldRayOriginKHR";
case BuiltInWorldRayDirectionNV: return "WorldRayDirectionNV"; case BuiltInWorldRayDirectionKHR: return "WorldRayDirectionKHR";
case BuiltInObjectRayOriginNV: return "ObjectRayOriginNV"; case BuiltInObjectRayOriginKHR: return "ObjectRayOriginKHR";
case BuiltInObjectRayDirectionNV: return "ObjectRayDirectionNV"; case BuiltInObjectRayDirectionKHR: return "ObjectRayDirectionKHR";
case BuiltInRayTminNV: return "RayTminNV"; case BuiltInRayTminKHR: return "RayTminKHR";
case BuiltInRayTmaxNV: return "RayTmaxNV"; case BuiltInRayTmaxKHR: return "RayTmaxKHR";
case BuiltInInstanceCustomIndexNV: return "InstanceCustomIndexNV"; case BuiltInInstanceCustomIndexKHR: return "InstanceCustomIndexKHR";
case BuiltInObjectToWorldNV: return "ObjectToWorldNV"; case BuiltInRayGeometryIndexKHR: return "RayGeometryIndexKHR";
case BuiltInWorldToObjectNV: return "WorldToObjectNV"; case BuiltInObjectToWorldKHR: return "ObjectToWorldKHR";
case BuiltInHitTNV: return "HitTNV"; case BuiltInWorldToObjectKHR: return "WorldToObjectKHR";
case BuiltInHitKindNV: return "HitKindNV"; case BuiltInHitTNV: return "HitTNV";
case BuiltInIncomingRayFlagsNV: return "IncomingRayFlagsNV"; case BuiltInHitKindKHR: return "HitKindKHR";
case BuiltInViewportMaskNV: return "ViewportMaskNV"; case BuiltInIncomingRayFlagsKHR: return "IncomingRayFlagsKHR";
case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; case BuiltInViewportMaskNV: return "ViewportMaskNV";
case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
case BuiltInPositionPerViewNV: return "PositionPerViewNV"; case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; case BuiltInPositionPerViewNV: return "PositionPerViewNV";
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
// case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT // case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT
// case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT // case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT
case BuiltInBaryCoordNV: return "BaryCoordNV"; case BuiltInBaryCoordNV: return "BaryCoordNV";
case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
case BuiltInFragSizeEXT: return "FragSizeEXT"; case BuiltInFragSizeEXT: return "FragSizeEXT";
case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT"; case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT";
case 5264: return "FullyCoveredEXT"; case 5264: return "FullyCoveredEXT";
@ -402,6 +426,7 @@ const char* BuiltInString(int builtIn)
case BuiltInSMCountNV: return "SMCountNV"; case BuiltInSMCountNV: return "SMCountNV";
case BuiltInWarpIDNV: return "WarpIDNV"; case BuiltInWarpIDNV: return "WarpIDNV";
case BuiltInSMIDNV: return "SMIDNV"; case BuiltInSMIDNV: return "SMIDNV";
case BuiltInCurrentRayTimeNV: return "CurrentRayTimeNV";
default: return "Bad"; default: return "Bad";
} }
@ -500,6 +525,8 @@ const char* ImageFormatString(int format)
case 37: return "Rg8ui"; case 37: return "Rg8ui";
case 38: return "R16ui"; case 38: return "R16ui";
case 39: return "R8ui"; case 39: return "R8ui";
case 40: return "R64ui";
case 41: return "R64i";
default: default:
return "Bad"; return "Bad";
@ -873,6 +900,12 @@ const char* CapabilityString(int info)
case CapabilityDeviceGroup: return "DeviceGroup"; case CapabilityDeviceGroup: return "DeviceGroup";
case CapabilityMultiView: return "MultiView"; 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 CapabilityStencilExportEXT: return "StencilExportEXT";
case CapabilityFloat16ImageAMD: return "Float16ImageAMD"; case CapabilityFloat16ImageAMD: return "Float16ImageAMD";
@ -890,6 +923,11 @@ const char* CapabilityString(int info)
case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV"; case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV";
case CapabilityRayTracingNV: return "RayTracingNV"; case CapabilityRayTracingNV: return "RayTracingNV";
case CapabilityRayTracingMotionBlurNV: return "RayTracingMotionBlurNV";
case CapabilityRayTracingKHR: return "RayTracingKHR";
case CapabilityRayQueryKHR: return "RayQueryKHR";
case CapabilityRayTracingProvisionalKHR: return "RayTracingProvisionalKHR";
case CapabilityRayTraversalPrimitiveCullingKHR: return "RayTraversalPrimitiveCullingKHR";
case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV"; case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV";
case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV"; case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV";
case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV"; case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
@ -928,11 +966,25 @@ const char* CapabilityString(int info)
case CapabilityFragmentShaderPixelInterlockEXT: return "CapabilityFragmentShaderPixelInterlockEXT"; case CapabilityFragmentShaderPixelInterlockEXT: return "CapabilityFragmentShaderPixelInterlockEXT";
case CapabilityFragmentShaderShadingRateInterlockEXT: return "CapabilityFragmentShaderShadingRateInterlockEXT"; case CapabilityFragmentShaderShadingRateInterlockEXT: return "CapabilityFragmentShaderShadingRateInterlockEXT";
case CapabilityFragmentShadingRateKHR: return "FragmentShadingRateKHR";
case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT"; case CapabilityDemoteToHelperInvocationEXT: return "DemoteToHelperInvocationEXT";
case CapabilityShaderClockKHR: return "ShaderClockKHR"; case CapabilityShaderClockKHR: return "ShaderClockKHR";
case CapabilityInt64ImageEXT: return "Int64ImageEXT";
case CapabilityIntegerFunctions2INTEL: return "CapabilityIntegerFunctions2INTEL"; 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";
default: return "Bad"; default: return "Bad";
} }
} }
@ -1264,6 +1316,7 @@ const char* OpcodeString(int op)
case 320: return "OpImageSparseRead"; case 320: return "OpImageSparseRead";
case OpModuleProcessed: return "OpModuleProcessed"; case OpModuleProcessed: return "OpModuleProcessed";
case OpExecutionModeId: return "OpExecutionModeId";
case OpDecorateId: return "OpDecorateId"; case OpDecorateId: return "OpDecorateId";
case 333: return "OpGroupNonUniformElect"; case 333: return "OpGroupNonUniformElect";
@ -1301,6 +1354,8 @@ const char* OpcodeString(int op)
case 365: return "OpGroupNonUniformQuadBroadcast"; case 365: return "OpGroupNonUniformQuadBroadcast";
case 366: return "OpGroupNonUniformQuadSwap"; case 366: return "OpGroupNonUniformQuadSwap";
case OpTerminateInvocation: return "OpTerminateInvocation";
case 4421: return "OpSubgroupBallotKHR"; case 4421: return "OpSubgroupBallotKHR";
case 4422: return "OpSubgroupFirstInvocationKHR"; case 4422: return "OpSubgroupFirstInvocationKHR";
case 4428: return "OpSubgroupAllKHR"; case 4428: return "OpSubgroupAllKHR";
@ -1308,6 +1363,10 @@ const char* OpcodeString(int op)
case 4430: return "OpSubgroupAllEqualKHR"; case 4430: return "OpSubgroupAllEqualKHR";
case 4432: return "OpSubgroupReadInvocationKHR"; case 4432: return "OpSubgroupReadInvocationKHR";
case OpAtomicFAddEXT: return "OpAtomicFAddEXT";
case OpAtomicFMinEXT: return "OpAtomicFMinEXT";
case OpAtomicFMaxEXT: return "OpAtomicFMaxEXT";
case 5000: return "OpGroupIAddNonUniformAMD"; case 5000: return "OpGroupIAddNonUniformAMD";
case 5001: return "OpGroupFAddNonUniformAMD"; case 5001: return "OpGroupFAddNonUniformAMD";
case 5002: return "OpGroupFMinNonUniformAMD"; case 5002: return "OpGroupFMinNonUniformAMD";
@ -1325,16 +1384,48 @@ const char* OpcodeString(int op)
case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE"; case OpDecorateStringGOOGLE: return "OpDecorateStringGOOGLE";
case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE"; 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 OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV";
case OpReportIntersectionNV: return "OpReportIntersectionNV";
case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV";
case OpTerminateRayNV: return "OpTerminateRayNV";
case OpTraceNV: return "OpTraceNV";
case OpTypeAccelerationStructureNV: return "OpTypeAccelerationStructureNV";
case OpExecuteCallableNV: return "OpExecuteCallableNV";
case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV"; case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV";
case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV"; case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
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 OpTypeCooperativeMatrixNV: return "OpTypeCooperativeMatrixNV"; case OpTypeCooperativeMatrixNV: return "OpTypeCooperativeMatrixNV";
case OpCooperativeMatrixLoadNV: return "OpCooperativeMatrixLoadNV"; case OpCooperativeMatrixLoadNV: return "OpCooperativeMatrixLoadNV";
case OpCooperativeMatrixStoreNV: return "OpCooperativeMatrixStoreNV"; case OpCooperativeMatrixStoreNV: return "OpCooperativeMatrixStoreNV";
@ -1388,6 +1479,7 @@ void Parameterize()
InstructionDesc[OpMemoryModel].setResultAndType(false, false); InstructionDesc[OpMemoryModel].setResultAndType(false, false);
InstructionDesc[OpEntryPoint].setResultAndType(false, false); InstructionDesc[OpEntryPoint].setResultAndType(false, false);
InstructionDesc[OpExecutionMode].setResultAndType(false, false); InstructionDesc[OpExecutionMode].setResultAndType(false, false);
InstructionDesc[OpExecutionModeId].setResultAndType(false, false);
InstructionDesc[OpTypeVoid].setResultAndType(true, false); InstructionDesc[OpTypeVoid].setResultAndType(true, false);
InstructionDesc[OpTypeBool].setResultAndType(true, false); InstructionDesc[OpTypeBool].setResultAndType(true, false);
InstructionDesc[OpTypeInt].setResultAndType(true, false); InstructionDesc[OpTypeInt].setResultAndType(true, false);
@ -1441,6 +1533,7 @@ void Parameterize()
InstructionDesc[OpBranchConditional].setResultAndType(false, false); InstructionDesc[OpBranchConditional].setResultAndType(false, false);
InstructionDesc[OpSwitch].setResultAndType(false, false); InstructionDesc[OpSwitch].setResultAndType(false, false);
InstructionDesc[OpKill].setResultAndType(false, false); InstructionDesc[OpKill].setResultAndType(false, false);
InstructionDesc[OpTerminateInvocation].setResultAndType(false, false);
InstructionDesc[OpReturn].setResultAndType(false, false); InstructionDesc[OpReturn].setResultAndType(false, false);
InstructionDesc[OpReturnValue].setResultAndType(false, false); InstructionDesc[OpReturnValue].setResultAndType(false, false);
InstructionDesc[OpUnreachable].setResultAndType(false, false); InstructionDesc[OpUnreachable].setResultAndType(false, false);
@ -1574,6 +1667,10 @@ void Parameterize()
InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'"); InstructionDesc[OpExecutionMode].operands.push(OperandExecutionMode, "'Mode'");
InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <<Execution_Mode,Execution Mode>>"); InstructionDesc[OpExecutionMode].operands.push(OperandOptionalLiteral, "See <<Execution_Mode,Execution Mode>>");
InstructionDesc[OpExecutionModeId].operands.push(OperandId, "'Entry Point'");
InstructionDesc[OpExecutionModeId].operands.push(OperandExecutionMode, "'Mode'");
InstructionDesc[OpExecutionModeId].operands.push(OperandVariableIds, "See <<Execution_Mode,Execution Mode>>");
InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'"); InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Width'");
InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'"); InstructionDesc[OpTypeInt].operands.push(OperandLiteralNumber, "'Signedness'");
@ -1667,7 +1764,7 @@ void Parameterize()
InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandId, "'Target'"); InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandId, "'Target'");
InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandDecoration, ""); InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandDecoration, "");
InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'"); InstructionDesc[OpDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'");
InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'"); InstructionDesc[OpMemberDecorate].operands.push(OperandId, "'Structure Type'");
InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'"); InstructionDesc[OpMemberDecorate].operands.push(OperandLiteralNumber, "'Member'");
@ -1677,7 +1774,7 @@ void Parameterize()
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandId, "'Structure Type'"); InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandId, "'Structure Type'");
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralNumber, "'Member'"); InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralNumber, "'Member'");
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandDecoration, ""); InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandDecoration, "");
InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandLiteralString, "'Literal String'"); InstructionDesc[OpMemberDecorateStringGOOGLE].operands.push(OperandVariableLiteralStrings, "'Literal Strings'");
InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'"); InstructionDesc[OpGroupDecorate].operands.push(OperandId, "'Decoration Group'");
InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'"); InstructionDesc[OpGroupDecorate].operands.push(OperandVariableIds, "'Targets'");
@ -2230,6 +2327,11 @@ void Parameterize()
InstructionDesc[OpAtomicIAdd].operands.push(OperandMemorySemantics, "'Semantics'"); InstructionDesc[OpAtomicIAdd].operands.push(OperandMemorySemantics, "'Semantics'");
InstructionDesc[OpAtomicIAdd].operands.push(OperandId, "'Value'"); 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(OperandId, "'Pointer'");
InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'"); InstructionDesc[OpAtomicISub].operands.push(OperandScope, "'Scope'");
InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'"); InstructionDesc[OpAtomicISub].operands.push(OperandMemorySemantics, "'Semantics'");
@ -2255,6 +2357,16 @@ void Parameterize()
InstructionDesc[OpAtomicSMax].operands.push(OperandMemorySemantics, "'Semantics'"); InstructionDesc[OpAtomicSMax].operands.push(OperandMemorySemantics, "'Semantics'");
InstructionDesc[OpAtomicSMax].operands.push(OperandId, "'Value'"); 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(OperandId, "'Pointer'");
InstructionDesc[OpAtomicAnd].operands.push(OperandScope, "'Scope'"); InstructionDesc[OpAtomicAnd].operands.push(OperandScope, "'Scope'");
InstructionDesc[OpAtomicAnd].operands.push(OperandMemorySemantics, "'Semantics'"); InstructionDesc[OpAtomicAnd].operands.push(OperandMemorySemantics, "'Semantics'");
@ -2633,7 +2745,7 @@ void Parameterize()
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'"); InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandScope, "'Execution'");
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X"); InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "X");
InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandLiteralNumber, "'Direction'"); InstructionDesc[OpGroupNonUniformQuadSwap].operands.push(OperandId, "'Direction'");
InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'"); InstructionDesc[OpSubgroupBallotKHR].operands.push(OperandId, "'Predicate'");
@ -2694,9 +2806,9 @@ void Parameterize()
InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X"); InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X");
InstructionDesc[OpTypeAccelerationStructureNV].setResultAndType(true, false); InstructionDesc[OpTypeAccelerationStructureKHR].setResultAndType(true, false);
InstructionDesc[OpTraceNV].operands.push(OperandId, "'NV Acceleration Structure'"); InstructionDesc[OpTraceNV].operands.push(OperandId, "'Acceleration Structure'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'"); InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'"); InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'"); InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'");
@ -2709,17 +2821,149 @@ void Parameterize()
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'"); InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'");
InstructionDesc[OpTraceNV].setResultAndType(false, false); InstructionDesc[OpTraceNV].setResultAndType(false, false);
InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Parameter'"); InstructionDesc[OpTraceRayMotionNV].operands.push(OperandId, "'Acceleration Structure'");
InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Kind'"); 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[OpIgnoreIntersectionNV].setResultAndType(false, false);
InstructionDesc[OpIgnoreIntersectionKHR].setResultAndType(false, false);
InstructionDesc[OpTerminateRayNV].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, "SBT Record Index");
InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID"); InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID");
InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false); 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[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'"); InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'");
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'"); InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'");
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Granularity'"); InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Granularity'");

View File

@ -125,6 +125,7 @@ enum OperandClass {
OperandVariableLiteralId, OperandVariableLiteralId,
OperandLiteralNumber, OperandLiteralNumber,
OperandLiteralString, OperandLiteralString,
OperandVariableLiteralStrings,
OperandSource, OperandSource,
OperandExecutionModel, OperandExecutionModel,
OperandAddressing, OperandAddressing,

View File

@ -784,8 +784,8 @@ inline std::istream& ParseNormalFloat(std::istream& is, bool negate_value,
if (val.isInfinity()) { if (val.isInfinity()) {
// Fail the parse. Emulate standard behaviour by setting the value to // Fail the parse. Emulate standard behaviour by setting the value to
// the closest normal value, and set the fail bit on the stream. // the closest normal value, and set the fail bit on the stream.
value.set_value((value.isNegative() | negate_value) ? T::lowest() value.set_value((value.isNegative() || negate_value) ? T::lowest()
: T::max()); : T::max());
is.setstate(std::ios_base::failbit); is.setstate(std::ios_base::failbit);
} }
return is; return is;

File diff suppressed because it is too large Load Diff

View File

@ -55,6 +55,7 @@
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <set>
namespace spv { namespace spv {
@ -110,27 +111,23 @@ public:
void addStringOperand(const char* str) void addStringOperand(const char* str)
{ {
unsigned int word; unsigned int word = 0;
char* wordString = (char*)&word; unsigned int shiftAmount = 0;
char* wordPtr = wordString;
int charCount = 0;
char c; char c;
do { do {
c = *(str++); c = *(str++);
*(wordPtr++) = c; word |= ((unsigned int)c) << shiftAmount;
++charCount; shiftAmount += 8;
if (charCount == 4) { if (shiftAmount == 32) {
addImmediateOperand(word); addImmediateOperand(word);
wordPtr = wordString; word = 0;
charCount = 0; shiftAmount = 0;
} }
} while (c != 0); } while (c != 0);
// deal with partial last word // deal with partial last word
if (charCount > 0) { if (shiftAmount > 0) {
// pad with 0s
for (; charCount < 4; ++charCount)
*(wordPtr++) = 0;
addImmediateOperand(word); addImmediateOperand(word);
} }
} }
@ -235,8 +232,7 @@ public:
assert(instructions.size() > 0); assert(instructions.size() > 0);
instructions.resize(1); instructions.resize(1);
successors.clear(); successors.clear();
Instruction* unreachable = new Instruction(OpUnreachable); addInstruction(std::unique_ptr<Instruction>(new Instruction(OpUnreachable)));
addInstruction(std::unique_ptr<Instruction>(unreachable));
} }
// Change this block into a canonical dead continue target branching to the // Change this block into a canonical dead continue target branching to the
// given header ID. Delete instructions as necessary. A canonical dead continue // given header ID. Delete instructions as necessary. A canonical dead continue
@ -263,6 +259,7 @@ public:
case OpBranchConditional: case OpBranchConditional:
case OpSwitch: case OpSwitch:
case OpKill: case OpKill:
case OpTerminateInvocation:
case OpReturn: case OpReturn:
case OpReturnValue: case OpReturnValue:
case OpUnreachable: case OpUnreachable:
@ -352,10 +349,28 @@ public:
const std::vector<Block*>& getBlocks() const { return blocks; } const std::vector<Block*>& getBlocks() const { return blocks; }
void addLocalVariable(std::unique_ptr<Instruction> inst); void addLocalVariable(std::unique_ptr<Instruction> inst);
Id getReturnType() const { return functionInstruction.getTypeId(); } Id getReturnType() const { return functionInstruction.getTypeId(); }
void setReturnPrecision(Decoration precision)
{
if (precision == DecorationRelaxedPrecision)
reducedPrecisionReturn = true;
}
Decoration getReturnPrecision() const
{ return reducedPrecisionReturn ? DecorationRelaxedPrecision : NoPrecision; }
void setImplicitThis() { implicitThis = true; } void setImplicitThis() { implicitThis = true; }
bool hasImplicitThis() const { return implicitThis; } 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<unsigned int>& out) const void dump(std::vector<unsigned int>& out) const
{ {
// OpFunction // OpFunction
@ -380,6 +395,8 @@ protected:
std::vector<Instruction*> parameterInstructions; std::vector<Instruction*> parameterInstructions;
std::vector<Block*> blocks; std::vector<Block*> blocks;
bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument
bool reducedPrecisionReturn;
std::set<int> reducedPrecisionParams; // list of parameter indexes that need a relaxed precision arg
}; };
// //
@ -440,7 +457,8 @@ protected:
// - the OpFunction instruction // - the OpFunction instruction
// - all the OpFunctionParameter instructions // - all the OpFunctionParameter instructions
__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent) __inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
: parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false) : parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false),
reducedPrecisionReturn(false)
{ {
// OpFunction // OpFunction
functionInstruction.addImmediateOperand(FunctionControlMaskNone); functionInstruction.addImmediateOperand(FunctionControlMaskNone);

View File

@ -1,5 +1,55 @@
# 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.
find_host_package(PythonInterp 3 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 ${PYTHON_EXECUTABLE} "${GLSLANG_INTRINSIC_PY}"
"-i" ${GLSLANG_INTRINSIC_HEADER_DIR}
"-o" ${GLSLANG_INTRINSIC_H}
DEPENDS ${GLSLANG_INTRINSIC_PY}
COMMENT "Generating ${GLSLANG_INTRINSIC_H}")
#add_custom_target(glslangValidator DEPENDS ${GLSLANG_INTRINSIC_H})
add_library(glslang-default-resource-limits add_library(glslang-default-resource-limits
${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp) ${CMAKE_CURRENT_SOURCE_DIR}/ResourceLimits.cpp
${CMAKE_CURRENT_SOURCE_DIR}/resource_limits_c.cpp)
set_property(TARGET glslang-default-resource-limits PROPERTY FOLDER glslang) set_property(TARGET glslang-default-resource-limits PROPERTY FOLDER glslang)
set_property(TARGET glslang-default-resource-limits PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET glslang-default-resource-limits PROPERTY POSITION_INDEPENDENT_CODE ON)
@ -7,8 +57,7 @@ target_include_directories(glslang-default-resource-limits
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>) PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}>)
set(SOURCES StandAlone.cpp DirStackFileIncluder.h ${GLSLANG_INTRINSIC_H})
set(SOURCES StandAlone.cpp DirStackFileIncluder.h)
add_executable(glslangValidator ${SOURCES}) add_executable(glslangValidator ${SOURCES})
set_property(TARGET glslangValidator PROPERTY FOLDER tools) set_property(TARGET glslangValidator PROPERTY FOLDER tools)
@ -29,13 +78,19 @@ elseif(UNIX)
if(NOT ANDROID) if(NOT ANDROID)
set(LIBRARIES ${LIBRARIES} pthread) set(LIBRARIES ${LIBRARIES} pthread)
endif() endif()
endif(WIN32) endif()
target_link_libraries(glslangValidator ${LIBRARIES}) target_link_libraries(glslangValidator ${LIBRARIES})
target_include_directories(glslangValidator PUBLIC target_include_directories(glslangValidator PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../External> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../External>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/External>) $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/External>)
if(ENABLE_OPT)
target_include_directories(glslangValidator
PRIVATE ${spirv-tools_SOURCE_DIR}/include
)
endif()
if(ENABLE_SPVREMAPPER) if(ENABLE_SPVREMAPPER)
set(REMAPPER_SOURCES spirv-remap.cpp) set(REMAPPER_SOURCES spirv-remap.cpp)
add_executable(spirv-remap ${REMAPPER_SOURCES}) add_executable(spirv-remap ${REMAPPER_SOURCES})
@ -46,7 +101,7 @@ endif()
if(WIN32) if(WIN32)
source_group("Source" FILES ${SOURCES}) source_group("Source" FILES ${SOURCES})
endif(WIN32) endif()
if(ENABLE_GLSLANG_INSTALL) if(ENABLE_GLSLANG_INSTALL)
install(TARGETS glslangValidator EXPORT glslangValidatorTargets install(TARGETS glslangValidator EXPORT glslangValidatorTargets
@ -61,7 +116,12 @@ if(ENABLE_GLSLANG_INSTALL)
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)
install(TARGETS glslang-default-resource-limits EXPORT glslang-default-resource-limitsTargets install(TARGETS glslang-default-resource-limits EXPORT glslang-default-resource-limitsTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
install(EXPORT glslang-default-resource-limitsTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
else()
install(TARGETS glslang-default-resource-limits EXPORT glslang-default-resource-limitsTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif() endif()
endif(ENABLE_GLSLANG_INSTALL) install(EXPORT glslang-default-resource-limitsTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
endif()

View File

@ -40,6 +40,7 @@
#include <string> #include <string>
#include <fstream> #include <fstream>
#include <algorithm> #include <algorithm>
#include <set>
#include "./../glslang/Public/ShaderLang.h" #include "./../glslang/Public/ShaderLang.h"
@ -84,12 +85,18 @@ public:
} }
} }
virtual std::set<std::string> getIncludedFiles()
{
return includedFiles;
}
virtual ~DirStackFileIncluder() override { } virtual ~DirStackFileIncluder() override { }
protected: protected:
typedef char tUserDataElement; typedef char tUserDataElement;
std::vector<std::string> directoryStack; std::vector<std::string> directoryStack;
int externalLocalDirectoryCount; int externalLocalDirectoryCount;
std::set<std::string> includedFiles;
// Search for a valid "local" path based on combining the stack of include // Search for a valid "local" path based on combining the stack of include
// directories and the nominal name of the header. // directories and the nominal name of the header.
@ -108,6 +115,7 @@ protected:
std::ifstream file(path, std::ios_base::binary | std::ios_base::ate); std::ifstream file(path, std::ios_base::binary | std::ios_base::ate);
if (file) { if (file) {
directoryStack.push_back(getDirectory(path)); directoryStack.push_back(getDirectory(path));
includedFiles.insert(path);
return newIncludeResult(path, file, (int)file.tellg()); return newIncludeResult(path, file, (int)file.tellg());
} }
} }

View File

@ -134,6 +134,7 @@ const TBuiltInResource DefaultTBuiltInResource = {
/* .maxTaskWorkGroupSizeY_NV = */ 1, /* .maxTaskWorkGroupSizeY_NV = */ 1,
/* .maxTaskWorkGroupSizeZ_NV = */ 1, /* .maxTaskWorkGroupSizeZ_NV = */ 1,
/* .maxMeshViewCountNV = */ 4, /* .maxMeshViewCountNV = */ 4,
/* .maxDualSourceDrawBuffersEXT = */ 1,
/* .limits = */ { /* .limits = */ {
/* .nonInductiveForLoops = */ 1, /* .nonInductiveForLoops = */ 1,
@ -243,6 +244,7 @@ std::string GetDefaultTBuiltInResourceString()
<< "MaxTaskWorkGroupSizeY_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeY_NV << "\n" << "MaxTaskWorkGroupSizeY_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeY_NV << "\n"
<< "MaxTaskWorkGroupSizeZ_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeZ_NV << "\n" << "MaxTaskWorkGroupSizeZ_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeZ_NV << "\n"
<< "MaxMeshViewCountNV " << DefaultTBuiltInResource.maxMeshViewCountNV << "\n" << "MaxMeshViewCountNV " << DefaultTBuiltInResource.maxMeshViewCountNV << "\n"
<< "MaxDualSourceDrawBuffersEXT " << DefaultTBuiltInResource.maxDualSourceDrawBuffersEXT << "\n"
<< "nonInductiveForLoops " << DefaultTBuiltInResource.limits.nonInductiveForLoops << "\n" << "nonInductiveForLoops " << DefaultTBuiltInResource.limits.nonInductiveForLoops << "\n"
<< "whileLoops " << DefaultTBuiltInResource.limits.whileLoops << "\n" << "whileLoops " << DefaultTBuiltInResource.limits.whileLoops << "\n"
<< "doWhileLoops " << DefaultTBuiltInResource.limits.doWhileLoops << "\n" << "doWhileLoops " << DefaultTBuiltInResource.limits.doWhileLoops << "\n"

View File

@ -1,6 +1,8 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013-2016 LunarG, Inc. // 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. // All rights reserved.
// //
@ -43,7 +45,6 @@
#include "Worklist.h" #include "Worklist.h"
#include "DirStackFileIncluder.h" #include "DirStackFileIncluder.h"
#include "./../glslang/Include/ShHandle.h" #include "./../glslang/Include/ShHandle.h"
#include "./../glslang/Include/revision.h"
#include "./../glslang/Public/ShaderLang.h" #include "./../glslang/Public/ShaderLang.h"
#include "../SPIRV/GlslangToSpv.h" #include "../SPIRV/GlslangToSpv.h"
#include "../SPIRV/GLSL.std.450.h" #include "../SPIRV/GLSL.std.450.h"
@ -58,11 +59,17 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <thread> #include <thread>
#include <set>
#include "../glslang/OSDependent/osinclude.h" #include "../glslang/OSDependent/osinclude.h"
// Build-time generated includes
#include "glslang/build_info.h"
#include "glslang/glsl_intrinsic_header.h"
extern "C" { extern "C" {
SH_IMPORT_EXPORT void ShOutputHtml(); GLSLANG_EXPORT void ShOutputHtml();
} }
// Command-line options // Command-line options
@ -105,6 +112,10 @@ bool targetHlslFunctionality1 = false;
bool SpvToolsDisassembler = false; bool SpvToolsDisassembler = false;
bool SpvToolsValidate = false; bool SpvToolsValidate = false;
bool NaNClamp = false; bool NaNClamp = false;
bool stripDebugInfo = false;
bool beQuiet = false;
bool VulkanRulesRelaxed = false;
bool autoSampledTextures = false;
// //
// Return codes from main/exit(). // Return codes from main/exit().
@ -159,12 +170,15 @@ int ReflectOptions = EShReflectionDefault;
int Options = 0; int Options = 0;
const char* ExecutableName = nullptr; const char* ExecutableName = nullptr;
const char* binaryFileName = nullptr; const char* binaryFileName = nullptr;
const char* depencyFileName = nullptr;
const char* entryPointName = nullptr; const char* entryPointName = nullptr;
const char* sourceEntryPointName = nullptr; const char* sourceEntryPointName = nullptr;
const char* shaderStageName = nullptr; const char* shaderStageName = nullptr;
const char* variableName = nullptr; const char* variableName = nullptr;
bool HlslEnable16BitTypes = false; bool HlslEnable16BitTypes = false;
bool HlslDX9compatible = false; bool HlslDX9compatible = false;
bool HlslDxPositionW = false;
bool EnhancedMsgs = false;
bool DumpBuiltinSymbols = false; bool DumpBuiltinSymbols = false;
std::vector<std::string> IncludeDirectoryList; std::vector<std::string> IncludeDirectoryList;
@ -178,6 +192,9 @@ glslang::EShTargetClientVersion ClientVersion; // not valid until Client i
glslang::EShTargetLanguage TargetLanguage = glslang::EShTargetNone; glslang::EShTargetLanguage TargetLanguage = glslang::EShTargetNone;
glslang::EShTargetLanguageVersion TargetVersion; // not valid until TargetLanguage is set 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<std::string> Processes; // what should be recorded by OpModuleProcessed, or equivalent std::vector<std::string> Processes; // what should be recorded by OpModuleProcessed, or equivalent
// Per descriptor-set binding base data // Per descriptor-set binding base data
@ -190,6 +207,17 @@ std::array<std::array<unsigned int, EShLangCount>, glslang::EResCount> baseBindi
std::array<std::array<TPerSetBaseBinding, EShLangCount>, glslang::EResCount> baseBindingForSet; std::array<std::array<TPerSetBaseBinding, EShLangCount>, glslang::EResCount> baseBindingForSet;
std::array<std::vector<std::string>, EShLangCount> baseResourceSetBinding; std::array<std::vector<std::string>, EShLangCount> baseResourceSetBinding;
std::vector<std::pair<std::string, glslang::TBlockStorageClass>> 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. // Add things like "#define ..." to a preamble to use in the beginning of the shader.
class TPreamble { class TPreamble {
public: public:
@ -241,7 +269,9 @@ protected:
std::string text; // contents of preamble std::string text; // contents of preamble
}; };
// Track the user's #define and #undef from the command line.
TPreamble UserPreamble; TPreamble UserPreamble;
std::string PreambleString;
// //
// Create the default name for saving a binary if -o is not provided. // Create the default name for saving a binary if -o is not provided.
@ -257,12 +287,12 @@ const char* GetBinaryName(EShLanguage stage)
case EShLangGeometry: name = "geom.spv"; break; case EShLangGeometry: name = "geom.spv"; break;
case EShLangFragment: name = "frag.spv"; break; case EShLangFragment: name = "frag.spv"; break;
case EShLangCompute: name = "comp.spv"; break; case EShLangCompute: name = "comp.spv"; break;
case EShLangRayGenNV: name = "rgen.spv"; break; case EShLangRayGen: name = "rgen.spv"; break;
case EShLangIntersectNV: name = "rint.spv"; break; case EShLangIntersect: name = "rint.spv"; break;
case EShLangAnyHitNV: name = "rahit.spv"; break; case EShLangAnyHit: name = "rahit.spv"; break;
case EShLangClosestHitNV: name = "rchit.spv"; break; case EShLangClosestHit: name = "rchit.spv"; break;
case EShLangMissNV: name = "rmiss.spv"; break; case EShLangMiss: name = "rmiss.spv"; break;
case EShLangCallableNV: name = "rcall.spv"; break; case EShLangCallable: name = "rcall.spv"; break;
case EShLangMeshNV: name = "mesh.spv"; break; case EShLangMeshNV: name = "mesh.spv"; break;
case EShLangTaskNV: name = "task.spv"; break; case EShLangTaskNV: name = "task.spv"; break;
default: name = "unknown"; break; default: name = "unknown"; break;
@ -326,13 +356,13 @@ void ProcessBindingBase(int& argc, char**& argv, glslang::TResourceType res)
lang = FindLanguage(argv[arg++], false); lang = FindLanguage(argv[arg++], false);
} }
if ((argc - arg) > 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) { if ((argc - arg) >= 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) {
// Parse a per-set binding base // Parse a per-set binding base
while ((argc - arg) > 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) { do {
const int baseNum = atoi(argv[arg++]); const int baseNum = atoi(argv[arg++]);
const int setNum = atoi(argv[arg++]); const int setNum = atoi(argv[arg++]);
perSetBase[setNum] = baseNum; perSetBase[setNum] = baseNum;
} } while ((argc - arg) >= 2 && isdigit(argv[arg + 0][0]) && isdigit(argv[arg + 1][0]));
} else { } else {
// Parse single binding base // Parse single binding base
singleBase = atoi(argv[arg++]); singleBase = atoi(argv[arg++]);
@ -390,6 +420,115 @@ void ProcessResourceSetBindingBase(int& argc, char**& argv, std::array<std::vect
} }
} }
//
// Process an optional binding base of one the forms:
// --argname name {uniform|buffer|push_constant}
void ProcessBlockStorage(int& argc, char**& argv, std::vector<std::pair<std::string, glslang::TBlockStorageClass>>& 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 = ::strtol(argv[curArg], NULL, 10);
if (errno || setVal < 0) {
printf("%s: invalid set\n", argv[curArg]);
usage();
}
*set = setVal;
curArg++;
}
if (binding) {
errno = 0;
int bindingVal = ::strtol(argv[curArg], NULL, 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 // Do all command-line argument parsing. This includes building up the work-items
// to be processed later, and saving all the command-line options. // to be processed later, and saving all the command-line options.
@ -518,6 +657,48 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
lowerword == "flatten-uniform-array" || lowerword == "flatten-uniform-array" ||
lowerword == "fua") { lowerword == "fua") {
Options |= EOptionFlattenUniformArrays; 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") { } else if (lowerword == "hlsl-offsets") {
Options |= EOptionHlslOffsets; Options |= EOptionHlslOffsets;
} else if (lowerword == "hlsl-iomap" || } else if (lowerword == "hlsl-iomap" ||
@ -528,6 +709,12 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
HlslEnable16BitTypes = true; HlslEnable16BitTypes = true;
} else if (lowerword == "hlsl-dx9-compatible") { } else if (lowerword == "hlsl-dx9-compatible") {
HlslDX9compatible = true; 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 } else if (lowerword == "invert-y" || // synonyms
lowerword == "iy") { lowerword == "iy") {
Options |= EOptionInvertY; Options |= EOptionInvertY;
@ -553,10 +740,27 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
ReflectOptions |= EShReflectionAllBlockVariables; ReflectOptions |= EShReflectionAllBlockVariables;
} else if (lowerword == "reflect-unwrap-io-blocks") { } else if (lowerword == "reflect-unwrap-io-blocks") {
ReflectOptions |= EShReflectionUnwrapIOBlocks; 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 } else if (lowerword == "resource-set-bindings" || // synonyms
lowerword == "resource-set-binding" || lowerword == "resource-set-binding" ||
lowerword == "rsb") { lowerword == "rsb") {
ProcessResourceSetBindingBase(argc, argv, baseResourceSetBinding); 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 } else if (lowerword == "shift-image-bindings" || // synonyms
lowerword == "shift-image-binding" || lowerword == "shift-image-binding" ||
lowerword == "sib") { lowerword == "sib") {
@ -611,6 +815,9 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
} else if (strcmp(argv[1], "vulkan1.2") == 0) { } else if (strcmp(argv[1], "vulkan1.2") == 0) {
setVulkanSpv(); setVulkanSpv();
ClientVersion = glslang::EShTargetVulkan_1_2; 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) { } else if (strcmp(argv[1], "opengl") == 0) {
setOpenGlSpv(); setOpenGlSpv();
ClientVersion = glslang::EShTargetOpenGL_450; ClientVersion = glslang::EShTargetOpenGL_450;
@ -632,9 +839,13 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
} else if (strcmp(argv[1], "spirv1.5") == 0) { } else if (strcmp(argv[1], "spirv1.5") == 0) {
TargetLanguage = glslang::EShTargetSpv; TargetLanguage = glslang::EShTargetSpv;
TargetVersion = glslang::EShTargetSpv_1_5; TargetVersion = glslang::EShTargetSpv_1_5;
} else if (strcmp(argv[1], "spirv1.6") == 0) {
TargetLanguage = glslang::EShTargetSpv;
TargetVersion = glslang::EShTargetSpv_1_6;
} else } else
Error("--target-env expected one of: vulkan1.0, vulkan1.1, vulkan1.2, opengl,\n" Error("--target-env expected one of: vulkan1.0, vulkan1.1, vulkan1.2,\n"
"spirv1.0, spirv1.1, spirv1.2, spirv1.3, spirv1.4, or spirv1.5"); "vulkan1.3, opengl, spirv1.0, spirv1.1, spirv1.2, spirv1.3,\n"
"spirv1.4, spirv1.5 or spirv1.6");
} }
bumpArg(); bumpArg();
} else if (lowerword == "undef-macro" || } else if (lowerword == "undef-macro" ||
@ -652,8 +863,18 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
variableName = argv[1]; variableName = argv[1];
bumpArg(); bumpArg();
break; break;
} else if (lowerword == "quiet") {
beQuiet = true;
} else if (lowerword == "depfile") {
if (argc <= 1)
Error("no <depfile-name> provided", lowerword.c_str());
depencyFileName = argv[1];
bumpArg();
} else if (lowerword == "version") { } else if (lowerword == "version") {
Options |= EOptionDumpVersions; Options |= EOptionDumpVersions;
} else if (lowerword == "help") {
usage();
break;
} else { } else {
Error("unrecognized command-line option", argv[0]); Error("unrecognized command-line option", argv[0]);
} }
@ -679,6 +900,8 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
setOpenGlSpv(); setOpenGlSpv();
if (argv[0][2] != 0) if (argv[0][2] != 0)
ClientInputSemanticsVersion = getAttachedNumber("-G<num> client input semantics"); ClientInputSemanticsVersion = getAttachedNumber("-G<num> client input semantics");
if (ClientInputSemanticsVersion != 100)
Error("unknown client version for -G, should be 100");
break; break;
case 'H': case 'H':
Options |= EOptionHumanReadableSpv; Options |= EOptionHumanReadableSpv;
@ -702,6 +925,9 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
else else
Error("unknown -O option"); Error("unknown -O option");
break; break;
case 'R':
VulkanRulesRelaxed = true;
break;
case 'S': case 'S':
if (argc <= 1) if (argc <= 1)
Error("no <stage> specified for -S"); Error("no <stage> specified for -S");
@ -715,6 +941,8 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
setVulkanSpv(); setVulkanSpv();
if (argv[0][2] != 0) if (argv[0][2] != 0)
ClientInputSemanticsVersion = getAttachedNumber("-V<num> client input semantics"); ClientInputSemanticsVersion = getAttachedNumber("-V<num> client input semantics");
if (ClientInputSemanticsVersion != 100)
Error("unknown client version for -V, should be 100");
break; break;
case 'c': case 'c':
Options |= EOptionDumpConfig; Options |= EOptionDumpConfig;
@ -739,7 +967,13 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
Error("-f: expected hlsl_functionality1"); Error("-f: expected hlsl_functionality1");
break; break;
case 'g': case 'g':
Options |= EOptionDebug; // Override previous -g or -g0 argument
stripDebugInfo = false;
Options &= ~EOptionDebug;
if (argv[0][2] == '0')
stripDebugInfo = true;
else
Options |= EOptionDebug;
break; break;
case 'h': case 'h':
usage(); usage();
@ -817,6 +1051,10 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
(Options & EOptionReadHlsl) == 0) (Options & EOptionReadHlsl) == 0)
Error("uniform array flattening only valid when compiling HLSL source."); 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 // rationalize client and target language
if (TargetLanguage == glslang::EShTargetNone) { if (TargetLanguage == glslang::EShTargetNone) {
switch (ClientVersion) { switch (ClientVersion) {
@ -832,6 +1070,10 @@ void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItem
TargetLanguage = glslang::EShTargetSpv; TargetLanguage = glslang::EShTargetSpv;
TargetVersion = glslang::EShTargetSpv_1_5; TargetVersion = glslang::EShTargetSpv_1_5;
break; break;
case glslang::EShTargetVulkan_1_3:
TargetLanguage = glslang::EShTargetSpv;
TargetVersion = glslang::EShTargetSpv_1_6;
break;
case glslang::EShTargetOpenGL_450: case glslang::EShTargetOpenGL_450:
TargetLanguage = glslang::EShTargetSpv; TargetLanguage = glslang::EShTargetSpv;
TargetVersion = glslang::EShTargetSpv_1_0; TargetVersion = glslang::EShTargetSpv_1_0;
@ -879,6 +1121,8 @@ void SetMessageOptions(EShMessages& messages)
messages = (EShMessages)(messages | EShMsgHlslDX9Compatible); messages = (EShMessages)(messages | EShMsgHlslDX9Compatible);
if (DumpBuiltinSymbols) if (DumpBuiltinSymbols)
messages = (EShMessages)(messages | EShMsgBuiltinSymbolTable); messages = (EShMessages)(messages | EShMsgBuiltinSymbolTable);
if (EnhancedMsgs)
messages = (EShMessages)(messages | EShMsgEnhanced);
} }
// //
@ -969,6 +1213,46 @@ struct ShaderCompUnit {
} }
}; };
// 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<std::string>& binaryFiles, const std::vector<std::string>& 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 // 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 // in the same program and link them together, making at most one linked module per
@ -985,6 +1269,12 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
EShMessages messages = EShMsgDefault; EShMessages messages = EShMsgDefault;
SetMessageOptions(messages); SetMessageOptions(messages);
DirStackFileIncluder includer;
std::for_each(IncludeDirectoryList.rbegin(), IncludeDirectoryList.rend(), [&includer](const std::string& dir) {
includer.pushExternalLocalDirectory(dir); });
std::vector<std::string> sources;
// //
// Per-shader processing... // Per-shader processing...
// //
@ -992,6 +1282,9 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
glslang::TProgram& program = *new glslang::TProgram; glslang::TProgram& program = *new glslang::TProgram;
for (auto it = compUnits.cbegin(); it != compUnits.cend(); ++it) { for (auto it = compUnits.cbegin(); it != compUnits.cend(); ++it) {
const auto &compUnit = *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); glslang::TShader* shader = new glslang::TShader(compUnit.stage);
shader->setStringsWithLengthsAndNames(compUnit.text, NULL, compUnit.fileNameList, compUnit.count); shader->setStringsWithLengthsAndNames(compUnit.text, NULL, compUnit.fileNameList, compUnit.count);
if (entryPointName) if (entryPointName)
@ -1002,8 +1295,19 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
"Use '-e <name>'.\n"); "Use '-e <name>'.\n");
shader->setSourceEntryPoint(sourceEntryPointName); shader->setSourceEntryPoint(sourceEntryPointName);
} }
shader->setOverrideVersion(GlslVersion);
std::string intrinsicString = getIntrinsic(compUnit.text, compUnit.count);
PreambleString = "";
if (UserPreamble.isSet()) if (UserPreamble.isSet())
shader->setPreamble(UserPreamble.get()); PreambleString.append(UserPreamble.get());
if (!intrinsicString.empty())
PreambleString.append(intrinsicString);
shader->setPreamble(PreambleString.c_str());
shader->addProcesses(Processes); shader->addProcesses(Processes);
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
@ -1023,6 +1327,9 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
shader->setNoStorageFormat((Options & EOptionNoStorageFormat) != 0); shader->setNoStorageFormat((Options & EOptionNoStorageFormat) != 0);
shader->setResourceSetBinding(baseResourceSetBinding[compUnit.stage]); shader->setResourceSetBinding(baseResourceSetBinding[compUnit.stage]);
if (autoSampledTextures)
shader->setTextureSamplerTransformMode(EShTexSampTransUpgradeTextureRemoveSampler);
if (Options & EOptionAutoMapBindings) if (Options & EOptionAutoMapBindings)
shader->setAutoMapBindings(true); shader->setAutoMapBindings(true);
@ -1037,6 +1344,24 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
shader->setUniformLocationBase(uniformBase); shader->setUniformLocationBase(uniformBase);
#endif #endif
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); shader->setNanMinMaxClamp(NaNClamp);
#ifdef ENABLE_HLSL #ifdef ENABLE_HLSL
@ -1048,6 +1373,12 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
if (Options & EOptionInvertY) if (Options & EOptionInvertY)
shader->setInvertY(true); shader->setInvertY(true);
if (HlslDxPositionW)
shader->setDxPositionW(true);
if (EnhancedMsgs)
shader->setEnhancedMsgs();
// Set up the environment, some subsettings take precedence over earlier // Set up the environment, some subsettings take precedence over earlier
// ways of setting things. // ways of setting things.
if (Options & EOptionSpv) { if (Options & EOptionSpv) {
@ -1060,15 +1391,14 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
if (targetHlslFunctionality1) if (targetHlslFunctionality1)
shader->setEnvTargetHlslFunctionality1(); shader->setEnvTargetHlslFunctionality1();
#endif #endif
if (VulkanRulesRelaxed)
shader->setEnvInputVulkanRulesRelaxed();
} }
shaders.push_back(shader); shaders.push_back(shader);
const int defaultVersion = Options & EOptionDefaultDesktop ? 110 : 100; const int defaultVersion = Options & EOptionDefaultDesktop ? 110 : 100;
DirStackFileIncluder includer;
std::for_each(IncludeDirectoryList.rbegin(), IncludeDirectoryList.rend(), [&includer](const std::string& dir) {
includer.pushExternalLocalDirectory(dir); });
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
if (Options & EOptionOutputPreprocessed) { if (Options & EOptionOutputPreprocessed) {
std::string str; std::string str;
@ -1090,7 +1420,8 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
if (! (Options & EOptionSuppressInfolog) && if (! (Options & EOptionSuppressInfolog) &&
! (Options & EOptionMemoryLeakMode)) { ! (Options & EOptionMemoryLeakMode)) {
PutsIfNonEmpty(compUnit.fileName[0].c_str()); if (!beQuiet)
PutsIfNonEmpty(compUnit.fileName[0].c_str());
PutsIfNonEmpty(shader->getInfoLog()); PutsIfNonEmpty(shader->getInfoLog());
PutsIfNonEmpty(shader->getInfoDebugLog()); PutsIfNonEmpty(shader->getInfoDebugLog());
} }
@ -1127,6 +1458,8 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
} }
#endif #endif
std::vector<std::string> outputFiles;
// Dump SPIR-V // Dump SPIR-V
if (Options & EOptionSpv) { if (Options & EOptionSpv) {
if (CompileFailed || LinkFailed) if (CompileFailed || LinkFailed)
@ -1135,11 +1468,12 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
for (int stage = 0; stage < EShLangCount; ++stage) { for (int stage = 0; stage < EShLangCount; ++stage) {
if (program.getIntermediate((EShLanguage)stage)) { if (program.getIntermediate((EShLanguage)stage)) {
std::vector<unsigned int> spirv; std::vector<unsigned int> spirv;
std::string warningsErrors;
spv::SpvBuildLogger logger; spv::SpvBuildLogger logger;
glslang::SpvOptions spvOptions; glslang::SpvOptions spvOptions;
if (Options & EOptionDebug) if (Options & EOptionDebug)
spvOptions.generateDebugInfo = true; spvOptions.generateDebugInfo = true;
else if (stripDebugInfo)
spvOptions.stripDebugInfo = true;
spvOptions.disableOptimizer = (Options & EOptionOptimizeDisable) != 0; spvOptions.disableOptimizer = (Options & EOptionOptimizeDisable) != 0;
spvOptions.optimizeSize = (Options & EOptionOptimizeSize) != 0; spvOptions.optimizeSize = (Options & EOptionOptimizeSize) != 0;
spvOptions.disassemble = SpvToolsDisassembler; spvOptions.disassemble = SpvToolsDisassembler;
@ -1155,6 +1489,8 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
} else { } else {
glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage)); glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage));
} }
outputFiles.push_back(GetBinaryName((EShLanguage)stage));
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
if (!SpvToolsDisassembler && (Options & EOptionHumanReadableSpv)) if (!SpvToolsDisassembler && (Options & EOptionHumanReadableSpv))
spv::Disassemble(std::cout, spirv); spv::Disassemble(std::cout, spirv);
@ -1165,6 +1501,13 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
} }
} }
if (depencyFileName && !(CompileFailed || LinkFailed)) {
std::set<std::string> 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 // Free everything up, program has to go before the shaders
// because it might have merged stuff from the shaders, and // because it might have merged stuff from the shaders, and
// the stuff from the shaders has to have its destructors called // the stuff from the shaders has to have its destructors called
@ -1255,13 +1598,13 @@ int singleMain()
#endif #endif
if (Options & EOptionDumpBareVersion) { if (Options & EOptionDumpBareVersion) {
printf("%d.%d.%d\n", printf("%d:%d.%d.%d%s\n", glslang::GetSpirvGeneratorVersion(), GLSLANG_VERSION_MAJOR, GLSLANG_VERSION_MINOR,
glslang::GetSpirvGeneratorVersion(), GLSLANG_MINOR_VERSION, GLSLANG_PATCH_LEVEL); GLSLANG_VERSION_PATCH, GLSLANG_VERSION_FLAVOR);
if (workList.empty()) if (workList.empty())
return ESuccess; return ESuccess;
} else if (Options & EOptionDumpVersions) { } else if (Options & EOptionDumpVersions) {
printf("Glslang Version: %d.%d.%d\n", printf("Glslang Version: %d:%d.%d.%d%s\n", glslang::GetSpirvGeneratorVersion(), GLSLANG_VERSION_MAJOR,
glslang::GetSpirvGeneratorVersion(), GLSLANG_MINOR_VERSION, GLSLANG_PATCH_LEVEL); GLSLANG_VERSION_MINOR, GLSLANG_VERSION_PATCH, GLSLANG_VERSION_FLAVOR);
printf("ESSL Version: %s\n", glslang::GetEsslVersionString()); printf("ESSL Version: %s\n", glslang::GetEsslVersionString());
printf("GLSL Version: %s\n", glslang::GetGlslVersionString()); printf("GLSL Version: %s\n", glslang::GetGlslVersionString());
std::string spirvVersion; std::string spirvVersion;
@ -1425,17 +1768,17 @@ EShLanguage FindLanguage(const std::string& name, bool parseStageName)
else if (stageName == "comp") else if (stageName == "comp")
return EShLangCompute; return EShLangCompute;
else if (stageName == "rgen") else if (stageName == "rgen")
return EShLangRayGenNV; return EShLangRayGen;
else if (stageName == "rint") else if (stageName == "rint")
return EShLangIntersectNV; return EShLangIntersect;
else if (stageName == "rahit") else if (stageName == "rahit")
return EShLangAnyHitNV; return EShLangAnyHit;
else if (stageName == "rchit") else if (stageName == "rchit")
return EShLangClosestHitNV; return EShLangClosestHit;
else if (stageName == "rmiss") else if (stageName == "rmiss")
return EShLangMissNV; return EShLangMiss;
else if (stageName == "rcall") else if (stageName == "rcall")
return EShLangCallableNV; return EShLangCallable;
else if (stageName == "mesh") else if (stageName == "mesh")
return EShLangMeshNV; return EShLangMeshNV;
else if (stageName == "task") else if (stageName == "task")
@ -1532,12 +1875,16 @@ void usage()
" 'ver', when present, is the version of the input semantics,\n" " 'ver', when present, is the version of the input semantics,\n"
" which will appear in #define GL_SPIRV ver;\n" " which will appear in #define GL_SPIRV ver;\n"
" '--client opengl100' is the same as -G100;\n" " '--client opengl100' is the same as -G100;\n"
" a '--target-env' for OpenGL will also imply '-G'\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" " -H print human readable form of SPIR-V; turns on -V\n"
" -I<dir> add dir to the include search path; includer's directory\n" " -I<dir> add dir to the include search path; includer's directory\n"
" is searched first, followed by left-to-right order of -I\n" " is searched first, followed by left-to-right order of -I\n"
" -Od disables optimization; may cause illegal SPIR-V for HLSL\n" " -Od disables optimization; may cause illegal SPIR-V for HLSL\n"
" -Os optimizes SPIR-V to minimize size\n" " -Os optimizes SPIR-V to minimize size\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 <stage> uses specified stage rather than parsing the file extension\n" " -S <stage> uses specified stage rather than parsing the file extension\n"
" choices for <stage> are vert, tesc, tese, geom, frag, or comp\n" " choices for <stage> are vert, tesc, tese, geom, frag, or comp\n"
" -U<name> | --undef-macro <name> | --U <name>\n" " -U<name> | --undef-macro <name> | --U <name>\n"
@ -1558,6 +1905,7 @@ void usage()
" 'hlsl_functionality1' enables use of the\n" " 'hlsl_functionality1' enables use of the\n"
" SPV_GOOGLE_hlsl_functionality1 extension\n" " SPV_GOOGLE_hlsl_functionality1 extension\n"
" -g generate debug information\n" " -g generate debug information\n"
" -g0 strip debug information\n"
" -h print this usage message\n" " -h print this usage message\n"
" -i intermediate tree (glslang AST) is printed out\n" " -i intermediate tree (glslang AST) is printed out\n"
" -l link all input files together to form a single module\n" " -l link all input files together to form a single module\n"
@ -1579,21 +1927,35 @@ void usage()
" without explicit bindings\n" " without explicit bindings\n"
" --auto-map-locations | --aml automatically locate input/output lacking\n" " --auto-map-locations | --aml automatically locate input/output lacking\n"
" 'location' (fragile, not cross stage)\n" " 'location' (fragile, not cross stage)\n"
" --auto-sampled-textures Removes sampler variables and converts\n"
" existing textures to sampled textures\n"
" --client {vulkan<ver>|opengl<ver>} see -V and -G\n" " --client {vulkan<ver>|opengl<ver>} see -V and -G\n"
" --depfile <file> writes depfile for build systems\n"
" --dump-builtin-symbols prints builtin symbol table prior each compile\n" " --dump-builtin-symbols prints builtin symbol table prior each compile\n"
" -dumpfullversion | -dumpversion print bare major.minor.patchlevel\n" " -dumpfullversion | -dumpversion print bare major.minor.patchlevel\n"
" --flatten-uniform-arrays | --fua flatten uniform texture/sampler arrays to\n" " --flatten-uniform-arrays | --fua flatten uniform texture/sampler arrays to\n"
" scalars\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" " --hlsl-offsets allow block offsets to follow HLSL rules\n"
" works independently of source language\n" " works independently of source language\n"
" --hlsl-iomap perform IO mapping in HLSL register space\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-enable-16bit-types allow 16-bit types in SPIR-V for HLSL\n"
" --hlsl-dx9-compatible interprets sampler declarations as a\n" " --hlsl-dx9-compatible interprets sampler declarations as a\n"
" texture/sampler combo like DirectX9 would.\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" " --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" " --keep-uncalled | --ku don't eliminate uncalled functions\n"
" --nan-clamp favor non-NaN operand in min, max, and clamp\n" " --nan-clamp favor non-NaN operand in min, max, and clamp\n"
" --no-storage-format | --nsf use Unknown image format\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" " --reflect-strict-array-suffix use strict array suffix rules when\n"
" reflecting\n" " reflecting\n"
" --reflect-basic-array-suffix arrays of basic types will have trailing [0]\n" " --reflect-basic-array-suffix arrays of basic types will have trailing [0]\n"
@ -1611,6 +1973,22 @@ void usage()
" --resource-set-binding [stage] set\n" " --resource-set-binding [stage] set\n"
" set descriptor set for all resources\n" " set descriptor set for all resources\n"
" --rsb synonym for --resource-set-binding\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" " --shift-image-binding [stage] num\n"
" base binding number for images (uav)\n" " base binding number for images (uav)\n"
" --shift-image-binding [stage] [num set]...\n" " --shift-image-binding [stage] [num set]...\n"
@ -1647,8 +2025,9 @@ void usage()
" --sep synonym for --source-entrypoint\n" " --sep synonym for --source-entrypoint\n"
" --stdin read from stdin instead of from a file;\n" " --stdin read from stdin instead of from a file;\n"
" requires providing the shader stage using -S\n" " requires providing the shader stage using -S\n"
" --target-env {vulkan1.0 | vulkan1.1 | vulkan1.2 | opengl | \n" " --target-env {vulkan1.0 | vulkan1.1 | vulkan1.2 | vulkan1.3 | opengl |\n"
" spirv1.0 | spirv1.1 | spirv1.2 | spirv1.3 | spirv1.4 | spirv1.5}\n" " spirv1.0 | spirv1.1 | spirv1.2 | spirv1.3 | spirv1.4 |\n"
" spirv1.5 | spirv1.6}\n"
" Set the execution environment that the\n" " Set the execution environment that the\n"
" generated code will be executed in.\n" " generated code will be executed in.\n"
" Defaults to:\n" " Defaults to:\n"
@ -1657,6 +2036,7 @@ void usage()
" * spirv1.0 under --target-env vulkan1.0\n" " * spirv1.0 under --target-env vulkan1.0\n"
" * spirv1.3 under --target-env vulkan1.1\n" " * spirv1.3 under --target-env vulkan1.1\n"
" * spirv1.5 under --target-env vulkan1.2\n" " * spirv1.5 under --target-env vulkan1.2\n"
" * spirv1.6 under --target-env vulkan1.3\n"
" Multiple --target-env can be specified.\n" " Multiple --target-env can be specified.\n"
" --variable-name <name>\n" " --variable-name <name>\n"
" --vn <name> creates a C header file that contains a\n" " --vn <name> creates a C header file that contains a\n"

View File

@ -0,0 +1,65 @@
/**
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 "resource_limits_c.h"
#include "ResourceLimits.h"
#include <stdlib.h>
#include <string.h>
#include <string>
const glslang_resource_t* glslang_default_resource(void)
{
return reinterpret_cast<const glslang_resource_t*>(&glslang::DefaultTBuiltInResource);
}
#if defined(__clang__) || defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
const char* glslang_default_resource_string()
{
std::string cpp_str = glslang::GetDefaultTBuiltInResourceString();
char* c_str = (char*)malloc(cpp_str.length() + 1);
strcpy(c_str, cpp_str.c_str());
return c_str;
}
#if defined(__clang__) || defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif
void glslang_decode_resource_limits(glslang_resource_t* resources, char* config)
{
glslang::DecodeResourceLimits(reinterpret_cast<TBuiltInResource*>(resources), config);
}

View File

@ -0,0 +1,54 @@
/**
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 "../glslang/Include/glslang_c_interface.h"
#ifdef __cplusplus
extern "C" {
#endif
// 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_

View File

@ -334,8 +334,6 @@ int main(int argc, char** argv)
if (outputDir.empty()) if (outputDir.empty())
usage(argv[0], "Output directory required"); usage(argv[0], "Output directory required");
std::string errmsg;
// Main operations: read, remap, and write. // Main operations: read, remap, and write.
execute(inputFile, outputDir, opts, verbosity); execute(inputFile, outputDir, opts, verbosity);

View File

@ -0,0 +1,39 @@
# 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.
declare_args() {
build_with_chromium = false
linux_use_bundled_binutils_override = true
ignore_elf32_limitations = true
use_system_xcode = true
}

View File

@ -34,4 +34,4 @@
# These are variables that are overridable by projects that include glslang. # These are variables that are overridable by projects that include glslang.
# The path to glslang dependencies. # The path to glslang dependencies.
glslang_spirv_tools_dir = "//Externals/spirv-tools" glslang_spirv_tools_dir = "//External/spirv-tools"

View File

@ -0,0 +1,38 @@
# 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.
# We are building inside glslang
spirv_tools_standalone = false
# Paths to SPIRV-Tools dependencies
spirv_tools_spirv_headers_dir = "//External/spirv-tools/external/spirv-headers"

View File

@ -18,6 +18,13 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="glslang\GenericCodeGen\CodeGen.cpp" /> <ClCompile Include="glslang\GenericCodeGen\CodeGen.cpp" />
<ClCompile Include="glslang\GenericCodeGen\Link.cpp" /> <ClCompile Include="glslang\GenericCodeGen\Link.cpp" />
<!--<ClCompile Include="glslang\HLSL\hlslAttributes.cpp" />
<ClCompile Include="glslang\HLSL\hlslGrammar.cpp" />
<ClCompile Include="glslang\HLSL\hlslOpMap.cpp" />
<ClCompile Include="glslang\HLSL\hlslParseables.cpp" />
<ClCompile Include="glslang\HLSL\hlslParseHelper.cpp" />
<ClCompile Include="glslang\HLSL\hlslScanContext.cpp" />
<ClCompile Include="glslang\HLSL\hlslTokenStream.cpp" />-->
<ClCompile Include="glslang\MachineIndependent\attribute.cpp" /> <ClCompile Include="glslang\MachineIndependent\attribute.cpp" />
<ClCompile Include="glslang\MachineIndependent\Constant.cpp" /> <ClCompile Include="glslang\MachineIndependent\Constant.cpp" />
<ClCompile Include="glslang\MachineIndependent\glslang_tab.cpp" /> <ClCompile Include="glslang\MachineIndependent\glslang_tab.cpp" />
@ -43,6 +50,7 @@
<ClCompile Include="glslang\MachineIndependent\RemoveTree.cpp" /> <ClCompile Include="glslang\MachineIndependent\RemoveTree.cpp" />
<ClCompile Include="glslang\MachineIndependent\Scan.cpp" /> <ClCompile Include="glslang\MachineIndependent\Scan.cpp" />
<ClCompile Include="glslang\MachineIndependent\ShaderLang.cpp" /> <ClCompile Include="glslang\MachineIndependent\ShaderLang.cpp" />
<ClCompile Include="glslang\MachineIndependent\SpirvIntrinsics.cpp" />
<ClCompile Include="glslang\MachineIndependent\SymbolTable.cpp" /> <ClCompile Include="glslang\MachineIndependent\SymbolTable.cpp" />
<ClCompile Include="glslang\MachineIndependent\Versions.cpp" /> <ClCompile Include="glslang\MachineIndependent\Versions.cpp" />
<ClCompile Include="glslang\OSDependent\Windows\ossource.cpp" /> <ClCompile Include="glslang\OSDependent\Windows\ossource.cpp" />
@ -58,6 +66,15 @@
<ClCompile Include="StandAlone\ResourceLimits.cpp" /> <ClCompile Include="StandAlone\ResourceLimits.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<!--<ClInclude Include="glslang\HLSL\hlslAttributes.h" />
<ClInclude Include="glslang\HLSL\hlslGrammar.h" />
<ClInclude Include="glslang\HLSL\hlslOpMap.h" />
<ClInclude Include="glslang\HLSL\hlslParseables.h" />
<ClInclude Include="glslang\HLSL\hlslParseHelper.h" />
<ClInclude Include="glslang\HLSL\hlslScanContext.h" />
<ClInclude Include="glslang\HLSL\hlslTokens.h" />
<ClInclude Include="glslang\HLSL\hlslTokenStream.h" />
<ClInclude Include="glslang\HLSL\pch.h" />-->
<ClInclude Include="glslang\Include\arrays.h" /> <ClInclude Include="glslang\Include\arrays.h" />
<ClInclude Include="glslang\Include\BaseTypes.h" /> <ClInclude Include="glslang\Include\BaseTypes.h" />
<ClInclude Include="glslang\Include\Common.h" /> <ClInclude Include="glslang\Include\Common.h" />
@ -68,6 +85,7 @@
<ClInclude Include="glslang\Include\PoolAlloc.h" /> <ClInclude Include="glslang\Include\PoolAlloc.h" />
<ClInclude Include="glslang\Include\revision.h" /> <ClInclude Include="glslang\Include\revision.h" />
<ClInclude Include="glslang\Include\ShHandle.h" /> <ClInclude Include="glslang\Include\ShHandle.h" />
<ClInclude Include="glslang\Include\SpirvIntrinsics.h" />
<ClInclude Include="glslang\Include\Types.h" /> <ClInclude Include="glslang\Include\Types.h" />
<ClInclude Include="glslang\MachineIndependent\attribute.h" /> <ClInclude Include="glslang\MachineIndependent\attribute.h" />
<ClInclude Include="glslang\MachineIndependent\glslang_tab.cpp.h" /> <ClInclude Include="glslang\MachineIndependent\glslang_tab.cpp.h" />
@ -95,6 +113,7 @@
<ClInclude Include="SPIRV\GLSL.std.450.h" /> <ClInclude Include="SPIRV\GLSL.std.450.h" />
<ClInclude Include="SPIRV\GlslangToSpv.h" /> <ClInclude Include="SPIRV\GlslangToSpv.h" />
<ClInclude Include="SPIRV\Logger.h" /> <ClInclude Include="SPIRV\Logger.h" />
<ClInclude Include="SPIRV\NonSemanticDebugPrintf.h" />
<ClInclude Include="SPIRV\spirv.hpp" /> <ClInclude Include="SPIRV\spirv.hpp" />
<ClInclude Include="SPIRV\SpvBuilder.h" /> <ClInclude Include="SPIRV\SpvBuilder.h" />
<ClInclude Include="SPIRV\spvIR.h" /> <ClInclude Include="SPIRV\spvIR.h" />

View File

@ -7,6 +7,27 @@
<ClCompile Include="glslang\GenericCodeGen\CodeGen.cpp"> <ClCompile Include="glslang\GenericCodeGen\CodeGen.cpp">
<Filter>glslang\GenericCodeGen</Filter> <Filter>glslang\GenericCodeGen</Filter>
</ClCompile> </ClCompile>
<!--<ClCompile Include="glslang\HLSL\hlslAttributes.cpp">
<Filter>glslang\HLSL</Filter>
</ClCompile>
<ClCompile Include="glslang\HLSL\hlslGrammar.cpp">
<Filter>glslang\HLSL</Filter>
</ClCompile>
<ClCompile Include="glslang\HLSL\hlslOpMap.cpp">
<Filter>glslang\HLSL</Filter>
</ClCompile>
<ClCompile Include="glslang\HLSL\hlslParseables.cpp">
<Filter>glslang\HLSL</Filter>
</ClCompile>
<ClCompile Include="glslang\HLSL\hlslParseHelper.cpp">
<Filter>glslang\HLSL</Filter>
</ClCompile>
<ClCompile Include="glslang\HLSL\hlslScanContext.cpp">
<Filter>glslang\HLSL</Filter>
</ClCompile>
<ClCompile Include="glslang\HLSL\hlslTokenStream.cpp">
<Filter>glslang\HLSL</Filter>
</ClCompile>-->
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpScanner.cpp"> <ClCompile Include="glslang\MachineIndependent\preprocessor\PpScanner.cpp">
<Filter>glslang\MachineIndependant\preprocessor</Filter> <Filter>glslang\MachineIndependant\preprocessor</Filter>
</ClCompile> </ClCompile>
@ -52,6 +73,9 @@
<ClCompile Include="glslang\MachineIndependent\ShaderLang.cpp"> <ClCompile Include="glslang\MachineIndependent\ShaderLang.cpp">
<Filter>glslang\MachineIndependant</Filter> <Filter>glslang\MachineIndependant</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="glslang\MachineIndependent\SpirvIntrinsics.cpp">
<Filter>glslang\MachineIndependant</Filter>
</ClCompile>
<ClCompile Include="glslang\MachineIndependent\SymbolTable.cpp"> <ClCompile Include="glslang\MachineIndependent\SymbolTable.cpp">
<Filter>glslang\MachineIndependant</Filter> <Filter>glslang\MachineIndependant</Filter>
</ClCompile> </ClCompile>
@ -126,9 +150,6 @@
<ClInclude Include="StandAlone\ResourceLimits.h"> <ClInclude Include="StandAlone\ResourceLimits.h">
<Filter>StandAlone</Filter> <Filter>StandAlone</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="glslang\Include\revision.h">
<Filter>glslang\Include</Filter>
</ClInclude>
<ClInclude Include="glslang\Include\ShHandle.h"> <ClInclude Include="glslang\Include\ShHandle.h">
<Filter>glslang\Include</Filter> <Filter>glslang\Include</Filter>
</ClInclude> </ClInclude>
@ -228,6 +249,9 @@
<ClInclude Include="SPIRV\Logger.h"> <ClInclude Include="SPIRV\Logger.h">
<Filter>SPIRV</Filter> <Filter>SPIRV</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="SPIRV\NonSemanticDebugPrintf.h">
<Filter>SPIRV</Filter>
</ClInclude>
<ClInclude Include="SPIRV\spirv.hpp"> <ClInclude Include="SPIRV\spirv.hpp">
<Filter>SPIRV</Filter> <Filter>SPIRV</Filter>
</ClInclude> </ClInclude>

View File

@ -0,0 +1,471 @@
/**
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 "StandAlone/ResourceLimits.h"
#include "glslang/Include/ShHandle.h"
#include "glslang/Include/ResourceLimits.h"
#include "glslang/MachineIndependent/Versions.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<unsigned int> 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:
/* Wrapper of IncludeResult which stores a glsl_include_result object internally */
class CallbackIncludeResult : public glslang::TShader::Includer::IncludeResult {
public:
CallbackIncludeResult(const std::string& headerName, const char* const headerData, const size_t headerLength,
void* userData, glsl_include_result_t* includeResult)
: glslang::TShader::Includer::IncludeResult(headerName, headerData, headerLength, userData),
includeResult(includeResult)
{
}
virtual ~CallbackIncludeResult() {}
protected:
friend class CallbackIncluder;
glsl_include_result_t* includeResult;
};
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 new CallbackIncludeResult(std::string(headerName), result->header_data, result->header_length,
nullptr, 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 new CallbackIncludeResult(std::string(headerName), result->header_data, result->header_length,
nullptr, 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 && (result->userData == nullptr)) {
CallbackIncludeResult* innerResult = static_cast<CallbackIncludeResult*>(result);
/* use internal free() function */
this->callbacks.free_include_result(this->context, innerResult->includeResult);
/* ignore internal fields of TShader::Includer::IncludeResult */
delete result;
return;
}
delete[] static_cast<char*>(result->userData);
delete result;
}
private:
CallbackIncluder() {}
/* C callback pointers */
glsl_include_callbacks_t callbacks;
/* User-defined context */
void* context;
};
GLSLANG_EXPORT int glslang_initialize_process() { return static_cast<int>(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_NV:
return EShLangTaskNV;
case GLSLANG_STAGE_MESH_NV:
return EShLangMeshNV;
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_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 Includer;
/* TODO: use custom callbacks if they are available in 'i->callbacks' */
return shader->shader->preprocess(
reinterpret_cast<const TBuiltInResource*>(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<const TBuiltInResource*>(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 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();
}

View File

@ -1,16 +1,62 @@
# 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) if(WIN32)
add_subdirectory(OSDependent/Windows) add_subdirectory(OSDependent/Windows)
elseif(UNIX) elseif(UNIX OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia")
add_subdirectory(OSDependent/Unix) add_subdirectory(OSDependent/Unix)
else(WIN32) else()
message("unknown platform") message("unknown platform")
endif(WIN32) endif()
if(EMSCRIPTEN OR ENABLE_GLSLANG_WEB) if(EMSCRIPTEN OR ENABLE_GLSLANG_JS)
# May be enabled on non-Emscripten builds for binary-size testing.
add_subdirectory(OSDependent/Web) add_subdirectory(OSDependent/Web)
endif(EMSCRIPTEN OR ENABLE_GLSLANG_WEB) endif()
set(SOURCES ################################################################################
# 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.m4 MachineIndependent/glslang.m4
MachineIndependent/glslang.y MachineIndependent/glslang.y
MachineIndependent/glslang_tab.cpp MachineIndependent/glslang_tab.cpp
@ -27,6 +73,7 @@ set(SOURCES
MachineIndependent/RemoveTree.cpp MachineIndependent/RemoveTree.cpp
MachineIndependent/Scan.cpp MachineIndependent/Scan.cpp
MachineIndependent/ShaderLang.cpp MachineIndependent/ShaderLang.cpp
MachineIndependent/SpirvIntrinsics.cpp
MachineIndependent/SymbolTable.cpp MachineIndependent/SymbolTable.cpp
MachineIndependent/Versions.cpp MachineIndependent/Versions.cpp
MachineIndependent/intermOut.cpp MachineIndependent/intermOut.cpp
@ -40,23 +87,9 @@ set(SOURCES
MachineIndependent/preprocessor/PpScanner.cpp MachineIndependent/preprocessor/PpScanner.cpp
MachineIndependent/preprocessor/PpTokens.cpp MachineIndependent/preprocessor/PpTokens.cpp
MachineIndependent/propagateNoContraction.cpp MachineIndependent/propagateNoContraction.cpp
GenericCodeGen/CodeGen.cpp )
GenericCodeGen/Link.cpp)
set(HEADERS set(MACHINEINDEPENDENT_HEADERS
Public/ShaderLang.h
Include/arrays.h
Include/BaseTypes.h
Include/Common.h
Include/ConstantUnion.h
Include/InfoSink.h
Include/InitializeGlobals.h
Include/intermediate.h
Include/PoolAlloc.h
Include/ResourceLimits.h
Include/revision.h
Include/ShHandle.h
Include/Types.h
MachineIndependent/attribute.h MachineIndependent/attribute.h
MachineIndependent/glslang_tab.cpp.h MachineIndependent/glslang_tab.cpp.h
MachineIndependent/gl_types.h MachineIndependent/gl_types.h
@ -74,50 +107,122 @@ set(HEADERS
MachineIndependent/parseVersions.h MachineIndependent/parseVersions.h
MachineIndependent/propagateNoContraction.h MachineIndependent/propagateNoContraction.h
MachineIndependent/preprocessor/PpContext.h MachineIndependent/preprocessor/PpContext.h
MachineIndependent/preprocessor/PpTokens.h) MachineIndependent/preprocessor/PpTokens.h
)
glslang_pch(SOURCES MachineIndependent/pch.cpp) 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)
add_library(glslang ${LIB_TYPE} ${BISON_GLSLParser_OUTPUT_SOURCE} ${SOURCES} ${HEADERS}) list(APPEND MACHINEINDEPENDENT_HEADERS
set_property(TARGET glslang PROPERTY FOLDER glslang) HLSL/hlslAttributes.h
set_property(TARGET glslang PROPERTY POSITION_INDEPENDENT_CODE ON) HLSL/hlslParseHelper.h
target_link_libraries(glslang OGLCompiler OSDependent) HLSL/hlslTokens.h
target_include_directories(glslang PUBLIC HLSL/hlslScanContext.h
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..> HLSL/hlslOpMap.h
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>) 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)
glslang_add_build_info_dependency(MachineIndependent)
glslang_pch(MachineIndependent MachineIndependent/pch.h)
target_link_libraries(MachineIndependent PRIVATE OGLCompiler 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} ${BISON_GLSLParser_OUTPUT_SOURCE} ${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 OGLCompiler OSDependent MachineIndependent)
target_include_directories(glslang PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
glslang_add_build_info_dependency(glslang)
glslang_only_export_explicit_symbols(glslang)
if(WIN32 AND BUILD_SHARED_LIBS) if(WIN32 AND BUILD_SHARED_LIBS)
set_target_properties(glslang PROPERTIES PREFIX "") set_target_properties(glslang PROPERTIES PREFIX "")
endif() endif()
if(ENABLE_HLSL) ################################################################################
target_link_libraries(glslang HLSL) # source_groups
endif() ################################################################################
if(WIN32) if(WIN32)
source_group("Public" REGULAR_EXPRESSION "Public/*") source_group("Public" REGULAR_EXPRESSION "Public/*")
source_group("MachineIndependent" REGULAR_EXPRESSION "MachineIndependent/[^/]*") source_group("MachineIndependent" REGULAR_EXPRESSION "MachineIndependent/[^/]*")
source_group("Include" REGULAR_EXPRESSION "Include/[^/]*") source_group("Include" REGULAR_EXPRESSION "Include/[^/]*")
source_group("GenericCodeGen" REGULAR_EXPRESSION "GenericCodeGen/*") source_group("GenericCodeGen" REGULAR_EXPRESSION "GenericCodeGen/*")
source_group("MachineIndependent\\Preprocessor" REGULAR_EXPRESSION "MachineIndependent/preprocessor/*") source_group("MachineIndependent\\Preprocessor" REGULAR_EXPRESSION "MachineIndependent/preprocessor/*")
endif(WIN32) source_group("HLSL" REGULAR_EXPRESSION "HLSL/*")
source_group("CInterface" REGULAR_EXPRESSION "CInterface/*")
endif()
################################################################################
# install
################################################################################
if(ENABLE_GLSLANG_INSTALL) if(ENABLE_GLSLANG_INSTALL)
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)
install(TARGETS glslang EXPORT glslangTargets install(TARGETS glslang
EXPORT glslangTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
else() else()
install(TARGETS glslang EXPORT glslangTargets install(TARGETS glslang MachineIndependent GenericCodeGen
EXPORT glslangTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif() endif()
install(EXPORT glslangTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
endif(ENABLE_GLSLANG_INSTALL)
if(ENABLE_GLSLANG_INSTALL) install(EXPORT glslangTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake)
foreach(file ${HEADERS})
set(ALL_HEADERS
${GLSLANG_HEADERS}
${MACHINEINDEPENDENT_HEADERS})
foreach(file ${ALL_HEADERS})
get_filename_component(dir ${file} DIRECTORY) get_filename_component(dir ${file} DIRECTORY)
install(FILES ${file} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/${dir}) install(FILES ${file} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/${dir})
endforeach() endforeach()
endif(ENABLE_GLSLANG_INSTALL)
install(FILES ${GLSLANG_BUILD_INFO_H} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang)
endif()

View File

@ -1,5 +1,9 @@
// //
// Copyright (C) 2018 The Khronos Group Inc. // 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. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
@ -32,4 +36,3 @@
// POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
// //
#include "pch.h"

View File

@ -39,8 +39,8 @@
#include <unordered_map> #include <unordered_map>
#include <functional> #include <functional>
#include "../glslang/MachineIndependent/attribute.h" #include "../MachineIndependent/attribute.h"
#include "../glslang/MachineIndependent/SymbolTable.h" #include "../MachineIndependent/SymbolTable.h"
#include "hlslScanContext.h" #include "hlslScanContext.h"
namespace glslang { namespace glslang {

View File

@ -161,8 +161,10 @@ bool HlslGrammar::acceptDeclarationList(TIntermNode*& nodeList)
return true; return true;
// declaration // declaration
if (! acceptDeclaration(nodeList)) if (! acceptDeclaration(nodeList)) {
expected("declaration");
return false; return false;
}
} while (true); } while (true);
return true; return true;
@ -382,6 +384,16 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
if (forbidDeclarators) if (forbidDeclarators)
return true; 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_list
// : declarator // : declarator
// : identifier // : identifier
@ -470,8 +482,9 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
} }
// TODO: things scoped within an annotation need their own name space; // TODO: things scoped within an annotation need their own name space;
// TODO: strings are not yet handled. // TODO: non-constant strings are not yet handled.
if (variableType.getBasicType() != EbtString && parseContext.getAnnotationNestingLevel() == 0) { if (!(variableType.getBasicType() == EbtString && !variableType.getQualifier().isConstant()) &&
parseContext.getAnnotationNestingLevel() == 0) {
if (typedefDecl) if (typedefDecl)
parseContext.declareTypedef(idToken.loc, *fullName, variableType); parseContext.declareTypedef(idToken.loc, *fullName, variableType);
else if (variableType.getBasicType() == EbtBlock) { else if (variableType.getBasicType() == EbtBlock) {
@ -697,7 +710,9 @@ bool HlslGrammar::acceptQualifier(TQualifier& qualifier)
qualifier.noContraction = true; qualifier.noContraction = true;
break; break;
case EHTokIn: case EHTokIn:
qualifier.storage = (qualifier.storage == EvqOut) ? EvqInOut : EvqIn; if (qualifier.storage != EvqUniform) {
qualifier.storage = (qualifier.storage == EvqOut) ? EvqInOut : EvqIn;
}
break; break;
case EHTokOut: case EHTokOut:
qualifier.storage = (qualifier.storage == EvqIn) ? EvqInOut : EvqOut; qualifier.storage = (qualifier.storage == EvqIn) ? EvqInOut : EvqOut;
@ -2516,6 +2531,8 @@ bool HlslGrammar::acceptMemberFunctionDefinition(TIntermNode*& nodeList, const T
// //
bool HlslGrammar::acceptFunctionParameters(TFunction& function) bool HlslGrammar::acceptFunctionParameters(TFunction& function)
{ {
parseContext.beginParameterParsing(function);
// LEFT_PAREN // LEFT_PAREN
if (! acceptTokenClass(EHTokLeftParen)) if (! acceptTokenClass(EHTokLeftParen))
return false; return false;
@ -3227,7 +3244,7 @@ bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
} }
// hook it up // hook it up
node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments); node = parseContext.handleFunctionCall(token.loc, constructorFunction, arguments);
return node != nullptr; return node != nullptr;
} }

View File

@ -39,11 +39,11 @@
#include "hlslGrammar.h" #include "hlslGrammar.h"
#include "hlslAttributes.h" #include "hlslAttributes.h"
#include "../glslang/Include/Common.h" #include "../Include/Common.h"
#include "../glslang/MachineIndependent/Scan.h" #include "../MachineIndependent/Scan.h"
#include "../glslang/MachineIndependent/preprocessor/PpContext.h" #include "../MachineIndependent/preprocessor/PpContext.h"
#include "../glslang/OSDependent/osinclude.h" #include "../OSDependent/osinclude.h"
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
@ -69,7 +69,8 @@ HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& int
clipDistanceOutput(nullptr), clipDistanceOutput(nullptr),
cullDistanceOutput(nullptr), cullDistanceOutput(nullptr),
clipDistanceInput(nullptr), clipDistanceInput(nullptr),
cullDistanceInput(nullptr) cullDistanceInput(nullptr),
parsingEntrypointParameters(false)
{ {
globalUniformDefaults.clear(); globalUniformDefaults.clear();
globalUniformDefaults.layoutMatrix = ElmRowMajor; globalUniformDefaults.layoutMatrix = ElmRowMajor;
@ -756,9 +757,6 @@ TIntermTyped* HlslParseContext::handleBracketOperator(const TSourceLoc& loc, TIn
// indexStructBufferContent returns nullptr if it isn't a structuredbuffer (SSBO). // indexStructBufferContent returns nullptr if it isn't a structuredbuffer (SSBO).
TIntermTyped* sbArray = indexStructBufferContent(loc, base); TIntermTyped* sbArray = indexStructBufferContent(loc, base);
if (sbArray != nullptr) { if (sbArray != nullptr) {
if (sbArray == nullptr)
return nullptr;
// Now we'll apply the [] index to that array // Now we'll apply the [] index to that array
const TOperator idxOp = (index->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect; const TOperator idxOp = (index->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect;
@ -816,7 +814,7 @@ TIntermTyped* HlslParseContext::handleBracketDereference(const TSourceLoc& loc,
base->getAsSymbolNode()->getName().c_str(), ""); base->getAsSymbolNode()->getName().c_str(), "");
else else
error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", ""); error(loc, " left of '[' is not of type array, matrix, or vector ", "expression", "");
} else if (base->getType().getQualifier().isFrontEndConstant() && } else if (base->getType().getQualifier().isFrontEndConstant() &&
index->getQualifier().isFrontEndConstant()) { index->getQualifier().isFrontEndConstant()) {
// both base and index are front-end constants // both base and index are front-end constants
checkIndex(loc, base->getType(), indexValue); checkIndex(loc, base->getType(), indexValue);
@ -1171,7 +1169,7 @@ bool HlslParseContext::shouldFlatten(const TType& type, TStorageQualifier qualif
} }
// Top level variable flattening: construct data // Top level variable flattening: construct data
void HlslParseContext::flatten(const TVariable& variable, bool linkage) void HlslParseContext::flatten(const TVariable& variable, bool linkage, bool arrayed)
{ {
const TType& type = variable.getType(); const TType& type = variable.getType();
@ -1183,8 +1181,15 @@ void HlslParseContext::flatten(const TVariable& variable, bool linkage)
TFlattenData(type.getQualifier().layoutBinding, TFlattenData(type.getQualifier().layoutBinding,
type.getQualifier().layoutLocation))); type.getQualifier().layoutLocation)));
// the item is a map pair, so first->second is the TFlattenData itself. // if flattening arrayed io struct, array each member of dereferenced type
flatten(variable, type, entry.first->second, variable.getName(), linkage, type.getQualifier(), nullptr); 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. // Recursively flatten the given variable at the provided type, building the flattenData as we go.
@ -1258,6 +1263,10 @@ int HlslParseContext::addFlattenedMember(const TVariable& variable, const TType&
} }
} }
// 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<int>(flattenData.members.size())); flattenData.offsets.push_back(static_cast<int>(flattenData.members.size()));
flattenData.members.push_back(memberVariable); flattenData.members.push_back(memberVariable);
@ -1367,7 +1376,7 @@ TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member)
return flattened ? flattened : base; return flattened ? flattened : base;
} }
TIntermTyped* HlslParseContext::flattenAccess(int uniqueId, int member, TStorageQualifier outerStorage, TIntermTyped* HlslParseContext::flattenAccess(long long uniqueId, int member, TStorageQualifier outerStorage,
const TType& dereferencedType, int subset) const TType& dereferencedType, int subset)
{ {
const auto flattenData = flattenMap.find(uniqueId); const auto flattenData = flattenMap.find(uniqueId);
@ -1435,7 +1444,7 @@ int HlslParseContext::findSubtreeOffset(const TType& type, int subset, const TVe
}; };
// Find and return the split IO TVariable for id, or nullptr if none. // Find and return the split IO TVariable for id, or nullptr if none.
TVariable* HlslParseContext::getSplitNonIoVar(int id) const TVariable* HlslParseContext::getSplitNonIoVar(long long id) const
{ {
const auto splitNonIoVar = splitNonIoVars.find(id); const auto splitNonIoVar = splitNonIoVars.find(id);
if (splitNonIoVar == splitNonIoVars.end()) if (splitNonIoVar == splitNonIoVars.end())
@ -1839,7 +1848,7 @@ void HlslParseContext::handleEntryPointAttributes(const TSourceLoc& loc, const T
error(loc, "invalid partitioning", "", ""); error(loc, "invalid partitioning", "", "");
} else { } else {
TVertexSpacing partitioning = EvsNone; TVertexSpacing partitioning = EvsNone;
if (partitionStr == "integer") { if (partitionStr == "integer") {
partitioning = EvsEqual; partitioning = EvsEqual;
} else if (partitionStr == "fractional_even") { } else if (partitionStr == "fractional_even") {
@ -1944,6 +1953,10 @@ void HlslParseContext::transferTypeAttributes(const TSourceLoc& loc, const TAttr
break; break;
case EatConstantId: case EatConstantId:
// specialization constant // specialization constant
if (type.getQualifier().storage != EvqConst) {
error(loc, "needs a const type", "constant_id", "");
break;
}
if (it->getInt(value)) { if (it->getInt(value)) {
TSourceLoc loc; TSourceLoc loc;
loc.init(); loc.init();
@ -2049,7 +2062,7 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
}; };
// if we aren't in the entry point, fix the IO as such and exit // if we aren't in the entry point, fix the IO as such and exit
if (userFunction.getName().compare(intermediate.getEntryPointName().c_str()) != 0) { if (! isEntrypointName(userFunction.getName())) {
remapNonEntryPointIO(userFunction); remapNonEntryPointIO(userFunction);
return nullptr; return nullptr;
} }
@ -2070,11 +2083,8 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
// Further this return/in/out transform by flattening, splitting, and assigning locations // Further this return/in/out transform by flattening, splitting, and assigning locations
const auto makeVariableInOut = [&](TVariable& variable) { const auto makeVariableInOut = [&](TVariable& variable) {
if (variable.getType().isStruct()) { if (variable.getType().isStruct()) {
if (variable.getType().getQualifier().isArrayedIo(language)) { bool arrayed = variable.getType().getQualifier().isArrayedIo(language);
if (variable.getType().containsBuiltIn()) flatten(variable, false /* don't track linkage here, it will be tracked in assignToInterface() */, arrayed);
split(variable);
} else if (shouldFlatten(variable.getType(), EvqVaryingIn /* not assigned yet, but close enough */, true))
flatten(variable, false /* don't track linkage here, it will be tracked in assignToInterface() */);
} }
// TODO: flatten arrays too // TODO: flatten arrays too
// TODO: flatten everything in I/O // TODO: flatten everything in I/O
@ -2105,6 +2115,23 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
makeVariableInOut(*(*it)); makeVariableInOut(*(*it));
} }
// Add uniform parameters to the $Global uniform block.
TVector<TVariable*> 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 // Synthesize the call
pushScope(); // matches the one in handleFunctionBody() pushScope(); // matches the one in handleFunctionBody()
@ -2125,6 +2152,7 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
TVector<TVariable*> argVars; TVector<TVariable*> argVars;
TIntermAggregate* synthBody = new TIntermAggregate(); TIntermAggregate* synthBody = new TIntermAggregate();
auto inputIt = inputs.begin(); auto inputIt = inputs.begin();
auto opaqueUniformIt = opaque_uniforms.begin();
TIntermTyped* callingArgs = nullptr; TIntermTyped* callingArgs = nullptr;
for (int i = 0; i < userFunction.getParamCount(); i++) { for (int i = 0; i < userFunction.getParamCount(); i++) {
@ -2139,10 +2167,34 @@ TIntermNode* HlslParseContext::transformEntryPoint(const TSourceLoc& loc, TFunct
TIntermSymbol* arg = intermediate.addSymbol(*argVars.back()); TIntermSymbol* arg = intermediate.addSymbol(*argVars.back());
handleFunctionArgument(&callee, callingArgs, arg); handleFunctionArgument(&callee, callingArgs, arg);
if (param.type->getQualifier().isParamInput()) { if (param.type->getQualifier().isParamInput()) {
intermediate.growAggregate(synthBody, handleAssign(loc, EOpAssign, arg, TIntermTyped* input = intermediate.addSymbol(**inputIt);
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++; 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 // Call
@ -2413,6 +2465,62 @@ void HlslParseContext::handleFunctionArgument(TFunction* function,
arguments = newArg; 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. // Position may require special handling: we can optionally invert Y.
// See: https://github.com/KhronosGroup/glslang/issues/1173 // See: https://github.com/KhronosGroup/glslang/issues/1173
// https://github.com/KhronosGroup/glslang/issues/494 // https://github.com/KhronosGroup/glslang/issues/494
@ -2449,7 +2557,7 @@ TIntermTyped* HlslParseContext::assignPosition(const TSourceLoc& loc, TOperator
TIntermTyped* rhsElement = intermediate.addIndex(EOpIndexDirect, tempSymR, index, loc); TIntermTyped* rhsElement = intermediate.addIndex(EOpIndexDirect, tempSymR, index, loc);
const TType derefType(right->getType(), 0); const TType derefType(right->getType(), 0);
lhsElement->setType(derefType); lhsElement->setType(derefType);
rhsElement->setType(derefType); rhsElement->setType(derefType);
@ -2469,7 +2577,7 @@ TIntermTyped* HlslParseContext::assignPosition(const TSourceLoc& loc, TOperator
return assignList; return assignList;
} }
// Clip and cull distance require special handling due to a semantic mismatch. In HLSL, // 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. // 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 // In SPIR-V, they are arrays of scalar floats in all cases. We must copy individual components
@ -2538,7 +2646,7 @@ TIntermAggregate* HlslParseContext::assignClipCullDistance(const TSourceLoc& loc
vecItems += (*semanticNSize)[x]; vecItems += (*semanticNSize)[x];
arrayLoc += (*semanticNSize)[x]; arrayLoc += (*semanticNSize)[x];
} }
// It can have up to 2 array dimensions (in the case of geometry shader inputs) // It can have up to 2 array dimensions (in the case of geometry shader inputs)
const TArraySizes* const internalArraySizes = internalNode->getType().getArraySizes(); const TArraySizes* const internalArraySizes = internalNode->getType().getArraySizes();
@ -2559,7 +2667,7 @@ TIntermAggregate* HlslParseContext::assignClipCullDistance(const TSourceLoc& loc
// into a float array, or vice versa. Here, we make the array the right size and type, // 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: // which depends on the incoming data, which has several potential dimensions:
// * Semantic ID // * Semantic ID
// * vector size // * vector size
// * array size // * array size
// Of those, semantic ID and array size cannot appear simultaneously. // Of those, semantic ID and array size cannot appear simultaneously.
// //
@ -2620,7 +2728,7 @@ TIntermAggregate* HlslParseContext::assignClipCullDistance(const TSourceLoc& loc
// Holds individual component assignments as we make them. // Holds individual component assignments as we make them.
TIntermTyped* clipCullAssign = nullptr; TIntermTyped* clipCullAssign = nullptr;
// If the types are homomorphic, use a simple assign. No need to mess about with // If the types are homomorphic, use a simple assign. No need to mess about with
// individual components. // individual components.
if (clipCullSym->getType().isArray() == internalNode->getType().isArray() && if (clipCullSym->getType().isArray() == internalNode->getType().isArray() &&
clipCullInnerArraySize == internalInnerArraySize && clipCullInnerArraySize == internalInnerArraySize &&
@ -2731,23 +2839,39 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
if (binaryNode == nullptr) if (binaryNode == nullptr)
return false; return false;
return (binaryNode->getOp() == EOpIndexDirect || binaryNode->getOp() == EOpIndexIndirect) && return (binaryNode->getOp() == EOpIndexDirect || binaryNode->getOp() == EOpIndexIndirect) &&
wasSplit(binaryNode->getLeft()); 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 // Return true if this stage assigns clip position with potentially inverted Y
const auto assignsClipPos = [this](const TIntermTyped* node) -> bool { const auto assignsClipPos = [this](const TIntermTyped* node) -> bool {
return node->getType().getQualifier().builtIn == EbvPosition && return node->getType().getQualifier().builtIn == EbvPosition &&
(language == EShLangVertex || language == EShLangGeometry || language == EShLangTessEvaluation); (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 isSplitLeft = wasSplit(left) || indexesSplit(left);
const bool isSplitRight = wasSplit(right) || indexesSplit(right); const bool isSplitRight = wasSplit(right) || indexesSplit(right);
const bool isFlattenLeft = wasFlattened(left); const bool isFlattenLeft = wasFlattened(leftSymbol);
const bool isFlattenRight = wasFlattened(right); const bool isFlattenRight = wasFlattened(rightSymbol);
// OK to do a single assign if neither side is split or flattened. Otherwise, // OK to do a single assign if neither side is split or flattened. Otherwise,
// fall through to a member-wise copy. // fall through to a member-wise copy.
if (!isFlattenLeft && !isFlattenRight && !isSplitLeft && !isSplitRight) { if (!isFlattenLeft && !isFlattenRight && !isSplitLeft && !isSplitRight) {
// Clip and cull distance requires more processing. See comment above assignClipCullDistance. // Clip and cull distance requires more processing. See comment above assignClipCullDistance.
@ -2793,10 +2917,10 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
memberCount = left->getType().getCumulativeArraySize(); memberCount = left->getType().getCumulativeArraySize();
if (isFlattenLeft) if (isFlattenLeft)
leftVariables = &flattenMap.find(left->getAsSymbolNode()->getId())->second.members; leftVariables = &flattenMap.find(leftSymbol->getId())->second.members;
if (isFlattenRight) { if (isFlattenRight) {
rightVariables = &flattenMap.find(right->getAsSymbolNode()->getId())->second.members; rightVariables = &flattenMap.find(rightSymbol->getId())->second.members;
} else { } else {
// The RHS is not flattened. There are several cases: // The RHS is not flattened. There are several cases:
// 1. 1 item to copy: Use the RHS directly. // 1. 1 item to copy: Use the RHS directly.
@ -2830,8 +2954,10 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
TStorageQualifier leftStorage = left->getType().getQualifier().storage; TStorageQualifier leftStorage = left->getType().getQualifier().storage;
TStorageQualifier rightStorage = right->getType().getQualifier().storage; TStorageQualifier rightStorage = right->getType().getQualifier().storage;
int leftOffset = findSubtreeOffset(*left); int leftOffsetStart = findSubtreeOffset(*left);
int rightOffset = findSubtreeOffset(*right); int rightOffsetStart = findSubtreeOffset(*right);
int leftOffset = leftOffsetStart;
int rightOffset = rightOffsetStart;
const auto getMember = [&](bool isLeft, const TType& type, int member, TIntermTyped* splitNode, int splitMember, const auto getMember = [&](bool isLeft, const TType& type, int member, TIntermTyped* splitNode, int splitMember,
bool flattened) bool flattened)
@ -2871,10 +2997,35 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
} }
} }
} else if (flattened && !shouldFlatten(derefType, isLeft ? leftStorage : rightStorage, false)) { } else if (flattened && !shouldFlatten(derefType, isLeft ? leftStorage : rightStorage, false)) {
if (isLeft) if (isLeft) {
// offset will cycle through variables for arrayed io
if (leftOffset >= static_cast<int>(leftVariables->size()))
leftOffset = leftOffsetStart;
subTree = intermediate.addSymbol(*(*leftVariables)[leftOffset++]); subTree = intermediate.addSymbol(*(*leftVariables)[leftOffset++]);
else } else {
// offset will cycle through variables for arrayed io
if (rightOffset >= static_cast<int>(rightVariables->size()))
rightOffset = rightOffsetStart;
subTree = intermediate.addSymbol(*(*rightVariables)[rightOffset++]); 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 { } else {
// Index operator if it's an aggregate, else EOpNull // Index operator if it's an aggregate, else EOpNull
const TOperator accessOp = type.isArray() ? EOpIndexDirect const TOperator accessOp = type.isArray() ? EOpIndexDirect
@ -2989,6 +3140,10 @@ TIntermTyped* HlslParseContext::handleAssign(const TSourceLoc& loc, TOperator op
subSplitLeft, subSplitRight); subSplitLeft, subSplitRight);
assignList = intermediate.growAggregate(assignList, clipCullAssign, loc); 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)) { } else if (assignsClipPos(subSplitLeft)) {
// Position can require special handling: see comment above assignPosition // Position can require special handling: see comment above assignPosition
TIntermTyped* positionAssign = assignPosition(loc, op, subSplitLeft, subSplitRight); TIntermTyped* positionAssign = assignPosition(loc, op, subSplitLeft, subSplitRight);
@ -3174,7 +3329,7 @@ TIntermAggregate* HlslParseContext::handleSamplerTextureCombine(const TSourceLoc
// shadow state. This depends on downstream optimization to // shadow state. This depends on downstream optimization to
// DCE one variant in [shadow, nonshadow] if both are present, // DCE one variant in [shadow, nonshadow] if both are present,
// or the SPIR-V module would be invalid. // or the SPIR-V module would be invalid.
int newId = texSymbol->getId(); long long newId = texSymbol->getId();
// Check to see if this texture has been given a shadow mode already. // Check to see if this texture has been given a shadow mode already.
// If so, look up the one we already have. // If so, look up the one we already have.
@ -3352,9 +3507,9 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte
// Byte address buffers index in bytes (only multiples of 4 permitted... not so much a byte address // 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. // buffer then, but that's what it calls itself.
const bool isByteAddressBuffer = (builtInType == EbvByteAddressBuffer || const bool isByteAddressBuffer = (builtInType == EbvByteAddressBuffer ||
builtInType == EbvRWByteAddressBuffer); builtInType == EbvRWByteAddressBuffer);
if (isByteAddressBuffer) if (isByteAddressBuffer)
argIndex = intermediate.addBinaryNode(EOpRightShift, argIndex, argIndex = intermediate.addBinaryNode(EOpRightShift, argIndex,
@ -3369,7 +3524,7 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte
const TType derefType(argArray->getType(), 0); const TType derefType(argArray->getType(), 0);
node->setType(derefType); node->setType(derefType);
} }
break; break;
case EOpMethodLoad2: case EOpMethodLoad2:
@ -3495,8 +3650,8 @@ void HlslParseContext::decomposeStructBufferMethods(const TSourceLoc& loc, TInte
const TType indexType(argValue->getType(), 0); const TType indexType(argValue->getType(), 0);
rValue->setType(indexType); rValue->setType(indexType);
} }
TIntermTyped* assign = intermediate.addAssign(EOpAssign, lValue, rValue, loc); TIntermTyped* assign = intermediate.addAssign(EOpAssign, lValue, rValue, loc);
body = intermediate.growAggregate(body, assign); body = intermediate.growAggregate(body, assign);
} }
@ -3673,7 +3828,7 @@ TIntermConstantUnion* HlslParseContext::getSamplePosArray(int count)
} }
TConstUnionArray* values = new TConstUnionArray(numSamples*2); TConstUnionArray* values = new TConstUnionArray(numSamples*2);
for (int pos=0; pos<count; ++pos) { for (int pos=0; pos<count; ++pos) {
TConstUnion x, y; TConstUnion x, y;
x.setDConst(sampleLoc[pos].x); x.setDConst(sampleLoc[pos].x);
@ -3707,7 +3862,7 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
result->setType(TType(node->getType().getBasicType(), EvqTemporary, node->getVectorSize())); result->setType(TType(node->getType().getBasicType(), EvqTemporary, node->getVectorSize()));
TIntermTyped* convertedResult = nullptr; TIntermTyped* convertedResult = nullptr;
TType retType; TType retType;
getTextureReturnType(sampler, retType); getTextureReturnType(sampler, retType);
@ -3733,7 +3888,7 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
for (unsigned m = 0; m < unsigned(retType.getStruct()->size()); ++m) { 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. 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 // 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 // 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. // other things, e.g, sub-structures, but HLSL doesn't allow them.
@ -3741,7 +3896,7 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
error(loc, "expected: scalar or vector type in texture structure", "", ""); error(loc, "expected: scalar or vector type in texture structure", "", "");
return nullptr; return nullptr;
} }
// Index into the struct variable to find the member to assign. // Index into the struct variable to find the member to assign.
TIntermTyped* structMember = intermediate.addIndex(EOpIndexDirectStruct, TIntermTyped* structMember = intermediate.addIndex(EOpIndexDirectStruct,
intermediate.addSymbol(*structVar, loc), intermediate.addSymbol(*structVar, loc),
@ -3763,14 +3918,14 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
TIntermTyped* structVecComponent = intermediate.addIndex(EOpIndexDirect, structMember, TIntermTyped* structVecComponent = intermediate.addIndex(EOpIndexDirect, structMember,
intermediate.addConstantUnion(component, loc), loc); intermediate.addConstantUnion(component, loc), loc);
memberAssign = intermediate.addAssign(EOpAssign, structVecComponent, vec4Member, loc); memberAssign = intermediate.addAssign(EOpAssign, structVecComponent, vec4Member, loc);
} else { } else {
// Scalar member: we can assign to it directly. // Scalar member: we can assign to it directly.
memberAssign = intermediate.addAssign(EOpAssign, structMember, vec4Member, loc); memberAssign = intermediate.addAssign(EOpAssign, structMember, vec4Member, loc);
} }
conversionAggregate->getSequence().push_back(memberAssign); conversionAggregate->getSequence().push_back(memberAssign);
} }
} }
@ -3809,7 +3964,7 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
if (arguments->getAsTyped()->getBasicType() != EbtSampler) if (arguments->getAsTyped()->getBasicType() != EbtSampler)
return; return;
} else { } else {
if (argAggregate->getSequence().size() == 0 || if (argAggregate->getSequence().size() == 0 ||
argAggregate->getSequence()[0] == nullptr || argAggregate->getSequence()[0] == nullptr ||
argAggregate->getSequence()[0]->getAsTyped()->getBasicType() != EbtSampler) argAggregate->getSequence()[0]->getAsTyped()->getBasicType() != EbtSampler)
return; return;
@ -3846,6 +4001,7 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
case Esd3D: constructOp = EOpConstructVec3; coordSize = 3; break; // 3D case Esd3D: constructOp = EOpConstructVec3; coordSize = 3; break; // 3D
case EsdCube: constructOp = EOpConstructVec3; coordSize = 3; break; // also 3D case EsdCube: constructOp = EOpConstructVec3; coordSize = 3; break; // also 3D
default: default:
error(loc, "unhandled DX9 texture LoD dimension", "", "");
break; break;
} }
@ -3882,7 +4038,9 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
case Esd2D: constructOp = EOpConstructVec2; break; // 2D case Esd2D: constructOp = EOpConstructVec2; break; // 2D
case Esd3D: constructOp = EOpConstructVec3; break; // 3D case Esd3D: constructOp = EOpConstructVec3; break; // 3D
case EsdCube: constructOp = EOpConstructVec3; break; // also 3D case EsdCube: constructOp = EOpConstructVec3; break; // also 3D
default: break; default:
error(loc, "unhandled DX9 texture bias dimension", "", "");
break;
} }
TIntermAggregate* constructCoord = new TIntermAggregate(constructOp); TIntermAggregate* constructCoord = new TIntermAggregate(constructOp);
@ -3932,12 +4090,12 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
txsample->getSequence().push_back(txcombine); txsample->getSequence().push_back(txcombine);
txsample->getSequence().push_back(argCoord); txsample->getSequence().push_back(argCoord);
if (argBias != nullptr)
txsample->getSequence().push_back(argBias);
if (argOffset != nullptr) if (argOffset != nullptr)
txsample->getSequence().push_back(argOffset); txsample->getSequence().push_back(argOffset);
if (argBias != nullptr)
txsample->getSequence().push_back(argBias);
node = convertReturn(txsample, sampler); node = convertReturn(txsample, sampler);
break; break;
@ -4006,7 +4164,8 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
case EsdBuffer: numDims = 1; break; // W (buffers) case EsdBuffer: numDims = 1; break; // W (buffers)
case EsdRect: numDims = 2; break; // W, H (rect) case EsdRect: numDims = 2; break; // W, H (rect)
default: default:
assert(0 && "unhandled texture dimension"); error(loc, "unhandled DX10 MethodGet dimension", "", "");
break;
} }
// Arrayed adds another dimension for the number of array elements // Arrayed adds another dimension for the number of array elements
@ -4142,7 +4301,9 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
case 3: constructOp = EOpConstructVec3; break; case 3: constructOp = EOpConstructVec3; break;
case 4: constructOp = EOpConstructVec4; break; case 4: constructOp = EOpConstructVec4; break;
case 5: constructOp = EOpConstructVec4; break; // cubeArrayShadow, cmp value is separate arg. case 5: constructOp = EOpConstructVec4; break; // cubeArrayShadow, cmp value is separate arg.
default: assert(0); break; default:
error(loc, "unhandled DX10 MethodSample dimension", "", "");
break;
} }
TIntermAggregate* coordWithCmp = new TIntermAggregate(constructOp); TIntermAggregate* coordWithCmp = new TIntermAggregate(constructOp);
@ -4506,13 +4667,13 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
int count = 0; int count = 0;
for (int val = 2; val <= 16; val *= 2) for (int val = 2; val <= 16; val *= 2)
idxtest[count++] = idxtest[count++] =
intermediate.addBinaryNode(EOpEqual, intermediate.addBinaryNode(EOpEqual,
intermediate.addSymbol(*outSampleCount, loc), intermediate.addSymbol(*outSampleCount, loc),
intermediate.addConstantUnion(val, loc), intermediate.addConstantUnion(val, loc),
loc, TType(EbtBool)); loc, TType(EbtBool));
const TOperator idxOp = (argSampIdx->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect; const TOperator idxOp = (argSampIdx->getQualifier().storage == EvqConst) ? EOpIndexDirect : EOpIndexIndirect;
// Create index ops into position arrays given sample index. // Create index ops into position arrays given sample index.
// TODO: should it be clamped? // TODO: should it be clamped?
TIntermTyped* index[4]; TIntermTyped* index[4];
@ -4527,13 +4688,13 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
// (sampleCount == 4) ? pos4[idx] : // (sampleCount == 4) ? pos4[idx] :
// (sampleCount == 8) ? pos8[idx] : // (sampleCount == 8) ? pos8[idx] :
// (sampleCount == 16) ? pos16[idx] : float2(0,0); // (sampleCount == 16) ? pos16[idx] : float2(0,0);
TIntermTyped* test = TIntermTyped* test =
intermediate.addSelection(idxtest[0], index[0], intermediate.addSelection(idxtest[0], index[0],
intermediate.addSelection(idxtest[1], index[1], intermediate.addSelection(idxtest[1], index[1],
intermediate.addSelection(idxtest[2], index[2], intermediate.addSelection(idxtest[2], index[2],
intermediate.addSelection(idxtest[3], index[3], intermediate.addSelection(idxtest[3], index[3],
getSamplePosArray(1), loc), loc), loc), loc); getSamplePosArray(1), loc), loc), loc), loc);
compoundStatement = intermediate.growAggregate(compoundStatement, test); compoundStatement = intermediate.growAggregate(compoundStatement, test);
compoundStatement->setOperator(EOpSequence); compoundStatement->setOperator(EOpSequence);
compoundStatement->setLoc(loc); compoundStatement->setLoc(loc);
@ -4546,7 +4707,7 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
case EOpSubpassLoad: case EOpSubpassLoad:
{ {
const TIntermTyped* argSubpass = const TIntermTyped* argSubpass =
argAggregate ? argAggregate->getSequence()[0]->getAsTyped() : argAggregate ? argAggregate->getSequence()[0]->getAsTyped() :
arguments->getAsTyped(); arguments->getAsTyped();
@ -4561,7 +4722,7 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
break; break;
} }
default: default:
break; // most pass through unchanged break; // most pass through unchanged
@ -5081,7 +5242,7 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
for (int idx = 0; idx < vecSize; ++idx) { for (int idx = 0; idx < vecSize; ++idx) {
TIntermTyped* idxConst = intermediate.addConstantUnion(idx, loc, true); TIntermTyped* idxConst = intermediate.addConstantUnion(idx, loc, true);
TIntermTyped* component = argValue->getType().isVector() ? TIntermTyped* component = argValue->getType().isVector() ?
intermediate.addIndex(EOpIndexDirect, argValue, idxConst, loc) : argValue; intermediate.addIndex(EOpIndexDirect, argValue, idxConst, loc) : argValue;
if (component != argValue) if (component != argValue)
@ -5093,7 +5254,7 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
unpackOp->setLoc(loc); unpackOp->setLoc(loc);
TIntermTyped* lowOrder = intermediate.addIndex(EOpIndexDirect, unpackOp, zero, loc); TIntermTyped* lowOrder = intermediate.addIndex(EOpIndexDirect, unpackOp, zero, loc);
if (result != nullptr) { if (result != nullptr) {
result->getSequence().push_back(lowOrder); result->getSequence().push_back(lowOrder);
node = result; node = result;
@ -5101,7 +5262,7 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
node = lowOrder; node = lowOrder;
} }
} }
break; break;
} }
@ -5132,7 +5293,7 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
for (int idx = 0; idx < vecSize; ++idx) { for (int idx = 0; idx < vecSize; ++idx) {
TIntermTyped* idxConst = intermediate.addConstantUnion(idx, loc, true); TIntermTyped* idxConst = intermediate.addConstantUnion(idx, loc, true);
TIntermTyped* component = argValue->getType().isVector() ? TIntermTyped* component = argValue->getType().isVector() ?
intermediate.addIndex(EOpIndexDirect, argValue, idxConst, loc) : argValue; intermediate.addIndex(EOpIndexDirect, argValue, idxConst, loc) : argValue;
if (component != argValue) if (component != argValue)
@ -5143,7 +5304,7 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
vec2ComponentAndZero->getSequence().push_back(zero); vec2ComponentAndZero->getSequence().push_back(zero);
vec2ComponentAndZero->setType(TType(EbtFloat, EvqTemporary, 2)); vec2ComponentAndZero->setType(TType(EbtFloat, EvqTemporary, 2));
vec2ComponentAndZero->setLoc(loc); vec2ComponentAndZero->setLoc(loc);
TIntermTyped* packOp = new TIntermUnary(EOpPackHalf2x16); TIntermTyped* packOp = new TIntermUnary(EOpPackHalf2x16);
packOp->getAsUnaryNode()->setOperand(vec2ComponentAndZero); packOp->getAsUnaryNode()->setOperand(vec2ComponentAndZero);
packOp->setLoc(loc); packOp->setLoc(loc);
@ -5216,7 +5377,7 @@ void HlslParseContext::decomposeIntrinsic(const TSourceLoc& loc, TIntermTyped*&
TIntermTyped* notinf = handleUnaryMath(loc, "!", EOpLogicalNot, isinf); TIntermTyped* notinf = handleUnaryMath(loc, "!", EOpLogicalNot, isinf);
notinf->setType(boolType); notinf->setType(boolType);
TIntermTyped* andNode = handleBinaryMath(loc, "and", EOpLogicalAnd, notnan, notinf); TIntermTyped* andNode = handleBinaryMath(loc, "and", EOpLogicalAnd, notnan, notinf);
andNode->setType(boolType); andNode->setType(boolType);
@ -5404,6 +5565,10 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct
op = fnCandidate->getBuiltInOp(); op = fnCandidate->getBuiltInOp();
if (builtIn && op != EOpNull) { 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. // A function call mapped to a built-in operation.
result = intermediate.addBuiltInFunctionCall(loc, op, fnCandidate->getParamCount() == 1, arguments, result = intermediate.addBuiltInFunctionCall(loc, op, fnCandidate->getParamCount() == 1, arguments,
fnCandidate->getType()); fnCandidate->getType());
@ -5600,7 +5765,7 @@ void HlslParseContext::addInputArgumentConversions(const TFunction& function, TI
// means take 'arguments' itself as the one argument. // means take 'arguments' itself as the one argument.
TIntermTyped* arg = function.getParamCount() == 1 TIntermTyped* arg = function.getParamCount() == 1
? arguments->getAsTyped() ? arguments->getAsTyped()
: (aggregate ? : (aggregate ?
aggregate->getSequence()[param]->getAsTyped() : aggregate->getSequence()[param]->getAsTyped() :
arguments->getAsTyped()); arguments->getAsTyped());
if (*function[param].type != arg->getType()) { if (*function[param].type != arg->getType()) {
@ -5671,7 +5836,7 @@ void HlslParseContext::expandArguments(const TSourceLoc& loc, const TFunction& f
else if (args.size() > 1) { else if (args.size() > 1) {
if (function.getParamCount() + functionParamNumberOffset == 1) { if (function.getParamCount() + functionParamNumberOffset == 1) {
arguments = intermediate.makeAggregate(args.front()); arguments = intermediate.makeAggregate(args.front());
std::for_each(args.begin() + 1, args.end(), std::for_each(args.begin() + 1, args.end(),
[&](TIntermTyped* arg) { [&](TIntermTyped* arg) {
arguments = intermediate.growAggregate(arguments, arg); arguments = intermediate.growAggregate(arguments, arg);
}); });
@ -5690,7 +5855,7 @@ void HlslParseContext::expandArguments(const TSourceLoc& loc, const TFunction& f
// means take 'arguments' itself as the one argument. // means take 'arguments' itself as the one argument.
TIntermTyped* arg = function.getParamCount() == 1 TIntermTyped* arg = function.getParamCount() == 1
? arguments->getAsTyped() ? arguments->getAsTyped()
: (aggregate ? : (aggregate ?
aggregate->getSequence()[param + functionParamNumberOffset]->getAsTyped() : aggregate->getSequence()[param + functionParamNumberOffset]->getAsTyped() :
arguments->getAsTyped()); arguments->getAsTyped());
@ -5983,8 +6148,12 @@ void HlslParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fn
case EOpInterpolateAtCentroid: case EOpInterpolateAtCentroid:
case EOpInterpolateAtSample: case EOpInterpolateAtSample:
case EOpInterpolateAtOffset: 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 // Make sure the first argument is an interpolant, or an array element of an interpolant
if (arg0->getType().getQualifier().storage != EvqVaryingIn) { // if (arg0->getType().getQualifier().storage != EvqVaryingIn) {
// It might still be an array element. // It might still be an array element.
// //
// We could check more, but the semantics of the first argument are already met; the // We could check more, but the semantics of the first argument are already met; the
@ -5992,11 +6161,11 @@ void HlslParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fn
// //
// ES and desktop 4.3 and earlier: swizzles may not be used // ES and desktop 4.3 and earlier: swizzles may not be used
// desktop 4.4 and later: swizzles may be used // desktop 4.4 and later: swizzles may be used
const TIntermTyped* base = TIntermediate::findLValueBase(arg0, true); // const TIntermTyped* base = TIntermediate::findLValueBase(arg0, true);
if (base == nullptr || base->getType().getQualifier().storage != EvqVaryingIn) // if (base == nullptr || base->getType().getQualifier().storage != EvqVaryingIn)
error(loc, "first argument must be an interpolant, or interpolant-array element", // error(loc, "first argument must be an interpolant, or interpolant-array element",
fnCandidate.getName().c_str(), ""); // fnCandidate.getName().c_str(), "");
} // }
break; break;
default: default:
@ -6051,6 +6220,32 @@ void HlslParseContext::handleSemantic(TSourceLoc loc, TQualifier& qualifier, TBu
return semanticNum; 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) { switch(builtIn) {
case EbvNone: case EbvNone:
// Get location numbers from fragment outputs, instead of // Get location numbers from fragment outputs, instead of
@ -6567,12 +6762,6 @@ void HlslParseContext::globalQualifierFix(const TSourceLoc&, TQualifier& qualifi
// //
// Merge characteristics of the 'src' qualifier into the 'dst'. // 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 HlslParseContext::mergeQualifiers(TQualifier& dst, const TQualifier& src) void HlslParseContext::mergeQualifiers(TQualifier& dst, const TQualifier& src)
{ {
@ -6590,8 +6779,7 @@ void HlslParseContext::mergeQualifiers(TQualifier& dst, const TQualifier& src)
mergeObjectLayoutQualifiers(dst, src, false); mergeObjectLayoutQualifiers(dst, src, false);
// individual qualifiers // individual qualifiers
bool repeated = false; #define MERGE_SINGLETON(field) dst.field |= src.field;
#define MERGE_SINGLETON(field) repeated |= dst.field && src.field; dst.field |= src.field;
MERGE_SINGLETON(invariant); MERGE_SINGLETON(invariant);
MERGE_SINGLETON(noContraction); MERGE_SINGLETON(noContraction);
MERGE_SINGLETON(centroid); MERGE_SINGLETON(centroid);
@ -6820,6 +7008,9 @@ void HlslParseContext::shareStructBufferType(TType& type)
if (lhs.isStruct() != rhs.isStruct()) if (lhs.isStruct() != rhs.isStruct())
return false; return false;
if (lhs.getQualifier().builtIn != rhs.getQualifier().builtIn)
return false;
if (lhs.isStruct() && rhs.isStruct()) { if (lhs.isStruct() && rhs.isStruct()) {
if (lhs.getStruct()->size() != rhs.getStruct()->size()) if (lhs.getStruct()->size() != rhs.getStruct()->size())
return false; return false;
@ -6865,7 +7056,6 @@ void HlslParseContext::paramFix(TType& type)
type.getQualifier().storage = EvqConstReadOnly; type.getQualifier().storage = EvqConstReadOnly;
break; break;
case EvqGlobal: case EvqGlobal:
case EvqUniform:
case EvqTemporary: case EvqTemporary:
type.getQualifier().storage = EvqIn; type.getQualifier().storage = EvqIn;
break; break;
@ -7515,7 +7705,17 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction
bool tie = false; bool tie = false;
// send to the generic selector // send to the generic selector
const TFunction* bestMatch = selectFunction(candidateList, call, convertible, better, tie); 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 (bestMatch == nullptr) {
// If there is nothing selected by allowing only up-conversions (to a larger linearize() value), // If there is nothing selected by allowing only up-conversions (to a larger linearize() value),
@ -7571,7 +7771,7 @@ const TFunction* HlslParseContext::findFunction(const TSourceLoc& loc, TFunction
if (args->getAsAggregate()) { if (args->getAsAggregate()) {
// Handle aggregates: put all args into the new function call // Handle aggregates: put all args into the new function call
for (int arg=0; arg<int(args->getAsAggregate()->getSequence().size()); ++arg) { 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. // TODO: But for constness, we could avoid the new & shallowCopy, and use the pointer directly.
TParameter param = { 0, new TType, nullptr }; TParameter param = { 0, new TType, nullptr };
param.type->shallowCopy(args->getAsAggregate()->getSequence()[arg]->getAsTyped()->getType()); param.type->shallowCopy(args->getAsAggregate()->getSequence()[arg]->getAsTyped()->getType());
@ -8465,7 +8665,7 @@ TIntermTyped* HlslParseContext::convertArray(TIntermTyped* node, const TType& ty
// bump up to the next component to consume // bump up to the next component to consume
const auto getNextComponent = [&]() { const auto getNextComponent = [&]() {
TIntermTyped* component; TIntermTyped* component;
component = handleBracketDereference(node->getLoc(), constructee, component = handleBracketDereference(node->getLoc(), constructee,
intermediate.addConstantUnion(constructeeElement, node->getLoc())); intermediate.addConstantUnion(constructeeElement, node->getLoc()));
if (component->isVector()) if (component->isVector())
component = handleBracketDereference(node->getLoc(), component, component = handleBracketDereference(node->getLoc(), component,
@ -8884,6 +9084,10 @@ void HlslParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier
// //
bool HlslParseContext::handleInputGeometry(const TSourceLoc& loc, const TLayoutGeometry& 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) { switch (geometry) {
case ElgPoints: // fall through case ElgPoints: // fall through
case ElgLines: // ... case ElgLines: // ...
@ -8914,6 +9118,10 @@ bool HlslParseContext::handleOutputGeometry(const TSourceLoc& loc, const TLayout
if (language != EShLangGeometry) if (language != EShLangGeometry)
return true; return true;
// these can be declared on non-entry-points, in which case they lose their meaning
if (! parsingEntrypointParameters)
return true;
switch (geometry) { switch (geometry) {
case ElgPoints: case ElgPoints:
case ElgLineStrip: case ElgLineStrip:
@ -9529,7 +9737,7 @@ bool HlslParseContext::setTextureReturnType(TSampler& sampler, const TType& retT
// Insert it in the vector that tracks struct return types. // Insert it in the vector that tracks struct return types.
sampler.structReturnIndex = unsigned(textureReturnStruct.size()); sampler.structReturnIndex = unsigned(textureReturnStruct.size());
textureReturnStruct.push_back(members); textureReturnStruct.push_back(members);
// Success! // Success!
return true; return true;
} }
@ -9577,7 +9785,7 @@ const TFunction* HlslParseContext::findPatchConstantFunction(const TSourceLoc& l
TVector<const TFunction*> candidateList; TVector<const TFunction*> candidateList;
bool builtIn; bool builtIn;
symbolTable.findFunctionNameList(mangledName, candidateList, 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 // 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. // allow any disambiguation of overloads.
if (candidateList.empty()) { if (candidateList.empty()) {
@ -9648,26 +9856,26 @@ void HlslParseContext::addPatchConstantInvocation()
return type.isSizedArray() && biType == EbvOutputPatch; return type.isSizedArray() && biType == EbvOutputPatch;
}; };
// We will perform these steps. Each is in a scoped block for separation: they could // We will perform these steps. Each is in a scoped block for separation: they could
// become separate functions to make addPatchConstantInvocation shorter. // become separate functions to make addPatchConstantInvocation shorter.
// //
// 1. Union the interfaces, and create built-ins for anything present in the PCF and // 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. // 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, // 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 // or the ones we created. Matching is based on built-in type. We may use synthesized
// variables from (1) above. // variables from (1) above.
// //
// 2B: Synthesize per control point invocations of wrapped entry point if the PCF requires them. // 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 // 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 // (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 // 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. // indirections into a complex R-value coming from the call to the PCF.
// //
// 4. Create a barrier. // 4. Create a barrier.
// //
// 5/5B. Call the PCF inside an if test for (invocation id == 0). // 5/5B. Call the PCF inside an if test for (invocation id == 0).
TFunction* patchConstantFunctionPtr = const_cast<TFunction*>(findPatchConstantFunction(loc)); TFunction* patchConstantFunctionPtr = const_cast<TFunction*>(findPatchConstantFunction(loc));
@ -9734,6 +9942,8 @@ void HlslParseContext::addPatchConstantInvocation()
} else { } else {
// Use the original declaration type for the linkage // Use the original declaration type for the linkage
paramType->getQualifier().builtIn = biType; paramType->getQualifier().builtIn = biType;
if (biType == EbvTessLevelInner || biType == EbvTessLevelOuter)
paramType->getQualifier().patch = true;
if (notInEntryPoint.count(tInterstageIoData(biType, storage)) == 1) if (notInEntryPoint.count(tInterstageIoData(biType, storage)) == 1)
addToLinkage(*paramType, patchConstantFunction[p].name, nullptr); addToLinkage(*paramType, patchConstantFunction[p].name, nullptr);
@ -9772,7 +9982,7 @@ void HlslParseContext::addPatchConstantInvocation()
} else { } else {
// find which built-in it is // find which built-in it is
const TBuiltInVariable biType = patchConstantFunction[p].getDeclaredBuiltIn(); const TBuiltInVariable biType = patchConstantFunction[p].getDeclaredBuiltIn();
if (biType == EbvInputPatch && inputPatch == nullptr) { if (biType == EbvInputPatch && inputPatch == nullptr) {
error(loc, "unimplemented: PCF input patch without entry point input patch parameter", "", ""); error(loc, "unimplemented: PCF input patch without entry point input patch parameter", "", "");
return; return;
@ -9879,7 +10089,7 @@ void HlslParseContext::addPatchConstantInvocation()
element->setType(derefType); element->setType(derefType);
element->setLoc(loc); element->setLoc(loc);
pcfCallSequence = intermediate.growAggregate(pcfCallSequence, pcfCallSequence = intermediate.growAggregate(pcfCallSequence,
handleAssign(loc, EOpAssign, element, callReturn)); handleAssign(loc, EOpAssign, element, callReturn));
} }
} }
@ -9905,8 +10115,8 @@ void HlslParseContext::addPatchConstantInvocation()
TVariable* pcfOutput = makeInternalVariable("@patchConstantOutput", outType); TVariable* pcfOutput = makeInternalVariable("@patchConstantOutput", outType);
pcfOutput->getWritableType().getQualifier().storage = EvqVaryingOut; pcfOutput->getWritableType().getQualifier().storage = EvqVaryingOut;
if (pcfOutput->getType().containsBuiltIn()) if (pcfOutput->getType().isStruct())
split(*pcfOutput); flatten(*pcfOutput, false);
assignToInterface(*pcfOutput); assignToInterface(*pcfOutput);
@ -9928,7 +10138,7 @@ void HlslParseContext::addPatchConstantInvocation()
pcfCallSequence = intermediate.growAggregate(pcfCallSequence, pcfCall); pcfCallSequence = intermediate.growAggregate(pcfCallSequence, pcfCall);
} }
// ================ Step 4: Barrier ================ // ================ Step 4: Barrier ================
TIntermTyped* barrier = new TIntermAggregate(EOpBarrier); TIntermTyped* barrier = new TIntermAggregate(EOpBarrier);
barrier->setLoc(loc); barrier->setLoc(loc);
barrier->setType(TType(EbtVoid)); barrier->setType(TType(EbtVoid));
@ -10000,7 +10210,7 @@ void HlslParseContext::finalizeAppendMethods()
// Patch append sequences, now that we know the stream output symbol. // Patch append sequences, now that we know the stream output symbol.
for (auto append = gsAppends.begin(); append != gsAppends.end(); ++append) { for (auto append = gsAppends.begin(); append != gsAppends.end(); ++append) {
append->node->getSequence()[0] = append->node->getSequence()[0] =
handleAssign(append->loc, EOpAssign, handleAssign(append->loc, EOpAssign,
intermediate.addSymbol(*gsStreamOutput, append->loc), intermediate.addSymbol(*gsStreamOutput, append->loc),
append->node->getSequence()[0]->getAsTyped()); append->node->getSequence()[0]->getAsTyped());

View File

@ -36,9 +36,9 @@
#ifndef HLSL_PARSE_INCLUDED_ #ifndef HLSL_PARSE_INCLUDED_
#define HLSL_PARSE_INCLUDED_ #define HLSL_PARSE_INCLUDED_
#include "../glslang/MachineIndependent/parseVersions.h" #include "../MachineIndependent/parseVersions.h"
#include "../glslang/MachineIndependent/ParseHelper.h" #include "../MachineIndependent/ParseHelper.h"
#include "../glslang/MachineIndependent/attribute.h" #include "../MachineIndependent/attribute.h"
#include <array> #include <array>
@ -60,8 +60,8 @@ public:
virtual const char* getGlobalUniformBlockName() const override { return "$Global"; } virtual const char* getGlobalUniformBlockName() const override { return "$Global"; }
virtual void setUniformBlockDefaults(TType& block) const override virtual void setUniformBlockDefaults(TType& block) const override
{ {
block.getQualifier().layoutPacking = ElpStd140; block.getQualifier().layoutPacking = globalUniformDefaults.layoutPacking;
block.getQualifier().layoutMatrix = ElmRowMajor; block.getQualifier().layoutMatrix = globalUniformDefaults.layoutMatrix;
} }
void reservedPpErrorCheck(const TSourceLoc&, const char* /*name*/, const char* /*op*/) override { } void reservedPpErrorCheck(const TSourceLoc&, const char* /*name*/, const char* /*op*/) override { }
@ -94,6 +94,7 @@ public:
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermTyped*); TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermTyped*);
TIntermAggregate* assignClipCullDistance(const TSourceLoc&, TOperator, int semanticId, TIntermTyped* left, TIntermTyped* right); TIntermAggregate* assignClipCullDistance(const TSourceLoc&, TOperator, int semanticId, TIntermTyped* left, TIntermTyped* right);
TIntermTyped* assignPosition(const TSourceLoc&, TOperator, 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 decomposeIntrinsic(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); void decomposeSampleMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
void decomposeStructBufferMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments); void decomposeStructBufferMethods(const TSourceLoc&, TIntermTyped*& node, TIntermNode* arguments);
@ -183,6 +184,11 @@ public:
void getFullNamespaceName(TString*&) const; void getFullNamespaceName(TString*&) const;
void addScopeMangler(TString&); void addScopeMangler(TString&);
void beginParameterParsing(TFunction& function)
{
parsingEntrypointParameters = isEntrypointName(function.getName());
}
void pushSwitchSequence(TIntermSequence* sequence) { switchSequenceStack.push_back(sequence); } void pushSwitchSequence(TIntermSequence* sequence) { switchSequenceStack.push_back(sequence); }
void popSwitchSequence() { switchSequenceStack.pop_back(); } void popSwitchSequence() { switchSequenceStack.pop_back(); }
@ -241,18 +247,19 @@ protected:
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer, TIntermTyped* scalarInit); TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer, TIntermTyped* scalarInit);
bool isScalarConstructor(const TIntermNode*); bool isScalarConstructor(const TIntermNode*);
TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage); 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). // Return true if this node requires L-value conversion (e.g, to an imageStore).
bool shouldConvertLValue(const TIntermNode*) const; bool shouldConvertLValue(const TIntermNode*) const;
// Array and struct flattening // Array and struct flattening
TIntermTyped* flattenAccess(TIntermTyped* base, int member); TIntermTyped* flattenAccess(TIntermTyped* base, int member);
TIntermTyped* flattenAccess(int uniqueId, int member, TStorageQualifier outerStorage, const TType&, int subset = -1); TIntermTyped* flattenAccess(long long uniqueId, int member, TStorageQualifier outerStorage, const TType&, int subset = -1);
int findSubtreeOffset(const TIntermNode&) const; int findSubtreeOffset(const TIntermNode&) const;
int findSubtreeOffset(const TType&, int subset, const TVector<int>& offsets) const; int findSubtreeOffset(const TType&, int subset, const TVector<int>& offsets) const;
bool shouldFlatten(const TType&, TStorageQualifier, bool topLevel) const; bool shouldFlatten(const TType&, TStorageQualifier, bool topLevel) const;
bool wasFlattened(const TIntermTyped* node) const; bool wasFlattened(const TIntermTyped* node) const;
bool wasFlattened(int id) const { return flattenMap.find(id) != flattenMap.end(); } bool wasFlattened(long long id) const { return flattenMap.find(id) != flattenMap.end(); }
int addFlattenedMember(const TVariable&, const TType&, TFlattenData&, const TString& name, bool linkage, int addFlattenedMember(const TVariable&, const TType&, TFlattenData&, const TString& name, bool linkage,
const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes); const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes);
@ -261,8 +268,8 @@ protected:
void splitBuiltIn(const TString& baseName, const TType& memberType, const TArraySizes*, const TQualifier&); void splitBuiltIn(const TString& baseName, const TType& memberType, const TArraySizes*, const TQualifier&);
const TType& split(const TType& type, const TString& name, const TQualifier&); const TType& split(const TType& type, const TString& name, const TQualifier&);
bool wasSplit(const TIntermTyped* node) const; bool wasSplit(const TIntermTyped* node) const;
bool wasSplit(int id) const { return splitNonIoVars.find(id) != splitNonIoVars.end(); } bool wasSplit(long long id) const { return splitNonIoVars.find(id) != splitNonIoVars.end(); }
TVariable* getSplitNonIoVar(int id) const; TVariable* getSplitNonIoVar(long long id) const;
void addPatchConstantInvocation(); void addPatchConstantInvocation();
void fixTextureShadowModes(); void fixTextureShadowModes();
void finalizeAppendMethods(); void finalizeAppendMethods();
@ -270,7 +277,7 @@ protected:
void fixBuiltInIoType(TType&); void fixBuiltInIoType(TType&);
void flatten(const TVariable& variable, bool linkage); void flatten(const TVariable& variable, bool linkage, bool arrayed = false);
int flatten(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage, int flatten(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage,
const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes); const TQualifier& outerQualifier, const TArraySizes* builtInArraySizes);
int flattenStruct(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage, int flattenStruct(const TVariable& variable, const TType&, TFlattenData&, TString name, bool linkage,
@ -314,7 +321,7 @@ protected:
// Finalization step: remove unused buffer blocks from linkage (we don't know until the // Finalization step: remove unused buffer blocks from linkage (we don't know until the
// shader is entirely compiled) // shader is entirely compiled)
void removeUnusedStructBufferCounters(); void removeUnusedStructBufferCounters();
static bool isClipOrCullDistance(TBuiltInVariable); static bool isClipOrCullDistance(TBuiltInVariable);
static bool isClipOrCullDistance(const TQualifier& qual) { return isClipOrCullDistance(qual.builtIn); } static bool isClipOrCullDistance(const TQualifier& qual) { return isClipOrCullDistance(qual.builtIn); }
static bool isClipOrCullDistance(const TType& type) { return isClipOrCullDistance(type.getQualifier()); } static bool isClipOrCullDistance(const TType& type) { return isClipOrCullDistance(type.getQualifier()); }
@ -380,7 +387,7 @@ protected:
// //
TVector<TSymbol*> ioArraySymbolResizeList; TVector<TSymbol*> ioArraySymbolResizeList;
TMap<int, TFlattenData> flattenMap; TMap<long long, TFlattenData> flattenMap;
// IO-type map. Maps a pure symbol-table form of a structure-member list into // 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, // each of the (up to) three kinds of IO, as each as different allowed decorations,
@ -393,7 +400,7 @@ protected:
TMap<const TTypeList*, tIoKinds> ioTypeMap; TMap<const TTypeList*, tIoKinds> ioTypeMap;
// Structure splitting data: // Structure splitting data:
TMap<int, TVariable*> splitNonIoVars; // variables with the built-in interstage IO removed, indexed by unique ID. TMap<long long, TVariable*> splitNonIoVars; // variables with the built-in interstage IO removed, indexed by unique ID.
// Structuredbuffer shared types. Typically there are only a few. // Structuredbuffer shared types. Typically there are only a few.
TVector<TType*> structBufferTypes; TVector<TType*> structBufferTypes;
@ -401,7 +408,7 @@ protected:
// This tracks texture sample user structure return types. Only a limited number are supported, as // This tracks texture sample user structure return types. Only a limited number are supported, as
// may fit in TSampler::structReturnIndex. // may fit in TSampler::structReturnIndex.
TVector<TTypeList*> textureReturnStruct; TVector<TTypeList*> textureReturnStruct;
TMap<TString, bool> structBufferCounter; // true if counter buffer is in use TMap<TString, bool> 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 // The built-in interstage IO map considers e.g, EvqPosition on input and output separately, so that we
@ -450,7 +457,7 @@ protected:
std::array<int, maxClipCullRegs> cullSemanticNSizeOut; // vector, indexed by cull semantic ID std::array<int, maxClipCullRegs> cullSemanticNSizeOut; // vector, indexed by cull semantic ID
// This tracks the first (mip level) argument to the .mips[][] operator. Since this can be nested as // 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 // in tx.mips[tx.mips[0][1].x][2], we need a stack. We also track the TSourceLoc for error reporting
// purposes. // purposes.
struct tMipsOperatorData { struct tMipsOperatorData {
tMipsOperatorData(TSourceLoc l, TIntermTyped* m) : loc(l), mipLevel(m) { } tMipsOperatorData(TSourceLoc l, TIntermTyped* m) : loc(l), mipLevel(m) { }
@ -482,18 +489,19 @@ protected:
struct tShadowTextureSymbols { struct tShadowTextureSymbols {
tShadowTextureSymbols() { symId.fill(-1); } tShadowTextureSymbols() { symId.fill(-1); }
void set(bool shadow, int id) { symId[int(shadow)] = id; } void set(bool shadow, long long id) { symId[int(shadow)] = id; }
int get(bool shadow) const { return symId[int(shadow)]; } long long get(bool shadow) const { return symId[int(shadow)]; }
// True if this texture has been seen with both shadow and non-shadow modes // 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 overloaded() const { return symId[0] != -1 && symId[1] != -1; }
bool isShadowId(int id) const { return symId[1] == id; } bool isShadowId(long long id) const { return symId[1] == id; }
private: private:
std::array<int, 2> symId; std::array<long long, 2> symId;
}; };
TMap<int, tShadowTextureSymbols*> textureShadowVariant; TMap<long long, tShadowTextureSymbols*> textureShadowVariant;
bool parsingEntrypointParameters;
}; };
// This is the prefix we use for built-in methods to avoid namespace collisions with // This is the prefix we use for built-in methods to avoid namespace collisions with

View File

@ -56,18 +56,6 @@
namespace { // anonymous namespace functions namespace { // anonymous namespace functions
const bool UseHlslTypes = true;
const char* BaseTypeName(const char argOrder, const char* scalarName, const char* vecName, const char* matName)
{
switch (argOrder) {
case 'S': return scalarName;
case 'V': return vecName;
case 'M': return matName;
default: return "UNKNOWN_TYPE";
}
}
// arg order queries // arg order queries
bool IsSamplerType(const char argType) { return argType == 'S' || argType == 's'; } bool IsSamplerType(const char argType) { return argType == 'S' || argType == 's'; }
bool IsArrayed(const char argOrder) { return argOrder == '@' || argOrder == '&' || argOrder == '#'; } bool IsArrayed(const char argOrder) { return argOrder == '@' || argOrder == '&' || argOrder == '#'; }
@ -216,8 +204,7 @@ int FixedVecSize(const char* arg)
return 0; // none found. return 0; // none found.
} }
// Create and return a type name. This is done in GLSL, not HLSL conventions, until such // Create and return a type name, using HLSL type conventions.
// time as builtins are parsed using the HLSL parser.
// //
// order: S = scalar, V = vector, M = matrix // order: S = scalar, V = vector, M = matrix
// argType: F = float, D = double, I = int, U = uint, B = bool, S = sampler // argType: F = float, D = double, I = int, U = uint, B = bool, S = sampler
@ -252,63 +239,35 @@ glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, cons
char order = *argOrder; char order = *argOrder;
if (UseHlslTypes) { switch (type) {
switch (type) { case '-': s += "void"; break;
case '-': s += "void"; break; case 'F': s += "float"; break;
case 'F': s += "float"; break; case 'D': s += "double"; break;
case 'D': s += "double"; break; case 'I': s += "int"; break;
case 'I': s += "int"; break; case 'U': s += "uint"; break;
case 'U': s += "uint"; break; case 'L': s += "int64_t"; break;
case 'L': s += "int64_t"; break; case 'M': s += "uint64_t"; break;
case 'M': s += "uint64_t"; break; case 'B': s += "bool"; break;
case 'B': s += "bool"; break; case 'S': s += "sampler"; break;
case 'S': s += "sampler"; break; case 's': s += "SamplerComparisonState"; break;
case 's': s += "SamplerComparisonState"; break; case 'T': s += ((isBuffer && isImage) ? "RWBuffer" :
case 'T': s += ((isBuffer && isImage) ? "RWBuffer" : isSubpass ? "SubpassInput" :
isSubpass ? "SubpassInput" : isBuffer ? "Buffer" :
isBuffer ? "Buffer" : isImage ? "RWTexture" : "Texture"); break;
isImage ? "RWTexture" : "Texture"); break; case 'i': s += ((isBuffer && isImage) ? "RWBuffer" :
case 'i': s += ((isBuffer && isImage) ? "RWBuffer" : isSubpass ? "SubpassInput" :
isSubpass ? "SubpassInput" : isBuffer ? "Buffer" :
isBuffer ? "Buffer" : isImage ? "RWTexture" : "Texture"); break;
isImage ? "RWTexture" : "Texture"); break; case 'u': s += ((isBuffer && isImage) ? "RWBuffer" :
case 'u': s += ((isBuffer && isImage) ? "RWBuffer" : isSubpass ? "SubpassInput" :
isSubpass ? "SubpassInput" : isBuffer ? "Buffer" :
isBuffer ? "Buffer" : isImage ? "RWTexture" : "Texture"); break;
isImage ? "RWTexture" : "Texture"); break; default: s += "UNKNOWN_TYPE"; break;
default: s += "UNKNOWN_TYPE"; break;
}
if (isSubpass && isMS)
s += "MS";
} else {
switch (type) {
case '-': s += "void"; break;
case 'F': s += BaseTypeName(order, "float", "vec", "mat"); break;
case 'D': s += BaseTypeName(order, "double", "dvec", "dmat"); break;
case 'I': s += BaseTypeName(order, "int", "ivec", "imat"); break;
case 'U': s += BaseTypeName(order, "uint", "uvec", "umat"); break;
case 'B': s += BaseTypeName(order, "bool", "bvec", "bmat"); break;
case 'S': s += "sampler"; break;
case 's': s += "samplerShadow"; break;
case 'T': // fall through
case 'i': // ...
case 'u': // ...
if (type != 'T') // create itexture, utexture, etc
s += type;
s += ((isImage && isBuffer) ? "imageBuffer" :
isSubpass ? "subpassInput" :
isImage ? "image" :
isBuffer ? "samplerBuffer" :
"texture");
break;
default: s += "UNKNOWN_TYPE"; break;
}
} }
if (isSubpass && isMS)
s += "MS";
// handle fixed vector sizes, such as float3, and only ever 3. // handle fixed vector sizes, such as float3, and only ever 3.
const int fixedVecSize = FixedVecSize(argOrder); const int fixedVecSize = FixedVecSize(argOrder);
if (fixedVecSize != 0) if (fixedVecSize != 0)
@ -324,7 +283,7 @@ glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, cons
case 1: s += "1D"; break; case 1: s += "1D"; break;
case 2: s += (isMS ? "2DMS" : "2D"); break; case 2: s += (isMS ? "2DMS" : "2D"); break;
case 3: s += "3D"; break; case 3: s += "3D"; break;
case 4: s += "Cube"; break; case 4: s += (type == 'S'? "CUBE" : "Cube"); break;
default: s += "UNKNOWN_SAMPLER"; break; default: s += "UNKNOWN_SAMPLER"; break;
} }
} }
@ -357,26 +316,24 @@ glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, cons
if (isArrayed) if (isArrayed)
s += "Array"; s += "Array";
// For HLSL, append return type for texture types switch (type) {
if (UseHlslTypes) { case 'i': s += "<int"; s += dim0Char; s += ">"; break;
switch (type) { case 'u': s += "<uint"; s += dim0Char; s += ">"; break;
case 'i': s += "<int"; s += dim0Char; s += ">"; break; case 'T': s += "<float"; s += dim0Char; s += ">"; break;
case 'u': s += "<uint"; s += dim0Char; s += ">"; break; default: break;
case 'T': s += "<float"; s += dim0Char; s += ">"; break;
default: break;
}
} }
return s; return s;
} }
// The GLSL parser can be used to parse a subset of HLSL prototypes. However, many valid HLSL prototypes // This rejects prototypes not normally valid for GLSL and it's way of finding
// are not valid GLSL prototypes. This rejects the invalid ones. Thus, there is a single switch below // overloaded built-ins under implicit type conversion.
// to enable creation of the entire HLSL space. //
inline bool IsValid(const char* cname, char retOrder, char retType, char argOrder, char argType, int dim0, int dim1) // It is possible that this is not needed, but that would require some tweaking
// of other rules to get the same results.
inline bool IsValid(const char* cname, char /* retOrder */, char /* retType */, char argOrder, char /* argType */, int dim0, int /* dim1 */)
{ {
const bool isVec = (argOrder == 'V'); const bool isVec = (argOrder == 'V');
const bool isMat = (argOrder == 'M');
const std::string name(cname); const std::string name(cname);
@ -387,26 +344,6 @@ inline bool IsValid(const char* cname, char retOrder, char retType, char argOrde
if (!IsTextureType(argOrder) && (isVec && dim0 == 1)) // avoid vec1 if (!IsTextureType(argOrder) && (isVec && dim0 == 1)) // avoid vec1
return false; return false;
if (UseHlslTypes) {
// NO further restrictions for HLSL
} else {
// GLSL parser restrictions
if ((isMat && (argType == 'I' || argType == 'U' || argType == 'B')) ||
(retOrder == 'M' && (retType == 'I' || retType == 'U' || retType == 'B')))
return false;
if (isMat && dim0 == 1 && dim1 == 1) // avoid mat1x1
return false;
if (isMat && dim1 == 1) // TODO: avoid mat Nx1 until we find the right GLSL profile
return false;
if (name == "GetRenderTargetSamplePosition" ||
name == "tex1D" ||
name == "tex1Dgrad")
return false;
}
return true; return true;
} }
@ -461,12 +398,10 @@ void TBuiltInParseablesHlsl::createMatTimesMat()
{ {
TString& s = commonBuiltins; TString& s = commonBuiltins;
const int first = (UseHlslTypes ? 1 : 2); for (int xRows = 1; xRows <=4; xRows++) {
for (int xCols = 1; xCols <=4; xCols++) {
for (int xRows = first; xRows <=4; xRows++) {
for (int xCols = first; xCols <=4; xCols++) {
const int yRows = xCols; const int yRows = xCols;
for (int yCols = first; yCols <=4; yCols++) { for (int yCols = 1; yCols <=4; yCols++) {
const int retRows = xRows; const int retRows = xRows;
const int retCols = yCols; const int retCols = yCols;
@ -670,7 +605,7 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c
{ "noise", "S", "F", "V", "F", EShLangPS, false }, { "noise", "S", "F", "V", "F", EShLangPS, false },
{ "normalize", nullptr, nullptr, "V", "F", EShLangAll, false }, { "normalize", nullptr, nullptr, "V", "F", EShLangAll, false },
{ "pow", nullptr, nullptr, "SVM,", "F,", EShLangAll, false }, { "pow", nullptr, nullptr, "SVM,", "F,", EShLangAll, false },
// { "printf", "-", "-", "", "", EShLangAll, false }, TODO: varargs { "printf", nullptr, nullptr, "-", "-", EShLangAll, false },
{ "Process2DQuadTessFactorsAvg", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false }, { "Process2DQuadTessFactorsAvg", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false },
{ "Process2DQuadTessFactorsMax", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false }, { "Process2DQuadTessFactorsMax", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false },
{ "Process2DQuadTessFactorsMin", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false }, { "Process2DQuadTessFactorsMin", "-", "-", "V4,V2,>V4,>V2,", "F,,,,", EShLangHS, false },
@ -730,8 +665,8 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c
{ "Sample", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangPS, true }, { "Sample", /*!O*/ "V4", nullptr, "%@,S,V", "FIU,S,F", EShLangPS, true },
{ "Sample", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangPS, true }, { "Sample", /* O*/ "V4", nullptr, "%@,S,V,", "FIU,S,F,I", EShLangPS, true },
{ "SampleBias", /*!O*/ "V4", nullptr, "%@,S,V,S", "FIU,S,F,", 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,,I", 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. // 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", "FIU,s,F,", EShLangPS, true },
@ -917,7 +852,7 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c
{ "WaveActiveAllEqual", "S", "B", "SV", "DFUI", EShLangPSCS, false}, { "WaveActiveAllEqual", "S", "B", "SV", "DFUI", EShLangPSCS, false},
{ "WaveActiveAllEqualBool", "S", "B", "S", "B", EShLangPSCS, false}, { "WaveActiveAllEqualBool", "S", "B", "S", "B", EShLangPSCS, false},
{ "WaveActiveCountBits", "S", "U", "S", "B", EShLangPSCS, false}, { "WaveActiveCountBits", "S", "U", "S", "B", EShLangPSCS, false},
{ "WaveActiveSum", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, { "WaveActiveSum", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WaveActiveProduct", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, { "WaveActiveProduct", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
{ "WaveActiveBitAnd", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false}, { "WaveActiveBitAnd", nullptr, nullptr, "SV", "DFUI", EShLangPSCS, false},
@ -1172,7 +1107,7 @@ void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profil
// symbolTable.relateToOperator("noise", EOpNoise); // TODO: check return type // symbolTable.relateToOperator("noise", EOpNoise); // TODO: check return type
symbolTable.relateToOperator("normalize", EOpNormalize); symbolTable.relateToOperator("normalize", EOpNormalize);
symbolTable.relateToOperator("pow", EOpPow); symbolTable.relateToOperator("pow", EOpPow);
// symbolTable.relateToOperator("printf", EOpPrintf); symbolTable.relateToOperator("printf", EOpDebugPrintf);
// symbolTable.relateToOperator("Process2DQuadTessFactorsAvg"); // symbolTable.relateToOperator("Process2DQuadTessFactorsAvg");
// symbolTable.relateToOperator("Process2DQuadTessFactorsMax"); // symbolTable.relateToOperator("Process2DQuadTessFactorsMax");
// symbolTable.relateToOperator("Process2DQuadTessFactorsMin"); // symbolTable.relateToOperator("Process2DQuadTessFactorsMin");
@ -1188,7 +1123,7 @@ void TBuiltInParseablesHlsl::identifyBuiltIns(int /*version*/, EProfile /*profil
symbolTable.relateToOperator("reflect", EOpReflect); symbolTable.relateToOperator("reflect", EOpReflect);
symbolTable.relateToOperator("refract", EOpRefract); symbolTable.relateToOperator("refract", EOpRefract);
symbolTable.relateToOperator("reversebits", EOpBitFieldReverse); symbolTable.relateToOperator("reversebits", EOpBitFieldReverse);
symbolTable.relateToOperator("round", EOpRoundEven); symbolTable.relateToOperator("round", EOpRound);
symbolTable.relateToOperator("rsqrt", EOpInverseSqrt); symbolTable.relateToOperator("rsqrt", EOpInverseSqrt);
symbolTable.relateToOperator("saturate", EOpSaturate); symbolTable.relateToOperator("saturate", EOpSaturate);
symbolTable.relateToOperator("sign", EOpSign); symbolTable.relateToOperator("sign", EOpSign);

View File

@ -36,7 +36,7 @@
#ifndef _HLSLPARSEABLES_INCLUDED_ #ifndef _HLSLPARSEABLES_INCLUDED_
#define _HLSLPARSEABLES_INCLUDED_ #define _HLSLPARSEABLES_INCLUDED_
#include "../glslang/MachineIndependent/Initialize.h" #include "../MachineIndependent/Initialize.h"
namespace glslang { namespace glslang {

View File

@ -42,15 +42,15 @@
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include "../glslang/Include/Types.h" #include "../Include/Types.h"
#include "../glslang/MachineIndependent/SymbolTable.h" #include "../MachineIndependent/SymbolTable.h"
#include "../glslang/MachineIndependent/ParseHelper.h" #include "../MachineIndependent/ParseHelper.h"
#include "hlslScanContext.h" #include "hlslScanContext.h"
#include "hlslTokens.h" #include "hlslTokens.h"
// preprocessor includes // preprocessor includes
#include "../glslang/MachineIndependent/preprocessor/PpContext.h" #include "../MachineIndependent/preprocessor/PpContext.h"
#include "../glslang/MachineIndependent/preprocessor/PpTokens.h" #include "../MachineIndependent/preprocessor/PpTokens.h"
namespace { namespace {
@ -317,7 +317,7 @@ void HlslScanContext::fillInKeywordMap()
(*KeywordMap)["sampler1D"] = EHTokSampler1d; (*KeywordMap)["sampler1D"] = EHTokSampler1d;
(*KeywordMap)["sampler2D"] = EHTokSampler2d; (*KeywordMap)["sampler2D"] = EHTokSampler2d;
(*KeywordMap)["sampler3D"] = EHTokSampler3d; (*KeywordMap)["sampler3D"] = EHTokSampler3d;
(*KeywordMap)["samplerCube"] = EHTokSamplerCube; (*KeywordMap)["samplerCUBE"] = EHTokSamplerCube;
(*KeywordMap)["sampler_state"] = EHTokSamplerState; (*KeywordMap)["sampler_state"] = EHTokSamplerState;
(*KeywordMap)["SamplerState"] = EHTokSamplerState; (*KeywordMap)["SamplerState"] = EHTokSamplerState;
(*KeywordMap)["SamplerComparisonState"] = EHTokSamplerComparisonState; (*KeywordMap)["SamplerComparisonState"] = EHTokSamplerComparisonState;

View File

@ -41,7 +41,7 @@
#ifndef HLSLSCANCONTEXT_H_ #ifndef HLSLSCANCONTEXT_H_
#define HLSLSCANCONTEXT_H_ #define HLSLSCANCONTEXT_H_
#include "../glslang/MachineIndependent/ParseHelper.h" #include "../MachineIndependent/ParseHelper.h"
#include "hlslTokens.h" #include "hlslTokens.h"
namespace glslang { namespace glslang {

View File

@ -34,21 +34,20 @@
// POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
// //
#include "hlslAttributes.h"
#include "hlslGrammar.h"
#include "hlslParseHelper.h" #include "hlslParseHelper.h"
#include "hlslScanContext.h" #include "hlslScanContext.h"
#include "hlslGrammar.h"
#include "hlslAttributes.h"
#include "../glslang/MachineIndependent/Scan.h" #include "../MachineIndependent/Scan.h"
#include "../glslang/MachineIndependent/preprocessor/PpContext.h" #include "../MachineIndependent/preprocessor/PpContext.h"
#include "../glslang/OSDependent/osinclude.h" #include "../OSDependent/osinclude.h"
#include <algorithm> #include <algorithm>
#include <functional>
#include <cctype>
#include <array> #include <array>
#include <cctype>
#include <functional>
#include <set> #include <set>
#endif /* _PCH_H */ #endif /* _PCH_H */

View File

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -61,8 +62,13 @@ enum TBasicType {
EbtSampler, EbtSampler,
EbtStruct, EbtStruct,
EbtBlock, EbtBlock,
EbtAccStructNV, EbtAccStruct,
EbtReference, EbtReference,
EbtRayQuery,
#ifndef GLSLANG_WEB
// SPIR-V type defined by spirv_type
EbtSpirvType,
#endif
// HLSL types that live only temporarily. // HLSL types that live only temporarily.
EbtString, EbtString,
@ -89,12 +95,15 @@ enum TStorageQualifier {
EvqUniform, // read only, shared with app EvqUniform, // read only, shared with app
EvqBuffer, // read/write, shared with app EvqBuffer, // read/write, shared with app
EvqShared, // compute shader's read/write 'shared' qualifier EvqShared, // compute shader's read/write 'shared' qualifier
#ifndef GLSLANG_WEB
EvqSpirvStorageClass, // spirv_storage_class
#endif
EvqPayloadNV, EvqPayload,
EvqPayloadInNV, EvqPayloadIn,
EvqHitAttrNV, EvqHitAttr,
EvqCallableDataNV, EvqCallableData,
EvqCallableDataInNV, EvqCallableDataIn,
// parameters // parameters
EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
@ -226,9 +235,15 @@ enum TBuiltInVariable {
EbvViewIndex, EbvViewIndex,
EbvDeviceIndex, EbvDeviceIndex,
EbvShadingRateKHR,
EbvPrimitiveShadingRateKHR,
EbvFragSizeEXT, EbvFragSizeEXT,
EbvFragInvocationCountEXT, EbvFragInvocationCountEXT,
EbvSecondaryFragDataEXT,
EbvSecondaryFragColorEXT,
EbvViewportMaskNV, EbvViewportMaskNV,
EbvSecondaryPositionNV, EbvSecondaryPositionNV,
EbvSecondaryViewportMaskNV, EbvSecondaryViewportMaskNV,
@ -238,20 +253,24 @@ enum TBuiltInVariable {
EbvFragmentSizeNV, EbvFragmentSizeNV,
EbvInvocationsPerPixelNV, EbvInvocationsPerPixelNV,
// ray tracing // ray tracing
EbvLaunchIdNV, EbvLaunchId,
EbvLaunchSizeNV, EbvLaunchSize,
EbvInstanceCustomIndexNV, EbvInstanceCustomIndex,
EbvWorldRayOriginNV, EbvGeometryIndex,
EbvWorldRayDirectionNV, EbvWorldRayOrigin,
EbvObjectRayOriginNV, EbvWorldRayDirection,
EbvObjectRayDirectionNV, EbvObjectRayOrigin,
EbvRayTminNV, EbvObjectRayDirection,
EbvRayTmaxNV, EbvRayTmin,
EbvHitTNV, EbvRayTmax,
EbvHitKindNV, EbvHitT,
EbvObjectToWorldNV, EbvHitKind,
EbvWorldToObjectNV, EbvObjectToWorld,
EbvIncomingRayFlagsNV, EbvObjectToWorld3x4,
EbvWorldToObject,
EbvWorldToObject3x4,
EbvIncomingRayFlags,
EbvCurrentRayTimeNV,
// barycentrics // barycentrics
EbvBaryCoordNV, EbvBaryCoordNV,
EbvBaryCoordNoPerspNV, EbvBaryCoordNoPerspNV,
@ -310,6 +329,9 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q)
case EvqGlobal: return "global"; break; case EvqGlobal: return "global"; break;
case EvqConst: return "const"; break; case EvqConst: return "const"; break;
case EvqConstReadOnly: return "const (read only)"; break; case EvqConstReadOnly: return "const (read only)"; break;
#ifndef GLSLANG_WEB
case EvqSpirvStorageClass: return "spirv_storage_class"; break;
#endif
case EvqVaryingIn: return "in"; break; case EvqVaryingIn: return "in"; break;
case EvqVaryingOut: return "out"; break; case EvqVaryingOut: return "out"; break;
case EvqUniform: return "uniform"; break; case EvqUniform: return "uniform"; break;
@ -328,11 +350,11 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q)
case EvqPointCoord: return "gl_PointCoord"; break; case EvqPointCoord: return "gl_PointCoord"; break;
case EvqFragColor: return "fragColor"; break; case EvqFragColor: return "fragColor"; break;
case EvqFragDepth: return "gl_FragDepth"; break; case EvqFragDepth: return "gl_FragDepth"; break;
case EvqPayloadNV: return "rayPayloadNV"; break; case EvqPayload: return "rayPayloadNV"; break;
case EvqPayloadInNV: return "rayPayloadInNV"; break; case EvqPayloadIn: return "rayPayloadInNV"; break;
case EvqHitAttrNV: return "hitAttributeNV"; break; case EvqHitAttr: return "hitAttributeNV"; break;
case EvqCallableDataNV: return "callableDataNV"; break; case EvqCallableData: return "callableDataNV"; break;
case EvqCallableDataInNV: return "callableDataInNV"; break; case EvqCallableDataIn: return "callableDataInNV"; break;
default: return "unknown qualifier"; default: return "unknown qualifier";
} }
} }
@ -428,6 +450,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvFragSizeEXT: return "FragSizeEXT"; case EbvFragSizeEXT: return "FragSizeEXT";
case EbvFragInvocationCountEXT: return "FragInvocationCountEXT"; case EbvFragInvocationCountEXT: return "FragInvocationCountEXT";
case EbvSecondaryFragDataEXT: return "SecondaryFragDataEXT";
case EbvSecondaryFragColorEXT: return "SecondaryFragColorEXT";
case EbvViewportMaskNV: return "ViewportMaskNV"; case EbvViewportMaskNV: return "ViewportMaskNV";
case EbvSecondaryPositionNV: return "SecondaryPositionNV"; case EbvSecondaryPositionNV: return "SecondaryPositionNV";
case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
@ -436,20 +461,22 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; case EbvFragFullyCoveredNV: return "FragFullyCoveredNV";
case EbvFragmentSizeNV: return "FragmentSizeNV"; case EbvFragmentSizeNV: return "FragmentSizeNV";
case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV"; case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV";
case EbvLaunchIdNV: return "LaunchIdNV"; case EbvLaunchId: return "LaunchIdNV";
case EbvLaunchSizeNV: return "LaunchSizeNV"; case EbvLaunchSize: return "LaunchSizeNV";
case EbvInstanceCustomIndexNV: return "InstanceCustomIndexNV"; case EbvInstanceCustomIndex: return "InstanceCustomIndexNV";
case EbvWorldRayOriginNV: return "WorldRayOriginNV"; case EbvGeometryIndex: return "GeometryIndexEXT";
case EbvWorldRayDirectionNV: return "WorldRayDirectionNV"; case EbvWorldRayOrigin: return "WorldRayOriginNV";
case EbvObjectRayOriginNV: return "ObjectRayOriginNV"; case EbvWorldRayDirection: return "WorldRayDirectionNV";
case EbvObjectRayDirectionNV: return "ObjectRayDirectionNV"; case EbvObjectRayOrigin: return "ObjectRayOriginNV";
case EbvRayTminNV: return "ObjectRayTminNV"; case EbvObjectRayDirection: return "ObjectRayDirectionNV";
case EbvRayTmaxNV: return "ObjectRayTmaxNV"; case EbvRayTmin: return "ObjectRayTminNV";
case EbvHitTNV: return "HitTNV"; case EbvRayTmax: return "ObjectRayTmaxNV";
case EbvHitKindNV: return "HitKindNV"; case EbvHitT: return "HitTNV";
case EbvIncomingRayFlagsNV: return "IncomingRayFlagsNV"; case EbvHitKind: return "HitKindNV";
case EbvObjectToWorldNV: return "ObjectToWorldNV"; case EbvIncomingRayFlags: return "IncomingRayFlagsNV";
case EbvWorldToObjectNV: return "WorldToObjectNV"; case EbvObjectToWorld: return "ObjectToWorldNV";
case EbvWorldToObject: return "WorldToObjectNV";
case EbvCurrentRayTimeNV: return "CurrentRayTimeNV";
case EbvBaryCoordNV: return "BaryCoordNV"; case EbvBaryCoordNV: return "BaryCoordNV";
case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV"; case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
@ -468,6 +495,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvWarpID: return "WarpIDNV"; case EbvWarpID: return "WarpIDNV";
case EbvSMID: return "SMIDNV"; case EbvSMID: return "SMIDNV";
case EbvShadingRateKHR: return "ShadingRateKHR";
case EbvPrimitiveShadingRateKHR: return "PrimitiveShadingRateKHR";
default: return "unknown built-in variable"; default: return "unknown built-in variable";
} }
} }

View File

@ -37,6 +37,22 @@
#ifndef _COMMON_INCLUDED_ #ifndef _COMMON_INCLUDED_
#define _COMMON_INCLUDED_ #define _COMMON_INCLUDED_
#include <algorithm>
#include <cassert>
#ifdef _MSC_VER
#include <cfloat>
#else
#include <cmath>
#endif
#include <cstdio>
#include <cstdlib>
#include <list>
#include <map>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700) #if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700)
#include <sstream> #include <sstream>
@ -50,7 +66,7 @@ std::string to_string(const T& val) {
} }
#endif #endif
#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API #if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || MINGW_HAS_SECURE_API
#include <basetsd.h> #include <basetsd.h>
#ifndef snprintf #ifndef snprintf
#define snprintf sprintf_s #define snprintf sprintf_s
@ -93,18 +109,6 @@ std::string to_string(const T& val) {
#pragma warning(disable : 4201) // nameless union #pragma warning(disable : 4201) // nameless union
#endif #endif
#include <set>
#include <unordered_set>
#include <vector>
#include <map>
#include <unordered_map>
#include <list>
#include <algorithm>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include "PoolAlloc.h" #include "PoolAlloc.h"
// //
@ -195,6 +199,10 @@ template <class K, class D, class HASH = std::hash<K>, class PRED = std::equal_t
class TUnorderedMap : public std::unordered_map<K, D, HASH, PRED, pool_allocator<std::pair<K const, D> > > { class TUnorderedMap : public std::unordered_map<K, D, HASH, PRED, pool_allocator<std::pair<K const, D> > > {
}; };
template <class K, class CMP = std::less<K> >
class TSet : public std::set<K, CMP, pool_allocator<K> > {
};
// //
// Persistent string memory. Should only be used for strings that survive // Persistent string memory. Should only be used for strings that survive
// across compiles/links. // across compiles/links.
@ -210,7 +218,7 @@ template <class T> T Max(const T a, const T b) { return a > b ? a : b; }
// //
// Create a TString object from an integer. // Create a TString object from an integer.
// //
#if defined _MSC_VER || defined MINGW_HAS_SECURE_API #if defined _MSC_VER || MINGW_HAS_SECURE_API
inline const TString String(const int i, const int base = 10) 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 char text[16]; // 32 bit ints are at most 10 digits in base 10
@ -287,6 +295,46 @@ template <class T> bool IsMultipleOfPow2(T number, int powerOf2)
return ! (number & (powerOf2 - 1)); return ! (number & (powerOf2 - 1));
} }
// Returns log2 of an integer power of 2.
// T should be integral.
template <class T> int IntLog2(T n)
{
assert(IsPow2(n));
int result = 0;
while ((T(1) << result) != n) {
result++;
}
return result;
}
inline bool IsInfinity(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_NINF:
case _FPCLASS_PINF:
return true;
default:
return false;
}
#else
return std::isinf(x);
#endif
}
inline bool IsNan(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_SNAN:
case _FPCLASS_QNAN:
return true;
default:
return false;
}
#else
return std::isnan(x);
#endif
}
} // end namespace glslang } // end namespace glslang
#endif // _COMMON_INCLUDED_ #endif // _COMMON_INCLUDED_

View File

@ -921,7 +921,7 @@ public:
else else
unionArray = new TConstUnionVector(size); unionArray = new TConstUnionVector(size);
} }
TConstUnionArray(const TConstUnionArray& a) : unionArray(a.unionArray) { } TConstUnionArray(const TConstUnionArray& a) = default;
TConstUnionArray(const TConstUnionArray& a, int start, int size) TConstUnionArray(const TConstUnionArray& a, int start, int size)
{ {
unionArray = new TConstUnionVector(size); unionArray = new TConstUnionVector(size);

View File

@ -306,6 +306,8 @@ public:
TPoolAllocator& getAllocator() const { return allocator; } TPoolAllocator& getAllocator() const { return allocator; }
pool_allocator select_on_container_copy_construction() const { return pool_allocator{}; }
protected: protected:
pool_allocator& operator=(const pool_allocator&) { return *this; } pool_allocator& operator=(const pool_allocator&) { return *this; }
TPoolAllocator& allocator; TPoolAllocator& allocator;

View File

@ -142,6 +142,7 @@ struct TBuiltInResource {
int maxTaskWorkGroupSizeY_NV; int maxTaskWorkGroupSizeY_NV;
int maxTaskWorkGroupSizeZ_NV; int maxTaskWorkGroupSizeZ_NV;
int maxMeshViewCountNV; int maxMeshViewCountNV;
int maxDualSourceDrawBuffersEXT;
TLimits limits; TLimits limits;
}; };

View File

@ -0,0 +1,128 @@
//
// 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
#ifndef GLSLANG_WEB
//
// GL_EXT_spirv_intrinsics
//
#include "Common.h"
namespace glslang {
class TIntermTyped;
class TIntermConstantUnion;
class TType;
// SPIR-V requirements
struct TSpirvRequirement {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
// capability = [..]
TSet<TString> extensions;
// extension = [..]
TSet<int> capabilities;
};
// SPIR-V execution modes
struct TSpirvExecutionMode {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
// spirv_execution_mode
TMap<int, TVector<const TIntermConstantUnion*>> modes;
// spirv_execution_mode_id
TMap<int, TVector<const TIntermTyped*> > modeIds;
};
// SPIR-V decorations
struct TSpirvDecorate {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
// spirv_decorate
TMap<int, TVector<const TIntermConstantUnion*> > decorates;
// spirv_decorate_id
TMap<int, TVector<const TIntermTyped*>> decorateIds;
// spirv_decorate_string
TMap<int, TVector<const TIntermConstantUnion*> > 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) { constant = arg; }
bool operator==(const TSpirvTypeParameter& rhs) const { return constant == rhs.constant; }
bool operator!=(const TSpirvTypeParameter& rhs) const { return !operator==(rhs); }
const TIntermConstantUnion* constant;
};
typedef TVector<TSpirvTypeParameter> 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
#endif // GLSLANG_WEB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,254 @@
/**
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 <stdbool.h>
#include <stdlib.h>
#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 maxDualSourceDrawBuffersEXT;
glslang_limits_t limits;
} glslang_resource_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;
} glslang_input_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;
#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();
GLSLANG_EXPORT void glslang_finalize_process();
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_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();
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 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 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 */

View File

@ -0,0 +1,211 @@
/**
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_NV,
GLSLANG_STAGE_INTERSECT_NV,
GLSLANG_STAGE_ANYHIT_NV,
GLSLANG_STAGE_CLOSESTHIT_NV,
GLSLANG_STAGE_MISS_NV,
GLSLANG_STAGE_CALLABLE_NV,
GLSLANG_STAGE_TASK_NV,
GLSLANG_STAGE_MESH_NV,
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_NV_MASK = (1 << GLSLANG_STAGE_RAYGEN_NV),
GLSLANG_STAGE_INTERSECT_NV_MASK = (1 << GLSLANG_STAGE_INTERSECT_NV),
GLSLANG_STAGE_ANYHIT_NV_MASK = (1 << GLSLANG_STAGE_ANYHIT_NV),
GLSLANG_STAGE_CLOSESTHIT_NV_MASK = (1 << GLSLANG_STAGE_CLOSESTHIT_NV),
GLSLANG_STAGE_MISS_NV_MASK = (1 << GLSLANG_STAGE_MISS_NV),
GLSLANG_STAGE_CALLABLE_NV_MASK = (1 << GLSLANG_STAGE_CALLABLE_NV),
GLSLANG_STAGE_TASK_NV_MASK = (1 << GLSLANG_STAGE_TASK_NV),
GLSLANG_STAGE_MESH_NV_MASK = (1 << GLSLANG_STAGE_MESH_NV),
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

View File

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -70,6 +71,9 @@ enum TOperator {
EOpFunctionCall, EOpFunctionCall,
EOpFunction, // For function definition EOpFunction, // For function definition
EOpParameters, // an aggregate listing the parameters to a function EOpParameters, // an aggregate listing the parameters to a function
#ifndef GLSLANG_WEB
EOpSpirvInst,
#endif
// //
// Unary operators // Unary operators
@ -279,6 +283,12 @@ enum TOperator {
EOpConvUvec2ToPtr, EOpConvUvec2ToPtr,
EOpConvPtrToUvec2, EOpConvPtrToUvec2,
// uint64_t -> accelerationStructureEXT
EOpConvUint64ToAccStruct,
// uvec2 -> accelerationStructureEXT
EOpConvUvec2ToAccStruct,
// //
// binary operations // binary operations
// //
@ -586,6 +596,7 @@ enum TOperator {
EOpTime, EOpTime,
EOpAtomicAdd, EOpAtomicAdd,
EOpAtomicSubtract,
EOpAtomicMin, EOpAtomicMin,
EOpAtomicMax, EOpAtomicMax,
EOpAtomicAnd, EOpAtomicAnd,
@ -621,17 +632,22 @@ enum TOperator {
EOpIsHelperInvocation, EOpIsHelperInvocation,
EOpDebugPrintf,
// //
// Branch // Branch
// //
EOpKill, // Fragment only EOpKill, // Fragment only
EOpTerminateInvocation, // Fragment only
EOpDemote, // Fragment only
EOpTerminateRayKHR, // Any-hit only
EOpIgnoreIntersectionKHR, // Any-hit only
EOpReturn, EOpReturn,
EOpBreak, EOpBreak,
EOpContinue, EOpContinue,
EOpCase, EOpCase,
EOpDefault, EOpDefault,
EOpDemote, // Fragment only
// //
// Constructors // Constructors
@ -748,6 +764,7 @@ enum TOperator {
EOpConstructNonuniform, // expected to be transformed away, not present in final AST EOpConstructNonuniform, // expected to be transformed away, not present in final AST
EOpConstructReference, EOpConstructReference,
EOpConstructCooperativeMatrix, EOpConstructCooperativeMatrix,
EOpConstructAccStruct,
EOpConstructGuardEnd, EOpConstructGuardEnd,
// //
@ -909,11 +926,43 @@ enum TOperator {
EOpMul32x16, EOpMul32x16,
EOpTraceNV, EOpTraceNV,
EOpReportIntersectionNV, EOpTraceRayMotionNV,
EOpTraceKHR,
EOpReportIntersection,
EOpIgnoreIntersectionNV, EOpIgnoreIntersectionNV,
EOpTerminateRayNV, EOpTerminateRayNV,
EOpExecuteCallableNV, EOpExecuteCallableNV,
EOpExecuteCallableKHR,
EOpWritePackedPrimitiveIndices4x8NV, EOpWritePackedPrimitiveIndices4x8NV,
//
// 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,
// //
// HLSL operations // HLSL operations
// //
@ -1091,6 +1140,8 @@ public:
virtual TBasicType getBasicType() const { return type.getBasicType(); } virtual TBasicType getBasicType() const { return type.getBasicType(); }
virtual TQualifier& getQualifier() { return type.getQualifier(); } virtual TQualifier& getQualifier() { return type.getQualifier(); }
virtual const TQualifier& getQualifier() const { 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 void propagatePrecision(TPrecisionQualifier);
virtual int getVectorSize() const { return type.getVectorSize(); } virtual int getVectorSize() const { return type.getVectorSize(); }
virtual int getMatrixCols() const { return type.getMatrixCols(); } virtual int getMatrixCols() const { return type.getMatrixCols(); }
@ -1104,7 +1155,7 @@ public:
virtual bool isIntegerDomain() const { return type.isIntegerDomain(); } virtual bool isIntegerDomain() const { return type.isIntegerDomain(); }
bool isAtomic() const { return type.isAtomic(); } bool isAtomic() const { return type.isAtomic(); }
bool isReference() const { return type.isReference(); } bool isReference() const { return type.isReference(); }
TString getCompleteString() const { return type.getCompleteString(); } TString getCompleteString(bool enhanced = false) const { return type.getCompleteString(enhanced); }
protected: protected:
TIntermTyped& operator=(const TIntermTyped&); TIntermTyped& operator=(const TIntermTyped&);
@ -1199,6 +1250,7 @@ public:
TOperator getFlowOp() const { return flowOp; } TOperator getFlowOp() const { return flowOp; }
TIntermTyped* getExpression() const { return expression; } TIntermTyped* getExpression() const { return expression; }
void setExpression(TIntermTyped* pExpression) { expression = pExpression; } void setExpression(TIntermTyped* pExpression) { expression = pExpression; }
void updatePrecision(TPrecisionQualifier parentPrecision);
protected: protected:
TOperator flowOp; TOperator flowOp;
TIntermTyped* expression; TIntermTyped* expression;
@ -1230,15 +1282,15 @@ public:
// if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from // 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 // per process threadPoolAllocator, then it causes increased memory usage per compile
// it is essential to use "symbol = sym" to assign to symbol // it is essential to use "symbol = sym" to assign to symbol
TIntermSymbol(int i, const TString& n, const TType& t) TIntermSymbol(long long i, const TString& n, const TType& t)
: TIntermTyped(t), id(i), : TIntermTyped(t), id(i),
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
flattenSubset(-1), flattenSubset(-1),
#endif #endif
constSubtree(nullptr) constSubtree(nullptr)
{ name = n; } { name = n; }
virtual int getId() const { return id; } virtual long long getId() const { return id; }
virtual void changeId(int i) { id = i; } virtual void changeId(long long i) { id = i; }
virtual const TString& getName() const { return name; } virtual const TString& getName() const { return name; }
virtual void traverse(TIntermTraverser*); virtual void traverse(TIntermTraverser*);
virtual TIntermSymbol* getAsSymbolNode() { return this; } virtual TIntermSymbol* getAsSymbolNode() { return this; }
@ -1249,15 +1301,17 @@ public:
TIntermTyped* getConstSubtree() const { return constSubtree; } TIntermTyped* getConstSubtree() const { return constSubtree; }
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
void setFlattenSubset(int subset) { flattenSubset = subset; } void setFlattenSubset(int subset) { flattenSubset = subset; }
virtual const TString& getAccessName() const;
int getFlattenSubset() const { return flattenSubset; } // -1 means full object int getFlattenSubset() const { return flattenSubset; } // -1 means full object
#endif #endif
// This is meant for cases where a node has already been constructed, and // This is meant for cases where a node has already been constructed, and
// later on, it becomes necessary to switch to a different symbol. // later on, it becomes necessary to switch to a different symbol.
virtual void switchId(int newId) { id = newId; } virtual void switchId(long long newId) { id = newId; }
protected: protected:
int id; // the unique id of the symbol this node represents long long id; // the unique id of the symbol this node represents
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced int flattenSubset; // how deeply the flattened object rooted at id has been dereferenced
#endif #endif
@ -1566,8 +1620,15 @@ public:
virtual TIntermUnary* getAsUnaryNode() { return this; } virtual TIntermUnary* getAsUnaryNode() { return this; }
virtual const TIntermUnary* getAsUnaryNode() const { return this; } virtual const TIntermUnary* getAsUnaryNode() const { return this; }
virtual void updatePrecision(); virtual void updatePrecision();
#ifndef GLSLANG_WEB
void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; }
const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; }
#endif
protected: protected:
TIntermTyped* operand; TIntermTyped* operand;
#ifndef GLSLANG_WEB
TSpirvInstruction spirvInst;
#endif
}; };
typedef TVector<TIntermNode*> TIntermSequence; typedef TVector<TIntermNode*> TIntermSequence;
@ -1582,6 +1643,7 @@ public:
~TIntermAggregate() { delete pragmaTable; } ~TIntermAggregate() { delete pragmaTable; }
virtual TIntermAggregate* getAsAggregate() { return this; } virtual TIntermAggregate* getAsAggregate() { return this; }
virtual const TIntermAggregate* getAsAggregate() const { return this; } virtual const TIntermAggregate* getAsAggregate() const { return this; }
virtual void updatePrecision();
virtual void setOperator(TOperator o) { op = o; } virtual void setOperator(TOperator o) { op = o; }
virtual TIntermSequence& getSequence() { return sequence; } virtual TIntermSequence& getSequence() { return sequence; }
virtual const TIntermSequence& getSequence() const { return sequence; } virtual const TIntermSequence& getSequence() const { return sequence; }
@ -1598,6 +1660,10 @@ public:
bool getDebug() const { return debug; } bool getDebug() const { return debug; }
void setPragmaTable(const TPragmaTable& pTable); void setPragmaTable(const TPragmaTable& pTable);
const TPragmaTable& getPragmaTable() const { return *pragmaTable; } const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
#ifndef GLSLANG_WEB
void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; }
const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; }
#endif
protected: protected:
TIntermAggregate(const TIntermAggregate&); // disallow copy constructor TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
@ -1608,6 +1674,9 @@ protected:
bool optimize; bool optimize;
bool debug; bool debug;
TPragmaTable* pragmaTable; TPragmaTable* pragmaTable;
#ifndef GLSLANG_WEB
TSpirvInstruction spirvInst;
#endif
}; };
// //
@ -1625,8 +1694,11 @@ public:
flatten(false), dontFlatten(false) {} flatten(false), dontFlatten(false) {}
virtual void traverse(TIntermTraverser*); virtual void traverse(TIntermTraverser*);
virtual TIntermTyped* getCondition() const { return condition; } virtual TIntermTyped* getCondition() const { return condition; }
virtual void setCondition(TIntermTyped* c) { condition = c; }
virtual TIntermNode* getTrueBlock() const { return trueBlock; } virtual TIntermNode* getTrueBlock() const { return trueBlock; }
virtual void setTrueBlock(TIntermTyped* tb) { trueBlock = tb; }
virtual TIntermNode* getFalseBlock() const { return falseBlock; } virtual TIntermNode* getFalseBlock() const { return falseBlock; }
virtual void setFalseBlock(TIntermTyped* fb) { falseBlock = fb; }
virtual TIntermSelection* getAsSelectionNode() { return this; } virtual TIntermSelection* getAsSelectionNode() { return this; }
virtual const TIntermSelection* getAsSelectionNode() const { return this; } virtual const TIntermSelection* getAsSelectionNode() const { return this; }

View File

@ -1,3 +0,0 @@
// This header is generated by the make-revision script.
#define GLSLANG_PATCH_LEVEL 3559

View File

@ -1,13 +0,0 @@
// The file revision.h should be updated to the latest version, somehow, on
// check-in, if glslang has changed.
//
// revision.template is the source for revision.h when using SubWCRev as the
// method of updating revision.h. You don't have to do it this way, the
// requirement is only that revision.h gets updated.
//
// revision.h is under source control so that not all consumers of glslang
// source have to figure out how to create revision.h just to get a build
// going. However, if it is not updated, it can be a version behind.
#define GLSLANG_REVISION "$WCREV$"
#define GLSLANG_DATE "$WCDATE$"

View File

@ -2,7 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2018 Google, Inc. // Copyright (C) 2018-2020 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -46,35 +46,6 @@ namespace {
using namespace glslang; using namespace glslang;
typedef union {
double d;
int i[2];
} DoubleIntUnion;
// Some helper functions
bool isNan(double x)
{
DoubleIntUnion u;
// tough to find a platform independent library function, do it directly
u.d = x;
int bitPatternL = u.i[0];
int bitPatternH = u.i[1];
return (bitPatternH & 0x7ff80000) == 0x7ff80000 &&
((bitPatternH & 0xFFFFF) != 0 || bitPatternL != 0);
}
bool isInf(double x)
{
DoubleIntUnion u;
// tough to find a platform independent library function, do it directly
u.d = x;
int bitPatternL = u.i[0];
int bitPatternH = u.i[1];
return (bitPatternH & 0x7ff00000) == 0x7ff00000 &&
(bitPatternH & 0xFFFFF) == 0 && bitPatternL == 0;
}
const double pi = 3.1415926535897932384626433832795; const double pi = 3.1415926535897932384626433832795;
} // end anonymous namespace } // end anonymous namespace
@ -529,7 +500,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
case EbtDouble: case EbtDouble:
case EbtFloat16: case EbtFloat16:
case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break; case EbtFloat: newConstArray[i].setDConst(-unionArray[i].getDConst()); break;
case EbtInt: newConstArray[i].setIConst(-unionArray[i].getIConst()); break; // Note: avoid UBSAN error regarding negating 0x80000000
case EbtInt: newConstArray[i].setIConst(
static_cast<unsigned int>(unionArray[i].getIConst()) == 0x80000000
? -0x7FFFFFFF - 1
: -unionArray[i].getIConst());
break;
case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break; case EbtUint: newConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break; case EbtInt8: newConstArray[i].setI8Const(-unionArray[i].getI8Const()); break;
@ -599,17 +575,11 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
newConstArray[i].setDConst(log(unionArray[i].getDConst())); newConstArray[i].setDConst(log(unionArray[i].getDConst()));
break; break;
case EOpExp2: case EOpExp2:
{ newConstArray[i].setDConst(exp2(unionArray[i].getDConst()));
const double inv_log2_e = 0.69314718055994530941723212145818; break;
newConstArray[i].setDConst(exp(unionArray[i].getDConst() * inv_log2_e));
break;
}
case EOpLog2: case EOpLog2:
{ newConstArray[i].setDConst(log2(unionArray[i].getDConst()));
const double log2_e = 1.4426950408889634073599246810019; break;
newConstArray[i].setDConst(log2_e * log(unionArray[i].getDConst()));
break;
}
case EOpSqrt: case EOpSqrt:
newConstArray[i].setDConst(sqrt(unionArray[i].getDConst())); newConstArray[i].setDConst(sqrt(unionArray[i].getDConst()));
break; break;
@ -664,12 +634,12 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
case EOpIsNan: case EOpIsNan:
{ {
newConstArray[i].setBConst(isNan(unionArray[i].getDConst())); newConstArray[i].setBConst(IsNan(unionArray[i].getDConst()));
break; break;
} }
case EOpIsInf: case EOpIsInf:
{ {
newConstArray[i].setBConst(isInf(unionArray[i].getDConst())); newConstArray[i].setBConst(IsInfinity(unionArray[i].getDConst()));
break; break;
} }
@ -1012,6 +982,7 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
case EOpMin: case EOpMin:
case EOpMax: case EOpMax:
case EOpMix: case EOpMix:
case EOpMod:
case EOpClamp: case EOpClamp:
case EOpLessThan: case EOpLessThan:
case EOpGreaterThan: case EOpGreaterThan:
@ -1074,6 +1045,14 @@ TIntermTyped* TIntermediate::fold(TIntermAggregate* aggrNode)
case EOpPow: case EOpPow:
newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst())); newConstArray[comp].setDConst(pow(childConstUnions[0][arg0comp].getDConst(), childConstUnions[1][arg1comp].getDConst()));
break; 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: case EOpMin:
switch(children[0]->getAsTyped()->getBasicType()) { switch(children[0]->getAsTyped()->getBasicType()) {
case EbtFloat16: case EbtFloat16:

File diff suppressed because it is too large Load Diff

View File

@ -71,6 +71,13 @@ void TIntermConstantUnion::traverse(TIntermTraverser *it)
it->visitConstantUnion(this); it->visitConstantUnion(this);
} }
const TString& TIntermSymbol::getAccessName() const {
if (getBasicType() == EbtBlock)
return getType().getTypeName();
else
return getName();
}
// //
// Traverse a binary node. // Traverse a binary node.
// //

486
Externals/glslang/glslang/MachineIndependent/Intermediate.cpp vendored Executable file → Normal file
View File

@ -1,7 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2015 LunarG, Inc. // Copyright (C) 2012-2015 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2015-2020 Google, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// //
// All rights reserved. // All rights reserved.
@ -65,7 +65,7 @@ namespace glslang {
// Returns the added node. // Returns the added node.
// //
TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray, TIntermSymbol* TIntermediate::addSymbol(long long id, const TString& name, const TType& type, const TConstUnionArray& constArray,
TIntermTyped* constSubtree, const TSourceLoc& loc) TIntermTyped* constSubtree, const TSourceLoc& loc)
{ {
TIntermSymbol* node = new TIntermSymbol(id, name, type); TIntermSymbol* node = new TIntermSymbol(id, name, type);
@ -113,14 +113,14 @@ TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc
// //
// Returns nullptr if the working conversions and promotions could not be found. // Returns nullptr if the working conversions and promotions could not be found.
// //
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc)
{ {
// No operations work on blocks // No operations work on blocks
if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock) if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
return nullptr; return nullptr;
// Convert "reference +/- int" and "reference - reference" to integer math // Convert "reference +/- int" and "reference - reference" to integer math
if ((op == EOpAdd || op == EOpSub) && extensionRequested(E_GL_EXT_buffer_reference2)) { if (op == EOpAdd || op == EOpSub) {
// No addressing math on struct with unsized array. // No addressing math on struct with unsized array.
if ((left->isReference() && left->getType().getReferentType()->containsUnsizedArray()) || if ((left->isReference() && left->getType().getReferentType()->containsUnsizedArray()) ||
@ -140,43 +140,44 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType); node = addBuiltInFunctionCall(loc, EOpConvUint64ToPtr, true, node, referenceType);
return node; 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;
}
} }
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. // Try converting the children's base types to compatible types.
auto children = addConversion(op, left, right); auto children = addPairConversion(op, left, right);
left = std::get<0>(children); left = std::get<0>(children);
right = std::get<1>(children); right = std::get<1>(children);
@ -226,13 +227,12 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
// //
// Low level: add binary node (no promotions or other argument modifications) // Low level: add binary node (no promotions or other argument modifications)
// //
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) const TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right,
const TSourceLoc& loc) const
{ {
// build the node // build the node
TIntermBinary* node = new TIntermBinary(op); TIntermBinary* node = new TIntermBinary(op);
if (loc.line == 0) node->setLoc(loc.line != 0 ? loc : left->getLoc());
loc = left->getLoc();
node->setLoc(loc);
node->setLeft(left); node->setLeft(left);
node->setRight(right); node->setRight(right);
@ -242,7 +242,8 @@ TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TI
// //
// like non-type form, but sets node's type. // like non-type form, but sets node's type.
// //
TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc, const TType& type) const TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right,
const TSourceLoc& loc, const TType& type) const
{ {
TIntermBinary* node = addBinaryNode(op, left, right, loc); TIntermBinary* node = addBinaryNode(op, left, right, loc);
node->setType(type); node->setType(type);
@ -252,12 +253,10 @@ TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TI
// //
// Low level: add unary node (no promotions or other argument modifications) // Low level: add unary node (no promotions or other argument modifications)
// //
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc) const TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc) const
{ {
TIntermUnary* node = new TIntermUnary(op); TIntermUnary* node = new TIntermUnary(op);
if (loc.line == 0) node->setLoc(loc.line != 0 ? loc : child->getLoc());
loc = child->getLoc();
node->setLoc(loc);
node->setOperand(child); node->setOperand(child);
return node; return node;
@ -266,7 +265,8 @@ TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSo
// //
// like non-type form, but sets node's type. // like non-type form, but sets node's type.
// //
TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc, const TType& type) const TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, const TSourceLoc& loc, const TType& type)
const
{ {
TIntermUnary* node = addUnaryNode(op, child, loc); TIntermUnary* node = addUnaryNode(op, child, loc);
node->setType(type); node->setType(type);
@ -281,7 +281,8 @@ TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSo
// Returns nullptr if the 'right' type could not be converted to match the 'left' type, // Returns nullptr if the 'right' type could not be converted to match the 'left' type,
// or the resulting operation cannot be properly promoted. // or the resulting operation cannot be properly promoted.
// //
TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right,
const TSourceLoc& loc)
{ {
// No block assignment // No block assignment
if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock) if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
@ -290,9 +291,7 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
// Convert "reference += int" to "reference = reference + int". We need this because the // 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 // "reference + int" calculation involves a cast back to the original type, which makes it
// not an lvalue. // not an lvalue.
if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference() && if ((op == EOpAddAssign || op == EOpSubAssign) && left->isReference()) {
extensionRequested(E_GL_EXT_buffer_reference2)) {
if (!(right->getType().isScalar() && right->getType().isIntegerDomain())) if (!(right->getType().isScalar() && right->getType().isIntegerDomain()))
return nullptr; return nullptr;
@ -338,7 +337,8 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm
// Returns the added node. // Returns the added node.
// The caller should set the type of the returned node. // The caller should set the type of the returned node.
// //
TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc) TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index,
const TSourceLoc& loc)
{ {
// caller should set the type // caller should set the type
return addBinaryNode(op, base, index, loc); return addBinaryNode(op, base, index, loc);
@ -349,7 +349,8 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT
// //
// Returns the added node. // Returns the added node.
// //
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc) TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child,
const TSourceLoc& loc)
{ {
if (child == 0) if (child == 0)
return nullptr; return nullptr;
@ -415,20 +416,24 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSo
// TODO: but, did this bypass constant folding? // TODO: but, did this bypass constant folding?
// //
switch (op) { switch (op) {
case EOpConstructInt8: case EOpConstructInt8:
case EOpConstructUint8: case EOpConstructUint8:
case EOpConstructInt16: case EOpConstructInt16:
case EOpConstructUint16: case EOpConstructUint16:
case EOpConstructInt: case EOpConstructInt:
case EOpConstructUint: case EOpConstructUint:
case EOpConstructInt64: case EOpConstructInt64:
case EOpConstructUint64: case EOpConstructUint64:
case EOpConstructBool: case EOpConstructBool:
case EOpConstructFloat: case EOpConstructFloat:
case EOpConstructDouble: case EOpConstructDouble:
case EOpConstructFloat16: case EOpConstructFloat16: {
return child; TIntermUnary* unary_node = child->getAsUnaryNode();
default: break; // some compilers want this if (unary_node != nullptr)
unary_node->updatePrecision();
return child;
}
default: break; // some compilers want this
} }
// //
@ -495,7 +500,8 @@ TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOper
// Returns an aggregate node, which could be the one passed in if // Returns an aggregate node, which could be the one passed in if
// it was already an aggregate. // it was already an aggregate.
// //
TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, TSourceLoc loc) TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type,
const TSourceLoc& loc)
{ {
TIntermAggregate* aggNode; TIntermAggregate* aggNode;
@ -510,8 +516,6 @@ TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator o
// //
aggNode = new TIntermAggregate(); aggNode = new TIntermAggregate();
aggNode->getSequence().push_back(node); aggNode->getSequence().push_back(node);
if (loc.line == 0)
loc = node->getLoc();
} }
} else } else
aggNode = new TIntermAggregate(); aggNode = new TIntermAggregate();
@ -520,8 +524,8 @@ TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator o
// Set the operator. // Set the operator.
// //
aggNode->setOperator(op); aggNode->setOperator(op);
if (loc.line != 0) if (loc.line != 0 || node != nullptr)
aggNode->setLoc(loc); aggNode->setLoc(loc.line != 0 ? loc : node->getLoc());
aggNode->setType(type); aggNode->setType(type);
@ -538,7 +542,7 @@ bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const
return false; return false;
case EbtAtomicUint: case EbtAtomicUint:
case EbtSampler: case EbtSampler:
case EbtAccStructNV: case EbtAccStruct:
// opaque types can be passed to functions // opaque types can be passed to functions
if (op == EOpFunction) if (op == EOpFunction)
break; break;
@ -819,22 +823,25 @@ TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped
node->getBasicType() == EbtFloat || node->getBasicType() == EbtFloat ||
node->getBasicType() == EbtDouble); node->getBasicType() == EbtDouble);
if (! getArithemeticInt8Enabled()) { if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) ||
if (((convertTo == EbtInt8 || convertTo == EbtUint8) && ! convertFromIntTypes) || ((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes)) {
((node->getBasicType() == EbtInt8 || node->getBasicType() == EbtUint8) && ! convertToIntTypes)) if (! getArithemeticInt8Enabled()) {
return nullptr; return nullptr;
}
} }
if (! getArithemeticInt16Enabled()) { if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) ||
if (((convertTo == EbtInt16 || convertTo == EbtUint16) && ! convertFromIntTypes) || ((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes)) {
((node->getBasicType() == EbtInt16 || node->getBasicType() == EbtUint16) && ! convertToIntTypes)) if (! getArithemeticInt16Enabled()) {
return nullptr; return nullptr;
}
} }
if (! getArithemeticFloat16Enabled()) { if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) ||
if ((convertTo == EbtFloat16 && ! convertFromFloatTypes) || (node->getBasicType() == EbtFloat16 && ! convertToFloatTypes)) {
(node->getBasicType() == EbtFloat16 && ! convertToFloatTypes)) if (! getArithemeticFloat16Enabled()) {
return nullptr; return nullptr;
}
} }
#endif #endif
@ -887,7 +894,7 @@ TIntermTyped* TIntermediate::addConversion(TBasicType convertTo, TIntermTyped* n
// Returns the converted pair of nodes. // Returns the converted pair of nodes.
// Returns <nullptr, nullptr> when there is no conversion. // Returns <nullptr, nullptr> when there is no conversion.
std::tuple<TIntermTyped*, TIntermTyped*> std::tuple<TIntermTyped*, TIntermTyped*>
TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) TIntermediate::addPairConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1)
{ {
if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1)) if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1))
return std::make_tuple(nullptr, nullptr); return std::make_tuple(nullptr, nullptr);
@ -940,7 +947,7 @@ TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* no
if (node0->getBasicType() == node1->getBasicType()) if (node0->getBasicType() == node1->getBasicType())
return std::make_tuple(node0, node1); return std::make_tuple(node0, node1);
promoteTo = getConversionDestinatonType(node0->getBasicType(), node1->getBasicType(), op); promoteTo = getConversionDestinationType(node0->getBasicType(), node1->getBasicType(), op);
if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes) if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes)
return std::make_tuple(nullptr, nullptr); return std::make_tuple(nullptr, nullptr);
@ -1040,64 +1047,30 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
// Note: callers are responsible for other aspects of shape, // Note: callers are responsible for other aspects of shape,
// like vector and matrix sizes. // like vector and matrix sizes.
TBasicType promoteTo;
// GL_EXT_shader_16bit_storage can't do OpConstantComposite with
// 16-bit types, so disable promotion for those types.
bool canPromoteConstant = true;
switch (op) { switch (op) {
// //
// Explicit conversions (unary operations) // Explicit conversions (unary operations)
// //
case EOpConstructBool: case EOpConstructBool:
promoteTo = EbtBool;
break;
case EOpConstructFloat: case EOpConstructFloat:
promoteTo = EbtFloat;
break;
case EOpConstructInt: case EOpConstructInt:
promoteTo = EbtInt;
break;
case EOpConstructUint: case EOpConstructUint:
promoteTo = EbtUint;
break;
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
case EOpConstructDouble: case EOpConstructDouble:
promoteTo = EbtDouble;
break;
case EOpConstructFloat16: case EOpConstructFloat16:
promoteTo = EbtFloat16;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16);
break;
case EOpConstructInt8: case EOpConstructInt8:
promoteTo = EbtInt8;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
break;
case EOpConstructUint8: case EOpConstructUint8:
promoteTo = EbtUint8;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
break;
case EOpConstructInt16: case EOpConstructInt16:
promoteTo = EbtInt16;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
break;
case EOpConstructUint16: case EOpConstructUint16:
promoteTo = EbtUint16;
canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
break;
case EOpConstructInt64: case EOpConstructInt64:
promoteTo = EbtInt64;
break;
case EOpConstructUint64: case EOpConstructUint64:
promoteTo = EbtUint64;
break; break;
#endif #endif
//
// Implicit conversions
//
case EOpLogicalNot: case EOpLogicalNot:
case EOpFunctionCall: case EOpFunctionCall:
@ -1152,9 +1125,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
if (type.getBasicType() == node->getType().getBasicType()) if (type.getBasicType() == node->getType().getBasicType())
return node; return node;
if (canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op)) if (! canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op))
promoteTo = type.getBasicType();
else
return nullptr; return nullptr;
break; break;
@ -1164,9 +1135,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EOpLeftShiftAssign: case EOpLeftShiftAssign:
case EOpRightShiftAssign: case EOpRightShiftAssign:
{ {
if (getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool) if (!(getSource() == EShSourceHlsl && node->getType().getBasicType() == EbtBool)) {
promoteTo = type.getBasicType();
else {
if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType())) if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType()))
return node; return node;
else else
@ -1184,13 +1153,44 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
return nullptr; return nullptr;
} }
bool canPromoteConstant = true;
#ifndef GLSLANG_WEB
// 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;
}
#endif
if (canPromoteConstant && node->getAsConstantUnion()) if (canPromoteConstant && node->getAsConstantUnion())
return promoteConstantUnion(promoteTo, node->getAsConstantUnion()); return promoteConstantUnion(type.getBasicType(), node->getAsConstantUnion());
// //
// Add a new newNode for the conversion. // Add a new newNode for the conversion.
// //
TIntermTyped* newNode = createConversion(promoteTo, node); TIntermTyped* newNode = createConversion(type.getBasicType(), node);
return newNode; return newNode;
} }
@ -1620,7 +1620,7 @@ bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const
// //
bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const
{ {
if (isEsProfile() || version == 110) if ((isEsProfile() && version < 310 ) || version == 110)
return false; return false;
if (from == to) if (from == to)
@ -1659,46 +1659,51 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
} }
} }
bool explicitTypesEnabled = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) || if (getSource() == EShSourceHlsl) {
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8) || // HLSL
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16) || if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int32) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int64) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float64);
if (explicitTypesEnabled) {
// integral promotions
if (isIntegralPromotion(from, to)) {
return true; return true;
} } else {
// GLSL
if (isIntegralPromotion(from, to) ||
isFPPromotion(from, to) ||
isIntegralConversion(from, to) ||
isFPConversion(from, to) ||
isFPIntegralConversion(from, to)) {
// floating-point promotions if (numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types) ||
if (isFPPromotion(from, to)) { numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int8) ||
return true; numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int16) ||
} numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int32) ||
numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_int64) ||
// integral conversions numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float16) ||
if (isIntegralConversion(from, to)) { numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float32) ||
return true; numericFeatures.contains(TNumericFeatures::shader_explicit_arithmetic_types_float64)) {
}
// floating-point conversions
if (isFPConversion(from, to)) {
return true;
}
// floating-integral conversions
if (isFPIntegralConversion(from, to)) {
return true;
}
// hlsl supported conversions
if (getSource() == EShSourceHlsl) {
if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
return true; 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 { } else {
switch (to) { switch (to) {
case EbtDouble: case EbtDouble:
@ -1708,13 +1713,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtInt64: case EbtInt64:
case EbtUint64: case EbtUint64:
case EbtFloat: case EbtFloat:
case EbtDouble: return version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64);
return true;
case EbtInt16: case EbtInt16:
case EbtUint16: case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16); return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) &&
numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
case EbtFloat16: case EbtFloat16:
return extensionRequested(E_GL_AMD_gpu_shader_half_float); return (version >= 400 || numericFeatures.contains(TNumericFeatures::gpu_shader_fp64)) &&
numericFeatures.contains(TNumericFeatures::gpu_shader_half_float);
default: default:
return false; return false;
} }
@ -1722,16 +1728,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
switch (from) { switch (from) {
case EbtInt: case EbtInt:
case EbtUint: case EbtUint:
case EbtFloat:
return true; return true;
case EbtBool: case EbtBool:
return getSource() == EShSourceHlsl; return getSource() == EShSourceHlsl;
case EbtInt16: case EbtInt16:
case EbtUint16: case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16); return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
case EbtFloat16: case EbtFloat16:
return return numericFeatures.contains(TNumericFeatures::gpu_shader_half_float) ||
extensionRequested(E_GL_AMD_gpu_shader_half_float) ||
getSource() == EShSourceHlsl; getSource() == EShSourceHlsl;
default: default:
return false; return false;
@ -1739,25 +1743,21 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtUint: case EbtUint:
switch (from) { switch (from) {
case EbtInt: case EbtInt:
return version >= 400 || getSource() == EShSourceHlsl; return version >= 400 || getSource() == EShSourceHlsl || IsRequestedExtension(E_GL_ARB_gpu_shader5);
case EbtUint:
return true;
case EbtBool: case EbtBool:
return getSource() == EShSourceHlsl; return getSource() == EShSourceHlsl;
case EbtInt16: case EbtInt16:
case EbtUint16: case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16); return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default: default:
return false; return false;
} }
case EbtInt: case EbtInt:
switch (from) { switch (from) {
case EbtInt:
return true;
case EbtBool: case EbtBool:
return getSource() == EShSourceHlsl; return getSource() == EShSourceHlsl;
case EbtInt16: case EbtInt16:
return extensionRequested(E_GL_AMD_gpu_shader_int16); return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default: default:
return false; return false;
} }
@ -1766,21 +1766,19 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtInt: case EbtInt:
case EbtUint: case EbtUint:
case EbtInt64: case EbtInt64:
case EbtUint64:
return true; return true;
case EbtInt16: case EbtInt16:
case EbtUint16: case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16); return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default: default:
return false; return false;
} }
case EbtInt64: case EbtInt64:
switch (from) { switch (from) {
case EbtInt: case EbtInt:
case EbtInt64:
return true; return true;
case EbtInt16: case EbtInt16:
return extensionRequested(E_GL_AMD_gpu_shader_int16); return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
default: default:
return false; return false;
} }
@ -1788,9 +1786,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
switch (from) { switch (from) {
case EbtInt16: case EbtInt16:
case EbtUint16: case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16); return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
case EbtFloat16:
return extensionRequested(E_GL_AMD_gpu_shader_half_float);
default: default:
break; break;
} }
@ -1798,8 +1794,7 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
case EbtUint16: case EbtUint16:
switch (from) { switch (from) {
case EbtInt16: case EbtInt16:
case EbtUint16: return numericFeatures.contains(TNumericFeatures::gpu_shader_int16);
return extensionRequested(E_GL_AMD_gpu_shader_int16);
default: default:
break; break;
} }
@ -1926,12 +1921,14 @@ static TBasicType getCorrespondingUnsignedType(TBasicType type)
// integer type corresponding to the type of the operand with signed // integer type corresponding to the type of the operand with signed
// integer type. // integer type.
std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinationType(TBasicType type0, TBasicType type1, TOperator op) const
{ {
TBasicType res0 = EbtNumTypes; TBasicType res0 = EbtNumTypes;
TBasicType res1 = EbtNumTypes; TBasicType res1 = EbtNumTypes;
if (isEsProfile() || version == 110) if ((isEsProfile() &&
(version < 310 || !numericFeatures.contains(TNumericFeatures::shader_implicit_conversions))) ||
version == 110)
return std::make_tuple(res0, res1); return std::make_tuple(res0, res1);
if (getSource() == EShSourceHlsl) { if (getSource() == EShSourceHlsl) {
@ -2305,6 +2302,10 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
case EbtReference: case EbtReference:
op = EOpConstructReference; op = EOpConstructReference;
break; break;
case EbtAccStruct:
op = EOpConstructAccStruct;
break;
#endif #endif
default: default:
break; break;
@ -2463,7 +2464,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
// //
// Get compatible types. // Get compatible types.
// //
auto children = addConversion(EOpSequence, trueBlock, falseBlock); auto children = addPairConversion(EOpSequence, trueBlock, falseBlock);
trueBlock = std::get<0>(children); trueBlock = std::get<0>(children);
falseBlock = std::get<1>(children); falseBlock = std::get<1>(children);
@ -2679,7 +2680,11 @@ TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors<selectorType>& selecto
// 'swizzleOkay' says whether or not it is okay to consider a swizzle // 'swizzleOkay' says whether or not it is okay to consider a swizzle
// a valid part of the dereference chain. // a valid part of the dereference chain.
// //
const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay) // 'BufferReferenceOk' says if type is buffer_reference, the routine stop to find the most left node.
//
//
const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay , bool bufferReferenceOk)
{ {
do { do {
const TIntermBinary* binary = node->getAsBinaryNode(); const TIntermBinary* binary = node->getAsBinaryNode();
@ -2697,6 +2702,8 @@ const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool
return nullptr; return nullptr;
} }
node = node->getAsBinaryNode()->getLeft(); node = node->getAsBinaryNode()->getLeft();
if (bufferReferenceOk && node->isReference())
return node;
} while (true); } while (true);
} }
@ -2750,6 +2757,22 @@ TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expres
return node; 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 // This is to be executed after the final root is put on top by the parsing
// process. // process.
@ -2774,6 +2797,9 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
case EShTexSampTransUpgradeTextureRemoveSampler: case EShTexSampTransUpgradeTextureRemoveSampler:
performTextureUpgradeAndSamplerRemovalTransformation(root); performTextureUpgradeAndSamplerRemovalTransformation(root);
break; break;
case EShTexSampTransCount:
assert(0);
break;
} }
#endif #endif
@ -2854,7 +2880,7 @@ void TIntermediate::addToCallGraph(TInfoSink& /*infoSink*/, const TString& calle
return; return;
} }
callGraph.push_front(TCall(caller, callee)); callGraph.emplace_front(caller, callee);
} }
// //
@ -3234,10 +3260,17 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
return false; return false;
break; break;
default: default:
if (operand->getBasicType() != EbtFloat) // 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; return false;
} }
@ -3247,9 +3280,11 @@ bool TIntermediate::promoteUnary(TIntermUnary& node)
return true; return true;
} }
// Propagate precision qualifiers *up* from children to parent.
void TIntermUnary::updatePrecision() void TIntermUnary::updatePrecision()
{ {
if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) { if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
getBasicType() == EbtFloat) {
if (operand->getQualifier().precision > getQualifier().precision) if (operand->getQualifier().precision > getQualifier().precision)
getQualifier().precision = operand->getQualifier().precision; getQualifier().precision = operand->getQualifier().precision;
} }
@ -3745,20 +3780,55 @@ bool TIntermediate::promoteAggregate(TIntermAggregate& node)
return false; return false;
} }
void TIntermBinary::updatePrecision() // 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 || getBasicType() == EbtFloat16) { if (getBasicType() == EbtInt || getBasicType() == EbtUint ||
getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision); getBasicType() == EbtFloat) {
if (getQualifier().precision != EpqNone) { TPrecisionQualifier maxPrecision = EpqNone;
left->propagatePrecision(getQualifier().precision); TIntermSequence operands = getSequence();
right->propagatePrecision(getQualifier().precision); 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) void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
{ {
if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat && getBasicType() != EbtFloat16)) if (getQualifier().precision != EpqNone ||
(getBasicType() != EbtInt && getBasicType() != EbtUint &&
getBasicType() != EbtFloat && getBasicType() != EbtFloat16))
return; return;
getQualifier().precision = newPrecision; getQualifier().precision = newPrecision;
@ -3832,7 +3902,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
case EbtFloat16: PROMOTE(setDConst, double, Get); break; \ case EbtFloat16: PROMOTE(setDConst, double, Get); break; \
case EbtFloat: PROMOTE(setDConst, double, Get); break; \ case EbtFloat: PROMOTE(setDConst, double, Get); break; \
case EbtDouble: PROMOTE(setDConst, double, Get); break; \ case EbtDouble: PROMOTE(setDConst, double, Get); break; \
case EbtInt8: PROMOTE(setI8Const, char, Get); break; \ case EbtInt8: PROMOTE(setI8Const, signed char, Get); break; \
case EbtInt16: PROMOTE(setI16Const, short, Get); break; \ case EbtInt16: PROMOTE(setI16Const, short, Get); break; \
case EbtInt: PROMOTE(setIConst, int, Get); break; \ case EbtInt: PROMOTE(setIConst, int, Get); break; \
case EbtInt64: PROMOTE(setI64Const, long long, Get); break; \ case EbtInt64: PROMOTE(setI64Const, long long, Get); break; \

View File

@ -74,14 +74,33 @@ public:
for (unsigned int f = 0; f < globals.size(); ++f) { for (unsigned int f = 0; f < globals.size(); ++f) {
TIntermAggregate* candidate = globals[f]->getAsAggregate(); TIntermAggregate* candidate = globals[f]->getAsAggregate();
if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) { if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) {
functions.push_back(candidate); destinations.push_back(candidate);
break; break;
} }
} }
} }
typedef std::list<TIntermAggregate*> TFunctionStack; void pushGlobalReference(const TString& name)
TFunctionStack functions; {
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<TIntermAggregate*> TDestinationStack;
TDestinationStack destinations;
protected: protected:
// To catch which function calls are not dead, and hence which functions must be visited. // To catch which function calls are not dead, and hence which functions must be visited.
@ -117,16 +136,27 @@ protected:
// and only visit each function once. // and only visit each function once.
void addFunctionCall(TIntermAggregate* call) void addFunctionCall(TIntermAggregate* call)
{ {
// // just use the map to ensure we process each function at most once // just use the map to ensure we process each function at most once
if (liveFunctions.find(call->getName()) == liveFunctions.end()) { if (liveFunctions.find(call->getName()) == liveFunctions.end()) {
liveFunctions.insert(call->getName()); liveFunctions.insert(call->getName());
pushFunction(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; const TIntermediate& intermediate;
typedef std::unordered_set<TString> TLiveFunctions; typedef std::unordered_set<TString> TLiveFunctions;
TLiveFunctions liveFunctions; TLiveFunctions liveFunctions;
typedef std::unordered_set<TString> TLiveGlobals;
TLiveGlobals liveGlobals;
bool traverseAll; bool traverseAll;
private: private:

View File

@ -74,6 +74,9 @@ void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason
{ {
if (messages & EShMsgOnlyPreprocessor) if (messages & EShMsgOnlyPreprocessor)
return; return;
// If enhanced msg readability, only print one error
if (messages & EShMsgEnhanced && numErrors > 0)
return;
va_list args; va_list args;
va_start(args, szExtraInfoFormat); va_start(args, szExtraInfoFormat);
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args); outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
@ -127,22 +130,6 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
{ {
TIntermBinary* binaryNode = node->getAsBinaryNode(); TIntermBinary* binaryNode = node->getAsBinaryNode();
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;
}
const char* symbol = nullptr; const char* symbol = nullptr;
TIntermSymbol* symNode = node->getAsSymbolNode(); TIntermSymbol* symNode = node->getAsSymbolNode();
if (symNode != nullptr) if (symNode != nullptr)
@ -157,11 +144,11 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
case EvqBuffer: case EvqBuffer:
if (node->getQualifier().isReadOnly()) if (node->getQualifier().isReadOnly())
message = "can't modify a readonly buffer"; message = "can't modify a readonly buffer";
if (node->getQualifier().isShaderRecordNV()) if (node->getQualifier().isShaderRecord())
message = "can't modify a shaderrecordnv qualified buffer"; message = "can't modify a shaderrecordnv qualified buffer";
break; break;
case EvqHitAttrNV: case EvqHitAttr:
if (language != EShLangIntersectNV) if (language != EShLangIntersect)
message = "cannot modify hitAttributeNV in this stage"; message = "cannot modify hitAttributeNV in this stage";
break; break;
#endif #endif
@ -181,9 +168,12 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
case EbtAtomicUint: case EbtAtomicUint:
message = "can't modify an atomic_uint"; message = "can't modify an atomic_uint";
break; break;
case EbtAccStructNV: case EbtAccStruct:
message = "can't modify accelerationStructureNV"; message = "can't modify accelerationStructureNV";
break; break;
case EbtRayQuery:
message = "can't modify rayQueryEXT";
break;
#endif #endif
default: default:
break; break;
@ -200,15 +190,40 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
// Everything else is okay, no error. // Everything else is okay, no error.
// //
if (message == nullptr) 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; return false;
}
// //
// If we get here, we have an error and a message. // If we get here, we have an error and a message.
// //
const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
if (symNode) if (symNode)
error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message); error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
else else
error(loc, " l-value required", op, "(%s)", message); 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; return true;
} }
@ -216,28 +231,41 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
// Test for and give an error if the node can't be read from. // 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) void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
{ {
TIntermBinary* binaryNode = node->getAsBinaryNode();
const TIntermSymbol* symNode = node->getAsSymbolNode();
if (! node) if (! node)
return; return;
TIntermBinary* binaryNode = node->getAsBinaryNode(); if (node->getQualifier().isWriteOnly()) {
if (binaryNode) { const TIntermTyped* leftMostTypeNode = TIntermediate::findLValueBase(node, true);
switch(binaryNode->getOp()) {
case EOpIndexDirect: if (symNode != nullptr)
case EOpIndexIndirect: error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
case EOpIndexDirectStruct: else if (binaryNode &&
case EOpVectorSwizzle: (binaryNode->getAsOperator()->getOp() == EOpIndexDirectStruct ||
case EOpMatrixSwizzle: binaryNode->getAsOperator()->getOp() == EOpIndexDirect))
rValueErrorCheck(loc, op, binaryNode->getLeft()); if(IsAnonymous(leftMostTypeNode->getAsSymbolNode()->getName()))
default: error(loc, "can't read from writeonly object: ", op, leftMostTypeNode->getAsSymbolNode()->getAccessName().c_str());
break; 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;
}
} }
return;
} }
TIntermSymbol* symNode = node->getAsSymbolNode();
if (symNode && symNode->getQualifier().isWriteOnly())
error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
} }
// Add 'symbol' to the list of deferred linkage symbols, which // Add 'symbol' to the list of deferred linkage symbols, which
@ -576,7 +604,6 @@ void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TStrin
selector.push_back(0); selector.push_back(0);
} }
#ifdef ENABLE_HLSL
// //
// Make the passed-in variable information become a member of the // Make the passed-in variable information become a member of the
// global uniform block. If this doesn't exist yet, make it. // global uniform block. If this doesn't exist yet, make it.
@ -598,6 +625,19 @@ void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& mem
globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding; globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding;
globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet; 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 += "\"" + memberType.getCompleteString() + "\"";
err += " versus ";
err += "\"" + symbol->getType().getCompleteString() + "\"";
error(loc, "Types must match:", memberType.getFieldName().c_str(), err.c_str());
}
return;
}
// Add the requested member as a member to the global block. // Add the requested member as a member to the global block.
TType* type = new TType; TType* type = new TType;
type->shallowCopy(memberType); type->shallowCopy(memberType);
@ -621,7 +661,67 @@ void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& mem
++firstNewMember; ++firstNewMember;
} }
#endif
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() void TParseContextBase::finish()
{ {

File diff suppressed because it is too large Load Diff

View File

@ -67,7 +67,8 @@ struct TPragma {
class TScanContext; class TScanContext;
class TPpContext; class TPpContext;
typedef std::set<int> TIdSetType; typedef std::set<long long> TIdSetType;
typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
// //
// Sharable code (as well as what's in TParseVersions) across // Sharable code (as well as what's in TParseVersions) across
@ -82,7 +83,8 @@ public:
: TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
scopeMangler("::"), scopeMangler("::"),
symbolTable(symbolTable), symbolTable(symbolTable),
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), blockNestingLevel(0), controlFlowNestingLevel(0),
currentFunctionType(nullptr),
postEntryPointReturn(false), postEntryPointReturn(false),
contextPragma(true, false), contextPragma(true, false),
beginInvocationInterlockCount(0), endInvocationInterlockCount(0), beginInvocationInterlockCount(0), endInvocationInterlockCount(0),
@ -90,7 +92,8 @@ public:
limits(resources.limits), limits(resources.limits),
globalUniformBlock(nullptr), globalUniformBlock(nullptr),
globalUniformBinding(TQualifier::layoutBindingEnd), globalUniformBinding(TQualifier::layoutBindingEnd),
globalUniformSet(TQualifier::layoutSetEnd) globalUniformSet(TQualifier::layoutSetEnd),
atomicCounterBlockSet(TQualifier::layoutSetEnd)
{ {
if (entryPoint != nullptr) if (entryPoint != nullptr)
sourceEntryPointName = *entryPoint; sourceEntryPointName = *entryPoint;
@ -152,10 +155,11 @@ public:
extensionCallback(line, extension, behavior); extensionCallback(line, extension, behavior);
} }
#ifdef ENABLE_HLSL
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
#endif
// 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 // Potentially rename shader entry point function
void renameShaderFunction(TString*& name) const void renameShaderFunction(TString*& name) const
@ -176,7 +180,8 @@ public:
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
int statementNestingLevel; // 0 if outside all flow control or compound statements int statementNestingLevel; // 0 if outside all flow control or compound statements
int loopNestingLevel; // 0 if outside all loops int loopNestingLevel; // 0 if outside all loops
int structNestingLevel; // 0 if outside blocks and structures int structNestingLevel; // 0 if outside structures
int blockNestingLevel; // 0 if outside blocks
int controlFlowNestingLevel; // 0 if outside all flow control int controlFlowNestingLevel; // 0 if outside all flow control
const TType* currentFunctionType; // the return type of the function that's currently being parsed 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 bool functionReturnsValue; // true if a non-void function has a return
@ -227,7 +232,25 @@ protected:
// override this to set the language-specific name // override this to set the language-specific name
virtual const char* getGlobalUniformBlockName() const { return ""; } virtual const char* getGlobalUniformBlockName() const { return ""; }
virtual void setUniformBlockDefaults(TType&) const { } virtual void setUniformBlockDefaults(TType&) const { }
virtual void finalizeGlobalUniformBlockLayout(TVariable&) { } virtual void finalizeGlobalUniformBlockLayout(TVariable&) {}
// Manage the atomic counter block (used for atomic_uints with Vulkan-Relaxed)
TMap<int, TVariable*> atomicCounterBuffers;
unsigned int atomicCounterBlockSet;
TMap<int, int> 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, virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, TPrefixType prefix, const char* szExtraInfoFormat, TPrefixType prefix,
va_list args); va_list args);
@ -290,6 +313,9 @@ public:
bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
void parserError(const char* s); // for bison's yyerror 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 reservedErrorCheck(const TSourceLoc&, const TString&);
void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override; void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override; bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
@ -315,6 +341,7 @@ public:
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); 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* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); 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); void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName);
TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
@ -326,6 +353,7 @@ public:
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) 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 builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&); void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&); void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);
@ -335,6 +363,10 @@ public:
void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode); 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 assignError(const TSourceLoc&, const char* op, TString left, TString right); void assignError(const TSourceLoc&, const char* op, TString left, TString right);
void unaryOpError(const TSourceLoc&, const char* op, TString operand); void unaryOpError(const TSourceLoc&, const char* op, TString operand);
void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
@ -358,10 +390,10 @@ public:
void boolCheck(const TSourceLoc&, const TPublicType&); void boolCheck(const TSourceLoc&, const TPublicType&);
void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
void accStructNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
void memberQualifierCheck(glslang::TPublicType&); void memberQualifierCheck(glslang::TPublicType&);
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&); void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false);
void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&); void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force); void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
@ -387,7 +419,7 @@ public:
void arrayLimitCheck(const TSourceLoc&, const TString&, int size); void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature); void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&); void inductiveLoopBodyCheck(TIntermNode*, long long loopIndexId, TSymbolTable&);
void constantIndexExpressionCheck(TIntermNode*); void constantIndexExpressionCheck(TIntermNode*);
void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&); void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
@ -412,17 +444,21 @@ public:
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to); void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&);
void blockStageIoCheck(const TSourceLoc&, const TQualifier&); void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
void fixXfbOffsets(TQualifier&, TTypeList&); void fixXfbOffsets(TQualifier&, TTypeList&);
void fixBlockUniformOffsets(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, const TString& identifier);
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
void invariantCheck(const TSourceLoc&, const TQualifier&); void invariantCheck(const TSourceLoc&, const TQualifier&);
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body); TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*);
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
TAttributeType attributeFromName(const TString& name) const; TAttributeType attributeFromName(const TString& name) const;
@ -435,6 +471,21 @@ public:
void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*); void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*);
// Determine loop control from attributes // Determine loop control from attributes
void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); 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* 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);
#endif #endif
void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember); void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember);
@ -453,6 +504,15 @@ protected:
void finish() override; void finish() override;
#endif #endif
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: public:
// //
// Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
@ -477,12 +537,15 @@ protected:
TQualifier globalUniformDefaults; TQualifier globalUniformDefaults;
TQualifier globalInputDefaults; TQualifier globalInputDefaults;
TQualifier globalOutputDefaults; TQualifier globalOutputDefaults;
TQualifier globalSharedDefaults;
TString currentCaller; // name of last function body entered (not valid when at global scope) TString currentCaller; // name of last function body entered (not valid when at global scope)
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point
bool anyIndexLimits; bool anyIndexLimits;
TIdSetType inductiveLoopIds; TIdSetType inductiveLoopIds;
TVector<TIntermTyped*> needsIndexLimitationChecking; TVector<TIntermTyped*> needsIndexLimitationChecking;
TStructRecord matrixFixRecord;
TStructRecord packingFixRecord;
// //
// Geometry shader input arrays: // Geometry shader input arrays:

View File

@ -2,6 +2,8 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013 LunarG, Inc. // Copyright (C) 2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2020 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -187,17 +189,15 @@ bool TInputScanner::scanVersion(int& version, EProfile& profile, bool& notFirstT
if (lookingInMiddle) { if (lookingInMiddle) {
notFirstToken = true; notFirstToken = true;
// make forward progress by finishing off the current line plus extra new lines // make forward progress by finishing off the current line plus extra new lines
if (peek() == '\n' || peek() == '\r') { if (peek() != '\n' && peek() != '\r') {
while (peek() == '\n' || peek() == '\r')
get();
} else
do { do {
c = get(); c = get();
} while (c != EndOfInput && c != '\n' && c != '\r'); } while (c != EndOfInput && c != '\n' && c != '\r');
while (peek() == '\n' || peek() == '\r') }
get(); while (peek() == '\n' || peek() == '\r')
if (peek() == EndOfInput) get();
return true; if (peek() == EndOfInput)
return true;
} }
lookingInMiddle = true; lookingInMiddle = true;
@ -365,6 +365,9 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["if"] = IF; (*KeywordMap)["if"] = IF;
(*KeywordMap)["else"] = ELSE; (*KeywordMap)["else"] = ELSE;
(*KeywordMap)["discard"] = DISCARD; (*KeywordMap)["discard"] = DISCARD;
(*KeywordMap)["terminateInvocation"] = TERMINATE_INVOCATION;
(*KeywordMap)["terminateRayEXT"] = TERMINATE_RAY;
(*KeywordMap)["ignoreIntersectionEXT"] = IGNORE_INTERSECTION;
(*KeywordMap)["return"] = RETURN; (*KeywordMap)["return"] = RETURN;
(*KeywordMap)["void"] = VOID; (*KeywordMap)["void"] = VOID;
(*KeywordMap)["bool"] = BOOL; (*KeywordMap)["bool"] = BOOL;
@ -416,6 +419,7 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["queuefamilycoherent"] = QUEUEFAMILYCOHERENT; (*KeywordMap)["queuefamilycoherent"] = QUEUEFAMILYCOHERENT;
(*KeywordMap)["workgroupcoherent"] = WORKGROUPCOHERENT; (*KeywordMap)["workgroupcoherent"] = WORKGROUPCOHERENT;
(*KeywordMap)["subgroupcoherent"] = SUBGROUPCOHERENT; (*KeywordMap)["subgroupcoherent"] = SUBGROUPCOHERENT;
(*KeywordMap)["shadercallcoherent"] = SHADERCALLCOHERENT;
(*KeywordMap)["nonprivate"] = NONPRIVATE; (*KeywordMap)["nonprivate"] = NONPRIVATE;
(*KeywordMap)["restrict"] = RESTRICT; (*KeywordMap)["restrict"] = RESTRICT;
(*KeywordMap)["readonly"] = READONLY; (*KeywordMap)["readonly"] = READONLY;
@ -470,6 +474,28 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY; (*KeywordMap)["image2DMSArray"] = IMAGE2DMSARRAY;
(*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY; (*KeywordMap)["iimage2DMSArray"] = IIMAGE2DMSARRAY;
(*KeywordMap)["uimage2DMSArray"] = UIMAGE2DMSARRAY; (*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)["double"] = DOUBLE;
(*KeywordMap)["dvec2"] = DVEC2; (*KeywordMap)["dvec2"] = DVEC2;
(*KeywordMap)["dvec3"] = DVEC3; (*KeywordMap)["dvec3"] = DVEC3;
@ -560,6 +586,18 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["f64mat4x2"] = F64MAT4X2; (*KeywordMap)["f64mat4x2"] = F64MAT4X2;
(*KeywordMap)["f64mat4x3"] = F64MAT4X3; (*KeywordMap)["f64mat4x3"] = F64MAT4X3;
(*KeywordMap)["f64mat4x4"] = F64MAT4X4; (*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;
#endif #endif
(*KeywordMap)["sampler2D"] = SAMPLER2D; (*KeywordMap)["sampler2D"] = SAMPLER2D;
@ -704,11 +742,18 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["precise"] = PRECISE; (*KeywordMap)["precise"] = PRECISE;
(*KeywordMap)["rayPayloadNV"] = PAYLOADNV; (*KeywordMap)["rayPayloadNV"] = PAYLOADNV;
(*KeywordMap)["rayPayloadEXT"] = PAYLOADEXT;
(*KeywordMap)["rayPayloadInNV"] = PAYLOADINNV; (*KeywordMap)["rayPayloadInNV"] = PAYLOADINNV;
(*KeywordMap)["rayPayloadInEXT"] = PAYLOADINEXT;
(*KeywordMap)["hitAttributeNV"] = HITATTRNV; (*KeywordMap)["hitAttributeNV"] = HITATTRNV;
(*KeywordMap)["hitAttributeEXT"] = HITATTREXT;
(*KeywordMap)["callableDataNV"] = CALLDATANV; (*KeywordMap)["callableDataNV"] = CALLDATANV;
(*KeywordMap)["callableDataEXT"] = CALLDATAEXT;
(*KeywordMap)["callableDataInNV"] = CALLDATAINNV; (*KeywordMap)["callableDataInNV"] = CALLDATAINNV;
(*KeywordMap)["callableDataInEXT"] = CALLDATAINEXT;
(*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV; (*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV;
(*KeywordMap)["accelerationStructureEXT"] = ACCSTRUCTEXT;
(*KeywordMap)["rayQueryEXT"] = RAYQUERYEXT;
(*KeywordMap)["perprimitiveNV"] = PERPRIMITIVENV; (*KeywordMap)["perprimitiveNV"] = PERPRIMITIVENV;
(*KeywordMap)["perviewNV"] = PERVIEWNV; (*KeywordMap)["perviewNV"] = PERVIEWNV;
(*KeywordMap)["taskNV"] = PERTASKNV; (*KeywordMap)["taskNV"] = PERTASKNV;
@ -843,6 +888,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
parseContext.error(loc, "not supported", "::", ""); parseContext.error(loc, "not supported", "::", "");
break; break;
case PpAtomConstString: parserToken->sType.lex.string = NewPoolTString(tokenText); return STRING_LITERAL;
case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT; case PpAtomConstInt: parserToken->sType.lex.i = ppToken.ival; return INTCONSTANT;
case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT; case PpAtomConstUint: parserToken->sType.lex.i = ppToken.ival; return UINTCONSTANT;
case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT; case PpAtomConstFloat: parserToken->sType.lex.d = ppToken.dval; return FLOATCONSTANT;
@ -905,10 +951,22 @@ int TScanContext::tokenizeIdentifier()
case CASE: case CASE:
return keyword; 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: case BUFFER:
afterBuffer = true; afterBuffer = true;
if ((parseContext.isEsProfile() && parseContext.version < 310) || if ((parseContext.isEsProfile() && parseContext.version < 310) ||
(!parseContext.isEsProfile() && parseContext.version < 430)) (!parseContext.isEsProfile() && (parseContext.version < 430 &&
!parseContext.extensionTurnedOn(E_GL_ARB_shader_storage_buffer_object))))
return identifierOrType(); return identifierOrType();
return keyword; return keyword;
@ -972,7 +1030,7 @@ int TScanContext::tokenizeIdentifier()
return keyword; return keyword;
case PACKED: case PACKED:
if ((parseContext.isEsProfile() && parseContext.version < 300) || if ((parseContext.isEsProfile() && parseContext.version < 300) ||
(!parseContext.isEsProfile() && parseContext.version < 330)) (!parseContext.isEsProfile() && parseContext.version < 140))
return reservedWord(); return reservedWord();
return identifierOrType(); return identifierOrType();
@ -1014,6 +1072,23 @@ int TScanContext::tokenizeIdentifier()
parseContext.extensionTurnedOn(E_GL_NV_ray_tracing)) parseContext.extensionTurnedOn(E_GL_NV_ray_tracing))
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
case PAYLOADEXT:
case PAYLOADINEXT:
case HITATTREXT:
case CALLDATAEXT:
case CALLDATAINEXT:
case ACCSTRUCTEXT:
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: case ATOMIC_UINT:
if ((parseContext.isEsProfile() && parseContext.version >= 310) || if ((parseContext.isEsProfile() && parseContext.version >= 310) ||
parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters)) parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
@ -1025,6 +1100,7 @@ int TScanContext::tokenizeIdentifier()
case QUEUEFAMILYCOHERENT: case QUEUEFAMILYCOHERENT:
case WORKGROUPCOHERENT: case WORKGROUPCOHERENT:
case SUBGROUPCOHERENT: case SUBGROUPCOHERENT:
case SHADERCALLCOHERENT:
case NONPRIVATE: case NONPRIVATE:
case RESTRICT: case RESTRICT:
case READONLY: case READONLY:
@ -1119,6 +1195,19 @@ int TScanContext::tokenizeIdentifier()
afterType = true; afterType = true;
return firstGenerationImage(false); 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 IMAGEBUFFER:
case IIMAGEBUFFER: case IIMAGEBUFFER:
case UIMAGEBUFFER: case UIMAGEBUFFER:
@ -1127,6 +1216,18 @@ int TScanContext::tokenizeIdentifier()
parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer)) parseContext.extensionsTurnedOn(Num_AEP_texture_buffer, AEP_texture_buffer))
return keyword; return keyword;
return firstGenerationImage(false); 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 IMAGE2D:
case IIMAGE2D: case IIMAGE2D:
@ -1143,6 +1244,20 @@ int TScanContext::tokenizeIdentifier()
afterType = true; afterType = true;
return firstGenerationImage(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 IMAGECUBEARRAY:
case IIMAGECUBEARRAY: case IIMAGECUBEARRAY:
case UIMAGECUBEARRAY: case UIMAGECUBEARRAY:
@ -1151,6 +1266,18 @@ int TScanContext::tokenizeIdentifier()
parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array)) parseContext.extensionsTurnedOn(Num_AEP_texture_cube_map_array, AEP_texture_cube_map_array))
return keyword; return keyword;
return secondGenerationImage(); 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 IMAGE2DMS:
case IIMAGE2DMS: case IIMAGE2DMS:
@ -1160,6 +1287,17 @@ int TScanContext::tokenizeIdentifier()
case UIMAGE2DMSARRAY: case UIMAGE2DMSARRAY:
afterType = true; afterType = true;
return secondGenerationImage(); 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 DOUBLE:
case DVEC2: case DVEC2:
@ -1168,8 +1306,8 @@ int TScanContext::tokenizeIdentifier()
afterType = true; afterType = true;
if (parseContext.isEsProfile() || parseContext.version < 150 || if (parseContext.isEsProfile() || parseContext.version < 150 ||
(!parseContext.symbolTable.atBuiltInLevel() && (!parseContext.symbolTable.atBuiltInLevel() &&
parseContext.version < 400 && (parseContext.version < 400 && !parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64) &&
!parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64))) (parseContext.version < 410 && !parseContext.extensionTurnedOn(E_GL_ARB_vertex_attrib_64bit)))))
reservedWord(); reservedWord();
return keyword; return keyword;
@ -1621,6 +1759,21 @@ int TScanContext::tokenizeIdentifier()
return keyword; return keyword;
else else
return identifierOrType(); 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();
#endif #endif
default: default:
@ -1746,7 +1899,9 @@ int TScanContext::dMat()
if (!parseContext.isEsProfile() && (parseContext.version >= 400 || if (!parseContext.isEsProfile() && (parseContext.version >= 400 ||
parseContext.symbolTable.atBuiltInLevel() || parseContext.symbolTable.atBuiltInLevel() ||
(parseContext.version >= 150 && parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_fp64)))) (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; return keyword;
if (parseContext.isForwardCompatible()) if (parseContext.isForwardCompatible())

View File

@ -1,7 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013-2016 LunarG, Inc. // Copyright (C) 2013-2016 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2015-2020 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -51,9 +51,9 @@
#include "ScanContext.h" #include "ScanContext.h"
#ifdef ENABLE_HLSL #ifdef ENABLE_HLSL
#include "../../hlsl/hlslParseHelper.h" #include "../HLSL/hlslParseHelper.h"
#include "../../hlsl/hlslParseables.h" #include "../HLSL/hlslParseables.h"
#include "../../hlsl/hlslScanContext.h" #include "../HLSL/hlslScanContext.h"
#endif #endif
#include "../Include/ShHandle.h" #include "../Include/ShHandle.h"
@ -72,6 +72,9 @@
// token to print ", but none of that seems appropriate for this file. // token to print ", but none of that seems appropriate for this file.
#include "preprocessor/PpTokens.h" #include "preprocessor/PpTokens.h"
// Build-time generated includes
#include "glslang/build_info.h"
namespace { // anonymous namespace for file-local functions and symbols namespace { // anonymous namespace for file-local functions and symbols
// Total number of successful initializers of glslang: a refcount // Total number of successful initializers of glslang: a refcount
@ -156,7 +159,7 @@ int MapVersionToIndex(int version)
return index; return index;
} }
const int SpvVersionCount = 3; // index range in MapSpvVersionToIndex const int SpvVersionCount = 4; // index range in MapSpvVersionToIndex
int MapSpvVersionToIndex(const SpvVersion& spvVersion) int MapSpvVersionToIndex(const SpvVersion& spvVersion)
{ {
@ -164,8 +167,12 @@ int MapSpvVersionToIndex(const SpvVersion& spvVersion)
if (spvVersion.openGl > 0) if (spvVersion.openGl > 0)
index = 1; index = 1;
else if (spvVersion.vulkan > 0) else if (spvVersion.vulkan > 0) {
index = 2; if (!spvVersion.vulkanRelaxed)
index = 2;
else
index = 3;
}
assert(index < SpvVersionCount); assert(index < SpvVersionCount);
@ -291,6 +298,9 @@ void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int versi
#ifdef GLSLANG_WEB #ifdef GLSLANG_WEB
profile = EEsProfile; profile = EEsProfile;
version = 310; version = 310;
#elif defined(GLSLANG_ANGLE)
profile = ECoreProfile;
version = 450;
#endif #endif
(*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]); (*symbolTables[language]).adoptLevels(*commonTable[CommonIndex(profile, language)]);
@ -312,6 +322,9 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
#ifdef GLSLANG_WEB #ifdef GLSLANG_WEB
profile = EEsProfile; profile = EEsProfile;
version = 310; version = 310;
#elif defined(GLSLANG_ANGLE)
profile = ECoreProfile;
version = 450;
#endif #endif
std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source)); std::unique_ptr<TBuiltInParseables> builtInParseables(CreateBuiltInParseables(infoSink, source));
@ -351,7 +364,6 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
(profile == EEsProfile && version >= 310)) (profile == EEsProfile && version >= 310))
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source, InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source,
infoSink, commonTable, symbolTables); infoSink, commonTable, symbolTables);
#endif
// check for compute // check for compute
if ((profile != EEsProfile && version >= 420) || if ((profile != EEsProfile && version >= 420) ||
@ -359,19 +371,20 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source, InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source,
infoSink, commonTable, symbolTables); infoSink, commonTable, symbolTables);
#ifndef GLSLANG_ANGLE
// check for ray tracing stages // check for ray tracing stages
if (profile != EEsProfile && version >= 450) { if (profile != EEsProfile && version >= 450) {
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGenNV, source, InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGen, source,
infoSink, commonTable, symbolTables); infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersectNV, source, InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersect, source,
infoSink, commonTable, symbolTables); infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHitNV, source, InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHit, source,
infoSink, commonTable, symbolTables); infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHitNV, source, InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHit, source,
infoSink, commonTable, symbolTables); infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMissNV, source, InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMiss, source,
infoSink, commonTable, symbolTables); infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallableNV, source, InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallable, source,
infoSink, commonTable, symbolTables); infoSink, commonTable, symbolTables);
} }
@ -386,6 +399,8 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
(profile == EEsProfile && version >= 320)) (profile == EEsProfile && version >= 320))
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source, InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source,
infoSink, commonTable, symbolTables); infoSink, commonTable, symbolTables);
#endif // !GLSLANG_ANGLE
#endif // !GLSLANG_WEB
return true; return true;
} }
@ -487,7 +502,7 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp
// Function to Print all builtins // Function to Print all builtins
void DumpBuiltinSymbolTable(TInfoSink& infoSink, const TSymbolTable& symbolTable) void DumpBuiltinSymbolTable(TInfoSink& infoSink, const TSymbolTable& symbolTable)
{ {
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
infoSink.debug << "BuiltinSymbolTable {\n"; infoSink.debug << "BuiltinSymbolTable {\n";
symbolTable.dump(infoSink, true); symbolTable.dump(infoSink, true);
@ -591,7 +606,7 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
break; break;
} }
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Correct for stage type... // Correct for stage type...
switch (stage) { switch (stage) {
case EShLangGeometry: case EShLangGeometry:
@ -623,12 +638,12 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
version = profile == EEsProfile ? 310 : 420; version = profile == EEsProfile ? 310 : 420;
} }
break; break;
case EShLangRayGenNV: case EShLangRayGen:
case EShLangIntersectNV: case EShLangIntersect:
case EShLangAnyHitNV: case EShLangAnyHit:
case EShLangClosestHitNV: case EShLangClosestHit:
case EShLangMissNV: case EShLangMiss:
case EShLangCallableNV: case EShLangCallable:
if (profile == EEsProfile || version < 460) { if (profile == EEsProfile || version < 460) {
correct = false; correct = false;
infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above"); infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above");
@ -712,10 +727,14 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
break; break;
case EShClientVulkan: case EShClientVulkan:
spvVersion.vulkanGlsl = environment->input.dialectVersion; spvVersion.vulkanGlsl = environment->input.dialectVersion;
spvVersion.vulkanRelaxed = environment->input.vulkanRulesRelaxed;
break; break;
case EShClientOpenGL: case EShClientOpenGL:
spvVersion.openGl = environment->input.dialectVersion; spvVersion.openGl = environment->input.dialectVersion;
break; break;
case EShClientCount:
assert(0);
break;
} }
switch (environment->input.languageFamily) { switch (environment->input.languageFamily) {
case EShSourceNone: case EShSourceNone:
@ -728,6 +747,9 @@ void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages
source = EShSourceHlsl; source = EShSourceHlsl;
messages = static_cast<EShMessages>(messages | EShMsgReadHlsl); messages = static_cast<EShMessages>(messages | EShMsgReadHlsl);
break; break;
case EShSourceCount:
assert(0);
break;
} }
} }
@ -791,6 +813,7 @@ bool ProcessDeferred(
// set version/profile to defaultVersion/defaultProfile regardless of the #version // set version/profile to defaultVersion/defaultProfile regardless of the #version
// directive in the source code // directive in the source code
bool forceDefaultVersionAndProfile, bool forceDefaultVersionAndProfile,
int overrideVersion, // overrides version specified by #verison or default version
bool forwardCompatible, // give errors for use of deprecated features bool forwardCompatible, // give errors for use of deprecated features
EShMessages messages, // warnings/errors/AST; things to print out EShMessages messages, // warnings/errors/AST; things to print out
TIntermediate& intermediate, // returned tree, etc. TIntermediate& intermediate, // returned tree, etc.
@ -861,7 +884,7 @@ bool ProcessDeferred(
: userInput.scanVersion(version, profile, versionNotFirstToken); : userInput.scanVersion(version, profile, versionNotFirstToken);
bool versionNotFound = version == 0; bool versionNotFound = version == 0;
if (forceDefaultVersionAndProfile && source == EShSourceGlsl) { if (forceDefaultVersionAndProfile && source == EShSourceGlsl) {
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound && if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound &&
(version != defaultVersion || profile != defaultProfile)) { (version != defaultVersion || profile != defaultProfile)) {
compiler->infoSink.info << "Warning, (version, profile) forced to be (" compiler->infoSink.info << "Warning, (version, profile) forced to be ("
@ -878,16 +901,22 @@ bool ProcessDeferred(
version = defaultVersion; version = defaultVersion;
profile = defaultProfile; profile = defaultProfile;
} }
if (source == EShSourceGlsl && overrideVersion != 0) {
version = overrideVersion;
}
bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage, bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage,
versionNotFirst, defaultVersion, source, version, profile, spvVersion); versionNotFirst, defaultVersion, source, version, profile, spvVersion);
#ifdef GLSLANG_WEB #ifdef GLSLANG_WEB
profile = EEsProfile; profile = EEsProfile;
version = 310; version = 310;
#elif defined(GLSLANG_ANGLE)
profile = ECoreProfile;
version = 450;
#endif #endif
bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst)); bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst));
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
bool warnVersionNotFirst = false; bool warnVersionNotFirst = false;
if (! versionWillBeError && versionNotFirstToken) { if (! versionWillBeError && versionNotFirstToken) {
if (messages & EShMsgRelaxedErrors) if (messages & EShMsgRelaxedErrors)
@ -929,6 +958,9 @@ bool ProcessDeferred(
if (cachedTable) if (cachedTable)
symbolTable->adoptLevels(*cachedTable); symbolTable->adoptLevels(*cachedTable);
if (intermediate.getUniqueId() != 0)
symbolTable->overwriteUniqueId(intermediate.getUniqueId());
// Add built-in symbols that are potentially context dependent; // Add built-in symbols that are potentially context dependent;
// they get popped again further down. // they get popped again further down.
if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion, if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion,
@ -957,7 +989,7 @@ bool ProcessDeferred(
parseContext->setLimits(*resources); parseContext->setLimits(*resources);
if (! goodVersion) if (! goodVersion)
parseContext->addError(); parseContext->addError();
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
if (warnVersionNotFirst) { if (warnVersionNotFirst) {
TSourceLoc loc; TSourceLoc loc;
loc.init(); loc.init();
@ -991,10 +1023,11 @@ bool ProcessDeferred(
bool success = processingContext(*parseContext, ppContext, fullInput, bool success = processingContext(*parseContext, ppContext, fullInput,
versionWillBeError, *symbolTable, versionWillBeError, *symbolTable,
intermediate, optLevel, messages); intermediate, optLevel, messages);
intermediate.setUniqueId(symbolTable->getMaxSymbolId());
return success; return success;
} }
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Responsible for keeping track of the most recent source string and line in // Responsible for keeping track of the most recent source string and line in
// the preprocessor and outputting newlines appropriately if the source string // the preprocessor and outputting newlines appropriately if the source string
@ -1217,14 +1250,16 @@ struct DoFullParse{
parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n"; parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n";
} }
#ifndef GLSLANG_ANGLE
if (messages & EShMsgAST) if (messages & EShMsgAST)
intermediate.output(parseContext.infoSink, true); intermediate.output(parseContext.infoSink, true);
#endif
return success; return success;
} }
}; };
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Take a single compilation unit, and run the preprocessor on it. // Take a single compilation unit, and run the preprocessor on it.
// Return: True if there were no issues found in preprocessing, // Return: True if there were no issues found in preprocessing,
// False if during preprocessing any unknown version, pragmas or // False if during preprocessing any unknown version, pragmas or
@ -1244,18 +1279,20 @@ bool PreprocessDeferred(
int defaultVersion, // use 100 for ES environment, 110 for desktop int defaultVersion, // use 100 for ES environment, 110 for desktop
EProfile defaultProfile, EProfile defaultProfile,
bool forceDefaultVersionAndProfile, bool forceDefaultVersionAndProfile,
int overrideVersion, // use 0 if not overriding GLSL version
bool forwardCompatible, // give errors for use of deprecated features bool forwardCompatible, // give errors for use of deprecated features
EShMessages messages, // warnings/errors/AST; things to print out EShMessages messages, // warnings/errors/AST; things to print out
TShader::Includer& includer, TShader::Includer& includer,
TIntermediate& intermediate, // returned tree, etc. TIntermediate& intermediate, // returned tree, etc.
std::string* outputString) std::string* outputString,
TEnvironment* environment = nullptr)
{ {
DoPreprocessing parser(outputString); DoPreprocessing parser(outputString);
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
preamble, optLevel, resources, defaultVersion, preamble, optLevel, resources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile, defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, messages, intermediate, parser, forwardCompatible, messages, intermediate, parser,
false, includer); false, includer, "", environment);
} }
#endif #endif
@ -1282,6 +1319,7 @@ bool CompileDeferred(
int defaultVersion, // use 100 for ES environment, 110 for desktop int defaultVersion, // use 100 for ES environment, 110 for desktop
EProfile defaultProfile, EProfile defaultProfile,
bool forceDefaultVersionAndProfile, bool forceDefaultVersionAndProfile,
int overrideVersion, // use 0 if not overriding GLSL version
bool forwardCompatible, // give errors for use of deprecated features bool forwardCompatible, // give errors for use of deprecated features
EShMessages messages, // warnings/errors/AST; things to print out EShMessages messages, // warnings/errors/AST; things to print out
TIntermediate& intermediate,// returned tree, etc. TIntermediate& intermediate,// returned tree, etc.
@ -1292,7 +1330,7 @@ bool CompileDeferred(
DoFullParse parser; DoFullParse parser;
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
preamble, optLevel, resources, defaultVersion, preamble, optLevel, resources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile, defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, messages, intermediate, parser, forwardCompatible, messages, intermediate, parser,
true, includer, sourceEntryPointName, environment); true, includer, sourceEntryPointName, environment);
} }
@ -1311,7 +1349,6 @@ int ShInitialize()
glslang::GetGlobalLock(); glslang::GetGlobalLock();
++NumberOfClients; ++NumberOfClients;
glslang::ReleaseGlobalLock();
if (PerProcessGPA == nullptr) if (PerProcessGPA == nullptr)
PerProcessGPA = new TPoolAllocator(); PerProcessGPA = new TPoolAllocator();
@ -1321,6 +1358,7 @@ int ShInitialize()
glslang::HlslScanContext::fillInKeywordMap(); glslang::HlslScanContext::fillInKeywordMap();
#endif #endif
glslang::ReleaseGlobalLock();
return 1; return 1;
} }
@ -1383,9 +1421,10 @@ int ShFinalize()
--NumberOfClients; --NumberOfClients;
assert(NumberOfClients >= 0); assert(NumberOfClients >= 0);
bool finalize = NumberOfClients == 0; bool finalize = NumberOfClients == 0;
glslang::ReleaseGlobalLock(); if (! finalize) {
if (! finalize) glslang::ReleaseGlobalLock();
return 1; return 1;
}
for (int version = 0; version < VersionCount; ++version) { for (int version = 0; version < VersionCount; ++version) {
for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) { for (int spvVersion = 0; spvVersion < SpvVersionCount; ++spvVersion) {
@ -1423,6 +1462,7 @@ int ShFinalize()
glslang::HlslScanContext::deleteKeywordMap(); glslang::HlslScanContext::deleteKeywordMap();
#endif #endif
glslang::ReleaseGlobalLock();
return 1; return 1;
} }
@ -1464,7 +1504,7 @@ int ShCompile(
TIntermediate intermediate(compiler->getLanguage()); TIntermediate intermediate(compiler->getLanguage());
TShader::ForbidIncluder includer; TShader::ForbidIncluder includer;
bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr, bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr,
"", optLevel, resources, defaultVersion, ENoProfile, false, "", optLevel, resources, defaultVersion, ENoProfile, false, 0,
forwardCompatible, messages, intermediate, includer); forwardCompatible, messages, intermediate, includer);
// //
@ -1678,19 +1718,29 @@ int ShGetUniformLocation(const ShHandle handle, const char* name)
namespace glslang { namespace glslang {
#include "../Include/revision.h" 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 QUOTE(s) #s
#define STR(n) QUOTE(n) #define STR(n) QUOTE(n)
const char* GetEsslVersionString() const char* GetEsslVersionString()
{ {
return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL); 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() const char* GetGlslVersionString()
{ {
return "4.60 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL); return "4.60 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR(
GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR;
} }
int GetKhronosToolId() int GetKhronosToolId()
@ -1715,7 +1765,7 @@ public:
}; };
TShader::TShader(EShLanguage s) TShader::TShader(EShLanguage s)
: stage(s), lengths(nullptr), stringNames(nullptr), preamble("") : stage(s), lengths(nullptr), stringNames(nullptr), preamble(""), overrideVersion(0)
{ {
pool = new TPoolAllocator; pool = new TPoolAllocator;
infoSink = new TInfoSink; infoSink = new TInfoSink;
@ -1725,6 +1775,7 @@ TShader::TShader(EShLanguage s)
// clear environment (avoid constructors in them for use in a C interface) // clear environment (avoid constructors in them for use in a C interface)
environment.input.languageFamily = EShSourceNone; environment.input.languageFamily = EShSourceNone;
environment.input.dialect = EShClientNone; environment.input.dialect = EShClientNone;
environment.input.vulkanRulesRelaxed = false;
environment.client.client = EShClientNone; environment.client.client = EShClientNone;
environment.target.language = EShTargetNone; environment.target.language = EShTargetNone;
environment.target.hlslFunctionality1 = false; environment.target.hlslFunctionality1 = false;
@ -1771,12 +1822,26 @@ void TShader::setSourceEntryPoint(const char* name)
sourceEntryPointName = name; sourceEntryPointName = name;
} }
// Log initial settings and transforms.
// See comment for class TProcesses.
void TShader::addProcesses(const std::vector<std::string>& p) void TShader::addProcesses(const std::vector<std::string>& p)
{ {
intermediate->addProcesses(p); intermediate->addProcesses(p);
} }
void TShader::setUniqueId(unsigned long long id)
{
intermediate->setUniqueId(id);
}
void TShader::setOverrideVersion(int version)
{
overrideVersion = version;
}
void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); } 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); } void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); }
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
@ -1824,6 +1889,15 @@ void TShader::setResourceSetBinding(const std::vector<std::string>& base) { in
void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); } void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); }
#endif #endif
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 #ifdef ENABLE_HLSL
// See comment above TDefaultHlslIoMapper in iomapper.cpp: // See comment above TDefaultHlslIoMapper in iomapper.cpp:
void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); } void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); }
@ -1847,12 +1921,12 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
return CompileDeferred(compiler, strings, numStrings, lengths, stringNames, return CompileDeferred(compiler, strings, numStrings, lengths, stringNames,
preamble, EShOptNone, builtInResources, defaultVersion, preamble, EShOptNone, builtInResources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile, defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, messages, *intermediate, includer, sourceEntryPointName, forwardCompatible, messages, *intermediate, includer, sourceEntryPointName,
&environment); &environment);
} }
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// Fill in a string with the result of preprocessing ShaderStrings // Fill in a string with the result of preprocessing ShaderStrings
// Returns true if all extensions, pragmas and version strings were valid. // Returns true if all extensions, pragmas and version strings were valid.
// //
@ -1874,8 +1948,9 @@ bool TShader::preprocess(const TBuiltInResource* builtInResources,
return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble, return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble,
EShOptNone, builtInResources, defaultVersion, EShOptNone, builtInResources, defaultVersion,
defaultProfile, forceDefaultVersionAndProfile, defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
forwardCompatible, message, includer, *intermediate, output_string); forwardCompatible, message, includer, *intermediate, output_string,
&environment);
} }
#endif #endif
@ -1890,7 +1965,7 @@ const char* TShader::getInfoDebugLog()
} }
TProgram::TProgram() : TProgram::TProgram() :
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
reflection(0), reflection(0),
#endif #endif
linked(false) linked(false)
@ -1906,7 +1981,7 @@ TProgram::TProgram() :
TProgram::~TProgram() TProgram::~TProgram()
{ {
delete infoSink; delete infoSink;
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
delete reflection; delete reflection;
#endif #endif
@ -1938,7 +2013,10 @@ bool TProgram::link(EShMessages messages)
error = true; error = true;
} }
// TODO: Link: cross-stage error checking if (!error) {
if (! crossStageCheck(messages))
error = true;
}
return ! error; return ! error;
} }
@ -1953,7 +2031,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
if (stages[stage].size() == 0) if (stages[stage].size() == 0)
return true; return true;
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
int numEsShaders = 0, numNonEsShaders = 0; int numEsShaders = 0, numNonEsShaders = 0;
for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) { for (auto it = stages[stage].begin(); it != stages[stage].end(); ++it) {
if ((*it)->intermediate->getProfile() == EEsProfile) { if ((*it)->intermediate->getProfile() == EEsProfile) {
@ -1982,7 +2060,9 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
intermediate[stage] = new TIntermediate(stage, intermediate[stage] = new TIntermediate(stage,
firstIntermediate->getVersion(), firstIntermediate->getVersion(),
firstIntermediate->getProfile()); 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. // The new TIntermediate must use the same origin as the original TIntermediates.
// Otherwise linking will fail due to different coordinate systems. // Otherwise linking will fail due to different coordinate systems.
@ -2007,12 +2087,77 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages)
#endif #endif
intermediate[stage]->finalCheck(*infoSink, (messages & EShMsgKeepUncalled) != 0); intermediate[stage]->finalCheck(*infoSink, (messages & EShMsgKeepUncalled) != 0);
#ifndef GLSLANG_ANGLE
if (messages & EShMsgAST) if (messages & EShMsgAST)
intermediate[stage]->output(*infoSink, true); intermediate[stage]->output(*infoSink, true);
#endif
return intermediate[stage]->getNumErrors() == 0; 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<TIntermediate*> 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() const char* TProgram::getInfoLog()
{ {
return infoSink->info.c_str(); return infoSink->info.c_str();
@ -2023,7 +2168,7 @@ const char* TProgram::getInfoDebugLog()
return infoSink->debug.c_str(); return infoSink->debug.c_str();
} }
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// //
// Reflection implementation. // Reflection implementation.
@ -2105,6 +2250,6 @@ bool TProgram::mapIO(TIoMapResolver* pResolver, TIoMapper* pIoMapper)
return ioMapper->doMap(pResolver, *infoSink); return ioMapper->doMap(pResolver, *infoSink);
} }
#endif // GLSLANG_WEB #endif // !GLSLANG_WEB && !GLSLANG_ANGLE
} // end namespace glslang } // end namespace glslang

View File

@ -0,0 +1,350 @@
//
// 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.
//
#ifndef GLSLANG_WEB
//
// GL_EXT_spirv_intrinsics
//
#include "../Include/intermediate.h"
#include "../Include/SpirvIntrinsics.h"
#include "../Include/Types.h"
#include "ParseHelper.h"
namespace glslang {
//
// 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, "unknow 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<const TIntermConstantUnion*> 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<const TIntermTyped*> 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<const TIntermConstantUnion*> 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<const TIntermTyped*> extraOperands;
for (auto arg : args->getSequence()) {
auto extraOperand = arg->getAsTyped();
assert(extraOperand != nullptr && extraOperand->getQualifier().isConstant());
extraOperands.push_back(extraOperand);
}
spirvDecorate->decorateIds[decoration] = extraOperands;
}
void TQualifier::setSpirvDecorateString(int decoration, const TIntermAggregate* args)
{
if (!spirvDecorate)
spirvDecorate = new TSpirvDecorate;
assert(args);
TVector<const TIntermConstantUnion*> 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) {
auto& constArray = constant->getAsConstantUnion() != nullptr ? constant->getAsConstantUnion()->getConstArray()
: constant->getAsSymbolNode()->getConstArray();
if (constant->getBasicType() == EbtFloat) {
float value = static_cast<float>(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);
};
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 {
assert(constant);
spirvTypeParams->push_back(TSpirvTypeParameter(constant));
}
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
#endif // GLSLANG_WEB

View File

@ -3,6 +3,7 @@
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2015-2018 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -74,7 +75,9 @@ void TType::buildMangledName(TString& mangledName) const
case EbtInt64: mangledName += "i64"; break; case EbtInt64: mangledName += "i64"; break;
case EbtUint64: mangledName += "u64"; break; case EbtUint64: mangledName += "u64"; break;
case EbtAtomicUint: mangledName += "au"; break; case EbtAtomicUint: mangledName += "au"; break;
case EbtAccStructNV: mangledName += "asnv"; break; case EbtAccStruct: mangledName += "as"; break;
case EbtRayQuery: mangledName += "rq"; break;
case EbtSpirvType: mangledName += "spv-t"; break;
#endif #endif
case EbtSampler: case EbtSampler:
switch (sampler.type) { switch (sampler.type) {
@ -83,6 +86,8 @@ void TType::buildMangledName(TString& mangledName) const
#endif #endif
case EbtInt: mangledName += "i"; break; case EbtInt: mangledName += "i"; break;
case EbtUint: mangledName += "u"; break; case EbtUint: mangledName += "u"; break;
case EbtInt64: mangledName += "i64"; break;
case EbtUint64: mangledName += "u64"; break;
default: break; // some compilers want this default: break; // some compilers want this
} }
if (sampler.isImageClass()) if (sampler.isImageClass())
@ -120,7 +125,7 @@ void TType::buildMangledName(TString& mangledName) const
mangledName += "-tx-struct"; mangledName += "-tx-struct";
char text[16]; // plenty enough space for the small integers. char text[16]; // plenty enough space for the small integers.
snprintf(text, sizeof(text), "%d-", sampler.getStructReturnIndex()); snprintf(text, sizeof(text), "%u-", sampler.getStructReturnIndex());
mangledName += text; mangledName += text;
} else { } else {
switch (sampler.getVectorSize()) { switch (sampler.getVectorSize()) {
@ -144,6 +149,8 @@ void TType::buildMangledName(TString& mangledName) const
if (typeName) if (typeName)
mangledName += *typeName; mangledName += *typeName;
for (unsigned int i = 0; i < structure->size(); ++i) { for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->getBasicType() == EbtVoid)
continue;
mangledName += '-'; mangledName += '-';
(*structure)[i].type->buildMangledName(mangledName); (*structure)[i].type->buildMangledName(mangledName);
} }
@ -164,7 +171,7 @@ void TType::buildMangledName(TString& mangledName) const
for (int i = 0; i < arraySizes->getNumDims(); ++i) { for (int i = 0; i < arraySizes->getNumDims(); ++i) {
if (arraySizes->getDimNode(i)) { if (arraySizes->getDimNode(i)) {
if (arraySizes->getDimNode(i)->getAsSymbolNode()) if (arraySizes->getDimNode(i)->getAsSymbolNode())
snprintf(buf, maxSize, "s%d", arraySizes->getDimNode(i)->getAsSymbolNode()->getId()); snprintf(buf, maxSize, "s%lld", arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
else else
snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i)); snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i));
} else } else
@ -176,7 +183,7 @@ void TType::buildMangledName(TString& mangledName) const
} }
} }
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
// //
// Dump functions. // Dump functions.
@ -272,8 +279,14 @@ TFunction::~TFunction()
// //
TSymbolTableLevel::~TSymbolTableLevel() TSymbolTableLevel::~TSymbolTableLevel()
{ {
for (tLevel::iterator it = level.begin(); it != level.end(); ++it) for (tLevel::iterator it = level.begin(); it != level.end(); ++it) {
delete (*it).second; const TString& name = it->first;
auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(),
[&name](const std::pair<TString, TString>& i) { return i.first == name; });
if (retargetIter == retargetedSymbols.end())
delete (*it).second;
}
delete [] defaultPrecision; delete [] defaultPrecision;
} }
@ -384,6 +397,9 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
implicitThis = copyOf.implicitThis; implicitThis = copyOf.implicitThis;
illegalImplicitThis = copyOf.illegalImplicitThis; illegalImplicitThis = copyOf.illegalImplicitThis;
defaultParamCount = copyOf.defaultParamCount; defaultParamCount = copyOf.defaultParamCount;
#ifndef GLSLANG_WEB
spirvInst = copyOf.spirvInst;
#endif
} }
TFunction* TFunction::clone() const TFunction* TFunction::clone() const
@ -408,6 +424,10 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
TSymbolTableLevel *symTableLevel = new TSymbolTableLevel(); TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
symTableLevel->anonId = anonId; symTableLevel->anonId = anonId;
symTableLevel->thisLevel = thisLevel; symTableLevel->thisLevel = thisLevel;
symTableLevel->retargetedSymbols.clear();
for (auto &s : retargetedSymbols) {
symTableLevel->retargetedSymbols.push_back({s.first, s.second});
}
std::vector<bool> containerCopied(anonId, false); std::vector<bool> containerCopied(anonId, false);
tLevel::const_iterator iter; tLevel::const_iterator iter;
for (iter = level.begin(); iter != level.end(); ++iter) { for (iter = level.begin(); iter != level.end(); ++iter) {
@ -423,8 +443,21 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
symTableLevel->insert(*container, false); symTableLevel->insert(*container, false);
containerCopied[anon->getAnonId()] = true; containerCopied[anon->getAnonId()] = true;
} }
} else } else {
const TString& name = iter->first;
auto retargetIter = std::find_if(retargetedSymbols.begin(), retargetedSymbols.end(),
[&name](const std::pair<TString, TString>& i) { return i.first == name; });
if (retargetIter != retargetedSymbols.end())
continue;
symTableLevel->insert(*iter->second->clone(), false); 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; return symTableLevel;

View File

@ -84,7 +84,7 @@ typedef TVector<const char*> TExtensionList;
class TSymbol { class TSymbol {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { } explicit TSymbol(const TString *n) : name(n), uniqueId(0), extensions(0), writable(true) { }
virtual TSymbol* clone() const = 0; virtual TSymbol* clone() const = 0;
virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool
@ -104,8 +104,8 @@ public:
virtual const TAnonMember* getAsAnonMember() const { return 0; } virtual const TAnonMember* getAsAnonMember() const { return 0; }
virtual const TType& getType() const = 0; virtual const TType& getType() const = 0;
virtual TType& getWritableType() = 0; virtual TType& getWritableType() = 0;
virtual void setUniqueId(int id) { uniqueId = id; } virtual void setUniqueId(long long id) { uniqueId = id; }
virtual int getUniqueId() const { return uniqueId; } virtual long long getUniqueId() const { return uniqueId; }
virtual void setExtensions(int numExts, const char* const exts[]) virtual void setExtensions(int numExts, const char* const exts[])
{ {
assert(extensions == 0); assert(extensions == 0);
@ -117,7 +117,7 @@ public:
virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); } virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); }
virtual const char** getExtensions() const { return extensions->data(); } virtual const char** getExtensions() const { return extensions->data(); }
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0; virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0;
void dumpExtensions(TInfoSink& infoSink) const; void dumpExtensions(TInfoSink& infoSink) const;
#endif #endif
@ -130,7 +130,7 @@ protected:
TSymbol& operator=(const TSymbol&); TSymbol& operator=(const TSymbol&);
const TString *name; const TString *name;
unsigned int uniqueId; // For cross-scope comparing during code generation unsigned long long uniqueId; // For cross-scope comparing during code generation
// For tracking what extensions must be present // For tracking what extensions must be present
// (don't use if correct version/profile is present). // (don't use if correct version/profile is present).
@ -196,7 +196,7 @@ public:
} }
virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); } virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); }
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const; virtual void dump(TInfoSink& infoSink, bool complete = false) const;
#endif #endif
@ -320,6 +320,15 @@ public:
virtual const TParameter& operator[](int i) const { return parameters[i]; } virtual const TParameter& operator[](int i) const { return parameters[i]; }
#ifndef GLSLANG_WEB #ifndef GLSLANG_WEB
virtual void setSpirvInstruction(const TSpirvInstruction& inst)
{
relateToOperator(EOpSpirvInst);
spirvInst = inst;
}
virtual const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; }
#endif
#if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const override; virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
#endif #endif
@ -342,6 +351,10 @@ protected:
// This is important for a static member function that has member variables in scope, // 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. // but is not allowed to use them, or see hidden symbols instead.
int defaultParamCount; int defaultParamCount;
#ifndef GLSLANG_WEB
TSpirvInstruction spirvInst; // SPIR-V instruction qualifiers
#endif
}; };
// //
@ -381,7 +394,7 @@ public:
virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); } virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); }
virtual int getAnonId() const { return anonId; } virtual int getAnonId() const { return anonId; }
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
virtual void dump(TInfoSink& infoSink, bool complete = false) const override; virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
#endif #endif
@ -400,13 +413,20 @@ public:
TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { } TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { }
~TSymbolTableLevel(); ~TSymbolTableLevel();
bool insert(TSymbol& symbol, bool separateNameSpaces) 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 // returning true means symbol was added to the table with no semantic errors
// //
const TString& name = symbol.getName(); const TString& name = symbol.getName();
if (name == "") { if (forcedKeyName.length()) {
return level.insert(tLevelPair(forcedKeyName, &symbol)).second;
}
else if (name == "") {
symbol.getAsVariable()->setAnonId(anonId++); symbol.getAsVariable()->setAnonId(anonId++);
// An empty name means an anonymous container, exposing its members to the external scope. // 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. // Give it a name and insert its members in the symbol table, pointing to the container.
@ -458,6 +478,16 @@ public:
return true; 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 TSymbol* find(const TString& name) const
{ {
tLevel::const_iterator it = level.find(name); tLevel::const_iterator it = level.find(name);
@ -551,7 +581,7 @@ public:
void relateToOperator(const char* name, TOperator op); void relateToOperator(const char* name, TOperator op);
void setFunctionExtensions(const char* name, int num, const char* const extensions[]); void setFunctionExtensions(const char* name, int num, const char* const extensions[]);
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
void dump(TInfoSink& infoSink, bool complete = false) const; void dump(TInfoSink& infoSink, bool complete = false) const;
#endif #endif
TSymbolTableLevel* clone() const; TSymbolTableLevel* clone() const;
@ -570,6 +600,8 @@ protected:
tLevel level; // named mappings tLevel level; // named mappings
TPrecisionQualifier *defaultPrecision; TPrecisionQualifier *defaultPrecision;
// pair<FromName, ToName>
TVector<std::pair<TString, TString>> retargetedSymbols;
int anonId; int anonId;
bool thisLevel; // True if this level of the symbol table is a structure scope containing member function 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. // that are supposed to see anonymous access to member variables.
@ -612,21 +644,28 @@ public:
// 3: user-shader globals // 3: user-shader globals
// //
protected: protected:
static const uint32_t LevelFlagBitOffset = 56;
static const int globalLevel = 3; static const int globalLevel = 3;
bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels static bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals static bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals static bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
public: public:
bool isEmpty() { return table.size() == 0; } bool isEmpty() { return table.size() == 0; }
bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); } bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
bool atGlobalLevel() { return isGlobalLevel(currentLevel()); } bool atGlobalLevel() { return isGlobalLevel(currentLevel()); }
static bool isBuiltInSymbol(long long uniqueId) {
int level = static_cast<int>(uniqueId >> LevelFlagBitOffset);
return isBuiltInLevel(level);
}
static constexpr uint64_t uniqueIdMask = (1LL << LevelFlagBitOffset) - 1;
static const uint32_t MaxLevelInUniqueID = 127;
void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; } void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
void setSeparateNameSpaces() { separateNameSpaces = true; } void setSeparateNameSpaces() { separateNameSpaces = true; }
void push() void push()
{ {
table.push_back(new TSymbolTableLevel); table.push_back(new TSymbolTableLevel);
updateUniqueIdLevelFlag();
} }
// Make a new symbol-table level to represent the scope introduced by a structure // Make a new symbol-table level to represent the scope introduced by a structure
@ -639,6 +678,7 @@ public:
{ {
assert(thisSymbol.getName().size() == 0); assert(thisSymbol.getName().size() == 0);
table.push_back(new TSymbolTableLevel); table.push_back(new TSymbolTableLevel);
updateUniqueIdLevelFlag();
table.back()->setThisLevel(); table.back()->setThisLevel();
insert(thisSymbol); insert(thisSymbol);
} }
@ -648,6 +688,7 @@ public:
table[currentLevel()]->getPreviousDefaultPrecisions(p); table[currentLevel()]->getPreviousDefaultPrecisions(p);
delete table.back(); delete table.back();
table.pop_back(); table.pop_back();
updateUniqueIdLevelFlag();
} }
// //
@ -685,6 +726,16 @@ public:
return table[currentLevel()]->amend(symbol, firstNewMember); 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 // To allocate an internal temporary, which will need to be uniquely
// identified by the consumer of the AST, but never need to // identified by the consumer of the AST, but never need to
@ -756,6 +807,12 @@ public:
return symbol; 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 // Find of a symbol that returns how many layers deep of nested
// structures-with-member-functions ('this' scopes) deep the symbol was // structures-with-member-functions ('this' scopes) deep the symbol was
// found in. // found in.
@ -853,8 +910,8 @@ public:
} }
} }
int getMaxSymbolId() { return uniqueId; } long long getMaxSymbolId() { return uniqueId; }
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
void dump(TInfoSink& infoSink, bool complete = false) const; void dump(TInfoSink& infoSink, bool complete = false) const;
#endif #endif
void copyTable(const TSymbolTable& copyOf); void copyTable(const TSymbolTable& copyOf);
@ -867,14 +924,27 @@ public:
table[level]->readOnly(); 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: protected:
TSymbolTable(TSymbolTable&); TSymbolTable(TSymbolTable&);
TSymbolTable& operator=(TSymbolTableLevel&); TSymbolTable& operator=(TSymbolTableLevel&);
int currentLevel() const { return static_cast<int>(table.size()) - 1; } int currentLevel() const { return static_cast<int>(table.size()) - 1; }
std::vector<TSymbolTableLevel*> table; std::vector<TSymbolTableLevel*> table;
int uniqueId; // for unique identification in code generation long long uniqueId; // for unique identification in code generation
bool noBuiltInRedeclarations; bool noBuiltInRedeclarations;
bool separateNameSpaces; bool separateNameSpaces;
unsigned int adoptedLevels; unsigned int adoptedLevels;

View File

@ -2,7 +2,8 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2015-2020 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -63,6 +64,7 @@
// checkDeprecated() // checkDeprecated()
// requireNotRemoved() // requireNotRemoved()
// requireExtensions() // requireExtensions()
// extensionRequires()
// //
// Typically, only the first two calls are needed. They go into a code path that // 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 // implements Feature F, and will log the proper error/warning messages. Parsing
@ -77,9 +79,11 @@
// const char* const XXX_extension_X = "XXX_extension_X"; // const char* const XXX_extension_X = "XXX_extension_X";
// //
// 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(), // 2) Add extension initialization to TParseVersions::initializeExtensionBehavior(),
// the first function below: // the first function below and optionally a entry to extensionData for additional
// error checks:
// //
// extensionBehavior[XXX_extension_X] = EBhDisable; // 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(): // 3) Add any preprocessor directives etc. in the next function, TParseVersions::getPreamble():
// //
@ -139,6 +143,8 @@
// set of extensions that both enable them and are necessary, given the version of the symbol // 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.) // 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 "parseVersions.h"
#include "localintermediate.h" #include "localintermediate.h"
@ -154,6 +160,22 @@ namespace glslang {
// //
void TParseVersions::initializeExtensionBehavior() 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}
};
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_texture_3D] = EBhDisable;
extensionBehavior[E_GL_OES_standard_derivatives] = EBhDisable; extensionBehavior[E_GL_OES_standard_derivatives] = EBhDisable;
extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable; extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable;
@ -178,6 +200,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_ARB_explicit_uniform_location] = EBhDisable; extensionBehavior[E_GL_ARB_explicit_uniform_location] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_image_load_store] = EBhDisable; extensionBehavior[E_GL_ARB_shader_image_load_store] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_atomic_counters] = 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_draw_parameters] = EBhDisable;
extensionBehavior[E_GL_ARB_shader_group_vote] = EBhDisable; extensionBehavior[E_GL_ARB_shader_group_vote] = EBhDisable;
extensionBehavior[E_GL_ARB_derivative_control] = EBhDisable; extensionBehavior[E_GL_ARB_derivative_control] = EBhDisable;
@ -196,6 +219,15 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_ARB_shader_clock] = EBhDisable; extensionBehavior[E_GL_ARB_shader_clock] = EBhDisable;
extensionBehavior[E_GL_ARB_uniform_buffer_object] = EBhDisable; extensionBehavior[E_GL_ARB_uniform_buffer_object] = EBhDisable;
extensionBehavior[E_GL_ARB_sample_shading] = 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_fragment_coord_conventions] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_basic] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_vote] = EBhDisable;
@ -221,9 +253,11 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_buffer_reference2] = EBhDisable; extensionBehavior[E_GL_EXT_buffer_reference2] = EBhDisable;
extensionBehavior[E_GL_EXT_buffer_reference_uvec2] = EBhDisable; extensionBehavior[E_GL_EXT_buffer_reference_uvec2] = EBhDisable;
extensionBehavior[E_GL_EXT_demote_to_helper_invocation] = 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_16bit_storage] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable; extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable;
extensionBehavior[E_GL_EXT_subgroup_uniform_control_flow] = EBhDisable;
// #line and #include // #line and #include
extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable; extensionBehavior[E_GL_GOOGLE_cpp_style_line_directive] = EBhDisable;
@ -253,6 +287,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_NV_shader_subgroup_partitioned] = EBhDisable; extensionBehavior[E_GL_NV_shader_subgroup_partitioned] = EBhDisable;
extensionBehavior[E_GL_NV_shading_rate_image] = EBhDisable; extensionBehavior[E_GL_NV_shading_rate_image] = EBhDisable;
extensionBehavior[E_GL_NV_ray_tracing] = 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_fragment_shader_barycentric] = EBhDisable;
extensionBehavior[E_GL_NV_compute_shader_derivatives] = EBhDisable; extensionBehavior[E_GL_NV_compute_shader_derivatives] = EBhDisable;
extensionBehavior[E_GL_NV_shader_texture_footprint] = EBhDisable; extensionBehavior[E_GL_NV_shader_texture_footprint] = EBhDisable;
@ -278,6 +313,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable; extensionBehavior[E_GL_EXT_tessellation_point_size] = EBhDisable;
extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisable; extensionBehavior[E_GL_EXT_texture_buffer] = EBhDisable;
extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisable; extensionBehavior[E_GL_EXT_texture_cube_map_array] = EBhDisable;
extensionBehavior[E_GL_EXT_null_initializer] = EBhDisable;
// OES matching AEP // OES matching AEP
extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable; extensionBehavior[E_GL_OES_geometry_shader] = EBhDisable;
@ -289,11 +325,22 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable; extensionBehavior[E_GL_OES_tessellation_point_size] = EBhDisable;
extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable; extensionBehavior[E_GL_OES_texture_buffer] = EBhDisable;
extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable; extensionBehavior[E_GL_OES_texture_cube_map_array] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_integer_mix] = EBhDisable;
// EXT extensions // EXT extensions
extensionBehavior[E_GL_EXT_device_group] = EBhDisable; extensionBehavior[E_GL_EXT_device_group] = EBhDisable;
extensionBehavior[E_GL_EXT_multiview] = EBhDisable; extensionBehavior[E_GL_EXT_multiview] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_realtime_clock] = 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_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;
// OVR extensions // OVR extensions
extensionBehavior[E_GL_OVR_multiview] = EBhDisable; extensionBehavior[E_GL_OVR_multiview] = EBhDisable;
@ -314,7 +361,10 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_int16] = 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_int64] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_subgroup_extended_types_float16] = 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;
} }
#endif // GLSLANG_WEB #endif // GLSLANG_WEB
// Get code that is not part of a shared symbol table, is specific to this shader, // Get code that is not part of a shared symbol table, is specific to this shader,
@ -336,6 +386,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_YUV_target 1\n" "#define GL_EXT_YUV_target 1\n"
"#define GL_EXT_shader_texture_lod 1\n" "#define GL_EXT_shader_texture_lod 1\n"
"#define GL_EXT_shadow_samplers 1\n" "#define GL_EXT_shadow_samplers 1\n"
"#define GL_EXT_fragment_shading_rate 1\n"
// AEP // AEP
"#define GL_ANDROID_extension_pack_es31a 1\n" "#define GL_ANDROID_extension_pack_es31a 1\n"
@ -352,6 +403,9 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_tessellation_point_size 1\n" "#define GL_EXT_tessellation_point_size 1\n"
"#define GL_EXT_texture_buffer 1\n" "#define GL_EXT_texture_buffer 1\n"
"#define GL_EXT_texture_cube_map_array 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 // OES matching AEP
"#define GL_OES_geometry_shader 1\n" "#define GL_OES_geometry_shader 1\n"
@ -366,11 +420,15 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_shader_non_constant_global_initializers 1\n" "#define GL_EXT_shader_non_constant_global_initializers 1\n"
; ;
if (isEsProfile() && version >= 300) { if (version >= 300) {
preamble += "#define GL_NV_shader_noperspective_interpolation 1\n"; 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 { } else { // !isEsProfile()
preamble = preamble =
"#define GL_FRAGMENT_PRECISION_HIGH 1\n" "#define GL_FRAGMENT_PRECISION_HIGH 1\n"
"#define GL_ARB_texture_rectangle 1\n" "#define GL_ARB_texture_rectangle 1\n"
@ -400,10 +458,18 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_ARB_sparse_texture_clamp 1\n" "#define GL_ARB_sparse_texture_clamp 1\n"
"#define GL_ARB_shader_stencil_export 1\n" "#define GL_ARB_shader_stencil_export 1\n"
"#define GL_ARB_sample_shading 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_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_post_depth_coverage 1\n"
"#define GL_ARB_fragment_shader_interlock 1\n" "#define GL_ARB_fragment_shader_interlock 1\n"
"#define GL_ARB_uniform_buffer_object 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_non_constant_global_initializers 1\n"
"#define GL_EXT_shader_image_load_formatted 1\n" "#define GL_EXT_shader_image_load_formatted 1\n"
"#define GL_EXT_post_depth_coverage 1\n" "#define GL_EXT_post_depth_coverage 1\n"
@ -418,6 +484,10 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_buffer_reference2 1\n" "#define GL_EXT_buffer_reference2 1\n"
"#define GL_EXT_buffer_reference_uvec2 1\n" "#define GL_EXT_buffer_reference_uvec2 1\n"
"#define GL_EXT_demote_to_helper_invocation 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 // GL_KHR_shader_subgroup
"#define GL_KHR_shader_subgroup_basic 1\n" "#define GL_KHR_shader_subgroup_basic 1\n"
@ -429,8 +499,13 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_KHR_shader_subgroup_clustered 1\n" "#define GL_KHR_shader_subgroup_clustered 1\n"
"#define GL_KHR_shader_subgroup_quad 1\n" "#define GL_KHR_shader_subgroup_quad 1\n"
"#define E_GL_EXT_shader_atomic_int64 1\n" "#define GL_EXT_shader_image_int64 1\n"
"#define E_GL_EXT_shader_realtime_clock 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_spirv_intrinsics 1\n"
"#define GL_AMD_shader_ballot 1\n" "#define GL_AMD_shader_ballot 1\n"
"#define GL_AMD_shader_trinary_minmax 1\n" "#define GL_AMD_shader_trinary_minmax 1\n"
@ -453,6 +528,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_NV_shader_subgroup_partitioned 1\n" "#define GL_NV_shader_subgroup_partitioned 1\n"
"#define GL_NV_shading_rate_image 1\n" "#define GL_NV_shading_rate_image 1\n"
"#define GL_NV_ray_tracing 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_fragment_shader_barycentric 1\n"
"#define GL_NV_compute_shader_derivatives 1\n" "#define GL_NV_compute_shader_derivatives 1\n"
"#define GL_NV_shader_texture_footprint 1\n" "#define GL_NV_shader_texture_footprint 1\n"
@ -473,6 +549,9 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_shader_subgroup_extended_types_int16 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_int64 1\n"
"#define GL_EXT_shader_subgroup_extended_types_float16 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"
; ;
if (version >= 150) { if (version >= 150) {
@ -482,6 +561,10 @@ void TParseVersions::getPreamble(std::string& preamble)
if (profile == ECompatibilityProfile) if (profile == ECompatibilityProfile)
preamble += "#define GL_compatibility_profile 1\n"; 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";
}
#endif // GLSLANG_WEB #endif // GLSLANG_WEB
} }
@ -508,6 +591,11 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_GOOGLE_include_directive 1\n" "#define GL_GOOGLE_include_directive 1\n"
"#define GL_KHR_blend_equation_advanced 1\n" "#define GL_KHR_blend_equation_advanced 1\n"
; ;
// other general extensions
preamble +=
"#define GL_EXT_terminate_invocation 1\n"
;
#endif #endif
// #define VULKAN XXXX // #define VULKAN XXXX
@ -529,6 +617,29 @@ void TParseVersions::getPreamble(std::string& preamble)
preamble += "\n"; preamble += "\n";
} }
#endif #endif
#ifndef GLSLANG_WEB
// 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 EShLangTaskNV: preamble += "#define GL_TASK_SHADER_NV 1 \n"; break;
case EShLangMeshNV: preamble += "#define GL_MESH_SHADER_NV 1 \n"; break;
default: break;
}
}
#endif
} }
// //
@ -544,12 +655,12 @@ const char* StageName(EShLanguage stage)
case EShLangTessControl: return "tessellation control"; case EShLangTessControl: return "tessellation control";
case EShLangTessEvaluation: return "tessellation evaluation"; case EShLangTessEvaluation: return "tessellation evaluation";
case EShLangGeometry: return "geometry"; case EShLangGeometry: return "geometry";
case EShLangRayGenNV: return "ray-generation"; case EShLangRayGen: return "ray-generation";
case EShLangIntersectNV: return "intersection"; case EShLangIntersect: return "intersection";
case EShLangAnyHitNV: return "any-hit"; case EShLangAnyHit: return "any-hit";
case EShLangClosestHitNV: return "closest-hit"; case EShLangClosestHit: return "closest-hit";
case EShLangMissNV: return "miss"; case EShLangMiss: return "miss";
case EShLangCallableNV: return "callable"; case EShLangCallable: return "callable";
case EShLangMeshNV: return "mesh"; case EShLangMeshNV: return "mesh";
case EShLangTaskNV: return "task"; case EShLangTaskNV: return "task";
#endif #endif
@ -712,7 +823,8 @@ bool TParseVersions::checkExtensionsRequested(const TSourceLoc& loc, int numExte
// Use when there are no profile/version to check, it's just an error if one of the // Use when there are no profile/version to check, it's just an error if one of the
// extensions is not present. // extensions is not present.
// //
void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc) void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[],
const char* featureDesc)
{ {
if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
return; return;
@ -731,7 +843,8 @@ void TParseVersions::requireExtensions(const TSourceLoc& loc, int numExtensions,
// Use by preprocessor when there are no profile/version to check, it's just an error if one of the // Use by preprocessor when there are no profile/version to check, it's just an error if one of the
// extensions is not present. // extensions is not present.
// //
void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[], const char* featureDesc) void TParseVersions::ppRequireExtensions(const TSourceLoc& loc, int numExtensions, const char* const extensions[],
const char* featureDesc)
{ {
if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc)) if (checkExtensionsRequested(loc, numExtensions, extensions, featureDesc))
return; return;
@ -797,10 +910,14 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString); error(getCurrentLoc(), "behavior not supported:", "#extension", behaviorString);
return; return;
} }
bool on = behavior != EBhDisable;
// check if extension is used with correct shader stage // check if extension is used with correct shader stage
checkExtensionStage(getCurrentLoc(), extension); checkExtensionStage(getCurrentLoc(), extension);
// check if extension has additional requirements
extensionRequires(getCurrentLoc(), extension, behaviorString);
// update the requested extension // update the requested extension
updateExtensionBehavior(extension, behavior); updateExtensionBehavior(extension, behavior);
@ -863,6 +980,32 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int64", behaviorString); updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_int64", behaviorString);
else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_float16") == 0) else if (strcmp(extension, "GL_EXT_shader_subgroup_extended_types_float16") == 0)
updateExtensionBehavior(line, "GL_EXT_shader_explicit_arithmetic_types_float16", behaviorString); 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) void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBehavior behavior)
@ -898,7 +1041,7 @@ void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBe
} else { } else {
if (iter->second == EBhDisablePartial) if (iter->second == EBhDisablePartial)
warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension); warn(getCurrentLoc(), "extension is only partially supported:", "#extension", extension);
if (behavior == EBhEnable || behavior == EBhRequire) if (behavior != EBhDisable)
intermediate.addRequestedExtension(extension); intermediate.addRequestedExtension(extension);
iter->second = behavior; iter->second = behavior;
} }
@ -917,6 +1060,24 @@ void TParseVersions::checkExtensionStage(const TSourceLoc& loc, const char * con
} }
} }
// 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);
}
}
// Call for any operation needing full GLSL integer data-type support. // Call for any operation needing full GLSL integer data-type support.
void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op) void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
{ {
@ -927,8 +1088,13 @@ void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
// Call for any operation needing GLSL double data-type support. // Call for any operation needing GLSL double data-type support.
void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op) void TParseVersions::doubleCheck(const TSourceLoc& loc, const char* op)
{ {
//requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); //requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, E_GL_ARB_gpu_shader_fp64, 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. // Call for any operation needing GLSL float16 data-type support.
@ -1148,7 +1314,7 @@ void TParseVersions::spvRemoved(const TSourceLoc& loc, const char* op)
// Call for any operation removed because Vulkan SPIR-V is being generated. // Call for any operation removed because Vulkan SPIR-V is being generated.
void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op) void TParseVersions::vulkanRemoved(const TSourceLoc& loc, const char* op)
{ {
if (spvVersion.vulkan > 0) if (spvVersion.vulkan > 0 && !spvVersion.vulkanRelaxed)
error(loc, "not allowed when using GLSL for Vulkan", op, ""); error(loc, "not allowed when using GLSL for Vulkan", op, "");
} }
@ -1169,5 +1335,12 @@ void TParseVersions::requireSpv(const TSourceLoc& loc, const char* op)
error(loc, "only allowed when generating SPIR-V", op, ""); error(loc, "only allowed when generating SPIR-V", op, "");
#endif #endif
} }
void TParseVersions::requireSpv(const TSourceLoc& loc, const char *op, unsigned int version)
{
#ifndef GLSLANG_WEB
if (spvVersion.spv < version)
error(loc, "not supported for current targeted SPIR-V version", op, "");
#endif
}
} // end namespace glslang } // end namespace glslang

View File

@ -3,6 +3,7 @@
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2015-2018 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -35,9 +36,12 @@
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
// //
#ifndef _VERSIONS_INCLUDED_ #ifndef _VERSIONS_INCLUDED_
#define _VERSIONS_INCLUDED_ #define _VERSIONS_INCLUDED_
#define LAST_ELEMENT_MARKER(x) x
// //
// Help manage multiple profiles, versions, extensions etc. // Help manage multiple profiles, versions, extensions etc.
// //
@ -49,12 +53,13 @@
// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible // Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible
// defects from mixing the two different forms. // defects from mixing the two different forms.
// //
typedef enum { typedef enum : unsigned {
EBadProfile = 0, EBadProfile = 0,
ENoProfile = (1 << 0), // only for desktop, before profiles showed up ENoProfile = (1 << 0), // only for desktop, before profiles showed up
ECoreProfile = (1 << 1), ECoreProfile = (1 << 1),
ECompatibilityProfile = (1 << 2), ECompatibilityProfile = (1 << 2),
EEsProfile = (1 << 3) EEsProfile = (1 << 3),
LAST_ELEMENT_MARKER(EProfileCount),
} EProfile; } EProfile;
namespace glslang { namespace glslang {
@ -82,11 +87,12 @@ inline const char* ProfileName(EProfile profile)
// The union of all requested rule sets will be applied. // The union of all requested rule sets will be applied.
// //
struct SpvVersion { struct SpvVersion {
SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {} 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 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 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 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" 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
}; };
// //
@ -130,6 +136,7 @@ const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attri
const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_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_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_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_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_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_derivative_control = "GL_ARB_derivative_control";
@ -148,6 +155,14 @@ const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shade
const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock"; 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_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_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_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic"; 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_vote = "GL_KHR_shader_subgroup_vote";
@ -182,6 +197,18 @@ const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_ref
const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2"; 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_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_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_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";
// Arrays of extensions for the above viewportEXTs duplications // Arrays of extensions for the above viewportEXTs duplications
@ -223,6 +250,7 @@ const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_
const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned"; 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_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 = "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_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_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_shader_texture_footprint = "GL_NV_shader_texture_footprint";
@ -253,6 +281,7 @@ const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessel
const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size"; 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_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_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 // OES matching AEP
const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader"; const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader";
@ -279,6 +308,10 @@ const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shad
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_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_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_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";
// Arrays of extensions for the above AEP duplications // Arrays of extensions for the above AEP duplications

View File

@ -123,6 +123,8 @@ TAttributeType TParseContext::attributeFromName(const TString& name) const
return EatPeelCount; return EatPeelCount;
else if (name == "partial_count") else if (name == "partial_count")
return EatPartialCount; return EatPartialCount;
else if (name == "subgroup_uniform_control_flow")
return EatSubgroupUniformControlFlow;
else else
return EatNone; return EatNone;
} }
@ -341,6 +343,29 @@ void TParseContext::handleLoopAttributes(const TAttributes& attributes, TIntermN
} }
} }
//
// 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:
intermediate.setSubgroupUniformControlFlow();
break;
default:
warn(loc, "attribute does not apply to a function", "", "");
break;
}
}
}
} // end namespace glslang } // end namespace glslang
#endif // GLSLANG_WEB #endif // GLSLANG_WEB

View File

@ -118,7 +118,8 @@ namespace glslang {
EatFormatR8ui, EatFormatR8ui,
EatFormatUnknown, EatFormatUnknown,
EatNonWritable, EatNonWritable,
EatNonReadable EatNonReadable,
EatSubgroupUniformControlFlow,
}; };
class TIntermAggregate; class TIntermAggregate;

View File

@ -49,9 +49,17 @@
#define GL_INT64_VEC4_ARB 0x8FEB #define GL_INT64_VEC4_ARB 0x8FEB
#define GL_UNSIGNED_INT64_ARB 0x140F #define GL_UNSIGNED_INT64_ARB 0x140F
#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5 #define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5
#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6 #define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6
#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7 #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 0x8B56
#define GL_BOOL_VEC2 0x8B57 #define GL_BOOL_VEC2 0x8B57

View File

@ -2,7 +2,8 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2015-2019 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -115,6 +116,9 @@ using namespace glslang;
glslang::TIntermNodePair nodePair; glslang::TIntermNodePair nodePair;
glslang::TIntermTyped* intermTypedNode; glslang::TIntermTyped* intermTypedNode;
glslang::TAttributes* attributes; glslang::TAttributes* attributes;
glslang::TSpirvRequirement* spirvReq;
glslang::TSpirvInstruction* spirvInst;
glslang::TSpirvTypeParameters* spirvTypeParams;
}; };
union { union {
glslang::TPublicType type; glslang::TPublicType type;
@ -204,6 +208,8 @@ GLSLANG_WEB_EXCLUDE_ON
%token <lex> F64MAT4X2 F64MAT4X3 F64MAT4X4 %token <lex> F64MAT4X2 F64MAT4X3 F64MAT4X4
%token <lex> ATOMIC_UINT %token <lex> ATOMIC_UINT
%token <lex> ACCSTRUCTNV %token <lex> ACCSTRUCTNV
%token <lex> ACCSTRUCTEXT
%token <lex> RAYQUERYEXT
%token <lex> FCOOPMATNV ICOOPMATNV UCOOPMATNV %token <lex> FCOOPMATNV ICOOPMATNV UCOOPMATNV
// combined image/sampler // combined image/sampler
@ -239,6 +245,18 @@ GLSLANG_WEB_EXCLUDE_ON
%token <lex> F16IMAGECUBE F16IMAGE1DARRAY F16IMAGE2DARRAY F16IMAGECUBEARRAY %token <lex> F16IMAGECUBE F16IMAGE1DARRAY F16IMAGE2DARRAY F16IMAGECUBEARRAY
%token <lex> F16IMAGEBUFFER F16IMAGE2DMS F16IMAGE2DMSARRAY %token <lex> F16IMAGEBUFFER F16IMAGE2DMS F16IMAGE2DMSARRAY
%token <lex> I64IMAGE1D U64IMAGE1D
%token <lex> I64IMAGE2D U64IMAGE2D
%token <lex> I64IMAGE3D U64IMAGE3D
%token <lex> I64IMAGE2DRECT U64IMAGE2DRECT
%token <lex> I64IMAGECUBE U64IMAGECUBE
%token <lex> I64IMAGEBUFFER U64IMAGEBUFFER
%token <lex> I64IMAGE1DARRAY U64IMAGE1DARRAY
%token <lex> I64IMAGE2DARRAY U64IMAGE2DARRAY
%token <lex> I64IMAGECUBEARRAY U64IMAGECUBEARRAY
%token <lex> I64IMAGE2DMS U64IMAGE2DMS
%token <lex> I64IMAGE2DMSARRAY U64IMAGE2DMSARRAY
// texture without sampler // texture without sampler
%token <lex> TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY %token <lex> TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY
%token <lex> TEXTURE1D ITEXTURE1D UTEXTURE1D %token <lex> TEXTURE1D ITEXTURE1D UTEXTURE1D
@ -256,6 +274,11 @@ GLSLANG_WEB_EXCLUDE_ON
%token <lex> SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS %token <lex> SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS
%token <lex> F16SUBPASSINPUT F16SUBPASSINPUTMS %token <lex> F16SUBPASSINPUT F16SUBPASSINPUTMS
// spirv intrinsics
%token <lex> SPIRV_INSTRUCTION SPIRV_EXECUTION_MODE SPIRV_EXECUTION_MODE_ID
%token <lex> SPIRV_DECORATE SPIRV_DECORATE_ID SPIRV_DECORATE_STRING
%token <lex> SPIRV_TYPE SPIRV_STORAGE_CLASS SPIRV_BY_REFERENCE SPIRV_LITERAL
GLSLANG_WEB_EXCLUDE_OFF GLSLANG_WEB_EXCLUDE_OFF
%token <lex> LEFT_OP RIGHT_OP %token <lex> LEFT_OP RIGHT_OP
@ -263,6 +286,7 @@ GLSLANG_WEB_EXCLUDE_OFF
%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN %token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN %token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
%token <lex> SUB_ASSIGN %token <lex> SUB_ASSIGN
%token <lex> STRING_LITERAL
%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT %token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT %token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
@ -277,6 +301,8 @@ GLSLANG_WEB_EXCLUDE_OFF
%token <lex> CENTROID IN OUT INOUT %token <lex> CENTROID IN OUT INOUT
%token <lex> STRUCT VOID WHILE %token <lex> STRUCT VOID WHILE
%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT %token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
%token <lex> TERMINATE_INVOCATION
%token <lex> TERMINATE_RAY IGNORE_INTERSECTION
%token <lex> UNIFORM SHARED BUFFER %token <lex> UNIFORM SHARED BUFFER
%token <lex> FLAT SMOOTH LAYOUT %token <lex> FLAT SMOOTH LAYOUT
@ -285,9 +311,10 @@ GLSLANG_WEB_EXCLUDE_ON
%token <lex> INT64CONSTANT UINT64CONSTANT %token <lex> INT64CONSTANT UINT64CONSTANT
%token <lex> SUBROUTINE DEMOTE %token <lex> SUBROUTINE DEMOTE
%token <lex> PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV %token <lex> PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV
%token <lex> PAYLOADEXT PAYLOADINEXT HITATTREXT CALLDATAEXT CALLDATAINEXT
%token <lex> PATCH SAMPLE NONUNIFORM %token <lex> PATCH SAMPLE NONUNIFORM
%token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT %token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT
%token <lex> SUBGROUPCOHERENT NONPRIVATE %token <lex> SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT
%token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV %token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV
%token <lex> PRECISE %token <lex> PRECISE
GLSLANG_WEB_EXCLUDE_OFF GLSLANG_WEB_EXCLUDE_OFF
@ -343,6 +370,19 @@ GLSLANG_WEB_EXCLUDE_ON
%type <interm.attributes> attribute attribute_list single_attribute %type <interm.attributes> attribute attribute_list single_attribute
%type <interm.intermNode> demote_statement %type <interm.intermNode> demote_statement
%type <interm.intermTypedNode> initializer_list %type <interm.intermTypedNode> initializer_list
%type <interm.spirvReq> spirv_requirements_list spirv_requirements_parameter
%type <interm.intermNode> spirv_extension_list spirv_capability_list
%type <interm.intermNode> spirv_execution_mode_qualifier
%type <interm.intermNode> spirv_execution_mode_parameter_list spirv_execution_mode_parameter spirv_execution_mode_id_parameter_list
%type <interm.type> spirv_storage_class_qualifier
%type <interm.type> spirv_decorate_qualifier
%type <interm.intermNode> spirv_decorate_parameter_list spirv_decorate_parameter
%type <interm.intermNode> spirv_decorate_id_parameter_list
%type <interm.intermNode> spirv_decorate_string_parameter_list
%type <interm.type> spirv_type_specifier
%type <interm.spirvTypeParams> spirv_type_parameter_list spirv_type_parameter
%type <interm.spirvInst> spirv_instruction_qualifier
%type <interm.spirvInst> spirv_instruction_qualifier_list spirv_instruction_qualifier_id
GLSLANG_WEB_EXCLUDE_OFF GLSLANG_WEB_EXCLUDE_OFF
%start translation_unit %start translation_unit
@ -377,6 +417,9 @@ primary_expression
$$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
} }
GLSLANG_WEB_EXCLUDE_ON GLSLANG_WEB_EXCLUDE_ON
| STRING_LITERAL {
$$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true);
}
| INT32CONSTANT { | INT32CONSTANT {
parseContext.explicitInt32Check($1.loc, "32-bit signed literal"); parseContext.explicitInt32Check($1.loc, "32-bit signed literal");
$$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
@ -755,7 +798,7 @@ conditional_expression
parseContext.rValueErrorCheck($5.loc, ":", $6); parseContext.rValueErrorCheck($5.loc, ":", $6);
$$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc); $$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(), $6->getCompleteString()); parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $6->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
$$ = $6; $$ = $6;
} }
} }
@ -770,9 +813,9 @@ assignment_expression
parseContext.specializationCheck($2.loc, $1->getType(), "="); parseContext.specializationCheck($2.loc, $1->getType(), "=");
parseContext.lValueErrorCheck($2.loc, "assign", $1); parseContext.lValueErrorCheck($2.loc, "assign", $1);
parseContext.rValueErrorCheck($2.loc, "assign", $3); parseContext.rValueErrorCheck($2.loc, "assign", $3);
$$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.loc); $$ = parseContext.addAssign($2.loc, $2.op, $1, $3);
if ($$ == 0) { if ($$ == 0) {
parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString()); parseContext.assignError($2.loc, "assign", $1->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $3->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
$$ = $1; $$ = $1;
} }
} }
@ -834,7 +877,7 @@ expression
parseContext.samplerConstructorLocationCheck($2.loc, ",", $3); parseContext.samplerConstructorLocationCheck($2.loc, ",", $3);
$$ = parseContext.intermediate.addComma($1, $3, $2.loc); $$ = parseContext.intermediate.addComma($1, $3, $2.loc);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $3->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
$$ = $3; $$ = $3;
} }
} }
@ -853,6 +896,20 @@ declaration
$$ = 0; $$ = 0;
// TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature // TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature
} }
GLSLANG_WEB_EXCLUDE_ON
| 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;
}
GLSLANG_WEB_EXCLUDE_OFF
| init_declarator_list SEMICOLON { | init_declarator_list SEMICOLON {
if ($1.intermNode && $1.intermNode->getAsAggregate()) if ($1.intermNode && $1.intermNode->getAsAggregate())
$1.intermNode->getAsAggregate()->setOperator(EOpSequence); $1.intermNode->getAsAggregate()->setOperator(EOpSequence);
@ -897,7 +954,7 @@ declaration
block_structure block_structure
: type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE { : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
--parseContext.structNestingLevel; --parseContext.blockNestingLevel;
parseContext.blockName = $2.string; parseContext.blockName = $2.string;
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
@ -922,6 +979,25 @@ function_prototype
$$.function = $1; $$.function = $1;
$$.loc = $2.loc; $$.loc = $2.loc;
} }
| function_declarator RIGHT_PAREN attribute {
$$.function = $1;
$$.loc = $2.loc;
parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($2.loc, *$3);
}
| attribute function_declarator RIGHT_PAREN {
$$.function = $2;
$$.loc = $3.loc;
parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($3.loc, *$1);
}
| attribute function_declarator RIGHT_PAREN attribute {
$$.function = $2;
$$.loc = $3.loc;
parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($3.loc, *$1);
parseContext.handleFunctionAttributes($3.loc, *$4);
}
; ;
function_declarator function_declarator
@ -1325,6 +1401,25 @@ GLSLANG_WEB_EXCLUDE_ON
| non_uniform_qualifier { | non_uniform_qualifier {
$$ = $1; $$ = $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();
}
GLSLANG_WEB_EXCLUDE_OFF GLSLANG_WEB_EXCLUDE_OFF
; ;
@ -1415,42 +1510,81 @@ GLSLANG_WEB_EXCLUDE_ON
} }
| HITATTRNV { | HITATTRNV {
parseContext.globalCheck($1.loc, "hitAttributeNV"); parseContext.globalCheck($1.loc, "hitAttributeNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask
| EShLangAnyHitNVMask), "hitAttributeNV"); | EShLangAnyHitMask), "hitAttributeNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV");
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqHitAttrNV; $$.qualifier.storage = EvqHitAttr;
}
| 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 { | PAYLOADNV {
parseContext.globalCheck($1.loc, "rayPayloadNV"); parseContext.globalCheck($1.loc, "rayPayloadNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask |
EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV"); EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV");
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqPayloadNV; $$.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 { | PAYLOADINNV {
parseContext.globalCheck($1.loc, "rayPayloadInNV"); parseContext.globalCheck($1.loc, "rayPayloadInNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitNVMask | parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask |
EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV"); EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV");
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqPayloadInNV; $$.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 { | CALLDATANV {
parseContext.globalCheck($1.loc, "callableDataNV"); parseContext.globalCheck($1.loc, "callableDataNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask |
EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV"); EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV");
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqCallableDataNV; $$.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 { | CALLDATAINNV {
parseContext.globalCheck($1.loc, "callableDataInNV"); parseContext.globalCheck($1.loc, "callableDataInNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV"); parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV");
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqCallableDataInNV; $$.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 { | COHERENT {
$$.init($1.loc); $$.init($1.loc);
@ -1481,6 +1615,11 @@ GLSLANG_WEB_EXCLUDE_ON
parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate");
$$.qualifier.nonprivate = true; $$.qualifier.nonprivate = true;
} }
| SHADERCALLCOHERENT {
$$.init($1.loc);
parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent");
$$.qualifier.shadercallcoherent = true;
}
| VOLATILE { | VOLATILE {
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.volatil = true; $$.qualifier.volatil = true;
@ -2350,7 +2489,15 @@ GLSLANG_WEB_EXCLUDE_ON
} }
| ACCSTRUCTNV { | ACCSTRUCTNV {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtAccStructNV; $$.basicType = EbtAccStruct;
}
| ACCSTRUCTEXT {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtAccStruct;
}
| RAYQUERYEXT {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtRayQuery;
} }
| ATOMIC_UINT { | ATOMIC_UINT {
parseContext.vulkanRemoved($1.loc, "atomic counter types"); parseContext.vulkanRemoved($1.loc, "atomic counter types");
@ -3143,6 +3290,116 @@ GLSLANG_WEB_EXCLUDE_ON
$$.basicType = EbtSampler; $$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint, Esd2D, true, false, true); $$.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 | SAMPLEREXTERNALOES { // GL_OES_EGL_image_external
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler; $$.basicType = EbtSampler;
@ -3223,6 +3480,10 @@ GLSLANG_WEB_EXCLUDE_ON
$$.basicType = EbtUint; $$.basicType = EbtUint;
$$.coopmat = true; $$.coopmat = true;
} }
| spirv_type_specifier {
parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier");
$$ = $1;
}
GLSLANG_WEB_EXCLUDE_OFF GLSLANG_WEB_EXCLUDE_OFF
| struct_specifier { | struct_specifier {
$$ = $1; $$ = $1;
@ -3391,6 +3652,12 @@ GLSLANG_WEB_EXCLUDE_ON
parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
$$ = $2; $$ = $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);
}
GLSLANG_WEB_EXCLUDE_OFF GLSLANG_WEB_EXCLUDE_OFF
; ;
@ -3523,6 +3790,7 @@ selection_statement
} }
GLSLANG_WEB_EXCLUDE_ON GLSLANG_WEB_EXCLUDE_ON
| attribute selection_statement_nonattributed { | attribute selection_statement_nonattributed {
parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
parseContext.handleSelectionAttributes(*$1, $2); parseContext.handleSelectionAttributes(*$1, $2);
$$ = $2; $$ = $2;
} }
@ -3570,6 +3838,7 @@ switch_statement
} }
GLSLANG_WEB_EXCLUDE_ON GLSLANG_WEB_EXCLUDE_ON
| attribute switch_statement_nonattributed { | attribute switch_statement_nonattributed {
parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
parseContext.handleSwitchAttributes(*$1, $2); parseContext.handleSwitchAttributes(*$1, $2);
$$ = $2; $$ = $2;
} }
@ -3634,6 +3903,7 @@ iteration_statement
} }
GLSLANG_WEB_EXCLUDE_ON GLSLANG_WEB_EXCLUDE_ON
| attribute iteration_statement_nonattributed { | attribute iteration_statement_nonattributed {
parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
parseContext.handleLoopAttributes(*$1, $2); parseContext.handleLoopAttributes(*$1, $2);
$$ = $2; $$ = $2;
} }
@ -3656,6 +3926,7 @@ iteration_statement_nonattributed
--parseContext.controlFlowNestingLevel; --parseContext.controlFlowNestingLevel;
} }
| DO { | DO {
parseContext.symbolTable.push();
++parseContext.loopNestingLevel; ++parseContext.loopNestingLevel;
++parseContext.statementNestingLevel; ++parseContext.statementNestingLevel;
++parseContext.controlFlowNestingLevel; ++parseContext.controlFlowNestingLevel;
@ -3667,6 +3938,7 @@ iteration_statement_nonattributed
parseContext.boolCheck($8.loc, $6); parseContext.boolCheck($8.loc, $6);
$$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc); $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc);
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
--parseContext.loopNestingLevel; --parseContext.loopNestingLevel;
--parseContext.statementNestingLevel; --parseContext.statementNestingLevel;
--parseContext.controlFlowNestingLevel; --parseContext.controlFlowNestingLevel;
@ -3745,6 +4017,20 @@ jump_statement
parseContext.requireStage($1.loc, EShLangFragment, "discard"); parseContext.requireStage($1.loc, EShLangFragment, "discard");
$$ = parseContext.intermediate.addBranch(EOpKill, $1.loc); $$ = parseContext.intermediate.addBranch(EOpKill, $1.loc);
} }
| TERMINATE_INVOCATION SEMICOLON {
parseContext.requireStage($1.loc, EShLangFragment, "terminateInvocation");
$$ = parseContext.intermediate.addBranch(EOpTerminateInvocation, $1.loc);
}
GLSLANG_WEB_EXCLUDE_ON
| 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);
}
GLSLANG_WEB_EXCLUDE_OFF
; ;
// Grammar Note: No 'goto'. Gotos are not supported. // Grammar Note: No 'goto'. Gotos are not supported.
@ -3782,6 +4068,14 @@ function_definition
: function_prototype { : function_prototype {
$1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */); $1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */);
$1.intermNode = parseContext.handleFunctionDefinition($1.loc, *$1.function); $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 { compound_statement_no_new_scope {
// May be best done as post process phase on intermediate code // May be best done as post process phase on intermediate code
@ -3797,6 +4091,17 @@ function_definition
$$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); $$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize);
$$->getAsAggregate()->setDebug(parseContext.contextPragma.debug); $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug);
$$->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable); $$->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;
}
} }
; ;
@ -3804,7 +4109,6 @@ GLSLANG_WEB_EXCLUDE_ON
attribute attribute
: LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET { : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET {
$$ = $3; $$ = $3;
parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_control_flow_attributes, "attribute");
} }
attribute_list attribute_list
@ -3824,4 +4128,270 @@ single_attribute
} }
GLSLANG_WEB_EXCLUDE_OFF GLSLANG_WEB_EXCLUDE_OFF
GLSLANG_WEB_EXCLUDE_ON
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
: constant_expression {
if ($1->getBasicType() != EbtFloat &&
$1->getBasicType() != EbtInt &&
$1->getBasicType() != EbtUint &&
$1->getBasicType() != EbtBool)
parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), "");
$$ = parseContext.intermediate.makeAggregate($1);
}
| spirv_decorate_id_parameter_list COMMA constant_expression {
if ($3->getBasicType() != EbtFloat &&
$3->getBasicType() != EbtInt &&
$3->getBasicType() != EbtUint &&
$3->getBasicType() != EbtBool)
parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), "");
$$ = parseContext.intermediate.growAggregate($1, $3);
}
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());
}
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);
}
GLSLANG_WEB_EXCLUDE_OFF
%% %%

View File

@ -2,7 +2,8 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc. // Copyright (C) 2015-2019 Google, Inc.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -115,6 +116,9 @@ using namespace glslang;
glslang::TIntermNodePair nodePair; glslang::TIntermNodePair nodePair;
glslang::TIntermTyped* intermTypedNode; glslang::TIntermTyped* intermTypedNode;
glslang::TAttributes* attributes; glslang::TAttributes* attributes;
glslang::TSpirvRequirement* spirvReq;
glslang::TSpirvInstruction* spirvInst;
glslang::TSpirvTypeParameters* spirvTypeParams;
}; };
union { union {
glslang::TPublicType type; glslang::TPublicType type;
@ -204,6 +208,8 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> F64MAT4X2 F64MAT4X3 F64MAT4X4 %token <lex> F64MAT4X2 F64MAT4X3 F64MAT4X4
%token <lex> ATOMIC_UINT %token <lex> ATOMIC_UINT
%token <lex> ACCSTRUCTNV %token <lex> ACCSTRUCTNV
%token <lex> ACCSTRUCTEXT
%token <lex> RAYQUERYEXT
%token <lex> FCOOPMATNV ICOOPMATNV UCOOPMATNV %token <lex> FCOOPMATNV ICOOPMATNV UCOOPMATNV
// combined image/sampler // combined image/sampler
@ -239,6 +245,18 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> F16IMAGECUBE F16IMAGE1DARRAY F16IMAGE2DARRAY F16IMAGECUBEARRAY %token <lex> F16IMAGECUBE F16IMAGE1DARRAY F16IMAGE2DARRAY F16IMAGECUBEARRAY
%token <lex> F16IMAGEBUFFER F16IMAGE2DMS F16IMAGE2DMSARRAY %token <lex> F16IMAGEBUFFER F16IMAGE2DMS F16IMAGE2DMSARRAY
%token <lex> I64IMAGE1D U64IMAGE1D
%token <lex> I64IMAGE2D U64IMAGE2D
%token <lex> I64IMAGE3D U64IMAGE3D
%token <lex> I64IMAGE2DRECT U64IMAGE2DRECT
%token <lex> I64IMAGECUBE U64IMAGECUBE
%token <lex> I64IMAGEBUFFER U64IMAGEBUFFER
%token <lex> I64IMAGE1DARRAY U64IMAGE1DARRAY
%token <lex> I64IMAGE2DARRAY U64IMAGE2DARRAY
%token <lex> I64IMAGECUBEARRAY U64IMAGECUBEARRAY
%token <lex> I64IMAGE2DMS U64IMAGE2DMS
%token <lex> I64IMAGE2DMSARRAY U64IMAGE2DMSARRAY
// texture without sampler // texture without sampler
%token <lex> TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY %token <lex> TEXTURECUBEARRAY ITEXTURECUBEARRAY UTEXTURECUBEARRAY
%token <lex> TEXTURE1D ITEXTURE1D UTEXTURE1D %token <lex> TEXTURE1D ITEXTURE1D UTEXTURE1D
@ -256,6 +274,11 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS %token <lex> SUBPASSINPUT SUBPASSINPUTMS ISUBPASSINPUT ISUBPASSINPUTMS USUBPASSINPUT USUBPASSINPUTMS
%token <lex> F16SUBPASSINPUT F16SUBPASSINPUTMS %token <lex> F16SUBPASSINPUT F16SUBPASSINPUTMS
// spirv intrinsics
%token <lex> SPIRV_INSTRUCTION SPIRV_EXECUTION_MODE SPIRV_EXECUTION_MODE_ID
%token <lex> SPIRV_DECORATE SPIRV_DECORATE_ID SPIRV_DECORATE_STRING
%token <lex> SPIRV_TYPE SPIRV_STORAGE_CLASS SPIRV_BY_REFERENCE SPIRV_LITERAL
%token <lex> LEFT_OP RIGHT_OP %token <lex> LEFT_OP RIGHT_OP
@ -263,6 +286,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN %token <lex> AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN
%token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN %token <lex> MOD_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN XOR_ASSIGN OR_ASSIGN
%token <lex> SUB_ASSIGN %token <lex> SUB_ASSIGN
%token <lex> STRING_LITERAL
%token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT %token <lex> LEFT_PAREN RIGHT_PAREN LEFT_BRACKET RIGHT_BRACKET LEFT_BRACE RIGHT_BRACE DOT
%token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT %token <lex> COMMA COLON EQUAL SEMICOLON BANG DASH TILDE PLUS STAR SLASH PERCENT
@ -277,6 +301,8 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> CENTROID IN OUT INOUT %token <lex> CENTROID IN OUT INOUT
%token <lex> STRUCT VOID WHILE %token <lex> STRUCT VOID WHILE
%token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT %token <lex> BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT
%token <lex> TERMINATE_INVOCATION
%token <lex> TERMINATE_RAY IGNORE_INTERSECTION
%token <lex> UNIFORM SHARED BUFFER %token <lex> UNIFORM SHARED BUFFER
%token <lex> FLAT SMOOTH LAYOUT %token <lex> FLAT SMOOTH LAYOUT
@ -285,9 +311,10 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> INT64CONSTANT UINT64CONSTANT %token <lex> INT64CONSTANT UINT64CONSTANT
%token <lex> SUBROUTINE DEMOTE %token <lex> SUBROUTINE DEMOTE
%token <lex> PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV %token <lex> PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV
%token <lex> PAYLOADEXT PAYLOADINEXT HITATTREXT CALLDATAEXT CALLDATAINEXT
%token <lex> PATCH SAMPLE NONUNIFORM %token <lex> PATCH SAMPLE NONUNIFORM
%token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT %token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT
%token <lex> SUBGROUPCOHERENT NONPRIVATE %token <lex> SUBGROUPCOHERENT NONPRIVATE SHADERCALLCOHERENT
%token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV %token <lex> NOPERSPECTIVE EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV
%token <lex> PRECISE %token <lex> PRECISE
@ -343,6 +370,19 @@ extern int yylex(YYSTYPE*, TParseContext&);
%type <interm.attributes> attribute attribute_list single_attribute %type <interm.attributes> attribute attribute_list single_attribute
%type <interm.intermNode> demote_statement %type <interm.intermNode> demote_statement
%type <interm.intermTypedNode> initializer_list %type <interm.intermTypedNode> initializer_list
%type <interm.spirvReq> spirv_requirements_list spirv_requirements_parameter
%type <interm.intermNode> spirv_extension_list spirv_capability_list
%type <interm.intermNode> spirv_execution_mode_qualifier
%type <interm.intermNode> spirv_execution_mode_parameter_list spirv_execution_mode_parameter spirv_execution_mode_id_parameter_list
%type <interm.type> spirv_storage_class_qualifier
%type <interm.type> spirv_decorate_qualifier
%type <interm.intermNode> spirv_decorate_parameter_list spirv_decorate_parameter
%type <interm.intermNode> spirv_decorate_id_parameter_list
%type <interm.intermNode> spirv_decorate_string_parameter_list
%type <interm.type> spirv_type_specifier
%type <interm.spirvTypeParams> spirv_type_parameter_list spirv_type_parameter
%type <interm.spirvInst> spirv_instruction_qualifier
%type <interm.spirvInst> spirv_instruction_qualifier_list spirv_instruction_qualifier_id
%start translation_unit %start translation_unit
@ -377,6 +417,9 @@ primary_expression
$$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true); $$ = parseContext.intermediate.addConstantUnion($1.b, $1.loc, true);
} }
| STRING_LITERAL {
$$ = parseContext.intermediate.addConstantUnion($1.string, $1.loc, true);
}
| INT32CONSTANT { | INT32CONSTANT {
parseContext.explicitInt32Check($1.loc, "32-bit signed literal"); parseContext.explicitInt32Check($1.loc, "32-bit signed literal");
$$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true); $$ = parseContext.intermediate.addConstantUnion($1.i, $1.loc, true);
@ -755,7 +798,7 @@ conditional_expression
parseContext.rValueErrorCheck($5.loc, ":", $6); parseContext.rValueErrorCheck($5.loc, ":", $6);
$$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc); $$ = parseContext.intermediate.addSelection($1, $4, $6, $2.loc);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(), $6->getCompleteString()); parseContext.binaryOpError($2.loc, ":", $4->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $6->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
$$ = $6; $$ = $6;
} }
} }
@ -770,9 +813,9 @@ assignment_expression
parseContext.specializationCheck($2.loc, $1->getType(), "="); parseContext.specializationCheck($2.loc, $1->getType(), "=");
parseContext.lValueErrorCheck($2.loc, "assign", $1); parseContext.lValueErrorCheck($2.loc, "assign", $1);
parseContext.rValueErrorCheck($2.loc, "assign", $3); parseContext.rValueErrorCheck($2.loc, "assign", $3);
$$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.loc); $$ = parseContext.addAssign($2.loc, $2.op, $1, $3);
if ($$ == 0) { if ($$ == 0) {
parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString()); parseContext.assignError($2.loc, "assign", $1->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $3->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
$$ = $1; $$ = $1;
} }
} }
@ -834,7 +877,7 @@ expression
parseContext.samplerConstructorLocationCheck($2.loc, ",", $3); parseContext.samplerConstructorLocationCheck($2.loc, ",", $3);
$$ = parseContext.intermediate.addComma($1, $3, $2.loc); $$ = parseContext.intermediate.addComma($1, $3, $2.loc);
if ($$ == 0) { if ($$ == 0) {
parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(), $3->getCompleteString()); parseContext.binaryOpError($2.loc, ",", $1->getCompleteString(parseContext.intermediate.getEnhancedMsgs()), $3->getCompleteString(parseContext.intermediate.getEnhancedMsgs()));
$$ = $3; $$ = $3;
} }
} }
@ -853,6 +896,20 @@ declaration
$$ = 0; $$ = 0;
// TODO: 4.0 functionality: subroutines: make the identifier a user type for this signature // 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 { | init_declarator_list SEMICOLON {
if ($1.intermNode && $1.intermNode->getAsAggregate()) if ($1.intermNode && $1.intermNode->getAsAggregate())
$1.intermNode->getAsAggregate()->setOperator(EOpSequence); $1.intermNode->getAsAggregate()->setOperator(EOpSequence);
@ -897,7 +954,7 @@ declaration
block_structure block_structure
: type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE { : type_qualifier IDENTIFIER LEFT_BRACE { parseContext.nestedBlockCheck($1.loc); } struct_declaration_list RIGHT_BRACE {
--parseContext.structNestingLevel; --parseContext.blockNestingLevel;
parseContext.blockName = $2.string; parseContext.blockName = $2.string;
parseContext.globalQualifierFixCheck($1.loc, $1.qualifier); parseContext.globalQualifierFixCheck($1.loc, $1.qualifier);
parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers); parseContext.checkNoShaderLayouts($1.loc, $1.shaderQualifiers);
@ -922,6 +979,25 @@ function_prototype
$$.function = $1; $$.function = $1;
$$.loc = $2.loc; $$.loc = $2.loc;
} }
| function_declarator RIGHT_PAREN attribute {
$$.function = $1;
$$.loc = $2.loc;
parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($2.loc, *$3);
}
| attribute function_declarator RIGHT_PAREN {
$$.function = $2;
$$.loc = $3.loc;
parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($3.loc, *$1);
}
| attribute function_declarator RIGHT_PAREN attribute {
$$.function = $2;
$$.loc = $3.loc;
parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
parseContext.handleFunctionAttributes($3.loc, *$1);
parseContext.handleFunctionAttributes($3.loc, *$4);
}
; ;
function_declarator function_declarator
@ -1325,6 +1401,25 @@ single_type_qualifier
| non_uniform_qualifier { | non_uniform_qualifier {
$$ = $1; $$ = $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();
}
; ;
@ -1415,42 +1510,81 @@ storage_qualifier
} }
| HITATTRNV { | HITATTRNV {
parseContext.globalCheck($1.loc, "hitAttributeNV"); parseContext.globalCheck($1.loc, "hitAttributeNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectMask | EShLangClosestHitMask
| EShLangAnyHitNVMask), "hitAttributeNV"); | EShLangAnyHitMask), "hitAttributeNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV");
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqHitAttrNV; $$.qualifier.storage = EvqHitAttr;
}
| 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 { | PAYLOADNV {
parseContext.globalCheck($1.loc, "rayPayloadNV"); parseContext.globalCheck($1.loc, "rayPayloadNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask | parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask | EShLangClosestHitMask |
EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV"); EShLangAnyHitMask | EShLangMissMask), "rayPayloadNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV");
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqPayloadNV; $$.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 { | PAYLOADINNV {
parseContext.globalCheck($1.loc, "rayPayloadInNV"); parseContext.globalCheck($1.loc, "rayPayloadInNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitNVMask | parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitMask |
EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV"); EShLangAnyHitMask | EShLangMissMask), "rayPayloadInNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV");
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqPayloadInNV; $$.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 { | CALLDATANV {
parseContext.globalCheck($1.loc, "callableDataNV"); parseContext.globalCheck($1.loc, "callableDataNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenMask |
EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV"); EShLangClosestHitMask | EShLangMissMask | EShLangCallableMask), "callableDataNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV");
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqCallableDataNV; $$.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 { | CALLDATAINNV {
parseContext.globalCheck($1.loc, "callableDataInNV"); parseContext.globalCheck($1.loc, "callableDataInNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV"); parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableMask), "callableDataInNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV"); parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV");
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqCallableDataInNV; $$.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 { | COHERENT {
$$.init($1.loc); $$.init($1.loc);
@ -1481,6 +1615,11 @@ storage_qualifier
parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate"); parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate");
$$.qualifier.nonprivate = true; $$.qualifier.nonprivate = true;
} }
| SHADERCALLCOHERENT {
$$.init($1.loc);
parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_ray_tracing, "shadercallcoherent");
$$.qualifier.shadercallcoherent = true;
}
| VOLATILE { | VOLATILE {
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.volatil = true; $$.qualifier.volatil = true;
@ -2350,7 +2489,15 @@ type_specifier_nonarray
} }
| ACCSTRUCTNV { | ACCSTRUCTNV {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtAccStructNV; $$.basicType = EbtAccStruct;
}
| ACCSTRUCTEXT {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtAccStruct;
}
| RAYQUERYEXT {
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtRayQuery;
} }
| ATOMIC_UINT { | ATOMIC_UINT {
parseContext.vulkanRemoved($1.loc, "atomic counter types"); parseContext.vulkanRemoved($1.loc, "atomic counter types");
@ -3143,6 +3290,116 @@ type_specifier_nonarray
$$.basicType = EbtSampler; $$.basicType = EbtSampler;
$$.sampler.setImage(EbtUint, Esd2D, true, false, true); $$.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 | SAMPLEREXTERNALOES { // GL_OES_EGL_image_external
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler; $$.basicType = EbtSampler;
@ -3223,6 +3480,10 @@ type_specifier_nonarray
$$.basicType = EbtUint; $$.basicType = EbtUint;
$$.coopmat = true; $$.coopmat = true;
} }
| spirv_type_specifier {
parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_spirv_intrinsics, "SPIR-V type specifier");
$$ = $1;
}
| struct_specifier { | struct_specifier {
$$ = $1; $$ = $1;
@ -3391,6 +3652,12 @@ initializer
parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature); parseContext.profileRequires($1.loc, ~EEsProfile, 420, E_GL_ARB_shading_language_420pack, initFeature);
$$ = $2; $$ = $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);
}
; ;
@ -3523,6 +3790,7 @@ selection_statement
} }
| attribute selection_statement_nonattributed { | attribute selection_statement_nonattributed {
parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
parseContext.handleSelectionAttributes(*$1, $2); parseContext.handleSelectionAttributes(*$1, $2);
$$ = $2; $$ = $2;
} }
@ -3570,6 +3838,7 @@ switch_statement
} }
| attribute switch_statement_nonattributed { | attribute switch_statement_nonattributed {
parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
parseContext.handleSwitchAttributes(*$1, $2); parseContext.handleSwitchAttributes(*$1, $2);
$$ = $2; $$ = $2;
} }
@ -3634,6 +3903,7 @@ iteration_statement
} }
| attribute iteration_statement_nonattributed { | attribute iteration_statement_nonattributed {
parseContext.requireExtensions($2->getLoc(), 1, &E_GL_EXT_control_flow_attributes, "attribute");
parseContext.handleLoopAttributes(*$1, $2); parseContext.handleLoopAttributes(*$1, $2);
$$ = $2; $$ = $2;
} }
@ -3656,6 +3926,7 @@ iteration_statement_nonattributed
--parseContext.controlFlowNestingLevel; --parseContext.controlFlowNestingLevel;
} }
| DO { | DO {
parseContext.symbolTable.push();
++parseContext.loopNestingLevel; ++parseContext.loopNestingLevel;
++parseContext.statementNestingLevel; ++parseContext.statementNestingLevel;
++parseContext.controlFlowNestingLevel; ++parseContext.controlFlowNestingLevel;
@ -3667,6 +3938,7 @@ iteration_statement_nonattributed
parseContext.boolCheck($8.loc, $6); parseContext.boolCheck($8.loc, $6);
$$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc); $$ = parseContext.intermediate.addLoop($3, $6, 0, false, $4.loc);
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
--parseContext.loopNestingLevel; --parseContext.loopNestingLevel;
--parseContext.statementNestingLevel; --parseContext.statementNestingLevel;
--parseContext.controlFlowNestingLevel; --parseContext.controlFlowNestingLevel;
@ -3745,6 +4017,20 @@ jump_statement
parseContext.requireStage($1.loc, EShLangFragment, "discard"); parseContext.requireStage($1.loc, EShLangFragment, "discard");
$$ = parseContext.intermediate.addBranch(EOpKill, $1.loc); $$ = 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. // Grammar Note: No 'goto'. Gotos are not supported.
@ -3782,6 +4068,14 @@ function_definition
: function_prototype { : function_prototype {
$1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */); $1.function = parseContext.handleFunctionDeclarator($1.loc, *$1.function, false /* not prototype */);
$1.intermNode = parseContext.handleFunctionDefinition($1.loc, *$1.function); $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 { compound_statement_no_new_scope {
// May be best done as post process phase on intermediate code // May be best done as post process phase on intermediate code
@ -3797,6 +4091,17 @@ function_definition
$$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize); $$->getAsAggregate()->setOptimize(parseContext.contextPragma.optimize);
$$->getAsAggregate()->setDebug(parseContext.contextPragma.debug); $$->getAsAggregate()->setDebug(parseContext.contextPragma.debug);
$$->getAsAggregate()->setPragmaTable(parseContext.contextPragma.pragmaTable); $$->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;
}
} }
; ;
@ -3804,7 +4109,6 @@ function_definition
attribute attribute
: LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET { : LEFT_BRACKET LEFT_BRACKET attribute_list RIGHT_BRACKET RIGHT_BRACKET {
$$ = $3; $$ = $3;
parseContext.requireExtensions($1.loc, 1, &E_GL_EXT_control_flow_attributes, "attribute");
} }
attribute_list attribute_list
@ -3824,4 +4128,270 @@ single_attribute
} }
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
: constant_expression {
if ($1->getBasicType() != EbtFloat &&
$1->getBasicType() != EbtInt &&
$1->getBasicType() != EbtUint &&
$1->getBasicType() != EbtBool)
parseContext.error($1->getLoc(), "this type not allowed", $1->getType().getBasicString(), "");
$$ = parseContext.intermediate.makeAggregate($1);
}
| spirv_decorate_id_parameter_list COMMA constant_expression {
if ($3->getBasicType() != EbtFloat &&
$3->getBasicType() != EbtInt &&
$3->getBasicType() != EbtUint &&
$3->getBasicType() != EbtBool)
parseContext.error($3->getLoc(), "this type not allowed", $3->getType().getBasicString(), "");
$$ = parseContext.intermediate.growAggregate($1, $3);
}
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());
}
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);
}
%% %%

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,9 @@
/* A Bison parser, made by GNU Bison 3.0.4. */ /* A Bison parser, made by GNU Bison 3.7.4. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -30,6 +31,10 @@
This special exception was added by the Free Software Foundation in This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */ 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 #ifndef YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
# define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED # define YY_YY_MACHINEINDEPENDENT_GLSLANG_TAB_CPP_H_INCLUDED
/* Debug traces. */ /* Debug traces. */
@ -40,428 +45,476 @@
extern int yydebug; extern int yydebug;
#endif #endif
/* Token type. */ /* Token kinds. */
#ifndef YYTOKENTYPE #ifndef YYTOKENTYPE
# define YYTOKENTYPE # define YYTOKENTYPE
enum yytokentype enum yytokentype
{ {
CONST = 258, YYEMPTY = -2,
BOOL = 259, YYEOF = 0, /* "end of file" */
INT = 260, YYerror = 256, /* error */
UINT = 261, YYUNDEF = 257, /* "invalid token" */
FLOAT = 262, CONST = 258, /* CONST */
BVEC2 = 263, BOOL = 259, /* BOOL */
BVEC3 = 264, INT = 260, /* INT */
BVEC4 = 265, UINT = 261, /* UINT */
IVEC2 = 266, FLOAT = 262, /* FLOAT */
IVEC3 = 267, BVEC2 = 263, /* BVEC2 */
IVEC4 = 268, BVEC3 = 264, /* BVEC3 */
UVEC2 = 269, BVEC4 = 265, /* BVEC4 */
UVEC3 = 270, IVEC2 = 266, /* IVEC2 */
UVEC4 = 271, IVEC3 = 267, /* IVEC3 */
VEC2 = 272, IVEC4 = 268, /* IVEC4 */
VEC3 = 273, UVEC2 = 269, /* UVEC2 */
VEC4 = 274, UVEC3 = 270, /* UVEC3 */
MAT2 = 275, UVEC4 = 271, /* UVEC4 */
MAT3 = 276, VEC2 = 272, /* VEC2 */
MAT4 = 277, VEC3 = 273, /* VEC3 */
MAT2X2 = 278, VEC4 = 274, /* VEC4 */
MAT2X3 = 279, MAT2 = 275, /* MAT2 */
MAT2X4 = 280, MAT3 = 276, /* MAT3 */
MAT3X2 = 281, MAT4 = 277, /* MAT4 */
MAT3X3 = 282, MAT2X2 = 278, /* MAT2X2 */
MAT3X4 = 283, MAT2X3 = 279, /* MAT2X3 */
MAT4X2 = 284, MAT2X4 = 280, /* MAT2X4 */
MAT4X3 = 285, MAT3X2 = 281, /* MAT3X2 */
MAT4X4 = 286, MAT3X3 = 282, /* MAT3X3 */
SAMPLER2D = 287, MAT3X4 = 283, /* MAT3X4 */
SAMPLER3D = 288, MAT4X2 = 284, /* MAT4X2 */
SAMPLERCUBE = 289, MAT4X3 = 285, /* MAT4X3 */
SAMPLER2DSHADOW = 290, MAT4X4 = 286, /* MAT4X4 */
SAMPLERCUBESHADOW = 291, SAMPLER2D = 287, /* SAMPLER2D */
SAMPLER2DARRAY = 292, SAMPLER3D = 288, /* SAMPLER3D */
SAMPLER2DARRAYSHADOW = 293, SAMPLERCUBE = 289, /* SAMPLERCUBE */
ISAMPLER2D = 294, SAMPLER2DSHADOW = 290, /* SAMPLER2DSHADOW */
ISAMPLER3D = 295, SAMPLERCUBESHADOW = 291, /* SAMPLERCUBESHADOW */
ISAMPLERCUBE = 296, SAMPLER2DARRAY = 292, /* SAMPLER2DARRAY */
ISAMPLER2DARRAY = 297, SAMPLER2DARRAYSHADOW = 293, /* SAMPLER2DARRAYSHADOW */
USAMPLER2D = 298, ISAMPLER2D = 294, /* ISAMPLER2D */
USAMPLER3D = 299, ISAMPLER3D = 295, /* ISAMPLER3D */
USAMPLERCUBE = 300, ISAMPLERCUBE = 296, /* ISAMPLERCUBE */
USAMPLER2DARRAY = 301, ISAMPLER2DARRAY = 297, /* ISAMPLER2DARRAY */
SAMPLER = 302, USAMPLER2D = 298, /* USAMPLER2D */
SAMPLERSHADOW = 303, USAMPLER3D = 299, /* USAMPLER3D */
TEXTURE2D = 304, USAMPLERCUBE = 300, /* USAMPLERCUBE */
TEXTURE3D = 305, USAMPLER2DARRAY = 301, /* USAMPLER2DARRAY */
TEXTURECUBE = 306, SAMPLER = 302, /* SAMPLER */
TEXTURE2DARRAY = 307, SAMPLERSHADOW = 303, /* SAMPLERSHADOW */
ITEXTURE2D = 308, TEXTURE2D = 304, /* TEXTURE2D */
ITEXTURE3D = 309, TEXTURE3D = 305, /* TEXTURE3D */
ITEXTURECUBE = 310, TEXTURECUBE = 306, /* TEXTURECUBE */
ITEXTURE2DARRAY = 311, TEXTURE2DARRAY = 307, /* TEXTURE2DARRAY */
UTEXTURE2D = 312, ITEXTURE2D = 308, /* ITEXTURE2D */
UTEXTURE3D = 313, ITEXTURE3D = 309, /* ITEXTURE3D */
UTEXTURECUBE = 314, ITEXTURECUBE = 310, /* ITEXTURECUBE */
UTEXTURE2DARRAY = 315, ITEXTURE2DARRAY = 311, /* ITEXTURE2DARRAY */
ATTRIBUTE = 316, UTEXTURE2D = 312, /* UTEXTURE2D */
VARYING = 317, UTEXTURE3D = 313, /* UTEXTURE3D */
FLOAT16_T = 318, UTEXTURECUBE = 314, /* UTEXTURECUBE */
FLOAT32_T = 319, UTEXTURE2DARRAY = 315, /* UTEXTURE2DARRAY */
DOUBLE = 320, ATTRIBUTE = 316, /* ATTRIBUTE */
FLOAT64_T = 321, VARYING = 317, /* VARYING */
INT64_T = 322, FLOAT16_T = 318, /* FLOAT16_T */
UINT64_T = 323, FLOAT32_T = 319, /* FLOAT32_T */
INT32_T = 324, DOUBLE = 320, /* DOUBLE */
UINT32_T = 325, FLOAT64_T = 321, /* FLOAT64_T */
INT16_T = 326, INT64_T = 322, /* INT64_T */
UINT16_T = 327, UINT64_T = 323, /* UINT64_T */
INT8_T = 328, INT32_T = 324, /* INT32_T */
UINT8_T = 329, UINT32_T = 325, /* UINT32_T */
I64VEC2 = 330, INT16_T = 326, /* INT16_T */
I64VEC3 = 331, UINT16_T = 327, /* UINT16_T */
I64VEC4 = 332, INT8_T = 328, /* INT8_T */
U64VEC2 = 333, UINT8_T = 329, /* UINT8_T */
U64VEC3 = 334, I64VEC2 = 330, /* I64VEC2 */
U64VEC4 = 335, I64VEC3 = 331, /* I64VEC3 */
I32VEC2 = 336, I64VEC4 = 332, /* I64VEC4 */
I32VEC3 = 337, U64VEC2 = 333, /* U64VEC2 */
I32VEC4 = 338, U64VEC3 = 334, /* U64VEC3 */
U32VEC2 = 339, U64VEC4 = 335, /* U64VEC4 */
U32VEC3 = 340, I32VEC2 = 336, /* I32VEC2 */
U32VEC4 = 341, I32VEC3 = 337, /* I32VEC3 */
I16VEC2 = 342, I32VEC4 = 338, /* I32VEC4 */
I16VEC3 = 343, U32VEC2 = 339, /* U32VEC2 */
I16VEC4 = 344, U32VEC3 = 340, /* U32VEC3 */
U16VEC2 = 345, U32VEC4 = 341, /* U32VEC4 */
U16VEC3 = 346, I16VEC2 = 342, /* I16VEC2 */
U16VEC4 = 347, I16VEC3 = 343, /* I16VEC3 */
I8VEC2 = 348, I16VEC4 = 344, /* I16VEC4 */
I8VEC3 = 349, U16VEC2 = 345, /* U16VEC2 */
I8VEC4 = 350, U16VEC3 = 346, /* U16VEC3 */
U8VEC2 = 351, U16VEC4 = 347, /* U16VEC4 */
U8VEC3 = 352, I8VEC2 = 348, /* I8VEC2 */
U8VEC4 = 353, I8VEC3 = 349, /* I8VEC3 */
DVEC2 = 354, I8VEC4 = 350, /* I8VEC4 */
DVEC3 = 355, U8VEC2 = 351, /* U8VEC2 */
DVEC4 = 356, U8VEC3 = 352, /* U8VEC3 */
DMAT2 = 357, U8VEC4 = 353, /* U8VEC4 */
DMAT3 = 358, DVEC2 = 354, /* DVEC2 */
DMAT4 = 359, DVEC3 = 355, /* DVEC3 */
F16VEC2 = 360, DVEC4 = 356, /* DVEC4 */
F16VEC3 = 361, DMAT2 = 357, /* DMAT2 */
F16VEC4 = 362, DMAT3 = 358, /* DMAT3 */
F16MAT2 = 363, DMAT4 = 359, /* DMAT4 */
F16MAT3 = 364, F16VEC2 = 360, /* F16VEC2 */
F16MAT4 = 365, F16VEC3 = 361, /* F16VEC3 */
F32VEC2 = 366, F16VEC4 = 362, /* F16VEC4 */
F32VEC3 = 367, F16MAT2 = 363, /* F16MAT2 */
F32VEC4 = 368, F16MAT3 = 364, /* F16MAT3 */
F32MAT2 = 369, F16MAT4 = 365, /* F16MAT4 */
F32MAT3 = 370, F32VEC2 = 366, /* F32VEC2 */
F32MAT4 = 371, F32VEC3 = 367, /* F32VEC3 */
F64VEC2 = 372, F32VEC4 = 368, /* F32VEC4 */
F64VEC3 = 373, F32MAT2 = 369, /* F32MAT2 */
F64VEC4 = 374, F32MAT3 = 370, /* F32MAT3 */
F64MAT2 = 375, F32MAT4 = 371, /* F32MAT4 */
F64MAT3 = 376, F64VEC2 = 372, /* F64VEC2 */
F64MAT4 = 377, F64VEC3 = 373, /* F64VEC3 */
DMAT2X2 = 378, F64VEC4 = 374, /* F64VEC4 */
DMAT2X3 = 379, F64MAT2 = 375, /* F64MAT2 */
DMAT2X4 = 380, F64MAT3 = 376, /* F64MAT3 */
DMAT3X2 = 381, F64MAT4 = 377, /* F64MAT4 */
DMAT3X3 = 382, DMAT2X2 = 378, /* DMAT2X2 */
DMAT3X4 = 383, DMAT2X3 = 379, /* DMAT2X3 */
DMAT4X2 = 384, DMAT2X4 = 380, /* DMAT2X4 */
DMAT4X3 = 385, DMAT3X2 = 381, /* DMAT3X2 */
DMAT4X4 = 386, DMAT3X3 = 382, /* DMAT3X3 */
F16MAT2X2 = 387, DMAT3X4 = 383, /* DMAT3X4 */
F16MAT2X3 = 388, DMAT4X2 = 384, /* DMAT4X2 */
F16MAT2X4 = 389, DMAT4X3 = 385, /* DMAT4X3 */
F16MAT3X2 = 390, DMAT4X4 = 386, /* DMAT4X4 */
F16MAT3X3 = 391, F16MAT2X2 = 387, /* F16MAT2X2 */
F16MAT3X4 = 392, F16MAT2X3 = 388, /* F16MAT2X3 */
F16MAT4X2 = 393, F16MAT2X4 = 389, /* F16MAT2X4 */
F16MAT4X3 = 394, F16MAT3X2 = 390, /* F16MAT3X2 */
F16MAT4X4 = 395, F16MAT3X3 = 391, /* F16MAT3X3 */
F32MAT2X2 = 396, F16MAT3X4 = 392, /* F16MAT3X4 */
F32MAT2X3 = 397, F16MAT4X2 = 393, /* F16MAT4X2 */
F32MAT2X4 = 398, F16MAT4X3 = 394, /* F16MAT4X3 */
F32MAT3X2 = 399, F16MAT4X4 = 395, /* F16MAT4X4 */
F32MAT3X3 = 400, F32MAT2X2 = 396, /* F32MAT2X2 */
F32MAT3X4 = 401, F32MAT2X3 = 397, /* F32MAT2X3 */
F32MAT4X2 = 402, F32MAT2X4 = 398, /* F32MAT2X4 */
F32MAT4X3 = 403, F32MAT3X2 = 399, /* F32MAT3X2 */
F32MAT4X4 = 404, F32MAT3X3 = 400, /* F32MAT3X3 */
F64MAT2X2 = 405, F32MAT3X4 = 401, /* F32MAT3X4 */
F64MAT2X3 = 406, F32MAT4X2 = 402, /* F32MAT4X2 */
F64MAT2X4 = 407, F32MAT4X3 = 403, /* F32MAT4X3 */
F64MAT3X2 = 408, F32MAT4X4 = 404, /* F32MAT4X4 */
F64MAT3X3 = 409, F64MAT2X2 = 405, /* F64MAT2X2 */
F64MAT3X4 = 410, F64MAT2X3 = 406, /* F64MAT2X3 */
F64MAT4X2 = 411, F64MAT2X4 = 407, /* F64MAT2X4 */
F64MAT4X3 = 412, F64MAT3X2 = 408, /* F64MAT3X2 */
F64MAT4X4 = 413, F64MAT3X3 = 409, /* F64MAT3X3 */
ATOMIC_UINT = 414, F64MAT3X4 = 410, /* F64MAT3X4 */
ACCSTRUCTNV = 415, F64MAT4X2 = 411, /* F64MAT4X2 */
FCOOPMATNV = 416, F64MAT4X3 = 412, /* F64MAT4X3 */
ICOOPMATNV = 417, F64MAT4X4 = 413, /* F64MAT4X4 */
UCOOPMATNV = 418, ATOMIC_UINT = 414, /* ATOMIC_UINT */
SAMPLERCUBEARRAY = 419, ACCSTRUCTNV = 415, /* ACCSTRUCTNV */
SAMPLERCUBEARRAYSHADOW = 420, ACCSTRUCTEXT = 416, /* ACCSTRUCTEXT */
ISAMPLERCUBEARRAY = 421, RAYQUERYEXT = 417, /* RAYQUERYEXT */
USAMPLERCUBEARRAY = 422, FCOOPMATNV = 418, /* FCOOPMATNV */
SAMPLER1D = 423, ICOOPMATNV = 419, /* ICOOPMATNV */
SAMPLER1DARRAY = 424, UCOOPMATNV = 420, /* UCOOPMATNV */
SAMPLER1DARRAYSHADOW = 425, SAMPLERCUBEARRAY = 421, /* SAMPLERCUBEARRAY */
ISAMPLER1D = 426, SAMPLERCUBEARRAYSHADOW = 422, /* SAMPLERCUBEARRAYSHADOW */
SAMPLER1DSHADOW = 427, ISAMPLERCUBEARRAY = 423, /* ISAMPLERCUBEARRAY */
SAMPLER2DRECT = 428, USAMPLERCUBEARRAY = 424, /* USAMPLERCUBEARRAY */
SAMPLER2DRECTSHADOW = 429, SAMPLER1D = 425, /* SAMPLER1D */
ISAMPLER2DRECT = 430, SAMPLER1DARRAY = 426, /* SAMPLER1DARRAY */
USAMPLER2DRECT = 431, SAMPLER1DARRAYSHADOW = 427, /* SAMPLER1DARRAYSHADOW */
SAMPLERBUFFER = 432, ISAMPLER1D = 428, /* ISAMPLER1D */
ISAMPLERBUFFER = 433, SAMPLER1DSHADOW = 429, /* SAMPLER1DSHADOW */
USAMPLERBUFFER = 434, SAMPLER2DRECT = 430, /* SAMPLER2DRECT */
SAMPLER2DMS = 435, SAMPLER2DRECTSHADOW = 431, /* SAMPLER2DRECTSHADOW */
ISAMPLER2DMS = 436, ISAMPLER2DRECT = 432, /* ISAMPLER2DRECT */
USAMPLER2DMS = 437, USAMPLER2DRECT = 433, /* USAMPLER2DRECT */
SAMPLER2DMSARRAY = 438, SAMPLERBUFFER = 434, /* SAMPLERBUFFER */
ISAMPLER2DMSARRAY = 439, ISAMPLERBUFFER = 435, /* ISAMPLERBUFFER */
USAMPLER2DMSARRAY = 440, USAMPLERBUFFER = 436, /* USAMPLERBUFFER */
SAMPLEREXTERNALOES = 441, SAMPLER2DMS = 437, /* SAMPLER2DMS */
SAMPLEREXTERNAL2DY2YEXT = 442, ISAMPLER2DMS = 438, /* ISAMPLER2DMS */
ISAMPLER1DARRAY = 443, USAMPLER2DMS = 439, /* USAMPLER2DMS */
USAMPLER1D = 444, SAMPLER2DMSARRAY = 440, /* SAMPLER2DMSARRAY */
USAMPLER1DARRAY = 445, ISAMPLER2DMSARRAY = 441, /* ISAMPLER2DMSARRAY */
F16SAMPLER1D = 446, USAMPLER2DMSARRAY = 442, /* USAMPLER2DMSARRAY */
F16SAMPLER2D = 447, SAMPLEREXTERNALOES = 443, /* SAMPLEREXTERNALOES */
F16SAMPLER3D = 448, SAMPLEREXTERNAL2DY2YEXT = 444, /* SAMPLEREXTERNAL2DY2YEXT */
F16SAMPLER2DRECT = 449, ISAMPLER1DARRAY = 445, /* ISAMPLER1DARRAY */
F16SAMPLERCUBE = 450, USAMPLER1D = 446, /* USAMPLER1D */
F16SAMPLER1DARRAY = 451, USAMPLER1DARRAY = 447, /* USAMPLER1DARRAY */
F16SAMPLER2DARRAY = 452, F16SAMPLER1D = 448, /* F16SAMPLER1D */
F16SAMPLERCUBEARRAY = 453, F16SAMPLER2D = 449, /* F16SAMPLER2D */
F16SAMPLERBUFFER = 454, F16SAMPLER3D = 450, /* F16SAMPLER3D */
F16SAMPLER2DMS = 455, F16SAMPLER2DRECT = 451, /* F16SAMPLER2DRECT */
F16SAMPLER2DMSARRAY = 456, F16SAMPLERCUBE = 452, /* F16SAMPLERCUBE */
F16SAMPLER1DSHADOW = 457, F16SAMPLER1DARRAY = 453, /* F16SAMPLER1DARRAY */
F16SAMPLER2DSHADOW = 458, F16SAMPLER2DARRAY = 454, /* F16SAMPLER2DARRAY */
F16SAMPLER1DARRAYSHADOW = 459, F16SAMPLERCUBEARRAY = 455, /* F16SAMPLERCUBEARRAY */
F16SAMPLER2DARRAYSHADOW = 460, F16SAMPLERBUFFER = 456, /* F16SAMPLERBUFFER */
F16SAMPLER2DRECTSHADOW = 461, F16SAMPLER2DMS = 457, /* F16SAMPLER2DMS */
F16SAMPLERCUBESHADOW = 462, F16SAMPLER2DMSARRAY = 458, /* F16SAMPLER2DMSARRAY */
F16SAMPLERCUBEARRAYSHADOW = 463, F16SAMPLER1DSHADOW = 459, /* F16SAMPLER1DSHADOW */
IMAGE1D = 464, F16SAMPLER2DSHADOW = 460, /* F16SAMPLER2DSHADOW */
IIMAGE1D = 465, F16SAMPLER1DARRAYSHADOW = 461, /* F16SAMPLER1DARRAYSHADOW */
UIMAGE1D = 466, F16SAMPLER2DARRAYSHADOW = 462, /* F16SAMPLER2DARRAYSHADOW */
IMAGE2D = 467, F16SAMPLER2DRECTSHADOW = 463, /* F16SAMPLER2DRECTSHADOW */
IIMAGE2D = 468, F16SAMPLERCUBESHADOW = 464, /* F16SAMPLERCUBESHADOW */
UIMAGE2D = 469, F16SAMPLERCUBEARRAYSHADOW = 465, /* F16SAMPLERCUBEARRAYSHADOW */
IMAGE3D = 470, IMAGE1D = 466, /* IMAGE1D */
IIMAGE3D = 471, IIMAGE1D = 467, /* IIMAGE1D */
UIMAGE3D = 472, UIMAGE1D = 468, /* UIMAGE1D */
IMAGE2DRECT = 473, IMAGE2D = 469, /* IMAGE2D */
IIMAGE2DRECT = 474, IIMAGE2D = 470, /* IIMAGE2D */
UIMAGE2DRECT = 475, UIMAGE2D = 471, /* UIMAGE2D */
IMAGECUBE = 476, IMAGE3D = 472, /* IMAGE3D */
IIMAGECUBE = 477, IIMAGE3D = 473, /* IIMAGE3D */
UIMAGECUBE = 478, UIMAGE3D = 474, /* UIMAGE3D */
IMAGEBUFFER = 479, IMAGE2DRECT = 475, /* IMAGE2DRECT */
IIMAGEBUFFER = 480, IIMAGE2DRECT = 476, /* IIMAGE2DRECT */
UIMAGEBUFFER = 481, UIMAGE2DRECT = 477, /* UIMAGE2DRECT */
IMAGE1DARRAY = 482, IMAGECUBE = 478, /* IMAGECUBE */
IIMAGE1DARRAY = 483, IIMAGECUBE = 479, /* IIMAGECUBE */
UIMAGE1DARRAY = 484, UIMAGECUBE = 480, /* UIMAGECUBE */
IMAGE2DARRAY = 485, IMAGEBUFFER = 481, /* IMAGEBUFFER */
IIMAGE2DARRAY = 486, IIMAGEBUFFER = 482, /* IIMAGEBUFFER */
UIMAGE2DARRAY = 487, UIMAGEBUFFER = 483, /* UIMAGEBUFFER */
IMAGECUBEARRAY = 488, IMAGE1DARRAY = 484, /* IMAGE1DARRAY */
IIMAGECUBEARRAY = 489, IIMAGE1DARRAY = 485, /* IIMAGE1DARRAY */
UIMAGECUBEARRAY = 490, UIMAGE1DARRAY = 486, /* UIMAGE1DARRAY */
IMAGE2DMS = 491, IMAGE2DARRAY = 487, /* IMAGE2DARRAY */
IIMAGE2DMS = 492, IIMAGE2DARRAY = 488, /* IIMAGE2DARRAY */
UIMAGE2DMS = 493, UIMAGE2DARRAY = 489, /* UIMAGE2DARRAY */
IMAGE2DMSARRAY = 494, IMAGECUBEARRAY = 490, /* IMAGECUBEARRAY */
IIMAGE2DMSARRAY = 495, IIMAGECUBEARRAY = 491, /* IIMAGECUBEARRAY */
UIMAGE2DMSARRAY = 496, UIMAGECUBEARRAY = 492, /* UIMAGECUBEARRAY */
F16IMAGE1D = 497, IMAGE2DMS = 493, /* IMAGE2DMS */
F16IMAGE2D = 498, IIMAGE2DMS = 494, /* IIMAGE2DMS */
F16IMAGE3D = 499, UIMAGE2DMS = 495, /* UIMAGE2DMS */
F16IMAGE2DRECT = 500, IMAGE2DMSARRAY = 496, /* IMAGE2DMSARRAY */
F16IMAGECUBE = 501, IIMAGE2DMSARRAY = 497, /* IIMAGE2DMSARRAY */
F16IMAGE1DARRAY = 502, UIMAGE2DMSARRAY = 498, /* UIMAGE2DMSARRAY */
F16IMAGE2DARRAY = 503, F16IMAGE1D = 499, /* F16IMAGE1D */
F16IMAGECUBEARRAY = 504, F16IMAGE2D = 500, /* F16IMAGE2D */
F16IMAGEBUFFER = 505, F16IMAGE3D = 501, /* F16IMAGE3D */
F16IMAGE2DMS = 506, F16IMAGE2DRECT = 502, /* F16IMAGE2DRECT */
F16IMAGE2DMSARRAY = 507, F16IMAGECUBE = 503, /* F16IMAGECUBE */
TEXTURECUBEARRAY = 508, F16IMAGE1DARRAY = 504, /* F16IMAGE1DARRAY */
ITEXTURECUBEARRAY = 509, F16IMAGE2DARRAY = 505, /* F16IMAGE2DARRAY */
UTEXTURECUBEARRAY = 510, F16IMAGECUBEARRAY = 506, /* F16IMAGECUBEARRAY */
TEXTURE1D = 511, F16IMAGEBUFFER = 507, /* F16IMAGEBUFFER */
ITEXTURE1D = 512, F16IMAGE2DMS = 508, /* F16IMAGE2DMS */
UTEXTURE1D = 513, F16IMAGE2DMSARRAY = 509, /* F16IMAGE2DMSARRAY */
TEXTURE1DARRAY = 514, I64IMAGE1D = 510, /* I64IMAGE1D */
ITEXTURE1DARRAY = 515, U64IMAGE1D = 511, /* U64IMAGE1D */
UTEXTURE1DARRAY = 516, I64IMAGE2D = 512, /* I64IMAGE2D */
TEXTURE2DRECT = 517, U64IMAGE2D = 513, /* U64IMAGE2D */
ITEXTURE2DRECT = 518, I64IMAGE3D = 514, /* I64IMAGE3D */
UTEXTURE2DRECT = 519, U64IMAGE3D = 515, /* U64IMAGE3D */
TEXTUREBUFFER = 520, I64IMAGE2DRECT = 516, /* I64IMAGE2DRECT */
ITEXTUREBUFFER = 521, U64IMAGE2DRECT = 517, /* U64IMAGE2DRECT */
UTEXTUREBUFFER = 522, I64IMAGECUBE = 518, /* I64IMAGECUBE */
TEXTURE2DMS = 523, U64IMAGECUBE = 519, /* U64IMAGECUBE */
ITEXTURE2DMS = 524, I64IMAGEBUFFER = 520, /* I64IMAGEBUFFER */
UTEXTURE2DMS = 525, U64IMAGEBUFFER = 521, /* U64IMAGEBUFFER */
TEXTURE2DMSARRAY = 526, I64IMAGE1DARRAY = 522, /* I64IMAGE1DARRAY */
ITEXTURE2DMSARRAY = 527, U64IMAGE1DARRAY = 523, /* U64IMAGE1DARRAY */
UTEXTURE2DMSARRAY = 528, I64IMAGE2DARRAY = 524, /* I64IMAGE2DARRAY */
F16TEXTURE1D = 529, U64IMAGE2DARRAY = 525, /* U64IMAGE2DARRAY */
F16TEXTURE2D = 530, I64IMAGECUBEARRAY = 526, /* I64IMAGECUBEARRAY */
F16TEXTURE3D = 531, U64IMAGECUBEARRAY = 527, /* U64IMAGECUBEARRAY */
F16TEXTURE2DRECT = 532, I64IMAGE2DMS = 528, /* I64IMAGE2DMS */
F16TEXTURECUBE = 533, U64IMAGE2DMS = 529, /* U64IMAGE2DMS */
F16TEXTURE1DARRAY = 534, I64IMAGE2DMSARRAY = 530, /* I64IMAGE2DMSARRAY */
F16TEXTURE2DARRAY = 535, U64IMAGE2DMSARRAY = 531, /* U64IMAGE2DMSARRAY */
F16TEXTURECUBEARRAY = 536, TEXTURECUBEARRAY = 532, /* TEXTURECUBEARRAY */
F16TEXTUREBUFFER = 537, ITEXTURECUBEARRAY = 533, /* ITEXTURECUBEARRAY */
F16TEXTURE2DMS = 538, UTEXTURECUBEARRAY = 534, /* UTEXTURECUBEARRAY */
F16TEXTURE2DMSARRAY = 539, TEXTURE1D = 535, /* TEXTURE1D */
SUBPASSINPUT = 540, ITEXTURE1D = 536, /* ITEXTURE1D */
SUBPASSINPUTMS = 541, UTEXTURE1D = 537, /* UTEXTURE1D */
ISUBPASSINPUT = 542, TEXTURE1DARRAY = 538, /* TEXTURE1DARRAY */
ISUBPASSINPUTMS = 543, ITEXTURE1DARRAY = 539, /* ITEXTURE1DARRAY */
USUBPASSINPUT = 544, UTEXTURE1DARRAY = 540, /* UTEXTURE1DARRAY */
USUBPASSINPUTMS = 545, TEXTURE2DRECT = 541, /* TEXTURE2DRECT */
F16SUBPASSINPUT = 546, ITEXTURE2DRECT = 542, /* ITEXTURE2DRECT */
F16SUBPASSINPUTMS = 547, UTEXTURE2DRECT = 543, /* UTEXTURE2DRECT */
LEFT_OP = 548, TEXTUREBUFFER = 544, /* TEXTUREBUFFER */
RIGHT_OP = 549, ITEXTUREBUFFER = 545, /* ITEXTUREBUFFER */
INC_OP = 550, UTEXTUREBUFFER = 546, /* UTEXTUREBUFFER */
DEC_OP = 551, TEXTURE2DMS = 547, /* TEXTURE2DMS */
LE_OP = 552, ITEXTURE2DMS = 548, /* ITEXTURE2DMS */
GE_OP = 553, UTEXTURE2DMS = 549, /* UTEXTURE2DMS */
EQ_OP = 554, TEXTURE2DMSARRAY = 550, /* TEXTURE2DMSARRAY */
NE_OP = 555, ITEXTURE2DMSARRAY = 551, /* ITEXTURE2DMSARRAY */
AND_OP = 556, UTEXTURE2DMSARRAY = 552, /* UTEXTURE2DMSARRAY */
OR_OP = 557, F16TEXTURE1D = 553, /* F16TEXTURE1D */
XOR_OP = 558, F16TEXTURE2D = 554, /* F16TEXTURE2D */
MUL_ASSIGN = 559, F16TEXTURE3D = 555, /* F16TEXTURE3D */
DIV_ASSIGN = 560, F16TEXTURE2DRECT = 556, /* F16TEXTURE2DRECT */
ADD_ASSIGN = 561, F16TEXTURECUBE = 557, /* F16TEXTURECUBE */
MOD_ASSIGN = 562, F16TEXTURE1DARRAY = 558, /* F16TEXTURE1DARRAY */
LEFT_ASSIGN = 563, F16TEXTURE2DARRAY = 559, /* F16TEXTURE2DARRAY */
RIGHT_ASSIGN = 564, F16TEXTURECUBEARRAY = 560, /* F16TEXTURECUBEARRAY */
AND_ASSIGN = 565, F16TEXTUREBUFFER = 561, /* F16TEXTUREBUFFER */
XOR_ASSIGN = 566, F16TEXTURE2DMS = 562, /* F16TEXTURE2DMS */
OR_ASSIGN = 567, F16TEXTURE2DMSARRAY = 563, /* F16TEXTURE2DMSARRAY */
SUB_ASSIGN = 568, SUBPASSINPUT = 564, /* SUBPASSINPUT */
LEFT_PAREN = 569, SUBPASSINPUTMS = 565, /* SUBPASSINPUTMS */
RIGHT_PAREN = 570, ISUBPASSINPUT = 566, /* ISUBPASSINPUT */
LEFT_BRACKET = 571, ISUBPASSINPUTMS = 567, /* ISUBPASSINPUTMS */
RIGHT_BRACKET = 572, USUBPASSINPUT = 568, /* USUBPASSINPUT */
LEFT_BRACE = 573, USUBPASSINPUTMS = 569, /* USUBPASSINPUTMS */
RIGHT_BRACE = 574, F16SUBPASSINPUT = 570, /* F16SUBPASSINPUT */
DOT = 575, F16SUBPASSINPUTMS = 571, /* F16SUBPASSINPUTMS */
COMMA = 576, SPIRV_INSTRUCTION = 572, /* SPIRV_INSTRUCTION */
COLON = 577, SPIRV_EXECUTION_MODE = 573, /* SPIRV_EXECUTION_MODE */
EQUAL = 578, SPIRV_EXECUTION_MODE_ID = 574, /* SPIRV_EXECUTION_MODE_ID */
SEMICOLON = 579, SPIRV_DECORATE = 575, /* SPIRV_DECORATE */
BANG = 580, SPIRV_DECORATE_ID = 576, /* SPIRV_DECORATE_ID */
DASH = 581, SPIRV_DECORATE_STRING = 577, /* SPIRV_DECORATE_STRING */
TILDE = 582, SPIRV_TYPE = 578, /* SPIRV_TYPE */
PLUS = 583, SPIRV_STORAGE_CLASS = 579, /* SPIRV_STORAGE_CLASS */
STAR = 584, SPIRV_BY_REFERENCE = 580, /* SPIRV_BY_REFERENCE */
SLASH = 585, SPIRV_LITERAL = 581, /* SPIRV_LITERAL */
PERCENT = 586, LEFT_OP = 582, /* LEFT_OP */
LEFT_ANGLE = 587, RIGHT_OP = 583, /* RIGHT_OP */
RIGHT_ANGLE = 588, INC_OP = 584, /* INC_OP */
VERTICAL_BAR = 589, DEC_OP = 585, /* DEC_OP */
CARET = 590, LE_OP = 586, /* LE_OP */
AMPERSAND = 591, GE_OP = 587, /* GE_OP */
QUESTION = 592, EQ_OP = 588, /* EQ_OP */
INVARIANT = 593, NE_OP = 589, /* NE_OP */
HIGH_PRECISION = 594, AND_OP = 590, /* AND_OP */
MEDIUM_PRECISION = 595, OR_OP = 591, /* OR_OP */
LOW_PRECISION = 596, XOR_OP = 592, /* XOR_OP */
PRECISION = 597, MUL_ASSIGN = 593, /* MUL_ASSIGN */
PACKED = 598, DIV_ASSIGN = 594, /* DIV_ASSIGN */
RESOURCE = 599, ADD_ASSIGN = 595, /* ADD_ASSIGN */
SUPERP = 600, MOD_ASSIGN = 596, /* MOD_ASSIGN */
FLOATCONSTANT = 601, LEFT_ASSIGN = 597, /* LEFT_ASSIGN */
INTCONSTANT = 602, RIGHT_ASSIGN = 598, /* RIGHT_ASSIGN */
UINTCONSTANT = 603, AND_ASSIGN = 599, /* AND_ASSIGN */
BOOLCONSTANT = 604, XOR_ASSIGN = 600, /* XOR_ASSIGN */
IDENTIFIER = 605, OR_ASSIGN = 601, /* OR_ASSIGN */
TYPE_NAME = 606, SUB_ASSIGN = 602, /* SUB_ASSIGN */
CENTROID = 607, STRING_LITERAL = 603, /* STRING_LITERAL */
IN = 608, LEFT_PAREN = 604, /* LEFT_PAREN */
OUT = 609, RIGHT_PAREN = 605, /* RIGHT_PAREN */
INOUT = 610, LEFT_BRACKET = 606, /* LEFT_BRACKET */
STRUCT = 611, RIGHT_BRACKET = 607, /* RIGHT_BRACKET */
VOID = 612, LEFT_BRACE = 608, /* LEFT_BRACE */
WHILE = 613, RIGHT_BRACE = 609, /* RIGHT_BRACE */
BREAK = 614, DOT = 610, /* DOT */
CONTINUE = 615, COMMA = 611, /* COMMA */
DO = 616, COLON = 612, /* COLON */
ELSE = 617, EQUAL = 613, /* EQUAL */
FOR = 618, SEMICOLON = 614, /* SEMICOLON */
IF = 619, BANG = 615, /* BANG */
DISCARD = 620, DASH = 616, /* DASH */
RETURN = 621, TILDE = 617, /* TILDE */
SWITCH = 622, PLUS = 618, /* PLUS */
CASE = 623, STAR = 619, /* STAR */
DEFAULT = 624, SLASH = 620, /* SLASH */
UNIFORM = 625, PERCENT = 621, /* PERCENT */
SHARED = 626, LEFT_ANGLE = 622, /* LEFT_ANGLE */
BUFFER = 627, RIGHT_ANGLE = 623, /* RIGHT_ANGLE */
FLAT = 628, VERTICAL_BAR = 624, /* VERTICAL_BAR */
SMOOTH = 629, CARET = 625, /* CARET */
LAYOUT = 630, AMPERSAND = 626, /* AMPERSAND */
DOUBLECONSTANT = 631, QUESTION = 627, /* QUESTION */
INT16CONSTANT = 632, INVARIANT = 628, /* INVARIANT */
UINT16CONSTANT = 633, HIGH_PRECISION = 629, /* HIGH_PRECISION */
FLOAT16CONSTANT = 634, MEDIUM_PRECISION = 630, /* MEDIUM_PRECISION */
INT32CONSTANT = 635, LOW_PRECISION = 631, /* LOW_PRECISION */
UINT32CONSTANT = 636, PRECISION = 632, /* PRECISION */
INT64CONSTANT = 637, PACKED = 633, /* PACKED */
UINT64CONSTANT = 638, RESOURCE = 634, /* RESOURCE */
SUBROUTINE = 639, SUPERP = 635, /* SUPERP */
DEMOTE = 640, FLOATCONSTANT = 636, /* FLOATCONSTANT */
PAYLOADNV = 641, INTCONSTANT = 637, /* INTCONSTANT */
PAYLOADINNV = 642, UINTCONSTANT = 638, /* UINTCONSTANT */
HITATTRNV = 643, BOOLCONSTANT = 639, /* BOOLCONSTANT */
CALLDATANV = 644, IDENTIFIER = 640, /* IDENTIFIER */
CALLDATAINNV = 645, TYPE_NAME = 641, /* TYPE_NAME */
PATCH = 646, CENTROID = 642, /* CENTROID */
SAMPLE = 647, IN = 643, /* IN */
NONUNIFORM = 648, OUT = 644, /* OUT */
COHERENT = 649, INOUT = 645, /* INOUT */
VOLATILE = 650, STRUCT = 646, /* STRUCT */
RESTRICT = 651, VOID = 647, /* VOID */
READONLY = 652, WHILE = 648, /* WHILE */
WRITEONLY = 653, BREAK = 649, /* BREAK */
DEVICECOHERENT = 654, CONTINUE = 650, /* CONTINUE */
QUEUEFAMILYCOHERENT = 655, DO = 651, /* DO */
WORKGROUPCOHERENT = 656, ELSE = 652, /* ELSE */
SUBGROUPCOHERENT = 657, FOR = 653, /* FOR */
NONPRIVATE = 658, IF = 654, /* IF */
NOPERSPECTIVE = 659, DISCARD = 655, /* DISCARD */
EXPLICITINTERPAMD = 660, RETURN = 656, /* RETURN */
PERVERTEXNV = 661, SWITCH = 657, /* SWITCH */
PERPRIMITIVENV = 662, CASE = 658, /* CASE */
PERVIEWNV = 663, DEFAULT = 659, /* DEFAULT */
PERTASKNV = 664, TERMINATE_INVOCATION = 660, /* TERMINATE_INVOCATION */
PRECISE = 665 TERMINATE_RAY = 661, /* TERMINATE_RAY */
IGNORE_INTERSECTION = 662, /* IGNORE_INTERSECTION */
UNIFORM = 663, /* UNIFORM */
SHARED = 664, /* SHARED */
BUFFER = 665, /* BUFFER */
FLAT = 666, /* FLAT */
SMOOTH = 667, /* SMOOTH */
LAYOUT = 668, /* LAYOUT */
DOUBLECONSTANT = 669, /* DOUBLECONSTANT */
INT16CONSTANT = 670, /* INT16CONSTANT */
UINT16CONSTANT = 671, /* UINT16CONSTANT */
FLOAT16CONSTANT = 672, /* FLOAT16CONSTANT */
INT32CONSTANT = 673, /* INT32CONSTANT */
UINT32CONSTANT = 674, /* UINT32CONSTANT */
INT64CONSTANT = 675, /* INT64CONSTANT */
UINT64CONSTANT = 676, /* UINT64CONSTANT */
SUBROUTINE = 677, /* SUBROUTINE */
DEMOTE = 678, /* DEMOTE */
PAYLOADNV = 679, /* PAYLOADNV */
PAYLOADINNV = 680, /* PAYLOADINNV */
HITATTRNV = 681, /* HITATTRNV */
CALLDATANV = 682, /* CALLDATANV */
CALLDATAINNV = 683, /* CALLDATAINNV */
PAYLOADEXT = 684, /* PAYLOADEXT */
PAYLOADINEXT = 685, /* PAYLOADINEXT */
HITATTREXT = 686, /* HITATTREXT */
CALLDATAEXT = 687, /* CALLDATAEXT */
CALLDATAINEXT = 688, /* CALLDATAINEXT */
PATCH = 689, /* PATCH */
SAMPLE = 690, /* SAMPLE */
NONUNIFORM = 691, /* NONUNIFORM */
COHERENT = 692, /* COHERENT */
VOLATILE = 693, /* VOLATILE */
RESTRICT = 694, /* RESTRICT */
READONLY = 695, /* READONLY */
WRITEONLY = 696, /* WRITEONLY */
DEVICECOHERENT = 697, /* DEVICECOHERENT */
QUEUEFAMILYCOHERENT = 698, /* QUEUEFAMILYCOHERENT */
WORKGROUPCOHERENT = 699, /* WORKGROUPCOHERENT */
SUBGROUPCOHERENT = 700, /* SUBGROUPCOHERENT */
NONPRIVATE = 701, /* NONPRIVATE */
SHADERCALLCOHERENT = 702, /* SHADERCALLCOHERENT */
NOPERSPECTIVE = 703, /* NOPERSPECTIVE */
EXPLICITINTERPAMD = 704, /* EXPLICITINTERPAMD */
PERVERTEXNV = 705, /* PERVERTEXNV */
PERPRIMITIVENV = 706, /* PERPRIMITIVENV */
PERVIEWNV = 707, /* PERVIEWNV */
PERTASKNV = 708, /* PERTASKNV */
PRECISE = 709 /* PRECISE */
}; };
typedef enum yytokentype yytoken_kind_t;
#endif #endif
/* Value type. */ /* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
union YYSTYPE union YYSTYPE
{ {
#line 96 "MachineIndependent/glslang.y" /* yacc.c:1909 */ #line 97 "MachineIndependent/glslang.y"
struct { struct {
glslang::TSourceLoc loc; glslang::TSourceLoc loc;
@ -484,6 +537,9 @@ union YYSTYPE
glslang::TIntermNodePair nodePair; glslang::TIntermNodePair nodePair;
glslang::TIntermTyped* intermTypedNode; glslang::TIntermTyped* intermTypedNode;
glslang::TAttributes* attributes; glslang::TAttributes* attributes;
glslang::TSpirvRequirement* spirvReq;
glslang::TSpirvInstruction* spirvInst;
glslang::TSpirvTypeParameters* spirvTypeParams;
}; };
union { union {
glslang::TPublicType type; glslang::TPublicType type;
@ -497,9 +553,9 @@ union YYSTYPE
glslang::TArraySizes* typeParameters; glslang::TArraySizes* typeParameters;
} interm; } interm;
#line 501 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */ #line 557 "MachineIndependent/glslang_tab.cpp.h"
};
};
typedef union YYSTYPE YYSTYPE; typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_DECLARED 1

View File

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2012-2016 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
// //
// All rights reserved. // All rights reserved.
// //
@ -35,7 +36,7 @@
// POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
// //
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#include "localintermediate.h" #include "localintermediate.h"
#include "../Include/InfoSink.h" #include "../Include/InfoSink.h"
@ -47,37 +48,6 @@
#endif #endif
#include <cstdint> #include <cstdint>
namespace {
bool IsInfinity(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_NINF:
case _FPCLASS_PINF:
return true;
default:
return false;
}
#else
return std::isinf(x);
#endif
}
bool IsNan(double x) {
#ifdef _MSC_VER
switch (_fpclass(x)) {
case _FPCLASS_SNAN:
case _FPCLASS_QNAN:
return true;
default:
return false;
}
#else
return std::isnan(x);
#endif
}
}
namespace glslang { namespace glslang {
@ -437,6 +407,9 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpConvUint64ToPtr: out.debug << "Convert uint64_t to pointer"; break; case EOpConvUint64ToPtr: out.debug << "Convert uint64_t to pointer"; break;
case EOpConvPtrToUint64: out.debug << "Convert pointer to uint64_t"; 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 EOpRadians: out.debug << "radians"; break;
case EOpDegrees: out.debug << "degrees"; break; case EOpDegrees: out.debug << "degrees"; break;
case EOpSin: out.debug << "sine"; break; case EOpSin: out.debug << "sine"; break;
@ -692,6 +665,10 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpConstructReference: out.debug << "Construct reference type"; break; case EOpConstructReference: out.debug << "Construct reference type"; break;
#ifndef GLSLANG_WEB
case EOpSpirvInst: out.debug << "spirv_instruction"; break;
#endif
default: out.debug.message(EPrefixError, "Bad unary op"); default: out.debug.message(EPrefixError, "Bad unary op");
} }
@ -828,6 +805,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break; case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
case EOpConstructReference: out.debug << "Construct reference"; break; case EOpConstructReference: out.debug << "Construct reference"; break;
case EOpConstructCooperativeMatrix: out.debug << "Construct cooperative matrix"; break; case EOpConstructCooperativeMatrix: out.debug << "Construct cooperative matrix"; break;
case EOpConstructAccStruct: out.debug << "Construct acceleration structure"; break;
case EOpLessThan: out.debug << "Compare Less Than"; break; case EOpLessThan: out.debug << "Compare Less Than"; break;
case EOpGreaterThan: out.debug << "Compare Greater Than"; break; case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
@ -881,6 +859,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpTime: out.debug << "time"; break; case EOpTime: out.debug << "time"; break;
case EOpAtomicAdd: out.debug << "AtomicAdd"; break; case EOpAtomicAdd: out.debug << "AtomicAdd"; break;
case EOpAtomicSubtract: out.debug << "AtomicSubtract"; break;
case EOpAtomicMin: out.debug << "AtomicMin"; break; case EOpAtomicMin: out.debug << "AtomicMin"; break;
case EOpAtomicMax: out.debug << "AtomicMax"; break; case EOpAtomicMax: out.debug << "AtomicMax"; break;
case EOpAtomicAnd: out.debug << "AtomicAnd"; break; case EOpAtomicAnd: out.debug << "AtomicAnd"; break;
@ -1079,17 +1058,51 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break; case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
case EOpTraceNV: out.debug << "traceNV"; break; case EOpTraceNV: out.debug << "traceNV"; break;
case EOpReportIntersectionNV: out.debug << "reportIntersectionNV"; 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 EOpIgnoreIntersectionNV: out.debug << "ignoreIntersectionNV"; break;
case EOpIgnoreIntersectionKHR: out.debug << "ignoreIntersectionKHR"; break;
case EOpTerminateRayNV: out.debug << "terminateRayNV"; break; case EOpTerminateRayNV: out.debug << "terminateRayNV"; break;
case EOpTerminateRayKHR: out.debug << "terminateRayKHR"; break;
case EOpExecuteCallableNV: out.debug << "executeCallableNV"; break; case EOpExecuteCallableNV: out.debug << "executeCallableNV"; break;
case EOpExecuteCallableKHR: out.debug << "executeCallableKHR"; break;
case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break; case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; 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 EOpCooperativeMatrixLoad: out.debug << "Load cooperative matrix"; break; case EOpCooperativeMatrixLoad: out.debug << "Load cooperative matrix"; break;
case EOpCooperativeMatrixStore: out.debug << "Store cooperative matrix"; break; case EOpCooperativeMatrixStore: out.debug << "Store cooperative matrix"; break;
case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices"; break; case EOpCooperativeMatrixMulAdd: out.debug << "MulAdd cooperative matrices"; break;
case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break; case EOpIsHelperInvocation: out.debug << "IsHelperInvocation"; break;
case EOpDebugPrintf: out.debug << "Debug printf"; break;
#ifndef GLSLANG_WEB
case EOpSpirvInst: out.debug << "spirv_instruction"; break;
#endif
default: out.debug.message(EPrefixError, "Bad aggregation op"); default: out.debug.message(EPrefixError, "Bad aggregation op");
} }
@ -1295,6 +1308,9 @@ static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const
out.debug << buf << "\n"; out.debug << buf << "\n";
} }
break; break;
case EbtString:
out.debug << "\"" << constUnion[i].getSConst()->c_str() << "\"\n";
break;
default: default:
out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc()); out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
break; break;
@ -1380,14 +1396,17 @@ bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node)
OutputTreeText(out, node, depth); OutputTreeText(out, node, depth);
switch (node->getFlowOp()) { switch (node->getFlowOp()) {
case EOpKill: out.debug << "Branch: Kill"; break; case EOpKill: out.debug << "Branch: Kill"; break;
case EOpBreak: out.debug << "Branch: Break"; break; case EOpTerminateInvocation: out.debug << "Branch: TerminateInvocation"; break;
case EOpContinue: out.debug << "Branch: Continue"; break; case EOpIgnoreIntersectionKHR: out.debug << "Branch: IgnoreIntersectionKHR"; break;
case EOpReturn: out.debug << "Branch: Return"; break; case EOpTerminateRayKHR: out.debug << "Branch: TerminateRayKHR"; break;
case EOpCase: out.debug << "case: "; break; case EOpBreak: out.debug << "Branch: Break"; break;
case EOpDemote: out.debug << "Demote"; break; case EOpContinue: out.debug << "Branch: Continue"; break;
case EOpDefault: out.debug << "default: "; break; case EOpReturn: out.debug << "Branch: Return"; break;
default: out.debug << "Branch: Unknown Branch"; 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()) { if (node->getExpression()) {
@ -1446,6 +1465,9 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
if (xfbMode) if (xfbMode)
infoSink.debug << "in xfb mode\n"; infoSink.debug << "in xfb mode\n";
if (getSubgroupUniformControlFlow())
infoSink.debug << "subgroup_uniform_control_flow\n";
switch (language) { switch (language) {
case EShLangVertex: case EShLangVertex:
break; break;
@ -1536,4 +1558,4 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
} // end namespace glslang } // end namespace glslang
#endif // not GLSLANG_WEB #endif // !GLSLANG_WEB && !GLSLANG_ANGLE

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@
// POSSIBILITY OF SUCH DAMAGE. // POSSIBILITY OF SUCH DAMAGE.
// //
#ifndef GLSLANG_WEB #if !defined(GLSLANG_WEB) && !defined(GLSLANG_ANGLE)
#ifndef _IOMAPPER_INCLUDED #ifndef _IOMAPPER_INCLUDED
#define _IOMAPPER_INCLUDED #define _IOMAPPER_INCLUDED
@ -52,7 +52,7 @@ namespace glslang {
class TIntermediate; class TIntermediate;
struct TVarEntryInfo { struct TVarEntryInfo {
int id; long long id;
TIntermSymbol* symbol; TIntermSymbol* symbol;
bool live; bool live;
int newBinding; int newBinding;
@ -61,6 +61,15 @@ struct TVarEntryInfo {
int newComponent; int newComponent;
int newIndex; int newIndex;
EShLanguage stage; EShLanguage stage;
void clearNewAssignments() {
newBinding = -1;
newSet = -1;
newLocation = -1;
newComponent = -1;
newIndex = -1;
}
struct TOrderById { struct TOrderById {
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; } inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; }
}; };
@ -87,6 +96,35 @@ struct TVarEntryInfo {
return lPoints > rPoints; 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. // Base class for shared TIoMapResolver services, used by several derivations.
@ -107,8 +145,8 @@ public:
void endCollect(EShLanguage) override {} void endCollect(EShLanguage) override {}
void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {} void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
int getBaseBinding(TResourceType res, unsigned int set) const; int getBaseBinding(EShLanguage stage, TResourceType res, unsigned int set) const;
const std::vector<std::string>& getResourceSetBinding() const; const std::vector<std::string>& getResourceSetBinding(EShLanguage stage) const;
virtual TResourceType getResourceType(const glslang::TType& type) = 0; virtual TResourceType getResourceType(const glslang::TType& type) = 0;
bool doAutoBindingMapping() const; bool doAutoBindingMapping() const;
bool doAutoLocationMapping() const; bool doAutoLocationMapping() const;
@ -122,22 +160,27 @@ public:
int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override; int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override; int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override; int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
void addStage(EShLanguage stage) override { void addStage(EShLanguage stage, TIntermediate& stageIntermediate) override {
if (stage < EShLangCount) if (stage < EShLangCount) {
stageMask[stage] = true; stageMask[stage] = true;
stageIntermediates[stage] = &stageIntermediate;
}
} }
uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage); uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
TSlotSetMap slots; TSlotSetMap slots;
bool hasError = false;
protected: protected:
TDefaultIoResolverBase(TDefaultIoResolverBase&); TDefaultIoResolverBase(TDefaultIoResolverBase&);
TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&); TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&);
const TIntermediate& intermediate; const TIntermediate& referenceIntermediate;
int nextUniformLocation; int nextUniformLocation;
int nextInputLocation; int nextInputLocation;
int nextOutputLocation; int nextOutputLocation;
bool stageMask[EShLangCount + 1]; bool stageMask[EShLangCount + 1];
const TIntermediate* stageIntermediates[EShLangCount];
// Return descriptor set specific base if there is one, and the generic base otherwise. // Return descriptor set specific base if there is one, and the generic base otherwise.
int selectBaseBinding(int base, int descriptorSetBase) const { int selectBaseBinding(int base, int descriptorSetBase) const {
return descriptorSetBase != -1 ? descriptorSetBase : base; return descriptorSetBase != -1 ? descriptorSetBase : base;
@ -185,7 +228,7 @@ protected:
} }
}; };
// Defaulf I/O resolver for OpenGL // Default I/O resolver for OpenGL
struct TDefaultGlslIoResolver : public TDefaultIoResolverBase { struct TDefaultGlslIoResolver : public TDefaultIoResolverBase {
public: public:
typedef std::map<TString, int> TVarSlotMap; // <resourceName, location/binding> typedef std::map<TString, int> TVarSlotMap; // <resourceName, location/binding>
@ -237,12 +280,13 @@ typedef std::map<TString, TVarEntryInfo> TVarLiveMap;
// In the future, if the vc++ compiler can handle such a situation, // In the future, if the vc++ compiler can handle such a situation,
// this part of the code will be removed. // this part of the code will be removed.
struct TVarLivePair : std::pair<const TString, TVarEntryInfo> { struct TVarLivePair : std::pair<const TString, TVarEntryInfo> {
TVarLivePair(std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {} TVarLivePair(const std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
TVarLivePair& operator=(const TVarLivePair& _Right) { TVarLivePair& operator=(const TVarLivePair& _Right) {
const_cast<TString&>(first) = _Right.first; const_cast<TString&>(first) = _Right.first;
second = _Right.second; second = _Right.second;
return (*this); return (*this);
} }
TVarLivePair(const TVarLivePair& src) : pair(src) { }
}; };
typedef std::vector<TVarLivePair> TVarLiveVector; typedef std::vector<TVarLivePair> TVarLiveVector;
@ -256,7 +300,7 @@ public:
bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; } bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; }
}; };
// I/O mapper for OpenGL // I/O mapper for GLSL
class TGlslIoMapper : public TIoMapper { class TGlslIoMapper : public TIoMapper {
public: public:
TGlslIoMapper() { TGlslIoMapper() {
@ -264,6 +308,10 @@ public:
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1)); memset(outVarMaps, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1)); memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * (EShLangCount + 1));
memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1)); memset(intermediates, 0, sizeof(TIntermediate*) * (EShLangCount + 1));
profile = ENoProfile;
version = 0;
autoPushConstantMaxSize = 128;
autoPushConstantBlockPacking = ElpStd430;
} }
virtual ~TGlslIoMapper() { virtual ~TGlslIoMapper() {
for (size_t stage = 0; stage < EShLangCount; stage++) { for (size_t stage = 0; stage < EShLangCount; stage++) {
@ -283,6 +331,13 @@ public:
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 // grow the reflection stage by stage
bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override; bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override;
bool doMap(TIoMapResolver*, TInfoSink&) override; bool doMap(TIoMapResolver*, TInfoSink&) override;
@ -290,10 +345,17 @@ public:
*uniformVarMap[EShLangCount]; *uniformVarMap[EShLangCount];
TIntermediate* intermediates[EShLangCount]; TIntermediate* intermediates[EShLangCount];
bool hadError = false; bool hadError = false;
EProfile profile;
int version;
private:
TString autoPushConstantBlockName;
unsigned int autoPushConstantMaxSize;
TLayoutPacking autoPushConstantBlockPacking;
}; };
} // end namespace glslang } // end namespace glslang
#endif // _IOMAPPER_INCLUDED #endif // _IOMAPPER_INCLUDED
#endif // GLSLANG_WEB #endif // !GLSLANG_WEB && !GLSLANG_ANGLE

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