Merge pull request #4113 from stenzek/externals-vulkan

Externals: Add Vulkan headers and glslang
This commit is contained in:
Pierre Bourdon
2016-08-11 16:15:32 +02:00
committed by GitHub
137 changed files with 78919 additions and 0 deletions
+2
View File
@@ -635,6 +635,8 @@ endif()
add_subdirectory(Externals/Bochs_disasm)
include_directories(Externals/Bochs_disasm)
add_subdirectory(Externals/glslang)
if(USE_SHARED_ENET)
check_lib(ENET libenet enet enet/enet.h QUIET)
include(CheckSymbolExists)
+120
View File
@@ -0,0 +1,120 @@
//
// File: vk_platform.h
//
/*
** Copyright (c) 2014-2015 The Khronos Group Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#ifndef VK_PLATFORM_H_
#define VK_PLATFORM_H_
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
/*
***************************************************************************************************
* Platform-specific directives and type declarations
***************************************************************************************************
*/
/* Platform-specific calling convention macros.
*
* Platforms should define these so that Vulkan clients call Vulkan commands
* with the same calling conventions that the Vulkan implementation expects.
*
* VKAPI_ATTR - Placed before the return type in function declarations.
* Useful for C++11 and GCC/Clang-style function attribute syntax.
* VKAPI_CALL - Placed after the return type in function declarations.
* Useful for MSVC-style calling convention syntax.
* VKAPI_PTR - Placed between the '(' and '*' in function pointer types.
*
* Function declaration: VKAPI_ATTR void VKAPI_CALL vkCommand(void);
* Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void);
*/
#if defined(_WIN32)
// On Windows, Vulkan commands use the stdcall convention
#define VKAPI_ATTR
#define VKAPI_CALL __stdcall
#define VKAPI_PTR VKAPI_CALL
#elif defined(__ANDROID__) && defined(__ARM_EABI__) && !defined(__ARM_ARCH_7A__)
// Android does not support Vulkan in native code using the "armeabi" ABI.
#error "Vulkan requires the 'armeabi-v7a' or 'armeabi-v7a-hard' ABI on 32-bit ARM CPUs"
#elif defined(__ANDROID__) && defined(__ARM_ARCH_7A__)
// On Android/ARMv7a, Vulkan functions use the armeabi-v7a-hard calling
// convention, even if the application's native code is compiled with the
// armeabi-v7a calling convention.
#define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
#define VKAPI_CALL
#define VKAPI_PTR VKAPI_ATTR
#else
// On other platforms, use the default calling convention
#define VKAPI_ATTR
#define VKAPI_CALL
#define VKAPI_PTR
#endif
#include <stddef.h>
#if !defined(VK_NO_STDINT_H)
#if defined(_MSC_VER) && (_MSC_VER < 1600)
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
#endif // !defined(VK_NO_STDINT_H)
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
// Platform-specific headers required by platform window system extensions.
// These are enabled prior to #including "vulkan.h". The same enable then
// controls inclusion of the extension interfaces in vulkan.h.
#ifdef VK_USE_PLATFORM_ANDROID_KHR
#include <android/native_window.h>
#endif
#ifdef VK_USE_PLATFORM_MIR_KHR
#include <mir_toolkit/client_types.h>
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#include <wayland-client.h>
#endif
#ifdef VK_USE_PLATFORM_WIN32_KHR
#include <windows.h>
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
#include <X11/Xlib.h>
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
#include <xcb/xcb.h>
#endif
#endif
File diff suppressed because it is too large Load Diff
+40
View File
@@ -0,0 +1,40 @@
# Windows Build Configuration for AppVeyor
# http://www.appveyor.com/docs/appveyor-yml
# build version format
version: "{build}"
os: Visual Studio 2013
platform:
- Any CPU
configuration:
- Debug
- Release
branches:
only:
- master
clone_depth: 5
matrix:
fast_finish: true # Show final status immediately if a test fails.
# scripts that run after cloning repository
install:
- git clone https://github.com/google/googletest.git External/googletest
build:
parallel: true # enable MSBuild parallel builds
verbosity: minimal
build_script:
- mkdir build && cd build
- cmake .. -DCMAKE_INSTALL_PREFIX=install
- cmake --build . --config %CONFIGURATION% --target install
test_script:
- ctest -C %CONFIGURATION% --output-on-failure
- cd ../Test && bash runtests
+12
View File
@@ -0,0 +1,12 @@
Language: Cpp
IndentWidth: 4
BreakBeforeBraces: Custom
BraceWrapping: { AfterFunction: true, AfterControlStatement: true }
IndentCaseLabels: false
ReflowComments: false
ColumnLimit: 120
AccessModifierOffset: -4
AlignTrailingComments: true
AllowShortBlocksOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
+60
View File
@@ -0,0 +1,60 @@
# Linux and Mac Build Configuration for Travis
language: cpp
os:
- linux
- osx
# Use Ubuntu 14.04 LTS (Trusty) as the Linux testing environment.
sudo: required
dist: trusty
env:
- GLSLANG_BUILD_TYPE=Release
- GLSLANG_BUILD_TYPE=Debug
compiler:
- clang
- gcc
matrix:
fast_finish: true # Show final status immediately if a test fails.
exclude:
# Skip GCC builds on Mac OS X.
- os: osx
compiler: gcc
cache:
apt: true
branches:
only:
- master
addons:
apt:
packages:
- clang-3.6
- ninja-build
install:
# Install ninja on Mac OS X.
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update && brew install ninja; fi
# Make sure that clang-3.6 is selected.
- if [[ "$TRAVIS_OS_NAME" == "linux" && "$CC" == "clang" ]]; then
export CC=clang-3.6 CXX=clang++-3.6;
fi
before_script:
- git clone https://github.com/google/googletest.git External/googletest
script:
- mkdir build && cd build
# We need to install the compiled binaries so the paths in the runtests script can resolve correctly.
- cmake -GNinja -DCMAKE_BUILD_TYPE=${GLSLANG_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=`pwd`/install ..
- ninja install
# Run Google-Test-based tests.
- ctest --output-on-failure
# Run runtests-based tests.
- cd ../Test && ./runtests
+58
View File
@@ -0,0 +1,58 @@
set(SRCS
glslang/GenericCodeGen/CodeGen.cpp
glslang/GenericCodeGen/Link.cpp
glslang/MachineIndependent/Constant.cpp
glslang/MachineIndependent/glslang_tab.cpp
glslang/MachineIndependent/InfoSink.cpp
glslang/MachineIndependent/Initialize.cpp
glslang/MachineIndependent/Intermediate.cpp
glslang/MachineIndependent/intermOut.cpp
glslang/MachineIndependent/IntermTraverse.cpp
glslang/MachineIndependent/limits.cpp
glslang/MachineIndependent/linkValidate.cpp
glslang/MachineIndependent/parseConst.cpp
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/PoolAlloc.cpp
glslang/MachineIndependent/preprocessor/Pp.cpp
glslang/MachineIndependent/preprocessor/PpAtom.cpp
glslang/MachineIndependent/preprocessor/PpContext.cpp
glslang/MachineIndependent/preprocessor/PpMemory.cpp
glslang/MachineIndependent/preprocessor/PpScanner.cpp
glslang/MachineIndependent/preprocessor/PpSymbols.cpp
glslang/MachineIndependent/preprocessor/PpTokens.cpp
glslang/MachineIndependent/propagateNoContraction.cpp
glslang/MachineIndependent/reflection.cpp
glslang/MachineIndependent/RemoveTree.cpp
glslang/MachineIndependent/Scan.cpp
glslang/MachineIndependent/ShaderLang.cpp
glslang/MachineIndependent/SymbolTable.cpp
glslang/MachineIndependent/Versions.cpp
glslang/OSDependent/Unix/ossource.cpp
hlsl/hlslGrammar.cpp
hlsl/hlslOpMap.cpp
hlsl/hlslParseables.cpp
hlsl/hlslParseHelper.cpp
hlsl/hlslScanContext.cpp
hlsl/hlslTokenStream.cpp
OGLCompilersDLL/InitializeDll.cpp
SPIRV/disassemble.cpp
SPIRV/doc.cpp
SPIRV/GlslangToSpv.cpp
SPIRV/InReadableOrder.cpp
SPIRV/Logger.cpp
SPIRV/SpvBuilder.cpp
SPIRV/SPVRemapper.cpp
)
# glslang requires C++11 at a minimum to compile.
add_definitions(-std=c++11)
# Silence some warnings that occur frequently to reduce noise in build logs.
add_definitions(-Wno-shadow)
add_definitions(-Wno-reorder)
add_definitions(-Wno-sign-compare)
add_definitions(-Wno-parentheses)
add_definitions(-Wno-unused-variable)
add_library(glslang STATIC ${SRCS})
+46
View File
@@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 2.8.12)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
enable_testing()
set(CMAKE_INSTALL_PREFIX "install" CACHE STRING "prefix")
project(glslang)
if(WIN32)
set(CMAKE_DEBUG_POSTFIX "d")
include(ChooseMSVCCRT.cmake)
add_definitions(-DGLSLANG_OSINCLUDE_WIN32)
elseif(UNIX)
add_definitions(-fPIC)
add_definitions(-DGLSLANG_OSINCLUDE_UNIX)
else(WIN32)
message("unknown platform")
endif(WIN32)
if(CMAKE_COMPILER_IS_GNUCXX)
add_definitions(-std=c++11)
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
add_definitions(-std=c++11)
endif()
function(glslang_set_link_args TARGET)
# For MinGW compiles, statically link against the GCC and C++ runtimes.
# This avoids the need to ship those runtimes as DLLs.
if(WIN32)
if(${CMAKE_CXX_COMPILER_ID} MATCHES "GNU")
set_target_properties(${TARGET} PROPERTIES
LINK_FLAGS "-static -static-libgcc -static-libstdc++")
endif()
endif(WIN32)
endfunction(glslang_set_link_args)
# We depend on these for later projects, so they should come first.
add_subdirectory(External)
add_subdirectory(glslang)
add_subdirectory(OGLCompilersDLL)
add_subdirectory(StandAlone)
add_subdirectory(SPIRV)
add_subdirectory(hlsl)
add_subdirectory(gtests)
+105
View File
@@ -0,0 +1,105 @@
# The macro choose_msvc_crt() takes a list of possible
# C runtimes to choose from, in the form of compiler flags,
# to present to the user. (MTd for /MTd, etc)
#
# The macro is invoked at the end of the file.
#
# CMake already sets CRT flags in the CMAKE_CXX_FLAGS_* and
# CMAKE_C_FLAGS_* variables by default. To let the user
# override that for each build type:
# 1. Detect which CRT is already selected, and reflect this in
# LLVM_USE_CRT_* so the user can have a better idea of what
# changes they're making.
# 2. Replace the flags in both variables with the new flag via a regex.
# 3. set() the variables back into the cache so the changes
# are user-visible.
### Helper macros: ###
macro(make_crt_regex regex crts)
set(${regex} "")
foreach(crt ${${crts}})
# Trying to match the beginning or end of the string with stuff
# like [ ^]+ didn't work, so use a bunch of parentheses instead.
set(${regex} "${${regex}}|(^| +)/${crt}($| +)")
endforeach(crt)
string(REGEX REPLACE "^\\|" "" ${regex} "${${regex}}")
endmacro(make_crt_regex)
macro(get_current_crt crt_current regex flagsvar)
# Find the selected-by-CMake CRT for each build type, if any.
# Strip off the leading slash and any whitespace.
string(REGEX MATCH "${${regex}}" ${crt_current} "${${flagsvar}}")
string(REPLACE "/" " " ${crt_current} "${${crt_current}}")
string(STRIP "${${crt_current}}" ${crt_current})
endmacro(get_current_crt)
# Replaces or adds a flag to a variable.
# Expects 'flag' to be padded with spaces.
macro(set_flag_in_var flagsvar regex flag)
string(REGEX MATCH "${${regex}}" current_flag "${${flagsvar}}")
if("${current_flag}" STREQUAL "")
set(${flagsvar} "${${flagsvar}}${${flag}}")
else()
string(REGEX REPLACE "${${regex}}" "${${flag}}" ${flagsvar} "${${flagsvar}}")
endif()
string(STRIP "${${flagsvar}}" ${flagsvar})
# Make sure this change gets reflected in the cache/gui.
# CMake requires the docstring parameter whenever set() touches the cache,
# so get the existing docstring and re-use that.
get_property(flagsvar_docs CACHE ${flagsvar} PROPERTY HELPSTRING)
set(${flagsvar} "${${flagsvar}}" CACHE STRING "${flagsvar_docs}" FORCE)
endmacro(set_flag_in_var)
macro(choose_msvc_crt MSVC_CRT)
if(LLVM_USE_CRT)
message(FATAL_ERROR
"LLVM_USE_CRT is deprecated. Use the CMAKE_BUILD_TYPE-specific
variables (LLVM_USE_CRT_DEBUG, etc) instead.")
endif()
make_crt_regex(MSVC_CRT_REGEX ${MSVC_CRT})
foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE})
string(TOUPPER "${build_type}" build)
if (NOT LLVM_USE_CRT_${build})
get_current_crt(LLVM_USE_CRT_${build}
MSVC_CRT_REGEX
CMAKE_CXX_FLAGS_${build})
set(LLVM_USE_CRT_${build}
"${LLVM_USE_CRT_${build}}"
CACHE STRING "Specify VC++ CRT to use for ${build_type} configurations."
FORCE)
set_property(CACHE LLVM_USE_CRT_${build}
PROPERTY STRINGS ;${${MSVC_CRT}})
endif(NOT LLVM_USE_CRT_${build})
endforeach(build_type)
foreach(build_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE})
string(TOUPPER "${build_type}" build)
if ("${LLVM_USE_CRT_${build}}" STREQUAL "")
set(flag_string " ")
else()
set(flag_string " /${LLVM_USE_CRT_${build}} ")
list(FIND ${MSVC_CRT} ${LLVM_USE_CRT_${build}} idx)
if (idx LESS 0)
message(FATAL_ERROR
"Invalid value for LLVM_USE_CRT_${build}: ${LLVM_USE_CRT_${build}}. Valid options are one of: ${${MSVC_CRT}}")
endif (idx LESS 0)
message(STATUS "Using ${build_type} VC++ CRT: ${LLVM_USE_CRT_${build}}")
endif()
foreach(lang C CXX)
set_flag_in_var(CMAKE_${lang}_FLAGS_${build} MSVC_CRT_REGEX flag_string)
endforeach(lang)
endforeach(build_type)
endmacro(choose_msvc_crt MSVC_CRT)
# List of valid CRTs for MSVC
set(MSVC_CRT
MD
MDd
MT
MTd)
choose_msvc_crt(MSVC_CRT)
+34
View File
@@ -0,0 +1,34 @@
# Suppress all warnings from external projects.
set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS -w)
if (TARGET gmock)
message(STATUS "Google Mock already configured - use it")
elseif(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/googletest)
# We need to make sure Google Test does not mess up with the
# global CRT settings on Windows.
if(WIN32)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
endif(WIN32)
add_subdirectory(googletest)
set(GTEST_TARGETS
gtest
gtest_main
gmock
gmock_main
)
foreach(target ${GTEST_TARGETS})
set_property(TARGET ${target} PROPERTY FOLDER gtest)
endforeach()
mark_as_advanced(gmock_build_tests
BUILD_GMOCK
BUILD_GTEST
BUILD_SHARED_LIBS
gtest_build_samples
gtest_build_tests
gtest_disable_pthreads
gtest_force_shared_crt
gtest_hide_internal_symbols)
else()
message(STATUS
"Google Mock was not found - tests based on that will not build")
endif()
+11
View File
@@ -0,0 +1,11 @@
set(SOURCES InitializeDll.cpp InitializeDll.h)
add_library(OGLCompiler STATIC ${SOURCES})
set_property(TARGET OGLCompiler PROPERTY FOLDER glslang)
if(WIN32)
source_group("Source" FILES ${SOURCES})
endif(WIN32)
install(TARGETS OGLCompiler
ARCHIVE DESTINATION lib)
+155
View File
@@ -0,0 +1,155 @@
//
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions
//are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
#define SH_EXPORTING
#include <assert.h>
#include "InitializeDll.h"
#include "../glslang/Include/InitializeGlobals.h"
#include "../glslang/Public/ShaderLang.h"
namespace glslang {
OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
bool InitProcess()
{
glslang::GetGlobalLock();
if (ThreadInitializeIndex != OS_INVALID_TLS_INDEX) {
//
// Function is re-entrant.
//
glslang::ReleaseGlobalLock();
return true;
}
ThreadInitializeIndex = OS_AllocTLSIndex();
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitProcess(): Failed to allocate TLS area for init flag");
glslang::ReleaseGlobalLock();
return false;
}
if (! InitializePoolIndex()) {
assert(0 && "InitProcess(): Failed to initialize global pool");
glslang::ReleaseGlobalLock();
return false;
}
if (! InitThread()) {
assert(0 && "InitProcess(): Failed to initialize thread");
glslang::ReleaseGlobalLock();
return false;
}
glslang::ReleaseGlobalLock();
return true;
}
bool InitThread()
{
//
// This function is re-entrant
//
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX) {
assert(0 && "InitThread(): Process hasn't been initalised.");
return false;
}
if (OS_GetTLSValue(ThreadInitializeIndex) != 0)
return true;
InitializeMemoryPools();
if (! OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
assert(0 && "InitThread(): Unable to set init flag.");
return false;
}
return true;
}
bool DetachThread()
{
bool success = true;
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
return true;
//
// Function is re-entrant and this thread may not have been initialized.
//
if (OS_GetTLSValue(ThreadInitializeIndex) != 0) {
if (!OS_SetTLSValue(ThreadInitializeIndex, (void *)0)) {
assert(0 && "DetachThread(): Unable to clear init flag.");
success = false;
}
FreeGlobalPools();
}
return success;
}
bool DetachProcess()
{
bool success = true;
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
return true;
ShFinalize();
success = DetachThread();
FreePoolIndex();
OS_FreeTLSIndex(ThreadInitializeIndex);
ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
return success;
}
} // end namespace glslang
+50
View File
@@ -0,0 +1,50 @@
//
//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions
//are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
#ifndef __INITIALIZEDLL_H
#define __INITIALIZEDLL_H
#include "../glslang/OSDependent/osinclude.h"
namespace glslang {
bool InitProcess();
bool InitThread();
bool DetachThread();
bool DetachProcess();
} // end namespace glslang
#endif // __INITIALIZEDLL_H
+137
View File
@@ -0,0 +1,137 @@
VERSION
--------------------------------------------------------------------------------
spirv-remap 0.97
INTRO:
--------------------------------------------------------------------------------
spirv-remap is a utility to improve compression of SPIR-V binary files via
entropy reduction, plus optional stripping of debug information and
load/store optimization. It transforms SPIR-V to SPIR-V, remapping IDs. The
resulting modules have an increased ID range (IDs are not as tightly packed
around zero), but will compress better when multiple modules are compressed
together, since compressor's dictionary can find better cross module
commonality.
Remapping is accomplished via canonicalization. Thus, modules can be
compressed one at a time with no loss of quality relative to operating on
many modules at once. The command line tool operates on multiple modules
only in the trivial repetition sense, for ease of use. The remapper API
only accepts a single module at a time.
There are two modes of use: command line, and a C++11 API. Both are
described below.
spirv-remap is currently in an alpha state. Although there are no known
remapping defects, it has only been exercised on one real world game shader
workload.
FEEDBACK
--------------------------------------------------------------------------------
Report defects, enhancements requests, code improvements, etc to:
spvremapper@lunarg.com
COMMAND LINE USAGE:
--------------------------------------------------------------------------------
Examples are given with a verbosity of one (-v), but more verbosity can be
had via -vv, -vvv, etc, or an integer parameter to --verbose, such as
"--verbose 4". With no verbosity, the command is silent and returns 0 on
success, and a positive integer error on failure.
Pre-built binaries for several OSs are available. Examples presented are
for Linux. Command line arguments can be provided in any order.
1. Basic ID remapping
Perform ID remapping on all shaders in "*.spv", writing new files with
the same basenames to /tmp/out_dir.
spirv-remap -v --map all --input *.spv --output /tmp/out_dir
2. Perform all possible size reductions
spirv-remap-linux-64 -v --do-everything --input *.spv --output /tmp/out_dir
Note that --do-everything is a synonym for:
--map all --dce all --opt all --strip all
API USAGE:
--------------------------------------------------------------------------------
The public interface to the remapper is defined in SPIRV/SPVRemapper.h as follows:
namespace spv {
class spirvbin_t
{
public:
enum Options { ... };
spirvbin_t(int verbose = 0); // construct
// remap an existing binary in memory
void remap(std::vector<std::uint32_t>& spv, std::uint32_t opts = DO_EVERYTHING);
// Type for error/log handler functions
typedef std::function<void(const std::string&)> errorfn_t;
typedef std::function<void(const std::string&)> logfn_t;
// Register error/log handling functions (can be c/c++ fn, lambda fn, or functor)
static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; }
static void registerLogHandler(logfn_t handler) { logHandler = handler; }
};
} // namespace spv
The class definition is in SPVRemapper.cpp.
remap() accepts an std::vector of SPIR-V words, modifies them per the
request given in 'opts', and leaves the 'spv' container with the result.
It is safe to instantiate one spirvbin_t per thread and process a different
SPIR-V in each.
The "opts" parameter to remap() accepts a bit mask of desired remapping
options. See REMAPPING AND OPTIMIZATION OPTIONS.
On error, the function supplied to registerErrorHandler() will be invoked.
This can be a standard C/C++ function, a lambda function, or a functor.
The default handler simply calls exit(5); The error handler is a static
members, so need only be set up once, not once per spirvbin_t instance.
Log messages are supplied to registerLogHandler(). By default, log
messages are eaten silently. The log handler is also a static member.
BUILD DEPENDENCIES:
--------------------------------------------------------------------------------
1. C++11 compatible compiler
2. cmake
3. glslang
BUILDING
--------------------------------------------------------------------------------
The standalone remapper is built along side glslangValidator through its
normal build process.
REMAPPING AND OPTIMIZATION OPTIONS
--------------------------------------------------------------------------------
API:
These are bits defined under spv::spirvbin_t::, and can be
bitwise or-ed together as desired.
MAP_TYPES = canonicalize type IDs
MAP_NAMES = canonicalize named data
MAP_FUNCS = canonicalize function bodies
DCE_FUNCS = remove dead functions
DCE_VARS = remove dead variables
DCE_TYPES = remove dead types
OPT_LOADSTORE = optimize unneeded load/stores
MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS)
DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES)
OPT_ALL = (OPT_LOADSTORE)
ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL)
DO_EVERYTHING = (STRIP | ALL_BUT_STRIP)
+293
View File
@@ -0,0 +1,293 @@
Also see the Khronos landing page for glslang as a reference front end:
https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/
The above page includes where to get binaries, and is kept up to date
regarding the feature level of glslang.
glslang
=======
[![Build Status](https://travis-ci.org/KhronosGroup/glslang.svg?branch=master)](https://travis-ci.org/KhronosGroup/glslang)
[![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 two components:
1. A front-end library for programmatic parsing of GLSL/ESSL into an AST.
2. A standalone wrapper, `glslangValidator`, that can be used as a shader
validation tool.
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.
Execution of Standalone Wrapper
-------------------------------
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,
and it will print out warnings/errors and optionally an AST.
The applied stage-specific rules are based on the file extension:
* `.vert` for a vertex shader
* `.tesc` for a tessellation control shader
* `.tese` for a tessellation evaluation shader
* `.geom` for a geometry shader
* `.frag` for a fragment shader
* `.comp` for a compute shader
There is also a non-shader extension
* `.conf` for a configuration file of limits, see usage statement for example
Building
--------
### Dependencies
* [CMake][cmake]: for generating compilation targets.
* [bison][bison]: _optional_, but needed when changing the grammar (glslang.y).
* [googletest][googletest]: _optional_, but should use if making any changes to glslang.
### Build steps
#### 1) Check-Out External Projects
```bash
cd <the directory glslang was cloned to, External will be a subdirectory>
git clone https://github.com/google/googletest.git External/googletest
```
#### 2) Configure
Assume the source directory is `$SOURCE_DIR` and
the build directory is `$BUILD_DIR`:
For building on Linux (assuming using the Ninja generator):
```bash
cd $BUILD_DIR
cmake -GNinja -DCMAKE_BUILD_TYPE={Debug|Release|RelWithDebInfo} \
-DCMAKE_INSTALL_PREFIX=`pwd`/install $SOURCE_DIR
```
For building on Windows:
```bash
cmake $SOURCE_DIR -DCMAKE_INSTALL_PREFIX=`pwd`/install
# The CMAKE_INSTALL_PREFIX part is for testing (explained later).
```
The CMake GUI also works for Windows (version 3.4.1 tested).
#### 3) Build and Install
```bash
# for Linux:
ninja install
# for Windows:
cmake --build . --config {Release|Debug|MinSizeRel|RelWithDebInfo} \
--target install
```
If using MSVC, after running CMake to configure, use the
Configuration Manager to check the `INSTALL` project.
### If you need to change the GLSL grammar
The grammar in `glslang/MachineIndependent/glslang.y` has to be recompiled with
bison if it changes, the output files are committed to the repo to avoid every
developer needing to have bison configured to compile the project when grammar
changes are quite infrequent. For windows you can get binaries from
[GnuWin32][bison-gnu-win32].
The command to rebuild is:
```bash
bison --defines=MachineIndependent/glslang_tab.cpp.h
-t MachineIndependent/glslang.y
-o MachineIndependent/glslang_tab.cpp
```
The above command is also available in the bash script at
`glslang/updateGrammar`.
Testing
-------
Right now, there are two test harnesses existing in glslang: one is [Google
Test](gtests/), one is the [`runtests` script](Test/runtests). The former
runs unit tests and single-shader single-threaded integration tests, while
the latter runs multiple-shader linking tests and multi-threaded tests.
### Running tests
The [`runtests` script](Test/runtests) requires compiled binaries to be
installed into `$BUILD_DIR/install`. Please make sure you have supplied the
correct configuration to CMake (using `-DCMAKE_INSTALL_PREFIX`) when building;
otherwise, you may want to modify the path in the `runtests` script.
Running Google Test-backed tests:
```bash
cd $BUILD_DIR
# for Linux:
ctest
# for Windows:
ctest -C {Debug|Release|RelWithDebInfo|MinSizeRel}
# or, run the test binary directly
# (which gives more fine-grained control like filtering):
<dir-to-glslangtests-in-build-dir>/glslangtests
```
Running `runtests` script-backed tests:
```bash
cd $SOURCE_DIR/Test && ./runtests
```
### Contributing tests
Test results should always be included with a pull request that modifies
functionality.
If you are writing unit tests, please use the Google Test framework and
place the tests under the `gtests/` directory.
Integration tests are placed in the `Test/` directory. It contains test input
and a subdirectory `baseResults/` that contains the expected results of the
tests. Both the tests and `baseResults/` are under source-code control.
Google Test runs those integration tests by reading the test input, compiling
them, and then compare against the expected results in `baseResults/`. The
integration tests to run via Google Test is registered in various
`gtests/*.FromFile.cpp` source files. `glslangtests` provides a command-line
option `--update-mode`, which, if supplied, will overwrite the golden files
under the `baseResults/` directory with real output from that invocation.
For more information, please check `gtests/` directory's
[README](gtests/README.md).
For the `runtests` script, it will generate current results in the
`localResults/` directory and `diff` them against the `baseResults/`.
When you want to update the tracked test results, they need to be
copied from `localResults/` to `baseResults/`. This can be done by
the `bump` shell script.
You can add your own private list of tests, not tracked publicly, by using
`localtestlist` to list non-tracked tests. This is automatically read
by `runtests` and included in the `diff` and `bump` process.
Programmatic Interfaces
-----------------------
Another piece of software can programmatically translate shaders to an AST
using one of two different interfaces:
* A new C++ class-oriented interface, or
* The original C functional interface
The `main()` in `StandAlone/StandAlone.cpp` shows examples using both styles.
### C++ Class Interface (new, preferred)
This interface is in roughly the last 1/3 of `ShaderLang.h`. It is in the
glslang namespace and contains the following.
```cxx
const char* GetEsslVersionString();
const char* GetGlslVersionString();
bool InitializeProcess();
void FinalizeProcess();
class TShader
bool parse(...);
void setStrings(...);
const char* getInfoLog();
class TProgram
void addShader(...);
bool link(...);
const char* getInfoLog();
Reflection queries
```
See `ShaderLang.h` and the usage of it in `StandAlone/StandAlone.cpp` for more
details.
### C Functional Interface (orignal)
This interface is in roughly the first 2/3 of `ShaderLang.h`, and referred to
as the `Sh*()` interface, as all the entry points start `Sh`.
The `Sh*()` interface takes a "compiler" call-back object, which it calls after
building call back that is passed the AST and can then execute a backend on it.
The following is a simplified resulting run-time call stack:
```c
ShCompile(shader, compiler) -> compiler(AST) -> <back end>
```
In practice, `ShCompile()` takes shader strings, default version, and
warning/error and other options for controlling compilation.
Basic Internal Operation
------------------------
* Initial lexical analysis is done by the preprocessor in
`MachineIndependent/Preprocessor`, and then refined by a GLSL scanner
in `MachineIndependent/Scan.cpp`. There is currently no use of flex.
* Code is parsed using bison on `MachineIndependent/glslang.y` with the
aid of a symbol table and an AST. The symbol table is not passed on to
the back-end; the intermediate representation stands on its own.
The tree is built by the grammar productions, many of which are
offloaded into `ParseHelper.cpp`, and by `Intermediate.cpp`.
* The intermediate representation is very high-level, and represented
as an in-memory tree. This serves to lose no information from the
original program, and to have efficient transfer of the result from
parsing to the back-end. In the AST, constants are propogated and
folded, and a very small amount of dead code is eliminated.
To aid linking and reflection, the last top-level branch in the AST
lists all global symbols.
* The primary algorithm of the back-end compiler is to traverse the
tree (high-level intermediate representation), and create an internal
object code representation. There is an example of how to do this
in `MachineIndependent/intermOut.cpp`.
* Reduction of the tree to a linear byte-code style low-level intermediate
representation is likely a good way to generate fully optimized code.
* There is currently some dead old-style linker-type code still lying around.
* Memory pool: parsing uses types derived from C++ `std` types, using a
custom allocator that puts them in a memory pool. This makes allocation
of individual container/contents just few cycles and deallocation free.
This pool is popped after the AST is made and processed.
The use is simple: if you are going to call `new`, there are three cases:
- the object comes from the pool (its base class has the macro
`POOL_ALLOCATOR_NEW_DELETE` in it) and you do not have to call `delete`
- it is a `TString`, in which case call `NewPoolTString()`, which gets
it from the pool, and there is no corresponding `delete`
- the object does not come from the pool, and you have to do normal
C++ memory management of what you `new`
[cmake]: https://cmake.org/
[bison]: https://www.gnu.org/software/bison/
[googletest]: https://github.com/google/googletest
[bison-gnu-win32]: http://gnuwin32.sourceforge.net/packages/bison.htm
+29
View File
@@ -0,0 +1,29 @@
set(SOURCES
GlslangToSpv.cpp
InReadableOrder.cpp
Logger.cpp
SpvBuilder.cpp
SPVRemapper.cpp
doc.cpp
disassemble.cpp)
set(HEADERS
spirv.hpp
GLSL.std.450.h
GlslangToSpv.h
Logger.h
SpvBuilder.h
SPVRemapper.h
spvIR.h
doc.h
disassemble.h)
add_library(SPIRV STATIC ${SOURCES} ${HEADERS})
set_property(TARGET SPIRV PROPERTY FOLDER glslang)
if(WIN32)
source_group("Source" FILES ${SOURCES} ${HEADERS})
endif(WIN32)
install(TARGETS SPIRV
ARCHIVE DESTINATION lib)
+131
View File
@@ -0,0 +1,131 @@
/*
** Copyright (c) 2014-2016 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and/or associated documentation files (the "Materials"),
** to deal in the Materials without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Materials, and to permit persons to whom the
** Materials are furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Materials.
**
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
** IN THE MATERIALS.
*/
#ifndef GLSLstd450_H
#define GLSLstd450_H
static const int GLSLstd450Version = 100;
static const int GLSLstd450Revision = 1;
enum GLSLstd450 {
GLSLstd450Bad = 0, // Don't use
GLSLstd450Round = 1,
GLSLstd450RoundEven = 2,
GLSLstd450Trunc = 3,
GLSLstd450FAbs = 4,
GLSLstd450SAbs = 5,
GLSLstd450FSign = 6,
GLSLstd450SSign = 7,
GLSLstd450Floor = 8,
GLSLstd450Ceil = 9,
GLSLstd450Fract = 10,
GLSLstd450Radians = 11,
GLSLstd450Degrees = 12,
GLSLstd450Sin = 13,
GLSLstd450Cos = 14,
GLSLstd450Tan = 15,
GLSLstd450Asin = 16,
GLSLstd450Acos = 17,
GLSLstd450Atan = 18,
GLSLstd450Sinh = 19,
GLSLstd450Cosh = 20,
GLSLstd450Tanh = 21,
GLSLstd450Asinh = 22,
GLSLstd450Acosh = 23,
GLSLstd450Atanh = 24,
GLSLstd450Atan2 = 25,
GLSLstd450Pow = 26,
GLSLstd450Exp = 27,
GLSLstd450Log = 28,
GLSLstd450Exp2 = 29,
GLSLstd450Log2 = 30,
GLSLstd450Sqrt = 31,
GLSLstd450InverseSqrt = 32,
GLSLstd450Determinant = 33,
GLSLstd450MatrixInverse = 34,
GLSLstd450Modf = 35, // second operand needs an OpVariable to write to
GLSLstd450ModfStruct = 36, // no OpVariable operand
GLSLstd450FMin = 37,
GLSLstd450UMin = 38,
GLSLstd450SMin = 39,
GLSLstd450FMax = 40,
GLSLstd450UMax = 41,
GLSLstd450SMax = 42,
GLSLstd450FClamp = 43,
GLSLstd450UClamp = 44,
GLSLstd450SClamp = 45,
GLSLstd450FMix = 46,
GLSLstd450IMix = 47, // Reserved
GLSLstd450Step = 48,
GLSLstd450SmoothStep = 49,
GLSLstd450Fma = 50,
GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to
GLSLstd450FrexpStruct = 52, // no OpVariable operand
GLSLstd450Ldexp = 53,
GLSLstd450PackSnorm4x8 = 54,
GLSLstd450PackUnorm4x8 = 55,
GLSLstd450PackSnorm2x16 = 56,
GLSLstd450PackUnorm2x16 = 57,
GLSLstd450PackHalf2x16 = 58,
GLSLstd450PackDouble2x32 = 59,
GLSLstd450UnpackSnorm2x16 = 60,
GLSLstd450UnpackUnorm2x16 = 61,
GLSLstd450UnpackHalf2x16 = 62,
GLSLstd450UnpackSnorm4x8 = 63,
GLSLstd450UnpackUnorm4x8 = 64,
GLSLstd450UnpackDouble2x32 = 65,
GLSLstd450Length = 66,
GLSLstd450Distance = 67,
GLSLstd450Cross = 68,
GLSLstd450Normalize = 69,
GLSLstd450FaceForward = 70,
GLSLstd450Reflect = 71,
GLSLstd450Refract = 72,
GLSLstd450FindILsb = 73,
GLSLstd450FindSMsb = 74,
GLSLstd450FindUMsb = 75,
GLSLstd450InterpolateAtCentroid = 76,
GLSLstd450InterpolateAtSample = 77,
GLSLstd450InterpolateAtOffset = 78,
GLSLstd450NMin = 79,
GLSLstd450NMax = 80,
GLSLstd450NClamp = 81,
GLSLstd450Count
};
#endif // #ifndef GLSLstd450_H
+4505
View File
File diff suppressed because it is too large Load Diff
+50
View File
@@ -0,0 +1,50 @@
//
//Copyright (C) 2014 LunarG, Inc.
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions
//are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
#include "../glslang/Include/intermediate.h"
#include <string>
#include <vector>
#include "Logger.h"
namespace glslang {
void GetSpirvVersion(std::string&);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger);
void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName);
void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName);
}
+113
View File
@@ -0,0 +1,113 @@
//
//Copyright (C) 2016 Google, Inc.
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions
//are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
// The SPIR-V spec requires code blocks to appear in an order satisfying the
// dominator-tree direction (ie, dominator before the dominated). This is,
// actually, easy to achieve: any pre-order CFG traversal algorithm will do it.
// Because such algorithms visit a block only after traversing some path to it
// from the root, they necessarily visit the block's idom first.
//
// But not every graph-traversal algorithm outputs blocks in an order that
// appears logical to human readers. The problem is that unrelated branches may
// be interspersed with each other, and merge blocks may come before some of the
// branches being merged.
//
// A good, human-readable order of blocks may be achieved by performing
// depth-first search but delaying merge nodes until after all their branches
// have been visited. This is implemented below by the inReadableOrder()
// function.
#include "spvIR.h"
#include <cassert>
#include <unordered_map>
using spv::Block;
using spv::Id;
namespace {
// Traverses CFG in a readable order, invoking a pre-set callback on each block.
// Use by calling visit() on the root block.
class ReadableOrderTraverser {
public:
explicit ReadableOrderTraverser(std::function<void(Block*)> callback) : callback_(callback) {}
// Visits the block if it hasn't been visited already and isn't currently
// being delayed. Invokes callback(block), then descends into its
// successors. Delays merge-block and continue-block processing until all
// the branches have been completed.
void visit(Block* block)
{
assert(block);
if (visited_[block] || delayed_[block])
return;
callback_(block);
visited_[block] = true;
Block* mergeBlock = nullptr;
Block* continueBlock = nullptr;
auto mergeInst = block->getMergeInstruction();
if (mergeInst) {
Id mergeId = mergeInst->getIdOperand(0);
mergeBlock = block->getParent().getParent().getInstruction(mergeId)->getBlock();
delayed_[mergeBlock] = true;
if (mergeInst->getOpCode() == spv::OpLoopMerge) {
Id continueId = mergeInst->getIdOperand(1);
continueBlock =
block->getParent().getParent().getInstruction(continueId)->getBlock();
delayed_[continueBlock] = true;
}
}
const auto successors = block->getSuccessors();
for (auto it = successors.cbegin(); it != successors.cend(); ++it)
visit(*it);
if (continueBlock) {
delayed_[continueBlock] = false;
visit(continueBlock);
}
if (mergeBlock) {
delayed_[mergeBlock] = false;
visit(mergeBlock);
}
}
private:
std::function<void(Block*)> callback_;
// Whether a block has already been visited or is being delayed.
std::unordered_map<Block *, bool> visited_, delayed_;
};
}
void spv::inReadableOrder(Block* root, std::function<void(Block*)> callback)
{
ReadableOrderTraverser(callback).visit(root);
}

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