mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-25 15:15:40 +00:00
Deps: Remove glslang
This commit is contained in:
parent
98241cb6ba
commit
52f1686520
|
@ -10,8 +10,6 @@ disable_compiler_warnings_for_target(libchdr)
|
||||||
add_subdirectory(xxhash EXCLUDE_FROM_ALL)
|
add_subdirectory(xxhash EXCLUDE_FROM_ALL)
|
||||||
disable_compiler_warnings_for_target(xxhash)
|
disable_compiler_warnings_for_target(xxhash)
|
||||||
add_subdirectory(rapidjson EXCLUDE_FROM_ALL)
|
add_subdirectory(rapidjson EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(glslang EXCLUDE_FROM_ALL)
|
|
||||||
disable_compiler_warnings_for_target(glslang)
|
|
||||||
add_subdirectory(imgui EXCLUDE_FROM_ALL)
|
add_subdirectory(imgui EXCLUDE_FROM_ALL)
|
||||||
disable_compiler_warnings_for_target(imgui)
|
disable_compiler_warnings_for_target(imgui)
|
||||||
add_subdirectory(simpleini EXCLUDE_FROM_ALL)
|
add_subdirectory(simpleini EXCLUDE_FROM_ALL)
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
Language: Cpp
|
|
||||||
IndentWidth: 4
|
|
||||||
PointerAlignment: Left
|
|
||||||
BreakBeforeBraces: Custom
|
|
||||||
BraceWrapping: { AfterFunction: true, AfterControlStatement: false }
|
|
||||||
IndentCaseLabels: false
|
|
||||||
ReflowComments: false
|
|
||||||
ColumnLimit: 120
|
|
||||||
AccessModifierOffset: -4
|
|
||||||
AlignTrailingComments: true
|
|
||||||
AllowShortBlocksOnASingleLine: false
|
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
|
@ -1,55 +0,0 @@
|
||||||
set(SRCS
|
|
||||||
glslang/CInterface/glslang_c_interface.cpp
|
|
||||||
glslang/GenericCodeGen/CodeGen.cpp
|
|
||||||
glslang/GenericCodeGen/Link.cpp
|
|
||||||
glslang/MachineIndependent/attribute.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/iomapper.cpp
|
|
||||||
glslang/MachineIndependent/limits.cpp
|
|
||||||
glslang/MachineIndependent/linkValidate.cpp
|
|
||||||
glslang/MachineIndependent/parseConst.cpp
|
|
||||||
glslang/MachineIndependent/ParseContextBase.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/PpScanner.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
|
|
||||||
OGLCompilersDLL/InitializeDll.cpp
|
|
||||||
SPIRV/disassemble.cpp
|
|
||||||
SPIRV/doc.cpp
|
|
||||||
SPIRV/GlslangToSpv.cpp
|
|
||||||
SPIRV/InReadableOrder.cpp
|
|
||||||
SPIRV/Logger.cpp
|
|
||||||
SPIRV/SpvBuilder.cpp
|
|
||||||
SPIRV/SpvPostProcess.cpp
|
|
||||||
SPIRV/SPVRemapper.cpp
|
|
||||||
SPIRV/SpvTools.cpp
|
|
||||||
StandAlone/ResourceLimits.cpp
|
|
||||||
StandAlone/resource_limits_c.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(glslang ${SRCS})
|
|
||||||
|
|
||||||
if(WIN32)
|
|
||||||
target_sources(glslang PRIVATE glslang/OSDependent/Windows/ossource.cpp)
|
|
||||||
else()
|
|
||||||
target_sources(glslang PRIVATE glslang/OSDependent/Unix/ossource.cpp)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_include_directories(glslang PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
A reminder that this issue tracker is managed by the Khronos Group. Interactions here should follow the Khronos Code of Conduct (https://www.khronos.org/developers/code-of-conduct), which prohibits aggressive or derogatory language. Please keep the discussion friendly and civil.
|
|
|
@ -1,108 +0,0 @@
|
||||||
Here, glslang proper means core GLSL parsing, HLSL parsing, and SPIR-V code
|
|
||||||
generation. Glslang proper requires use of two licenses, one that covers
|
|
||||||
non-preprocessing and an additional one that covers preprocessing.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Other parts, outside of glslang proper, include:
|
|
||||||
|
|
||||||
- gl_types.h, only needed for OpenGL-like reflection, and can be left out of
|
|
||||||
a parse and codegen project. See it for its license.
|
|
||||||
|
|
||||||
- update_glslang_sources.py, which is not part of the project proper and does
|
|
||||||
not need to be used.
|
|
||||||
|
|
||||||
- the SPIR-V "remapper", which is optional, but has the same license as
|
|
||||||
glslang proper
|
|
||||||
|
|
||||||
- Google tests and SPIR-V tools, and anything in the external subdirectory
|
|
||||||
are external and optional; see them for their respective licenses.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The core of glslang-proper, minus the preprocessor is licenced as follows:
|
|
||||||
|
|
||||||
//
|
|
||||||
// Copyright (C) 2015-2018 Google, Inc.
|
|
||||||
// Copyright (C) <various other dates and companies>
|
|
||||||
//
|
|
||||||
// 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 preprocessor has the core license stated above, plus an additional licence:
|
|
||||||
|
|
||||||
/****************************************************************************\
|
|
||||||
Copyright (c) 2002, NVIDIA Corporation.
|
|
||||||
|
|
||||||
NVIDIA Corporation("NVIDIA") supplies this software to you in
|
|
||||||
consideration of your agreement to the following terms, and your use,
|
|
||||||
installation, modification or redistribution of this NVIDIA software
|
|
||||||
constitutes acceptance of these terms. If you do not agree with these
|
|
||||||
terms, please do not use, install, modify or redistribute this NVIDIA
|
|
||||||
software.
|
|
||||||
|
|
||||||
In consideration of your agreement to abide by the following terms, and
|
|
||||||
subject to these terms, NVIDIA grants you a personal, non-exclusive
|
|
||||||
license, under NVIDIA's copyrights in this original NVIDIA software (the
|
|
||||||
"NVIDIA Software"), to use, reproduce, modify and redistribute the
|
|
||||||
NVIDIA Software, with or without modifications, in source and/or binary
|
|
||||||
forms; provided that if you redistribute the NVIDIA Software, you must
|
|
||||||
retain the copyright notice of NVIDIA, this notice and the following
|
|
||||||
text and disclaimers in all such redistributions of the NVIDIA Software.
|
|
||||||
Neither the name, trademarks, service marks nor logos of NVIDIA
|
|
||||||
Corporation may be used to endorse or promote products derived from the
|
|
||||||
NVIDIA Software without specific prior written permission from NVIDIA.
|
|
||||||
Except as expressly stated in this notice, no other rights or licenses
|
|
||||||
express or implied, are granted by NVIDIA herein, including but not
|
|
||||||
limited to any patent rights that may be infringed by your derivative
|
|
||||||
works or by other works in which the NVIDIA Software may be
|
|
||||||
incorporated. No hardware is licensed hereunder.
|
|
||||||
|
|
||||||
THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
|
|
||||||
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
|
||||||
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
|
|
||||||
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
|
||||||
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
|
|
||||||
PRODUCTS.
|
|
||||||
|
|
||||||
IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
|
|
||||||
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
||||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
|
|
||||||
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
|
|
||||||
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
|
|
||||||
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
|
||||||
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
\****************************************************************************/
|
|
|
@ -1,166 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define SH_EXPORTING
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#include "InitializeDll.h"
|
|
||||||
#include "../glslang/Include/InitializeGlobals.h"
|
|
||||||
#include "../glslang/Public/ShaderLang.h"
|
|
||||||
#include "../glslang/Include/PoolAlloc.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
OS_TLSIndex ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
|
|
||||||
|
|
||||||
// Per-process initialization.
|
|
||||||
// Needs to be called at least once before parsing, etc. is done.
|
|
||||||
// Will also do thread initialization for the calling thread; other
|
|
||||||
// threads will need to do that explicitly.
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per-thread scoped initialization.
|
|
||||||
// Must be called at least once by each new thread sharing the
|
|
||||||
// symbol tables, etc., needed to parse.
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (! OS_SetTLSValue(ThreadInitializeIndex, (void *)1)) {
|
|
||||||
assert(0 && "InitThread(): Unable to set init flag.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
glslang::SetThreadPoolAllocator(nullptr);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not necessary to call this: InitThread() is reentrant, and the need
|
|
||||||
// to do per thread tear down has been removed.
|
|
||||||
//
|
|
||||||
// This is kept, with memory management removed, to satisfy any exiting
|
|
||||||
// calls to it that rely on it.
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not necessary to call this: InitProcess() is reentrant.
|
|
||||||
//
|
|
||||||
// This is kept, with memory management removed, to satisfy any exiting
|
|
||||||
// calls to it that rely on it.
|
|
||||||
//
|
|
||||||
// Users of glslang should call shFinalize() or glslang::FinalizeProcess() for
|
|
||||||
// process-scoped memory tear down.
|
|
||||||
bool DetachProcess()
|
|
||||||
{
|
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
if (ThreadInitializeIndex == OS_INVALID_TLS_INDEX)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
success = DetachThread();
|
|
||||||
|
|
||||||
OS_FreeTLSIndex(ThreadInitializeIndex);
|
|
||||||
ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
|
|
||||||
DeinitializePoolIndex();
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
|
@ -1,49 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
#ifndef __INITIALIZEDLL_H
|
|
||||||
#define __INITIALIZEDLL_H
|
|
||||||
|
|
||||||
#include "../glslang/OSDependent/osinclude.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
bool InitProcess();
|
|
||||||
bool InitThread();
|
|
||||||
bool DetachThread(); // not called from standalone, perhaps other tools rely on parts of it
|
|
||||||
bool DetachProcess(); // not called from standalone, perhaps other tools rely on parts of it
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // __INITIALIZEDLL_H
|
|
||||||
|
|
|
@ -1,137 +0,0 @@
|
||||||
|
|
||||||
VERSION
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
spirv-remap 0.97
|
|
||||||
|
|
||||||
INTRO:
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
spirv-remap is a utility to improve compression of SPIR-V binary files via
|
|
||||||
entropy reduction, plus optional stripping of debug information and
|
|
||||||
load/store optimization. It transforms SPIR-V to SPIR-V, remapping IDs. The
|
|
||||||
resulting modules have an increased ID range (IDs are not as tightly packed
|
|
||||||
around zero), but will compress better when multiple modules are compressed
|
|
||||||
together, since compressor's dictionary can find better cross module
|
|
||||||
commonality.
|
|
||||||
|
|
||||||
Remapping is accomplished via canonicalization. Thus, modules can be
|
|
||||||
compressed one at a time with no loss of quality relative to operating on
|
|
||||||
many modules at once. The command line tool operates on multiple modules
|
|
||||||
only in the trivial repetition sense, for ease of use. The remapper API
|
|
||||||
only accepts a single module at a time.
|
|
||||||
|
|
||||||
There are two modes of use: command line, and a C++11 API. Both are
|
|
||||||
described below.
|
|
||||||
|
|
||||||
spirv-remap is currently in an alpha state. Although there are no known
|
|
||||||
remapping defects, it has only been exercised on one real world game shader
|
|
||||||
workload.
|
|
||||||
|
|
||||||
|
|
||||||
FEEDBACK
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
Report defects, enhancements requests, code improvements, etc to:
|
|
||||||
spvremapper@lunarg.com
|
|
||||||
|
|
||||||
|
|
||||||
COMMAND LINE USAGE:
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
Examples are given with a verbosity of one (-v), but more verbosity can be
|
|
||||||
had via -vv, -vvv, etc, or an integer parameter to --verbose, such as
|
|
||||||
"--verbose 4". With no verbosity, the command is silent and returns 0 on
|
|
||||||
success, and a positive integer error on failure.
|
|
||||||
|
|
||||||
Pre-built binaries for several OSs are available. Examples presented are
|
|
||||||
for Linux. Command line arguments can be provided in any order.
|
|
||||||
|
|
||||||
1. Basic ID remapping
|
|
||||||
|
|
||||||
Perform ID remapping on all shaders in "*.spv", writing new files with
|
|
||||||
the same basenames to /tmp/out_dir.
|
|
||||||
|
|
||||||
spirv-remap -v --map all --input *.spv --output /tmp/out_dir
|
|
||||||
|
|
||||||
2. Perform all possible size reductions
|
|
||||||
|
|
||||||
spirv-remap-linux-64 -v --do-everything --input *.spv --output /tmp/out_dir
|
|
||||||
|
|
||||||
Note that --do-everything is a synonym for:
|
|
||||||
|
|
||||||
--map all --dce all --opt all --strip all
|
|
||||||
|
|
||||||
API USAGE:
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
The public interface to the remapper is defined in SPIRV/SPVRemapper.h as follows:
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
|
|
||||||
class spirvbin_t
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Options { ... };
|
|
||||||
spirvbin_t(int verbose = 0); // construct
|
|
||||||
|
|
||||||
// remap an existing binary in memory
|
|
||||||
void remap(std::vector<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
|
|
||||||
member, so need only be set up once, not once per spirvbin_t instance.
|
|
||||||
|
|
||||||
Log messages are supplied to registerLogHandler(). By default, log
|
|
||||||
messages are eaten silently. The log handler is also a static member.
|
|
||||||
|
|
||||||
BUILD DEPENDENCIES:
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
1. C++11 compatible compiler
|
|
||||||
2. cmake
|
|
||||||
3. glslang
|
|
||||||
|
|
||||||
|
|
||||||
BUILDING
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
The standalone remapper is built along side 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)
|
|
||||||
|
|
|
@ -1,442 +0,0 @@
|
||||||
# News
|
|
||||||
|
|
||||||
[![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)
|
|
||||||
|
|
||||||
## Planned Deprecations/Removals
|
|
||||||
|
|
||||||
1. **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.
|
|
||||||
|
|
||||||
2. **Visual Studio 2013, 20-July, 2020.** Keeping code compiling for MS Visual Studio 2013 will no longer be
|
|
||||||
a goal as of July 20, 2020, the fifth anniversary of the release of Visual Studio 2015.
|
|
||||||
|
|
||||||
# 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:
|
|
||||||
|
|
||||||
https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/
|
|
||||||
|
|
||||||
The above page, while not kept up to date, includes additional information regarding glslang as a reference validator.
|
|
||||||
|
|
||||||
# How to Use Glslang
|
|
||||||
|
|
||||||
## Execution of Standalone Wrapper
|
|
||||||
|
|
||||||
To use the standalone binary form, execute `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
|
|
||||||
|
|
||||||
Instead of building manually, you can also download the binaries for your
|
|
||||||
platform directly from the [master-tot release][master-tot-release] on GitHub.
|
|
||||||
Those binaries are automatically uploaded by the buildbots after successful
|
|
||||||
testing and they always reflect the current top of the tree of the master
|
|
||||||
branch.
|
|
||||||
|
|
||||||
### Dependencies
|
|
||||||
|
|
||||||
* A C++11 compiler.
|
|
||||||
(For MSVS: 2015 is recommended, 2013 is fully supported/tested, and 2010 support is attempted, but not tested.)
|
|
||||||
* [CMake][cmake]: for generating compilation targets.
|
|
||||||
* make: _Linux_, ninja is an alternative, if configured.
|
|
||||||
* [Python 3.x][python]: for executing SPIRV-Tools scripts. (Optional if not using SPIRV-Tools and the 'External' subdirectory does not exist.)
|
|
||||||
* [bison][bison]: _optional_, but needed when changing the grammar (glslang.y).
|
|
||||||
* [googletest][googletest]: _optional_, but should use if making any changes to glslang.
|
|
||||||
|
|
||||||
### Build steps
|
|
||||||
|
|
||||||
The following steps assume a Bash shell. On Windows, that could be the Git Bash
|
|
||||||
shell or some other shell of your choosing.
|
|
||||||
|
|
||||||
#### 1) Check-Out this project
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd <parent of where you want glslang to be>
|
|
||||||
git clone https://github.com/KhronosGroup/glslang.git
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2) 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
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to use googletest with Visual Studio 2013, you also need to check out an older version:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# to use googletest with Visual Studio 2013
|
|
||||||
cd External/googletest
|
|
||||||
git checkout 440527a61e1c91188195f7de212c63c77e8f0a45
|
|
||||||
cd ../..
|
|
||||||
```
|
|
||||||
|
|
||||||
If you wish to assure that SPIR-V generated from HLSL is legal for Vulkan,
|
|
||||||
wish to invoke -Os to reduce SPIR-V size from HLSL or GLSL, or wish to run the
|
|
||||||
integrated test suite, install spirv-tools with this:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./update_glslang_sources.py
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3) Configure
|
|
||||||
|
|
||||||
Assume the source directory is `$SOURCE_DIR` and the build directory is
|
|
||||||
`$BUILD_DIR`. First ensure the build directory exists, then navigate to it:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
mkdir -p $BUILD_DIR
|
|
||||||
cd $BUILD_DIR
|
|
||||||
```
|
|
||||||
|
|
||||||
For building on Linux:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$(pwd)/install" $SOURCE_DIR
|
|
||||||
# "Release" (for CMAKE_BUILD_TYPE) could also be "Debug" or "RelWithDebInfo"
|
|
||||||
```
|
|
||||||
|
|
||||||
For building on Android:
|
|
||||||
```bash
|
|
||||||
cmake $SOURCE_DIR -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="$(pwd)/install" -DANDROID_ABI=arm64-v8a -DCMAKE_BUILD_TYPE=Release -DANDROID_STL=c++_static -DANDROID_PLATFORM=android-24 -DCMAKE_SYSTEM_NAME=Android -DANDROID_TOOLCHAIN=clang -DANDROID_ARM_MODE=arm -DCMAKE_MAKE_PROGRAM=$ANDROID_NDK_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:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cmake $SOURCE_DIR -DCMAKE_INSTALL_PREFIX="$(pwd)/install"
|
|
||||||
# The CMAKE_INSTALL_PREFIX part is for testing (explained later).
|
|
||||||
```
|
|
||||||
|
|
||||||
The CMake GUI also works for Windows (version 3.4.1 tested).
|
|
||||||
|
|
||||||
Also, consider using `git config --global core.fileMode false` (or with `--local`) on Windows
|
|
||||||
to prevent the addition of execution permission on files.
|
|
||||||
|
|
||||||
#### 4) Build and Install
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# for Linux:
|
|
||||||
make -j4 install
|
|
||||||
|
|
||||||
# for Windows:
|
|
||||||
cmake --build . --config Release --target install
|
|
||||||
# "Release" (for --config) could also be "Debug", "MinSizeRel", or "RelWithDebInfo"
|
|
||||||
```
|
|
||||||
|
|
||||||
If using MSVC, after running CMake to configure, use the
|
|
||||||
Configuration Manager to check the `INSTALL` project.
|
|
||||||
|
|
||||||
### If you 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
|
|
||||||
m4 -P MachineIndependent/glslang.m4 > MachineIndependent/glslang.y
|
|
||||||
bison --defines=MachineIndependent/glslang_tab.cpp.h
|
|
||||||
-t MachineIndependent/glslang.y
|
|
||||||
-o MachineIndependent/glslang_tab.cpp
|
|
||||||
```
|
|
||||||
|
|
||||||
The above commands are also available in the bash script in `updateGrammar`,
|
|
||||||
when executed from the glslang subdirectory of the glslang repository.
|
|
||||||
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).
|
|
||||||
|
|
||||||
### Building to WASM for the Web and Node
|
|
||||||
### Building a standalone JS/WASM library for the Web and Node
|
|
||||||
|
|
||||||
Use the steps in [Build Steps](#build-steps), with the following notes/exceptions:
|
|
||||||
* `emsdk` needs to be present in your executable search path, *PATH* for
|
|
||||||
Bash-like environments:
|
|
||||||
+ [Instructions located here](https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install)
|
|
||||||
* Wrap cmake call: `emcmake cmake`
|
|
||||||
* Set `-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
|
|
||||||
(or if using your own scripts, `m4` needs a `-DGLSLANG_WEB` argument)
|
|
||||||
+ optionally, for GLSL compilation error messages, turn on
|
|
||||||
`-DENABLE_GLSLANG_WEBMIN_DEVEL=ON`
|
|
||||||
* To get a fully minimized build, make sure to use `brotli` to compress the .js
|
|
||||||
and .wasm files
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
emcmake cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GLSLANG_JS=ON \
|
|
||||||
-DENABLE_HLSL=OFF -DBUILD_TESTING=OFF -DENABLE_OPT=OFF -DINSTALL_GTEST=OFF ..
|
|
||||||
```
|
|
||||||
|
|
||||||
## Building glslang - Using vcpkg
|
|
||||||
|
|
||||||
You can download and install glslang using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
|
||||||
|
|
||||||
git clone https://github.com/Microsoft/vcpkg.git
|
|
||||||
cd vcpkg
|
|
||||||
./bootstrap-vcpkg.sh
|
|
||||||
./vcpkg integrate install
|
|
||||||
./vcpkg install glslang
|
|
||||||
|
|
||||||
The glslang port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
Right now, there are two test harnesses existing in glslang: one is [Google
|
|
||||||
Test](gtests/), one is the [`runtests` script](Test/runtests). The former
|
|
||||||
runs unit tests and single-shader single-threaded integration tests, while
|
|
||||||
the latter runs multiple-shader linking tests and multi-threaded tests.
|
|
||||||
|
|
||||||
### Running tests
|
|
||||||
|
|
||||||
The [`runtests` script](Test/runtests) requires compiled binaries to be
|
|
||||||
installed into `$BUILD_DIR/install`. Please make sure you have supplied the
|
|
||||||
correct configuration to CMake (using `-DCMAKE_INSTALL_PREFIX`) when building;
|
|
||||||
otherwise, you may want to modify the path in the `runtests` script.
|
|
||||||
|
|
||||||
Running Google Test-backed tests:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd $BUILD_DIR
|
|
||||||
|
|
||||||
# for Linux:
|
|
||||||
ctest
|
|
||||||
|
|
||||||
# for Windows:
|
|
||||||
ctest -C {Debug|Release|RelWithDebInfo|MinSizeRel}
|
|
||||||
|
|
||||||
# or, run the test binary directly
|
|
||||||
# (which gives more fine-grained control like filtering):
|
|
||||||
<dir-to-glslangtests-in-build-dir>/glslangtests
|
|
||||||
```
|
|
||||||
|
|
||||||
Running `runtests` script-backed tests:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd $SOURCE_DIR/Test && ./runtests
|
|
||||||
```
|
|
||||||
|
|
||||||
If some tests fail with validation errors, there may be a mismatch between the
|
|
||||||
version of `spirv-val` on the system and the version of glslang. In this
|
|
||||||
case, it is necessary to run `update_glslang_sources.py`. See "Check-Out
|
|
||||||
External Projects" above for more details.
|
|
||||||
|
|
||||||
### Contributing tests
|
|
||||||
|
|
||||||
Test results should always be included with a pull request that modifies
|
|
||||||
functionality.
|
|
||||||
|
|
||||||
If you are writing unit tests, please use the Google Test framework and
|
|
||||||
place the tests under the `gtests/` directory.
|
|
||||||
|
|
||||||
Integration tests are placed in the `Test/` directory. It contains test input
|
|
||||||
and a subdirectory `baseResults/` that contains the expected results of the
|
|
||||||
tests. Both the tests and `baseResults/` are under source-code control.
|
|
||||||
|
|
||||||
Google Test runs those integration tests by reading the test input, compiling
|
|
||||||
them, and then compare against the expected results in `baseResults/`. The
|
|
||||||
integration tests to run via Google Test is registered in various
|
|
||||||
`gtests/*.FromFile.cpp` source files. `glslangtests` provides a command-line
|
|
||||||
option `--update-mode`, which, if supplied, will overwrite the golden files
|
|
||||||
under the `baseResults/` directory with real output from that invocation.
|
|
||||||
For more information, please check `gtests/` directory's
|
|
||||||
[README](gtests/README.md).
|
|
||||||
|
|
||||||
For the `runtests` script, it will generate current results in the
|
|
||||||
`localResults/` directory and `diff` them against the `baseResults/`.
|
|
||||||
When you want to update the tracked test results, they need to be
|
|
||||||
copied from `localResults/` to `baseResults/`. This can be done by
|
|
||||||
the `bump` shell script.
|
|
||||||
|
|
||||||
You can add your own private list of tests, not tracked publicly, by using
|
|
||||||
`localtestlist` to list non-tracked tests. This is automatically read
|
|
||||||
by `runtests` and included in the `diff` and `bump` process.
|
|
||||||
|
|
||||||
## Programmatic Interfaces
|
|
||||||
|
|
||||||
Another piece of software can programmatically translate shaders to an AST
|
|
||||||
using one of two different interfaces:
|
|
||||||
* A new C++ class-oriented interface, or
|
|
||||||
* The original C functional interface
|
|
||||||
|
|
||||||
The `main()` in `StandAlone/StandAlone.cpp` shows examples using both styles.
|
|
||||||
|
|
||||||
### C++ Class Interface (new, preferred)
|
|
||||||
|
|
||||||
This interface is in roughly the last 1/3 of `ShaderLang.h`. It is in the
|
|
||||||
glslang namespace and contains the following, here with suggested calls
|
|
||||||
for generating SPIR-V:
|
|
||||||
|
|
||||||
```cxx
|
|
||||||
const char* GetEsslVersionString();
|
|
||||||
const char* GetGlslVersionString();
|
|
||||||
bool InitializeProcess();
|
|
||||||
void FinalizeProcess();
|
|
||||||
|
|
||||||
class TShader
|
|
||||||
setStrings(...);
|
|
||||||
setEnvInput(EShSourceHlsl or EShSourceGlsl, stage, EShClientVulkan or EShClientOpenGL, 100);
|
|
||||||
setEnvClient(EShClientVulkan or EShClientOpenGL, EShTargetVulkan_1_0 or EShTargetVulkan_1_1 or EShTargetOpenGL_450);
|
|
||||||
setEnvTarget(EShTargetSpv, EShTargetSpv_1_0 or EShTargetSpv_1_3);
|
|
||||||
bool parse(...);
|
|
||||||
const char* getInfoLog();
|
|
||||||
|
|
||||||
class TProgram
|
|
||||||
void addShader(...);
|
|
||||||
bool link(...);
|
|
||||||
const char* getInfoLog();
|
|
||||||
Reflection queries
|
|
||||||
```
|
|
||||||
|
|
||||||
For just validating (not generating code), substitute these calls:
|
|
||||||
|
|
||||||
```cxx
|
|
||||||
setEnvInput(EShSourceHlsl or EShSourceGlsl, stage, EShClientNone, 0);
|
|
||||||
setEnvClient(EShClientNone, 0);
|
|
||||||
setEnvTarget(EShTargetNone, 0);
|
|
||||||
```
|
|
||||||
|
|
||||||
See `ShaderLang.h` and the usage of it in `StandAlone/StandAlone.cpp` for more
|
|
||||||
details. There is a block comment giving more detail above the calls for
|
|
||||||
`setEnvInput, setEnvClient, and setEnvTarget`.
|
|
||||||
|
|
||||||
### C Functional Interface (original)
|
|
||||||
|
|
||||||
This interface is in roughly the first 2/3 of `ShaderLang.h`, and referred to
|
|
||||||
as the `Sh*()` interface, as all the entry points start `Sh`.
|
|
||||||
|
|
||||||
The `Sh*()` interface takes a "compiler" call-back object, which it calls after
|
|
||||||
building call back that is passed the AST and can then execute a back end on it.
|
|
||||||
|
|
||||||
The following is a simplified resulting run-time call stack:
|
|
||||||
|
|
||||||
```c
|
|
||||||
ShCompile(shader, compiler) -> compiler(AST) -> <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 propagated and
|
|
||||||
folded, and a very small amount of dead code is eliminated.
|
|
||||||
|
|
||||||
To aid linking and reflection, the last top-level branch in the AST
|
|
||||||
lists all global symbols.
|
|
||||||
|
|
||||||
* The primary algorithm of the back-end compiler is to traverse the
|
|
||||||
tree (high-level intermediate representation), and create an internal
|
|
||||||
object code representation. There is an example of how to do this
|
|
||||||
in `MachineIndependent/intermOut.cpp`.
|
|
||||||
|
|
||||||
* Reduction of the tree to a linear byte-code style low-level intermediate
|
|
||||||
representation is likely a good way to generate fully optimized code.
|
|
||||||
|
|
||||||
* There is currently some dead old-style linker-type code still lying around.
|
|
||||||
|
|
||||||
* Memory pool: parsing uses types derived from C++ `std` types, using a
|
|
||||||
custom allocator that puts them in a memory pool. This makes allocation
|
|
||||||
of individual container/contents just few cycles and deallocation free.
|
|
||||||
This pool is popped after the AST is made and processed.
|
|
||||||
|
|
||||||
The use is simple: if you are going to call `new`, there are three cases:
|
|
||||||
|
|
||||||
- the object comes from the pool (its base class has the macro
|
|
||||||
`POOL_ALLOCATOR_NEW_DELETE` in it) and you do not have to call `delete`
|
|
||||||
|
|
||||||
- it is a `TString`, in which case call `NewPoolTString()`, which gets
|
|
||||||
it from the pool, and there is no corresponding `delete`
|
|
||||||
|
|
||||||
- the object does not come from the pool, and you have to do normal
|
|
||||||
C++ memory management of what you `new`
|
|
||||||
|
|
||||||
* Features can be protected by version/extension/stage/profile:
|
|
||||||
See the comment in `glslang/MachineIndependent/Versions.cpp`.
|
|
||||||
|
|
||||||
[cmake]: https://cmake.org/
|
|
||||||
[python]: https://www.python.org/
|
|
||||||
[bison]: https://www.gnu.org/software/bison/
|
|
||||||
[googletest]: https://github.com/google/googletest
|
|
||||||
[bison-gnu-win32]: http://gnuwin32.sourceforge.net/packages/bison.htm
|
|
||||||
[master-tot-release]: https://github.com/KhronosGroup/glslang/releases/tag/master-tot
|
|
|
@ -1,108 +0,0 @@
|
||||||
/*
|
|
||||||
** Copyright (c) 2014-2016 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
** of this software and/or associated documentation files (the "Materials"),
|
|
||||||
** to deal in the Materials without restriction, including without limitation
|
|
||||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
|
||||||
** Materials are furnished to do so, subject to the following conditions:
|
|
||||||
**
|
|
||||||
** The above copyright notice and this permission notice shall be included in
|
|
||||||
** all copies or substantial portions of the Materials.
|
|
||||||
**
|
|
||||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
|
||||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
|
||||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
|
||||||
**
|
|
||||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
|
||||||
** IN THE MATERIALS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLSLextAMD_H
|
|
||||||
#define GLSLextAMD_H
|
|
||||||
|
|
||||||
static const int GLSLextAMDVersion = 100;
|
|
||||||
static const int GLSLextAMDRevision = 7;
|
|
||||||
|
|
||||||
// SPV_AMD_shader_ballot
|
|
||||||
static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot";
|
|
||||||
|
|
||||||
enum ShaderBallotAMD {
|
|
||||||
ShaderBallotBadAMD = 0, // Don't use
|
|
||||||
|
|
||||||
SwizzleInvocationsAMD = 1,
|
|
||||||
SwizzleInvocationsMaskedAMD = 2,
|
|
||||||
WriteInvocationAMD = 3,
|
|
||||||
MbcntAMD = 4,
|
|
||||||
|
|
||||||
ShaderBallotCountAMD
|
|
||||||
};
|
|
||||||
|
|
||||||
// SPV_AMD_shader_trinary_minmax
|
|
||||||
static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax";
|
|
||||||
|
|
||||||
enum ShaderTrinaryMinMaxAMD {
|
|
||||||
ShaderTrinaryMinMaxBadAMD = 0, // Don't use
|
|
||||||
|
|
||||||
FMin3AMD = 1,
|
|
||||||
UMin3AMD = 2,
|
|
||||||
SMin3AMD = 3,
|
|
||||||
FMax3AMD = 4,
|
|
||||||
UMax3AMD = 5,
|
|
||||||
SMax3AMD = 6,
|
|
||||||
FMid3AMD = 7,
|
|
||||||
UMid3AMD = 8,
|
|
||||||
SMid3AMD = 9,
|
|
||||||
|
|
||||||
ShaderTrinaryMinMaxCountAMD
|
|
||||||
};
|
|
||||||
|
|
||||||
// SPV_AMD_shader_explicit_vertex_parameter
|
|
||||||
static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter";
|
|
||||||
|
|
||||||
enum ShaderExplicitVertexParameterAMD {
|
|
||||||
ShaderExplicitVertexParameterBadAMD = 0, // Don't use
|
|
||||||
|
|
||||||
InterpolateAtVertexAMD = 1,
|
|
||||||
|
|
||||||
ShaderExplicitVertexParameterCountAMD
|
|
||||||
};
|
|
||||||
|
|
||||||
// SPV_AMD_gcn_shader
|
|
||||||
static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader";
|
|
||||||
|
|
||||||
enum GcnShaderAMD {
|
|
||||||
GcnShaderBadAMD = 0, // Don't use
|
|
||||||
|
|
||||||
CubeFaceIndexAMD = 1,
|
|
||||||
CubeFaceCoordAMD = 2,
|
|
||||||
TimeAMD = 3,
|
|
||||||
|
|
||||||
GcnShaderCountAMD
|
|
||||||
};
|
|
||||||
|
|
||||||
// SPV_AMD_gpu_shader_half_float
|
|
||||||
static const char* const E_SPV_AMD_gpu_shader_half_float = "SPV_AMD_gpu_shader_half_float";
|
|
||||||
|
|
||||||
// SPV_AMD_texture_gather_bias_lod
|
|
||||||
static const char* const E_SPV_AMD_texture_gather_bias_lod = "SPV_AMD_texture_gather_bias_lod";
|
|
||||||
|
|
||||||
// SPV_AMD_gpu_shader_int16
|
|
||||||
static const char* const E_SPV_AMD_gpu_shader_int16 = "SPV_AMD_gpu_shader_int16";
|
|
||||||
|
|
||||||
// SPV_AMD_shader_image_load_store_lod
|
|
||||||
static const char* const E_SPV_AMD_shader_image_load_store_lod = "SPV_AMD_shader_image_load_store_lod";
|
|
||||||
|
|
||||||
// SPV_AMD_shader_fragment_mask
|
|
||||||
static const char* const E_SPV_AMD_shader_fragment_mask = "SPV_AMD_shader_fragment_mask";
|
|
||||||
|
|
||||||
// SPV_AMD_gpu_shader_half_float_fetch
|
|
||||||
static const char* const E_SPV_AMD_gpu_shader_half_float_fetch = "SPV_AMD_gpu_shader_half_float_fetch";
|
|
||||||
|
|
||||||
#endif // #ifndef GLSLextAMD_H
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*
|
|
||||||
** Copyright (c) 2014-2016 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
** of this software and/or associated documentation files (the "Materials"),
|
|
||||||
** to deal in the Materials without restriction, including without limitation
|
|
||||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
|
||||||
** Materials are furnished to do so, subject to the following conditions:
|
|
||||||
**
|
|
||||||
** The above copyright notice and this permission notice shall be included in
|
|
||||||
** all copies or substantial portions of the Materials.
|
|
||||||
**
|
|
||||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
|
||||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
|
||||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
|
||||||
**
|
|
||||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
|
||||||
** IN THE MATERIALS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLSLextEXT_H
|
|
||||||
#define GLSLextEXT_H
|
|
||||||
|
|
||||||
static const int GLSLextEXTVersion = 100;
|
|
||||||
static const int GLSLextEXTRevision = 2;
|
|
||||||
|
|
||||||
static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export";
|
|
||||||
static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer";
|
|
||||||
static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered";
|
|
||||||
static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
|
|
||||||
static const char* const E_SPV_EXT_demote_to_helper_invocation = "SPV_EXT_demote_to_helper_invocation";
|
|
||||||
|
|
||||||
#endif // #ifndef GLSLextEXT_H
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
** Copyright (c) 2014-2020 The Khronos Group Inc.
|
|
||||||
** Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
|
|
||||||
**
|
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
** of this software and/or associated documentation files (the "Materials"),
|
|
||||||
** to deal in the Materials without restriction, including without limitation
|
|
||||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
|
||||||
** Materials are furnished to do so, subject to the following conditions:
|
|
||||||
**
|
|
||||||
** The above copyright notice and this permission notice shall be included in
|
|
||||||
** all copies or substantial portions of the Materials.
|
|
||||||
**
|
|
||||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
|
||||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
|
||||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
|
||||||
**
|
|
||||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
|
||||||
** IN THE MATERIALS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLSLextKHR_H
|
|
||||||
#define GLSLextKHR_H
|
|
||||||
|
|
||||||
static const int GLSLextKHRVersion = 100;
|
|
||||||
static const int GLSLextKHRRevision = 2;
|
|
||||||
|
|
||||||
static const char* const E_SPV_KHR_shader_ballot = "SPV_KHR_shader_ballot";
|
|
||||||
static const char* const E_SPV_KHR_subgroup_vote = "SPV_KHR_subgroup_vote";
|
|
||||||
static const char* const E_SPV_KHR_device_group = "SPV_KHR_device_group";
|
|
||||||
static const char* const E_SPV_KHR_multiview = "SPV_KHR_multiview";
|
|
||||||
static const char* const E_SPV_KHR_shader_draw_parameters = "SPV_KHR_shader_draw_parameters";
|
|
||||||
static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit_storage";
|
|
||||||
static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage";
|
|
||||||
static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class";
|
|
||||||
static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage";
|
|
||||||
static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model";
|
|
||||||
static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer";
|
|
||||||
static const char* const E_SPV_KHR_physical_storage_buffer = "SPV_KHR_physical_storage_buffer";
|
|
||||||
static const char* const E_SPV_EXT_fragment_shader_interlock = "SPV_EXT_fragment_shader_interlock";
|
|
||||||
static const char* const E_SPV_KHR_shader_clock = "SPV_KHR_shader_clock";
|
|
||||||
static const char* const E_SPV_KHR_non_semantic_info = "SPV_KHR_non_semantic_info";
|
|
||||||
static const char* const E_SPV_KHR_ray_tracing = "SPV_KHR_ray_tracing";
|
|
||||||
static const char* const E_SPV_KHR_ray_query = "SPV_KHR_ray_query";
|
|
||||||
#endif // #ifndef GLSLextKHR_H
|
|
|
@ -1,81 +0,0 @@
|
||||||
/*
|
|
||||||
** Copyright (c) 2014-2017 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
** of this software and/or associated documentation files (the "Materials"),
|
|
||||||
** to deal in the Materials without restriction, including without limitation
|
|
||||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
|
||||||
** Materials are furnished to do so, subject to the following conditions:
|
|
||||||
**
|
|
||||||
** The above copyright notice and this permission notice shall be included in
|
|
||||||
** all copies or substantial portions of the Materials.
|
|
||||||
**
|
|
||||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
|
||||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
|
||||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
|
||||||
**
|
|
||||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
|
||||||
** IN THE MATERIALS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLSLextNV_H
|
|
||||||
#define GLSLextNV_H
|
|
||||||
|
|
||||||
enum BuiltIn;
|
|
||||||
enum Decoration;
|
|
||||||
enum Op;
|
|
||||||
enum Capability;
|
|
||||||
|
|
||||||
static const int GLSLextNVVersion = 100;
|
|
||||||
static const int GLSLextNVRevision = 11;
|
|
||||||
|
|
||||||
//SPV_NV_sample_mask_override_coverage
|
|
||||||
const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage";
|
|
||||||
|
|
||||||
//SPV_NV_geometry_shader_passthrough
|
|
||||||
const char* const E_SPV_NV_geometry_shader_passthrough = "SPV_NV_geometry_shader_passthrough";
|
|
||||||
|
|
||||||
//SPV_NV_viewport_array2
|
|
||||||
const char* const E_SPV_NV_viewport_array2 = "SPV_NV_viewport_array2";
|
|
||||||
const char* const E_ARB_shader_viewport_layer_array = "SPV_ARB_shader_viewport_layer_array";
|
|
||||||
|
|
||||||
//SPV_NV_stereo_view_rendering
|
|
||||||
const char* const E_SPV_NV_stereo_view_rendering = "SPV_NV_stereo_view_rendering";
|
|
||||||
|
|
||||||
//SPV_NVX_multiview_per_view_attributes
|
|
||||||
const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes";
|
|
||||||
|
|
||||||
//SPV_NV_shader_subgroup_partitioned
|
|
||||||
const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned";
|
|
||||||
|
|
||||||
//SPV_NV_fragment_shader_barycentric
|
|
||||||
const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric";
|
|
||||||
|
|
||||||
//SPV_NV_compute_shader_derivatives
|
|
||||||
const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives";
|
|
||||||
|
|
||||||
//SPV_NV_shader_image_footprint
|
|
||||||
const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint";
|
|
||||||
|
|
||||||
//SPV_NV_mesh_shader
|
|
||||||
const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader";
|
|
||||||
|
|
||||||
//SPV_NV_raytracing
|
|
||||||
const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing";
|
|
||||||
|
|
||||||
//SPV_NV_shading_rate
|
|
||||||
const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate";
|
|
||||||
|
|
||||||
//SPV_NV_cooperative_matrix
|
|
||||||
const char* const E_SPV_NV_cooperative_matrix = "SPV_NV_cooperative_matrix";
|
|
||||||
|
|
||||||
//SPV_NV_shader_sm_builtins
|
|
||||||
const char* const E_SPV_NV_shader_sm_builtins = "SPV_NV_shader_sm_builtins";
|
|
||||||
|
|
||||||
#endif // #ifndef GLSLextNV_H
|
|
|
@ -1,131 +0,0 @@
|
||||||
/*
|
|
||||||
** Copyright (c) 2014-2016 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
** of this software and/or associated documentation files (the "Materials"),
|
|
||||||
** to deal in the Materials without restriction, including without limitation
|
|
||||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
|
||||||
** Materials are furnished to do so, subject to the following conditions:
|
|
||||||
**
|
|
||||||
** The above copyright notice and this permission notice shall be included in
|
|
||||||
** all copies or substantial portions of the Materials.
|
|
||||||
**
|
|
||||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
|
||||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
|
||||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
|
||||||
**
|
|
||||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
||||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
||||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
||||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
|
||||||
** IN THE MATERIALS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef GLSLstd450_H
|
|
||||||
#define GLSLstd450_H
|
|
||||||
|
|
||||||
static const int GLSLstd450Version = 100;
|
|
||||||
static const int GLSLstd450Revision = 1;
|
|
||||||
|
|
||||||
enum GLSLstd450 {
|
|
||||||
GLSLstd450Bad = 0, // Don't use
|
|
||||||
|
|
||||||
GLSLstd450Round = 1,
|
|
||||||
GLSLstd450RoundEven = 2,
|
|
||||||
GLSLstd450Trunc = 3,
|
|
||||||
GLSLstd450FAbs = 4,
|
|
||||||
GLSLstd450SAbs = 5,
|
|
||||||
GLSLstd450FSign = 6,
|
|
||||||
GLSLstd450SSign = 7,
|
|
||||||
GLSLstd450Floor = 8,
|
|
||||||
GLSLstd450Ceil = 9,
|
|
||||||
GLSLstd450Fract = 10,
|
|
||||||
|
|
||||||
GLSLstd450Radians = 11,
|
|
||||||
GLSLstd450Degrees = 12,
|
|
||||||
GLSLstd450Sin = 13,
|
|
||||||
GLSLstd450Cos = 14,
|
|
||||||
GLSLstd450Tan = 15,
|
|
||||||
GLSLstd450Asin = 16,
|
|
||||||
GLSLstd450Acos = 17,
|
|
||||||
GLSLstd450Atan = 18,
|
|
||||||
GLSLstd450Sinh = 19,
|
|
||||||
GLSLstd450Cosh = 20,
|
|
||||||
GLSLstd450Tanh = 21,
|
|
||||||
GLSLstd450Asinh = 22,
|
|
||||||
GLSLstd450Acosh = 23,
|
|
||||||
GLSLstd450Atanh = 24,
|
|
||||||
GLSLstd450Atan2 = 25,
|
|
||||||
|
|
||||||
GLSLstd450Pow = 26,
|
|
||||||
GLSLstd450Exp = 27,
|
|
||||||
GLSLstd450Log = 28,
|
|
||||||
GLSLstd450Exp2 = 29,
|
|
||||||
GLSLstd450Log2 = 30,
|
|
||||||
GLSLstd450Sqrt = 31,
|
|
||||||
GLSLstd450InverseSqrt = 32,
|
|
||||||
|
|
||||||
GLSLstd450Determinant = 33,
|
|
||||||
GLSLstd450MatrixInverse = 34,
|
|
||||||
|
|
||||||
GLSLstd450Modf = 35, // second operand needs an OpVariable to write to
|
|
||||||
GLSLstd450ModfStruct = 36, // no OpVariable operand
|
|
||||||
GLSLstd450FMin = 37,
|
|
||||||
GLSLstd450UMin = 38,
|
|
||||||
GLSLstd450SMin = 39,
|
|
||||||
GLSLstd450FMax = 40,
|
|
||||||
GLSLstd450UMax = 41,
|
|
||||||
GLSLstd450SMax = 42,
|
|
||||||
GLSLstd450FClamp = 43,
|
|
||||||
GLSLstd450UClamp = 44,
|
|
||||||
GLSLstd450SClamp = 45,
|
|
||||||
GLSLstd450FMix = 46,
|
|
||||||
GLSLstd450IMix = 47, // Reserved
|
|
||||||
GLSLstd450Step = 48,
|
|
||||||
GLSLstd450SmoothStep = 49,
|
|
||||||
|
|
||||||
GLSLstd450Fma = 50,
|
|
||||||
GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to
|
|
||||||
GLSLstd450FrexpStruct = 52, // no OpVariable operand
|
|
||||||
GLSLstd450Ldexp = 53,
|
|
||||||
|
|
||||||
GLSLstd450PackSnorm4x8 = 54,
|
|
||||||
GLSLstd450PackUnorm4x8 = 55,
|
|
||||||
GLSLstd450PackSnorm2x16 = 56,
|
|
||||||
GLSLstd450PackUnorm2x16 = 57,
|
|
||||||
GLSLstd450PackHalf2x16 = 58,
|
|
||||||
GLSLstd450PackDouble2x32 = 59,
|
|
||||||
GLSLstd450UnpackSnorm2x16 = 60,
|
|
||||||
GLSLstd450UnpackUnorm2x16 = 61,
|
|
||||||
GLSLstd450UnpackHalf2x16 = 62,
|
|
||||||
GLSLstd450UnpackSnorm4x8 = 63,
|
|
||||||
GLSLstd450UnpackUnorm4x8 = 64,
|
|
||||||
GLSLstd450UnpackDouble2x32 = 65,
|
|
||||||
|
|
||||||
GLSLstd450Length = 66,
|
|
||||||
GLSLstd450Distance = 67,
|
|
||||||
GLSLstd450Cross = 68,
|
|
||||||
GLSLstd450Normalize = 69,
|
|
||||||
GLSLstd450FaceForward = 70,
|
|
||||||
GLSLstd450Reflect = 71,
|
|
||||||
GLSLstd450Refract = 72,
|
|
||||||
|
|
||||||
GLSLstd450FindILsb = 73,
|
|
||||||
GLSLstd450FindSMsb = 74,
|
|
||||||
GLSLstd450FindUMsb = 75,
|
|
||||||
|
|
||||||
GLSLstd450InterpolateAtCentroid = 76,
|
|
||||||
GLSLstd450InterpolateAtSample = 77,
|
|
||||||
GLSLstd450InterpolateAtOffset = 78,
|
|
||||||
|
|
||||||
GLSLstd450NMin = 79,
|
|
||||||
GLSLstd450NMax = 80,
|
|
||||||
GLSLstd450NClamp = 81,
|
|
||||||
|
|
||||||
GLSLstd450Count
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // #ifndef GLSLstd450_H
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,61 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2014 LunarG, Inc.
|
|
||||||
// Copyright (C) 2015-2018 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1900
|
|
||||||
#pragma warning(disable : 4464) // relative include path contains '..'
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "SpvTools.h"
|
|
||||||
#include "glslang/Include/intermediate.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "Logger.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
void GetSpirvVersion(std::string&);
|
|
||||||
int GetSpirvGeneratorVersion();
|
|
||||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
|
||||||
SpvOptions* options = nullptr);
|
|
||||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
|
||||||
spv::SpvBuildLogger* logger, SpvOptions* options = nullptr);
|
|
||||||
void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName);
|
|
||||||
void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2016 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// The SPIR-V spec requires code blocks to appear in an order satisfying the
|
|
||||||
// dominator-tree direction (ie, dominator before the dominated). This is,
|
|
||||||
// actually, easy to achieve: any pre-order CFG traversal algorithm will do it.
|
|
||||||
// Because such algorithms visit a block only after traversing some path to it
|
|
||||||
// from the root, they necessarily visit the block's idom first.
|
|
||||||
//
|
|
||||||
// But not every graph-traversal algorithm outputs blocks in an order that
|
|
||||||
// appears logical to human readers. The problem is that unrelated branches may
|
|
||||||
// be interspersed with each other, and merge blocks may come before some of the
|
|
||||||
// branches being merged.
|
|
||||||
//
|
|
||||||
// A good, human-readable order of blocks may be achieved by performing
|
|
||||||
// depth-first search but delaying merge nodes until after all their branches
|
|
||||||
// have been visited. This is implemented below by the inReadableOrder()
|
|
||||||
// function.
|
|
||||||
|
|
||||||
#include "spvIR.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
using spv::Block;
|
|
||||||
using spv::Id;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
// Traverses CFG in a readable order, invoking a pre-set callback on each block.
|
|
||||||
// Use by calling visit() on the root block.
|
|
||||||
class ReadableOrderTraverser {
|
|
||||||
public:
|
|
||||||
ReadableOrderTraverser(std::function<void(Block*, spv::ReachReason, Block*)> callback)
|
|
||||||
: callback_(callback) {}
|
|
||||||
// Visits the block if it hasn't been visited already and isn't currently
|
|
||||||
// being delayed. Invokes callback(block, why, header), then descends into its
|
|
||||||
// successors. Delays merge-block and continue-block processing until all
|
|
||||||
// the branches have been completed. If |block| is an unreachable merge block or
|
|
||||||
// an unreachable continue target, then |header| is the corresponding header block.
|
|
||||||
void visit(Block* block, spv::ReachReason why, Block* header)
|
|
||||||
{
|
|
||||||
assert(block);
|
|
||||||
if (why == spv::ReachViaControlFlow) {
|
|
||||||
reachableViaControlFlow_.insert(block);
|
|
||||||
}
|
|
||||||
if (visited_.count(block) || delayed_.count(block))
|
|
||||||
return;
|
|
||||||
callback_(block, why, header);
|
|
||||||
visited_.insert(block);
|
|
||||||
Block* mergeBlock = nullptr;
|
|
||||||
Block* continueBlock = nullptr;
|
|
||||||
auto mergeInst = block->getMergeInstruction();
|
|
||||||
if (mergeInst) {
|
|
||||||
Id mergeId = mergeInst->getIdOperand(0);
|
|
||||||
mergeBlock = block->getParent().getParent().getInstruction(mergeId)->getBlock();
|
|
||||||
delayed_.insert(mergeBlock);
|
|
||||||
if (mergeInst->getOpCode() == spv::OpLoopMerge) {
|
|
||||||
Id continueId = mergeInst->getIdOperand(1);
|
|
||||||
continueBlock =
|
|
||||||
block->getParent().getParent().getInstruction(continueId)->getBlock();
|
|
||||||
delayed_.insert(continueBlock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (why == spv::ReachViaControlFlow) {
|
|
||||||
const auto& successors = block->getSuccessors();
|
|
||||||
for (auto it = successors.cbegin(); it != successors.cend(); ++it)
|
|
||||||
visit(*it, why, nullptr);
|
|
||||||
}
|
|
||||||
if (continueBlock) {
|
|
||||||
const spv::ReachReason continueWhy =
|
|
||||||
(reachableViaControlFlow_.count(continueBlock) > 0)
|
|
||||||
? spv::ReachViaControlFlow
|
|
||||||
: spv::ReachDeadContinue;
|
|
||||||
delayed_.erase(continueBlock);
|
|
||||||
visit(continueBlock, continueWhy, block);
|
|
||||||
}
|
|
||||||
if (mergeBlock) {
|
|
||||||
const spv::ReachReason mergeWhy =
|
|
||||||
(reachableViaControlFlow_.count(mergeBlock) > 0)
|
|
||||||
? spv::ReachViaControlFlow
|
|
||||||
: spv::ReachDeadMerge;
|
|
||||||
delayed_.erase(mergeBlock);
|
|
||||||
visit(mergeBlock, mergeWhy, block);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::function<void(Block*, spv::ReachReason, Block*)> callback_;
|
|
||||||
// Whether a block has already been visited or is being delayed.
|
|
||||||
std::unordered_set<Block *> visited_, delayed_;
|
|
||||||
|
|
||||||
// The set of blocks that actually are reached via control flow.
|
|
||||||
std::unordered_set<Block *> reachableViaControlFlow_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void spv::inReadableOrder(Block* root, std::function<void(Block*, spv::ReachReason, Block*)> callback)
|
|
||||||
{
|
|
||||||
ReadableOrderTraverser(callback).visit(root, spv::ReachViaControlFlow, nullptr);
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2016 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
|
|
||||||
#include "Logger.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iterator>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
|
|
||||||
void SpvBuildLogger::tbdFunctionality(const std::string& f)
|
|
||||||
{
|
|
||||||
if (std::find(std::begin(tbdFeatures), std::end(tbdFeatures), f) == std::end(tbdFeatures))
|
|
||||||
tbdFeatures.push_back(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpvBuildLogger::missingFunctionality(const std::string& f)
|
|
||||||
{
|
|
||||||
if (std::find(std::begin(missingFeatures), std::end(missingFeatures), f) == std::end(missingFeatures))
|
|
||||||
missingFeatures.push_back(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string SpvBuildLogger::getAllMessages() const {
|
|
||||||
std::ostringstream messages;
|
|
||||||
for (auto it = tbdFeatures.cbegin(); it != tbdFeatures.cend(); ++it)
|
|
||||||
messages << "TBD functionality: " << *it << "\n";
|
|
||||||
for (auto it = missingFeatures.cbegin(); it != missingFeatures.cend(); ++it)
|
|
||||||
messages << "Missing functionality: " << *it << "\n";
|
|
||||||
for (auto it = warnings.cbegin(); it != warnings.cend(); ++it)
|
|
||||||
messages << "warning: " << *it << "\n";
|
|
||||||
for (auto it = errors.cbegin(); it != errors.cend(); ++it)
|
|
||||||
messages << "error: " << *it << "\n";
|
|
||||||
return messages.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end spv namespace
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,83 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2016 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
#ifndef GLSLANG_SPIRV_LOGGER_H
|
|
||||||
#define GLSLANG_SPIRV_LOGGER_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
|
|
||||||
// A class for holding all SPIR-V build status messages, including
|
|
||||||
// missing/TBD functionalities, warnings, and errors.
|
|
||||||
class SpvBuildLogger {
|
|
||||||
public:
|
|
||||||
SpvBuildLogger() {}
|
|
||||||
|
|
||||||
#ifdef GLSLANG_WEB
|
|
||||||
void tbdFunctionality(const std::string& f) { }
|
|
||||||
void missingFunctionality(const std::string& f) { }
|
|
||||||
void warning(const std::string& w) { }
|
|
||||||
void error(const std::string& e) { errors.push_back(e); }
|
|
||||||
std::string getAllMessages() { return ""; }
|
|
||||||
#else
|
|
||||||
|
|
||||||
// Registers a TBD functionality.
|
|
||||||
void tbdFunctionality(const std::string& f);
|
|
||||||
// Registers a missing functionality.
|
|
||||||
void missingFunctionality(const std::string& f);
|
|
||||||
|
|
||||||
// Logs a warning.
|
|
||||||
void warning(const std::string& w) { warnings.push_back(w); }
|
|
||||||
// Logs an error.
|
|
||||||
void error(const std::string& e) { errors.push_back(e); }
|
|
||||||
|
|
||||||
// Returns all messages accumulated in the order of:
|
|
||||||
// TBD functionalities, missing functionalities, warnings, errors.
|
|
||||||
std::string getAllMessages() const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
|
||||||
SpvBuildLogger(const SpvBuildLogger&);
|
|
||||||
|
|
||||||
std::vector<std::string> tbdFeatures;
|
|
||||||
std::vector<std::string> missingFeatures;
|
|
||||||
std::vector<std::string> warnings;
|
|
||||||
std::vector<std::string> errors;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end spv namespace
|
|
||||||
|
|
||||||
#endif // GLSLANG_SPIRV_LOGGER_H
|
|
|
@ -1,50 +0,0 @@
|
||||||
// Copyright (c) 2020 The Khronos Group Inc.
|
|
||||||
//
|
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
// copy of this software and/or associated documentation files (the
|
|
||||||
// "Materials"), to deal in the Materials without restriction, including
|
|
||||||
// without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
// distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
// permit persons to whom the Materials are furnished to do so, subject to
|
|
||||||
// the following conditions:
|
|
||||||
//
|
|
||||||
// The above copyright notice and this permission notice shall be included
|
|
||||||
// in all copies or substantial portions of the Materials.
|
|
||||||
//
|
|
||||||
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
|
||||||
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
|
||||||
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
|
||||||
// https://www.khronos.org/registry/
|
|
||||||
//
|
|
||||||
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
|
|
||||||
#define SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum {
|
|
||||||
NonSemanticDebugPrintfRevision = 1,
|
|
||||||
NonSemanticDebugPrintfRevision_BitWidthPadding = 0x7fffffff
|
|
||||||
};
|
|
||||||
|
|
||||||
enum NonSemanticDebugPrintfInstructions {
|
|
||||||
NonSemanticDebugPrintfDebugPrintf = 1,
|
|
||||||
NonSemanticDebugPrintfInstructionsMax = 0x7fffffff
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // SPIRV_UNIFIED1_NonSemanticDebugPrintf_H_
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,304 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2015 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef SPIRVREMAPPER_H
|
|
||||||
#define SPIRVREMAPPER_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
|
|
||||||
// MSVC defines __cplusplus as an older value, even when it supports almost all of 11.
|
|
||||||
// We handle that here by making our own symbol.
|
|
||||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700)
|
|
||||||
# define use_cpp11 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class spirvbin_base_t
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Options {
|
|
||||||
NONE = 0,
|
|
||||||
STRIP = (1<<0),
|
|
||||||
MAP_TYPES = (1<<1),
|
|
||||||
MAP_NAMES = (1<<2),
|
|
||||||
MAP_FUNCS = (1<<3),
|
|
||||||
DCE_FUNCS = (1<<4),
|
|
||||||
DCE_VARS = (1<<5),
|
|
||||||
DCE_TYPES = (1<<6),
|
|
||||||
OPT_LOADSTORE = (1<<7),
|
|
||||||
OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV
|
|
||||||
MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS),
|
|
||||||
DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES),
|
|
||||||
OPT_ALL = (OPT_LOADSTORE),
|
|
||||||
|
|
||||||
ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL),
|
|
||||||
DO_EVERYTHING = (STRIP | ALL_BUT_STRIP)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace SPV
|
|
||||||
|
|
||||||
#if !defined (use_cpp11)
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
class spirvbin_t : public spirvbin_base_t
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
spirvbin_t(int /*verbose = 0*/) { }
|
|
||||||
|
|
||||||
void remap(std::vector<std::uint32_t>& /*spv*/, unsigned int /*opts = 0*/)
|
|
||||||
{
|
|
||||||
printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n");
|
|
||||||
exit(5);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace SPV
|
|
||||||
|
|
||||||
#else // defined (use_cpp11)
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#include "spirv.hpp"
|
|
||||||
#include "spvIR.h"
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
|
|
||||||
// class to hold SPIR-V binary data for remapping, DCE, and debug stripping
|
|
||||||
class spirvbin_t : public spirvbin_base_t
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose), errorLatch(false)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
virtual ~spirvbin_t() { }
|
|
||||||
|
|
||||||
// remap on an existing binary in memory
|
|
||||||
void remap(std::vector<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 lambda fn / functor / etc)
|
|
||||||
static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; }
|
|
||||||
static void registerLogHandler(logfn_t handler) { logHandler = handler; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// This can be overridden to provide other message behavior if needed
|
|
||||||
virtual void msg(int minVerbosity, int indent, const std::string& txt) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Local to global, or global to local ID map
|
|
||||||
typedef std::unordered_map<spv::Id, spv::Id> idmap_t;
|
|
||||||
typedef std::unordered_set<spv::Id> idset_t;
|
|
||||||
typedef std::unordered_map<spv::Id, int> blockmap_t;
|
|
||||||
|
|
||||||
void remap(std::uint32_t opts = DO_EVERYTHING);
|
|
||||||
|
|
||||||
// Map of names to IDs
|
|
||||||
typedef std::unordered_map<std::string, spv::Id> namemap_t;
|
|
||||||
|
|
||||||
typedef std::uint32_t spirword_t;
|
|
||||||
|
|
||||||
typedef std::pair<unsigned, unsigned> range_t;
|
|
||||||
typedef std::function<void(spv::Id&)> idfn_t;
|
|
||||||
typedef std::function<bool(spv::Op, unsigned start)> instfn_t;
|
|
||||||
|
|
||||||
// Special Values for ID map:
|
|
||||||
static const spv::Id unmapped; // unchanged from default value
|
|
||||||
static const spv::Id unused; // unused ID
|
|
||||||
static const int header_size; // SPIR header = 5 words
|
|
||||||
|
|
||||||
class id_iterator_t;
|
|
||||||
|
|
||||||
// For mapping type entries between different shaders
|
|
||||||
typedef std::vector<spirword_t> typeentry_t;
|
|
||||||
typedef std::map<spv::Id, typeentry_t> globaltypes_t;
|
|
||||||
|
|
||||||
// A set that preserves position order, and a reverse map
|
|
||||||
typedef std::set<int> posmap_t;
|
|
||||||
typedef std::unordered_map<spv::Id, int> posmap_rev_t;
|
|
||||||
|
|
||||||
// Maps and ID to the size of its base type, if known.
|
|
||||||
typedef std::unordered_map<spv::Id, unsigned> typesize_map_t;
|
|
||||||
|
|
||||||
// handle error
|
|
||||||
void error(const std::string& txt) const { errorLatch = true; errorHandler(txt); }
|
|
||||||
|
|
||||||
bool isConstOp(spv::Op opCode) const;
|
|
||||||
bool isTypeOp(spv::Op opCode) const;
|
|
||||||
bool isStripOp(spv::Op opCode) const;
|
|
||||||
bool isFlowCtrl(spv::Op opCode) const;
|
|
||||||
range_t literalRange(spv::Op opCode) const;
|
|
||||||
range_t typeRange(spv::Op opCode) const;
|
|
||||||
range_t constRange(spv::Op opCode) const;
|
|
||||||
unsigned typeSizeInWords(spv::Id id) const;
|
|
||||||
unsigned idTypeSizeInWords(spv::Id id) const;
|
|
||||||
|
|
||||||
spv::Id& asId(unsigned word) { return spv[word]; }
|
|
||||||
const spv::Id& asId(unsigned word) const { return spv[word]; }
|
|
||||||
spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); }
|
|
||||||
std::uint32_t asOpCodeHash(unsigned word);
|
|
||||||
spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); }
|
|
||||||
unsigned asWordCount(unsigned word) const { return opWordCount(spv[word]); }
|
|
||||||
spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); }
|
|
||||||
unsigned idPos(spv::Id id) const;
|
|
||||||
|
|
||||||
static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; }
|
|
||||||
static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); }
|
|
||||||
|
|
||||||
// Header access & set methods
|
|
||||||
spirword_t magic() const { return spv[0]; } // return magic number
|
|
||||||
spirword_t bound() const { return spv[3]; } // return Id bound from header
|
|
||||||
spirword_t bound(spirword_t b) { return spv[3] = b; }
|
|
||||||
spirword_t genmagic() const { return spv[2]; } // generator magic
|
|
||||||
spirword_t genmagic(spirword_t m) { return spv[2] = m; }
|
|
||||||
spirword_t schemaNum() const { return spv[4]; } // schema number from header
|
|
||||||
|
|
||||||
// Mapping fns: get
|
|
||||||
spv::Id localId(spv::Id id) const { return idMapL[id]; }
|
|
||||||
|
|
||||||
// Mapping fns: set
|
|
||||||
inline spv::Id localId(spv::Id id, spv::Id newId);
|
|
||||||
void countIds(spv::Id id);
|
|
||||||
|
|
||||||
// Return next unused new local ID.
|
|
||||||
// NOTE: boost::dynamic_bitset would be more efficient due to find_next(),
|
|
||||||
// which std::vector<bool> doens't have.
|
|
||||||
inline spv::Id nextUnusedId(spv::Id id);
|
|
||||||
|
|
||||||
void buildLocalMaps();
|
|
||||||
std::string literalString(unsigned word) const; // Return literal as a std::string
|
|
||||||
int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; }
|
|
||||||
|
|
||||||
bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); }
|
|
||||||
bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; }
|
|
||||||
bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; }
|
|
||||||
bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); }
|
|
||||||
bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); }
|
|
||||||
|
|
||||||
// bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const;
|
|
||||||
// spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const;
|
|
||||||
std::uint32_t hashType(unsigned typeStart) const;
|
|
||||||
|
|
||||||
spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0);
|
|
||||||
int processInstruction(unsigned word, instfn_t, idfn_t);
|
|
||||||
|
|
||||||
void validate() const;
|
|
||||||
void mapTypeConst();
|
|
||||||
void mapFnBodies();
|
|
||||||
void optLoadStore();
|
|
||||||
void dceFuncs();
|
|
||||||
void dceVars();
|
|
||||||
void dceTypes();
|
|
||||||
void mapNames();
|
|
||||||
void foldIds(); // fold IDs to smallest space
|
|
||||||
void forwardLoadStores(); // load store forwarding (EXPERIMENTAL)
|
|
||||||
void offsetIds(); // create relative offset IDs
|
|
||||||
|
|
||||||
void applyMap(); // remap per local name map
|
|
||||||
void mapRemainder(); // map any IDs we haven't touched yet
|
|
||||||
void stripDebug(); // strip all debug info
|
|
||||||
void stripDeadRefs(); // strips debug info for now-dead references after DCE
|
|
||||||
void strip(); // remove debug symbols
|
|
||||||
|
|
||||||
std::vector<spirword_t> spv; // SPIR words
|
|
||||||
|
|
||||||
namemap_t nameMap; // ID names from OpName
|
|
||||||
|
|
||||||
// Since we want to also do binary ops, we can't use std::vector<bool>. we could use
|
|
||||||
// boost::dynamic_bitset, but we're trying to avoid a boost dependency.
|
|
||||||
typedef std::uint64_t bits_t;
|
|
||||||
std::vector<bits_t> mapped; // which new IDs have been mapped
|
|
||||||
static const int mBits = sizeof(bits_t) * 4;
|
|
||||||
|
|
||||||
bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); }
|
|
||||||
void setMapped(spv::Id id) { resizeMapped(id); mapped[id/mBits] |= (1LL<<(id%mBits)); }
|
|
||||||
void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); }
|
|
||||||
size_t maxMappedId() const { return mapped.size() * mBits; }
|
|
||||||
|
|
||||||
// Add a strip range for a given instruction starting at 'start'
|
|
||||||
// Note: avoiding brace initializers to please older versions os MSVC.
|
|
||||||
void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); }
|
|
||||||
|
|
||||||
// Function start and end. use unordered_map because we'll have
|
|
||||||
// many fewer functions than IDs.
|
|
||||||
std::unordered_map<spv::Id, range_t> fnPos;
|
|
||||||
|
|
||||||
// Which functions are called, anywhere in the module, with a call count
|
|
||||||
std::unordered_map<spv::Id, int> fnCalls;
|
|
||||||
|
|
||||||
posmap_t typeConstPos; // word positions that define types & consts (ordered)
|
|
||||||
posmap_rev_t idPosR; // reverse map from IDs to positions
|
|
||||||
typesize_map_t idTypeSizeMap; // maps each ID to its type size, if known.
|
|
||||||
|
|
||||||
std::vector<spv::Id> idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs
|
|
||||||
|
|
||||||
spv::Id entryPoint; // module entry point
|
|
||||||
spv::Id largestNewId; // biggest new ID we have mapped anything to
|
|
||||||
|
|
||||||
// Sections of the binary to strip, given as [begin,end)
|
|
||||||
std::vector<range_t> stripRange;
|
|
||||||
|
|
||||||
// processing options:
|
|
||||||
std::uint32_t options;
|
|
||||||
int verbose; // verbosity level
|
|
||||||
|
|
||||||
// Error latch: this is set if the error handler is ever executed. It would be better to
|
|
||||||
// use a try/catch block and throw, but that's not desired for certain environments, so
|
|
||||||
// this is the alternative.
|
|
||||||
mutable bool errorLatch;
|
|
||||||
|
|
||||||
static errorfn_t errorHandler;
|
|
||||||
static logfn_t logHandler;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace SPV
|
|
||||||
|
|
||||||
#endif // defined (use_cpp11)
|
|
||||||
#endif // SPIRVREMAPPER_H
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,838 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2014-2015 LunarG, Inc.
|
|
||||||
// Copyright (C) 2015-2020 Google, Inc.
|
|
||||||
// Copyright (C) 2017 ARM Limited.
|
|
||||||
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
//
|
|
||||||
// "Builder" is an interface to fully build SPIR-V IR. Allocate one of
|
|
||||||
// these to build (a thread safe) internal SPIR-V representation (IR),
|
|
||||||
// and then dump it as a binary stream according to the SPIR-V specification.
|
|
||||||
//
|
|
||||||
// A Builder has a 1:1 relationship with a SPIR-V module.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef SpvBuilder_H
|
|
||||||
#define SpvBuilder_H
|
|
||||||
|
|
||||||
#include "Logger.h"
|
|
||||||
#include "spirv.hpp"
|
|
||||||
#include "spvIR.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
#include <set>
|
|
||||||
#include <sstream>
|
|
||||||
#include <stack>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
Spv_1_0 = (1 << 16),
|
|
||||||
Spv_1_1 = (1 << 16) | (1 << 8),
|
|
||||||
Spv_1_2 = (1 << 16) | (2 << 8),
|
|
||||||
Spv_1_3 = (1 << 16) | (3 << 8),
|
|
||||||
Spv_1_4 = (1 << 16) | (4 << 8),
|
|
||||||
Spv_1_5 = (1 << 16) | (5 << 8),
|
|
||||||
} SpvVersion;
|
|
||||||
|
|
||||||
class Builder {
|
|
||||||
public:
|
|
||||||
Builder(unsigned int spvVersion, unsigned int userNumber, SpvBuildLogger* logger);
|
|
||||||
virtual ~Builder();
|
|
||||||
|
|
||||||
static const int maxMatrixSize = 4;
|
|
||||||
|
|
||||||
unsigned int getSpvVersion() const { return spvVersion; }
|
|
||||||
|
|
||||||
void setSource(spv::SourceLanguage lang, int version)
|
|
||||||
{
|
|
||||||
source = lang;
|
|
||||||
sourceVersion = version;
|
|
||||||
}
|
|
||||||
spv::Id getStringId(const std::string& str)
|
|
||||||
{
|
|
||||||
auto sItr = stringIds.find(str);
|
|
||||||
if (sItr != stringIds.end())
|
|
||||||
return sItr->second;
|
|
||||||
spv::Id strId = getUniqueId();
|
|
||||||
Instruction* fileString = new Instruction(strId, NoType, OpString);
|
|
||||||
const char* file_c_str = str.c_str();
|
|
||||||
fileString->addStringOperand(file_c_str);
|
|
||||||
strings.push_back(std::unique_ptr<Instruction>(fileString));
|
|
||||||
module.mapInstruction(fileString);
|
|
||||||
stringIds[file_c_str] = strId;
|
|
||||||
return strId;
|
|
||||||
}
|
|
||||||
void setSourceFile(const std::string& file)
|
|
||||||
{
|
|
||||||
sourceFileStringId = getStringId(file);
|
|
||||||
}
|
|
||||||
void setSourceText(const std::string& text) { sourceText = text; }
|
|
||||||
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
|
|
||||||
void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); }
|
|
||||||
void setEmitOpLines() { emitOpLines = true; }
|
|
||||||
void addExtension(const char* ext) { extensions.insert(ext); }
|
|
||||||
void removeExtension(const char* ext)
|
|
||||||
{
|
|
||||||
extensions.erase(ext);
|
|
||||||
}
|
|
||||||
void addIncorporatedExtension(const char* ext, SpvVersion incorporatedVersion)
|
|
||||||
{
|
|
||||||
if (getSpvVersion() < static_cast<unsigned>(incorporatedVersion))
|
|
||||||
addExtension(ext);
|
|
||||||
}
|
|
||||||
void promoteIncorporatedExtension(const char* baseExt, const char* promoExt, SpvVersion incorporatedVersion)
|
|
||||||
{
|
|
||||||
removeExtension(baseExt);
|
|
||||||
addIncorporatedExtension(promoExt, incorporatedVersion);
|
|
||||||
}
|
|
||||||
void addInclude(const std::string& name, const std::string& text)
|
|
||||||
{
|
|
||||||
spv::Id incId = getStringId(name);
|
|
||||||
includeFiles[incId] = &text;
|
|
||||||
}
|
|
||||||
Id import(const char*);
|
|
||||||
void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
|
|
||||||
{
|
|
||||||
addressModel = addr;
|
|
||||||
memoryModel = mem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addCapability(spv::Capability cap) { capabilities.insert(cap); }
|
|
||||||
|
|
||||||
// To get a new <id> for anything needing a new one.
|
|
||||||
Id getUniqueId() { return ++uniqueId; }
|
|
||||||
|
|
||||||
// To get a set of new <id>s, e.g., for a set of function parameters
|
|
||||||
Id getUniqueIds(int numIds)
|
|
||||||
{
|
|
||||||
Id id = uniqueId + 1;
|
|
||||||
uniqueId += numIds;
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate OpLine for non-filename-based #line directives (ie no filename
|
|
||||||
// seen yet): Log the current line, and if different than the last one,
|
|
||||||
// issue a new OpLine using the new line and current source file name.
|
|
||||||
void setLine(int line);
|
|
||||||
|
|
||||||
// If filename null, generate OpLine for non-filename-based line directives,
|
|
||||||
// else do filename-based: Log the current line and file, and if different
|
|
||||||
// than the last one, issue a new OpLine using the new line and file
|
|
||||||
// name.
|
|
||||||
void setLine(int line, const char* filename);
|
|
||||||
// Low-level OpLine. See setLine() for a layered helper.
|
|
||||||
void addLine(Id fileName, int line, int column);
|
|
||||||
|
|
||||||
// For creating new types (will return old type if the requested one was already made).
|
|
||||||
Id makeVoidType();
|
|
||||||
Id makeBoolType();
|
|
||||||
Id makePointer(StorageClass, Id pointee);
|
|
||||||
Id makeForwardPointer(StorageClass);
|
|
||||||
Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee);
|
|
||||||
Id makeIntegerType(int width, bool hasSign); // generic
|
|
||||||
Id makeIntType(int width) { return makeIntegerType(width, true); }
|
|
||||||
Id makeUintType(int width) { return makeIntegerType(width, false); }
|
|
||||||
Id makeFloatType(int width);
|
|
||||||
Id makeStructType(const std::vector<Id>& members, const char*);
|
|
||||||
Id makeStructResultType(Id type0, Id type1);
|
|
||||||
Id makeVectorType(Id component, int size);
|
|
||||||
Id makeMatrixType(Id component, int cols, int rows);
|
|
||||||
Id makeArrayType(Id element, Id sizeId, int stride); // 0 stride means no stride decoration
|
|
||||||
Id makeRuntimeArray(Id element);
|
|
||||||
Id makeFunctionType(Id returnType, const std::vector<Id>& paramTypes);
|
|
||||||
Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
|
|
||||||
Id makeSamplerType();
|
|
||||||
Id makeSampledImageType(Id imageType);
|
|
||||||
Id makeCooperativeMatrixType(Id component, Id scope, Id rows, Id cols);
|
|
||||||
|
|
||||||
// accelerationStructureNV type
|
|
||||||
Id makeAccelerationStructureType();
|
|
||||||
// rayQueryEXT type
|
|
||||||
Id makeRayQueryType();
|
|
||||||
|
|
||||||
// For querying about types.
|
|
||||||
Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
|
|
||||||
Id getDerefTypeId(Id resultId) const;
|
|
||||||
Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); }
|
|
||||||
Op getTypeClass(Id typeId) const { return getOpCode(typeId); }
|
|
||||||
Op getMostBasicTypeClass(Id typeId) const;
|
|
||||||
int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
|
|
||||||
int getNumTypeConstituents(Id typeId) const;
|
|
||||||
int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); }
|
|
||||||
Id getScalarTypeId(Id typeId) const;
|
|
||||||
Id getContainedTypeId(Id typeId) const;
|
|
||||||
Id getContainedTypeId(Id typeId, int) const;
|
|
||||||
StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
|
|
||||||
ImageFormat getImageTypeFormat(Id typeId) const
|
|
||||||
{ return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
|
|
||||||
|
|
||||||
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
|
|
||||||
bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
|
|
||||||
bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); }
|
|
||||||
bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); }
|
|
||||||
bool isCooperativeMatrix(Id resultId)const { return isCooperativeMatrixType(getTypeId(resultId)); }
|
|
||||||
bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
|
|
||||||
bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
|
|
||||||
|
|
||||||
bool isBoolType(Id typeId)
|
|
||||||
{ return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
|
|
||||||
bool isIntType(Id typeId) const
|
|
||||||
{ return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) != 0; }
|
|
||||||
bool isUintType(Id typeId) const
|
|
||||||
{ return getTypeClass(typeId) == OpTypeInt && module.getInstruction(typeId)->getImmediateOperand(1) == 0; }
|
|
||||||
bool isFloatType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat; }
|
|
||||||
bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
|
|
||||||
bool isScalarType(Id typeId) const
|
|
||||||
{ return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt ||
|
|
||||||
getTypeClass(typeId) == OpTypeBool; }
|
|
||||||
bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
|
|
||||||
bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; }
|
|
||||||
bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; }
|
|
||||||
bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; }
|
|
||||||
#ifdef GLSLANG_WEB
|
|
||||||
bool isCooperativeMatrixType(Id typeId)const { return false; }
|
|
||||||
#else
|
|
||||||
bool isCooperativeMatrixType(Id typeId)const { return getTypeClass(typeId) == OpTypeCooperativeMatrixNV; }
|
|
||||||
#endif
|
|
||||||
bool isAggregateType(Id typeId) const
|
|
||||||
{ return isArrayType(typeId) || isStructType(typeId) || isCooperativeMatrixType(typeId); }
|
|
||||||
bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
|
|
||||||
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
|
|
||||||
bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
|
|
||||||
bool containsType(Id typeId, Op typeOp, unsigned int width) const;
|
|
||||||
bool containsPhysicalStorageBufferOrArray(Id typeId) const;
|
|
||||||
|
|
||||||
bool isConstantOpCode(Op opcode) const;
|
|
||||||
bool isSpecConstantOpCode(Op opcode) const;
|
|
||||||
bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
|
|
||||||
bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
|
|
||||||
bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
|
|
||||||
unsigned int getConstantScalar(Id resultId) const
|
|
||||||
{ return module.getInstruction(resultId)->getImmediateOperand(0); }
|
|
||||||
StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
|
|
||||||
|
|
||||||
int getScalarTypeWidth(Id typeId) const
|
|
||||||
{
|
|
||||||
Id scalarTypeId = getScalarTypeId(typeId);
|
|
||||||
assert(getTypeClass(scalarTypeId) == OpTypeInt || getTypeClass(scalarTypeId) == OpTypeFloat);
|
|
||||||
return module.getInstruction(scalarTypeId)->getImmediateOperand(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int getTypeNumColumns(Id typeId) const
|
|
||||||
{
|
|
||||||
assert(isMatrixType(typeId));
|
|
||||||
return getNumTypeConstituents(typeId);
|
|
||||||
}
|
|
||||||
int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); }
|
|
||||||
int getTypeNumRows(Id typeId) const
|
|
||||||
{
|
|
||||||
assert(isMatrixType(typeId));
|
|
||||||
return getNumTypeComponents(getContainedTypeId(typeId));
|
|
||||||
}
|
|
||||||
int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
|
|
||||||
|
|
||||||
Dim getTypeDimensionality(Id typeId) const
|
|
||||||
{
|
|
||||||
assert(isImageType(typeId));
|
|
||||||
return (Dim)module.getInstruction(typeId)->getImmediateOperand(1);
|
|
||||||
}
|
|
||||||
Id getImageType(Id resultId) const
|
|
||||||
{
|
|
||||||
Id typeId = getTypeId(resultId);
|
|
||||||
assert(isImageType(typeId) || isSampledImageType(typeId));
|
|
||||||
return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId;
|
|
||||||
}
|
|
||||||
bool isArrayedImageType(Id typeId) const
|
|
||||||
{
|
|
||||||
assert(isImageType(typeId));
|
|
||||||
return module.getInstruction(typeId)->getImmediateOperand(3) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For making new constants (will return old constant if the requested one was already made).
|
|
||||||
Id makeBoolConstant(bool b, bool specConstant = false);
|
|
||||||
Id makeInt8Constant(int i, bool specConstant = false)
|
|
||||||
{ return makeIntConstant(makeIntType(8), (unsigned)i, specConstant); }
|
|
||||||
Id makeUint8Constant(unsigned u, bool specConstant = false)
|
|
||||||
{ return makeIntConstant(makeUintType(8), u, specConstant); }
|
|
||||||
Id makeInt16Constant(int i, bool specConstant = false)
|
|
||||||
{ return makeIntConstant(makeIntType(16), (unsigned)i, specConstant); }
|
|
||||||
Id makeUint16Constant(unsigned u, bool specConstant = false)
|
|
||||||
{ return makeIntConstant(makeUintType(16), u, specConstant); }
|
|
||||||
Id makeIntConstant(int i, bool specConstant = false)
|
|
||||||
{ return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
|
|
||||||
Id makeUintConstant(unsigned u, bool specConstant = false)
|
|
||||||
{ return makeIntConstant(makeUintType(32), u, specConstant); }
|
|
||||||
Id makeInt64Constant(long long i, bool specConstant = false)
|
|
||||||
{ return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
|
|
||||||
Id makeUint64Constant(unsigned long long u, bool specConstant = false)
|
|
||||||
{ return makeInt64Constant(makeUintType(64), u, specConstant); }
|
|
||||||
Id makeFloatConstant(float f, bool specConstant = false);
|
|
||||||
Id makeDoubleConstant(double d, bool specConstant = false);
|
|
||||||
Id makeFloat16Constant(float f16, bool specConstant = false);
|
|
||||||
Id makeFpConstant(Id type, double d, bool specConstant = false);
|
|
||||||
|
|
||||||
// Turn the array of constants into a proper spv constant of the requested type.
|
|
||||||
Id makeCompositeConstant(Id type, const std::vector<Id>& comps, bool specConst = false);
|
|
||||||
|
|
||||||
// Methods for adding information outside the CFG.
|
|
||||||
Instruction* addEntryPoint(ExecutionModel, Function*, const char* name);
|
|
||||||
void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
|
|
||||||
void addName(Id, const char* name);
|
|
||||||
void addMemberName(Id, int member, const char* name);
|
|
||||||
void addDecoration(Id, Decoration, int num = -1);
|
|
||||||
void addDecoration(Id, Decoration, const char*);
|
|
||||||
void addDecorationId(Id id, Decoration, Id idDecoration);
|
|
||||||
void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
|
|
||||||
void addMemberDecoration(Id, unsigned int member, Decoration, const char*);
|
|
||||||
|
|
||||||
// At the end of what block do the next create*() instructions go?
|
|
||||||
void setBuildPoint(Block* bp) { buildPoint = bp; }
|
|
||||||
Block* getBuildPoint() const { return buildPoint; }
|
|
||||||
|
|
||||||
// Make the entry-point function. The returned pointer is only valid
|
|
||||||
// for the lifetime of this builder.
|
|
||||||
Function* makeEntryPoint(const char*);
|
|
||||||
|
|
||||||
// Make a shader-style function, and create its entry block if entry is non-zero.
|
|
||||||
// Return the function, pass back the entry.
|
|
||||||
// The returned pointer is only valid for the lifetime of this builder.
|
|
||||||
Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name,
|
|
||||||
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
|
|
||||||
// code. In the case of an implicit return, no post-return block is inserted.
|
|
||||||
void makeReturn(bool implicit, Id retVal = 0);
|
|
||||||
|
|
||||||
// Generate all the code needed to finish up a function.
|
|
||||||
void leaveFunction();
|
|
||||||
|
|
||||||
// Create a discard.
|
|
||||||
void makeDiscard();
|
|
||||||
|
|
||||||
// Create a global or function local or IO variable.
|
|
||||||
Id createVariable(StorageClass, Id type, const char* name = 0, Id initializer = NoResult);
|
|
||||||
|
|
||||||
// Create an intermediate with an undefined value.
|
|
||||||
Id createUndefined(Id type);
|
|
||||||
|
|
||||||
// Store into an Id and return the l-value
|
|
||||||
void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
|
|
||||||
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
|
|
||||||
|
|
||||||
// Load from an Id and return it
|
|
||||||
Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
|
|
||||||
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
|
|
||||||
|
|
||||||
// Create an OpAccessChain instruction
|
|
||||||
Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
|
|
||||||
|
|
||||||
// Create an OpArrayLength instruction
|
|
||||||
Id createArrayLength(Id base, unsigned int member);
|
|
||||||
|
|
||||||
// Create an OpCooperativeMatrixLengthNV instruction
|
|
||||||
Id createCooperativeMatrixLength(Id type);
|
|
||||||
|
|
||||||
// Create an OpCompositeExtract instruction
|
|
||||||
Id createCompositeExtract(Id composite, Id typeId, unsigned index);
|
|
||||||
Id createCompositeExtract(Id composite, Id typeId, const std::vector<unsigned>& indexes);
|
|
||||||
Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index);
|
|
||||||
Id createCompositeInsert(Id object, Id composite, Id typeId, const std::vector<unsigned>& indexes);
|
|
||||||
|
|
||||||
Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex);
|
|
||||||
Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex);
|
|
||||||
|
|
||||||
void createNoResultOp(Op);
|
|
||||||
void createNoResultOp(Op, Id operand);
|
|
||||||
void createNoResultOp(Op, const std::vector<Id>& operands);
|
|
||||||
void createNoResultOp(Op, const std::vector<IdImmediate>& operands);
|
|
||||||
void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask);
|
|
||||||
void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics);
|
|
||||||
Id createUnaryOp(Op, Id typeId, Id operand);
|
|
||||||
Id createBinOp(Op, Id typeId, Id operand1, Id operand2);
|
|
||||||
Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
|
|
||||||
Id createOp(Op, Id typeId, const std::vector<Id>& operands);
|
|
||||||
Id createOp(Op, Id typeId, const std::vector<IdImmediate>& operands);
|
|
||||||
Id createFunctionCall(spv::Function*, const std::vector<spv::Id>&);
|
|
||||||
Id createSpecConstantOp(Op, Id typeId, const std::vector<spv::Id>& operands, const std::vector<unsigned>& literals);
|
|
||||||
|
|
||||||
// Take an rvalue (source) and a set of channels to extract from it to
|
|
||||||
// make a new rvalue, which is returned.
|
|
||||||
Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector<unsigned>& channels);
|
|
||||||
|
|
||||||
// Take a copy of an lvalue (target) and a source of components, and set the
|
|
||||||
// source components into the lvalue where the 'channels' say to put them.
|
|
||||||
// An updated version of the target is returned.
|
|
||||||
// (No true lvalue or stores are used.)
|
|
||||||
Id createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector<unsigned>& channels);
|
|
||||||
|
|
||||||
// If both the id and precision are valid, the id
|
|
||||||
// gets tagged with the requested precision.
|
|
||||||
// The passed in id is always the returned id, to simplify use patterns.
|
|
||||||
Id setPrecision(Id id, Decoration precision)
|
|
||||||
{
|
|
||||||
if (precision != NoPrecision && id != NoResult)
|
|
||||||
addDecoration(id, precision);
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Can smear a scalar to a vector for the following forms:
|
|
||||||
// - promoteScalar(scalar, vector) // smear scalar to width of vector
|
|
||||||
// - promoteScalar(vector, scalar) // smear scalar to width of vector
|
|
||||||
// - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to
|
|
||||||
// - promoteScalar(scalar, scalar) // do nothing
|
|
||||||
// Other forms are not allowed.
|
|
||||||
//
|
|
||||||
// Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'.
|
|
||||||
// The type of the created vector is a vector of components of the same type as the scalar.
|
|
||||||
//
|
|
||||||
// Note: One of the arguments will change, with the result coming back that way rather than
|
|
||||||
// through the return value.
|
|
||||||
void promoteScalar(Decoration precision, Id& left, Id& right);
|
|
||||||
|
|
||||||
// Make a value by smearing the scalar to fill the type.
|
|
||||||
// vectorType should be the correct type for making a vector of scalarVal.
|
|
||||||
// (No conversions are done.)
|
|
||||||
Id smearScalar(Decoration precision, Id scalarVal, Id vectorType);
|
|
||||||
|
|
||||||
// Create a call to a built-in function.
|
|
||||||
Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector<Id>& args);
|
|
||||||
|
|
||||||
// List of parameters used to create a texture operation
|
|
||||||
struct TextureParameters {
|
|
||||||
Id sampler;
|
|
||||||
Id coords;
|
|
||||||
Id bias;
|
|
||||||
Id lod;
|
|
||||||
Id Dref;
|
|
||||||
Id offset;
|
|
||||||
Id offsets;
|
|
||||||
Id gradX;
|
|
||||||
Id gradY;
|
|
||||||
Id sample;
|
|
||||||
Id component;
|
|
||||||
Id texelOut;
|
|
||||||
Id lodClamp;
|
|
||||||
Id granularity;
|
|
||||||
Id coarse;
|
|
||||||
bool nonprivate;
|
|
||||||
bool volatil;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Select the correct texture operation based on all inputs, and emit the correct instruction
|
|
||||||
Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather,
|
|
||||||
bool noImplicit, const TextureParameters&, ImageOperandsMask);
|
|
||||||
|
|
||||||
// Emit the OpTextureQuery* instruction that was passed in.
|
|
||||||
// Figure out the right return value and type, and return it.
|
|
||||||
Id createTextureQueryCall(Op, const TextureParameters&, bool isUnsignedResult);
|
|
||||||
|
|
||||||
Id createSamplePositionCall(Decoration precision, Id, Id);
|
|
||||||
|
|
||||||
Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned);
|
|
||||||
Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id);
|
|
||||||
|
|
||||||
// Reduction comparison for composites: For equal and not-equal resulting in a scalar.
|
|
||||||
Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */);
|
|
||||||
|
|
||||||
// OpCompositeConstruct
|
|
||||||
Id createCompositeConstruct(Id typeId, const std::vector<Id>& constituents);
|
|
||||||
|
|
||||||
// vector or scalar constructor
|
|
||||||
Id createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId);
|
|
||||||
|
|
||||||
// matrix constructor
|
|
||||||
Id createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id constructee);
|
|
||||||
|
|
||||||
// Helper to use for building nested control flow with if-then-else.
|
|
||||||
class If {
|
|
||||||
public:
|
|
||||||
If(Id condition, unsigned int ctrl, Builder& builder);
|
|
||||||
~If() {}
|
|
||||||
|
|
||||||
void makeBeginElse();
|
|
||||||
void makeEndIf();
|
|
||||||
|
|
||||||
private:
|
|
||||||
If(const If&);
|
|
||||||
If& operator=(If&);
|
|
||||||
|
|
||||||
Builder& builder;
|
|
||||||
Id condition;
|
|
||||||
unsigned int control;
|
|
||||||
Function* function;
|
|
||||||
Block* headerBlock;
|
|
||||||
Block* thenBlock;
|
|
||||||
Block* elseBlock;
|
|
||||||
Block* mergeBlock;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Make a switch statement. A switch has 'numSegments' of pieces of code, not containing
|
|
||||||
// any case/default labels, all separated by one or more case/default labels. Each possible
|
|
||||||
// case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this
|
|
||||||
// number space. How to compute the value is given by 'condition', as in switch(condition).
|
|
||||||
//
|
|
||||||
// The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches.
|
|
||||||
//
|
|
||||||
// Use a defaultSegment < 0 if there is no default segment (to branch to post switch).
|
|
||||||
//
|
|
||||||
// Returns the right set of basic blocks to start each code segment with, so that the caller's
|
|
||||||
// recursion stack can hold the memory for it.
|
|
||||||
//
|
|
||||||
void makeSwitch(Id condition, unsigned int control, int numSegments, const std::vector<int>& caseValues,
|
|
||||||
const std::vector<int>& valueToSegment, int defaultSegment, std::vector<Block*>& segmentBB);
|
|
||||||
|
|
||||||
// Add a branch to the innermost switch's merge block.
|
|
||||||
void addSwitchBreak();
|
|
||||||
|
|
||||||
// Move to the next code segment, passing in the return argument in makeSwitch()
|
|
||||||
void nextSwitchSegment(std::vector<Block*>& segmentBB, int segment);
|
|
||||||
|
|
||||||
// Finish off the innermost switch.
|
|
||||||
void endSwitch(std::vector<Block*>& segmentBB);
|
|
||||||
|
|
||||||
struct LoopBlocks {
|
|
||||||
LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) :
|
|
||||||
head(head), body(body), merge(merge), continue_target(continue_target) { }
|
|
||||||
Block &head, &body, &merge, &continue_target;
|
|
||||||
private:
|
|
||||||
LoopBlocks();
|
|
||||||
LoopBlocks& operator=(const LoopBlocks&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Start a new loop and prepare the builder to generate code for it. Until
|
|
||||||
// closeLoop() is called for this loop, createLoopContinue() and
|
|
||||||
// createLoopExit() will target its corresponding blocks.
|
|
||||||
LoopBlocks& makeNewLoop();
|
|
||||||
|
|
||||||
// Create a new block in the function containing the build point. Memory is
|
|
||||||
// owned by the function object.
|
|
||||||
Block& makeNewBlock();
|
|
||||||
|
|
||||||
// Add a branch to the continue_target of the current (innermost) loop.
|
|
||||||
void createLoopContinue();
|
|
||||||
|
|
||||||
// Add an exit (e.g. "break") from the innermost loop that we're currently
|
|
||||||
// in.
|
|
||||||
void createLoopExit();
|
|
||||||
|
|
||||||
// Close the innermost loop that you're in
|
|
||||||
void closeLoop();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Access chain design for an R-Value vs. L-Value:
|
|
||||||
//
|
|
||||||
// There is a single access chain the builder is building at
|
|
||||||
// any particular time. Such a chain can be used to either to a load or
|
|
||||||
// a store, when desired.
|
|
||||||
//
|
|
||||||
// Expressions can be r-values, l-values, or both, or only r-values:
|
|
||||||
// a[b.c].d = .... // l-value
|
|
||||||
// ... = a[b.c].d; // r-value, that also looks like an l-value
|
|
||||||
// ++a[b.c].d; // r-value and l-value
|
|
||||||
// (x + y)[2]; // r-value only, can't possibly be l-value
|
|
||||||
//
|
|
||||||
// Computing an r-value means generating code. Hence,
|
|
||||||
// r-values should only be computed when they are needed, not speculatively.
|
|
||||||
//
|
|
||||||
// Computing an l-value means saving away information for later use in the compiler,
|
|
||||||
// no code is generated until the l-value is later dereferenced. It is okay
|
|
||||||
// to speculatively generate an l-value, just not okay to speculatively dereference it.
|
|
||||||
//
|
|
||||||
// The base of the access chain (the left-most variable or expression
|
|
||||||
// from which everything is based) can be set either as an l-value
|
|
||||||
// or as an r-value. Most efficient would be to set an l-value if one
|
|
||||||
// is available. If an expression was evaluated, the resulting r-value
|
|
||||||
// can be set as the chain base.
|
|
||||||
//
|
|
||||||
// The users of this single access chain can save and restore if they
|
|
||||||
// want to nest or manage multiple chains.
|
|
||||||
//
|
|
||||||
|
|
||||||
struct AccessChain {
|
|
||||||
Id base; // for l-values, pointer to the base object, for r-values, the base object
|
|
||||||
std::vector<Id> indexChain;
|
|
||||||
Id instr; // cache the instruction that generates this access chain
|
|
||||||
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 preSwizzleBaseType; // dereferenced type, before swizzle or component is applied;
|
|
||||||
// NoType unless a swizzle or component is present
|
|
||||||
bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value
|
|
||||||
unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment.
|
|
||||||
// Only tracks base and (optional) component selection alignment.
|
|
||||||
|
|
||||||
// Accumulate whether anything in the chain of structures has coherent decorations.
|
|
||||||
struct CoherentFlags {
|
|
||||||
CoherentFlags() { clear(); }
|
|
||||||
#ifdef GLSLANG_WEB
|
|
||||||
void clear() { }
|
|
||||||
bool isVolatile() const { return false; }
|
|
||||||
CoherentFlags operator |=(const CoherentFlags &other) { return *this; }
|
|
||||||
#else
|
|
||||||
bool isVolatile() const { return volatil; }
|
|
||||||
bool anyCoherent() const {
|
|
||||||
return coherent || devicecoherent || queuefamilycoherent || workgroupcoherent ||
|
|
||||||
subgroupcoherent || shadercallcoherent;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned coherent : 1;
|
|
||||||
unsigned devicecoherent : 1;
|
|
||||||
unsigned queuefamilycoherent : 1;
|
|
||||||
unsigned workgroupcoherent : 1;
|
|
||||||
unsigned subgroupcoherent : 1;
|
|
||||||
unsigned shadercallcoherent : 1;
|
|
||||||
unsigned nonprivate : 1;
|
|
||||||
unsigned volatil : 1;
|
|
||||||
unsigned isImage : 1;
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
coherent = 0;
|
|
||||||
devicecoherent = 0;
|
|
||||||
queuefamilycoherent = 0;
|
|
||||||
workgroupcoherent = 0;
|
|
||||||
subgroupcoherent = 0;
|
|
||||||
shadercallcoherent = 0;
|
|
||||||
nonprivate = 0;
|
|
||||||
volatil = 0;
|
|
||||||
isImage = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoherentFlags operator |=(const CoherentFlags &other) {
|
|
||||||
coherent |= other.coherent;
|
|
||||||
devicecoherent |= other.devicecoherent;
|
|
||||||
queuefamilycoherent |= other.queuefamilycoherent;
|
|
||||||
workgroupcoherent |= other.workgroupcoherent;
|
|
||||||
subgroupcoherent |= other.subgroupcoherent;
|
|
||||||
shadercallcoherent |= other.shadercallcoherent;
|
|
||||||
nonprivate |= other.nonprivate;
|
|
||||||
volatil |= other.volatil;
|
|
||||||
isImage |= other.isImage;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
CoherentFlags coherentFlags;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// the SPIR-V builder maintains a single active chain that
|
|
||||||
// the following methods operate on
|
|
||||||
//
|
|
||||||
|
|
||||||
// for external save and restore
|
|
||||||
AccessChain getAccessChain() { return accessChain; }
|
|
||||||
void setAccessChain(AccessChain newChain) { accessChain = newChain; }
|
|
||||||
|
|
||||||
// clear accessChain
|
|
||||||
void clearAccessChain();
|
|
||||||
|
|
||||||
// set new base as an l-value base
|
|
||||||
void setAccessChainLValue(Id lValue)
|
|
||||||
{
|
|
||||||
assert(isPointer(lValue));
|
|
||||||
accessChain.base = lValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// set new base value as an r-value
|
|
||||||
void setAccessChainRValue(Id rValue)
|
|
||||||
{
|
|
||||||
accessChain.isRValue = true;
|
|
||||||
accessChain.base = rValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// push offset onto the end of the chain
|
|
||||||
void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
|
|
||||||
{
|
|
||||||
accessChain.indexChain.push_back(offset);
|
|
||||||
accessChain.coherentFlags |= coherentFlags;
|
|
||||||
accessChain.alignment |= alignment;
|
|
||||||
}
|
|
||||||
|
|
||||||
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
|
|
||||||
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType,
|
|
||||||
AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
|
|
||||||
|
|
||||||
// push a dynamic component selection onto the access chain, only applicable with a
|
|
||||||
// non-trivial swizzle or no swizzle
|
|
||||||
void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags,
|
|
||||||
unsigned int alignment)
|
|
||||||
{
|
|
||||||
if (accessChain.swizzle.size() != 1) {
|
|
||||||
accessChain.component = component;
|
|
||||||
if (accessChain.preSwizzleBaseType == NoType)
|
|
||||||
accessChain.preSwizzleBaseType = preSwizzleBaseType;
|
|
||||||
}
|
|
||||||
accessChain.coherentFlags |= coherentFlags;
|
|
||||||
accessChain.alignment |= alignment;
|
|
||||||
}
|
|
||||||
|
|
||||||
// use accessChain and swizzle to store value
|
|
||||||
void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone,
|
|
||||||
spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
|
|
||||||
|
|
||||||
// use accessChain and swizzle to load an r-value
|
|
||||||
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType,
|
|
||||||
spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax,
|
|
||||||
unsigned int alignment = 0);
|
|
||||||
|
|
||||||
// Return whether or not the access chain can be represented in SPIR-V
|
|
||||||
// as an l-value.
|
|
||||||
// E.g., a[3].yx cannot be, while a[3].y and a[3].y[x] can be.
|
|
||||||
bool isSpvLvalue() const { return accessChain.swizzle.size() <= 1; }
|
|
||||||
|
|
||||||
// get the direct pointer for an l-value
|
|
||||||
Id accessChainGetLValue();
|
|
||||||
|
|
||||||
// Get the inferred SPIR-V type of the result of the current access chain,
|
|
||||||
// based on the type of the base and the chain of dereferences.
|
|
||||||
Id accessChainGetInferredType();
|
|
||||||
|
|
||||||
// Add capabilities, extensions, remove unneeded decorations, etc.,
|
|
||||||
// based on the resulting SPIR-V.
|
|
||||||
void postProcess();
|
|
||||||
|
|
||||||
// Prune unreachable blocks in the CFG and remove unneeded decorations.
|
|
||||||
void postProcessCFG();
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
// Add capabilities, extensions based on instructions in the module.
|
|
||||||
void postProcessFeatures();
|
|
||||||
// Hook to visit each instruction in a block in a function
|
|
||||||
void postProcess(Instruction&);
|
|
||||||
// Hook to visit each non-32-bit sized float/int operation in a block.
|
|
||||||
void postProcessType(const Instruction&, spv::Id typeId);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void dump(std::vector<unsigned int>&) const;
|
|
||||||
|
|
||||||
void createBranch(Block* block);
|
|
||||||
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
|
|
||||||
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
|
|
||||||
const std::vector<unsigned int>& operands);
|
|
||||||
|
|
||||||
// Sets to generate opcode for specialization constants.
|
|
||||||
void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
|
|
||||||
// Sets to generate opcode for non-specialization constants (normal mode).
|
|
||||||
void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; }
|
|
||||||
// Check if the builder is generating code for spec constants.
|
|
||||||
bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Id makeIntConstant(Id typeId, unsigned value, bool specConstant);
|
|
||||||
Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant);
|
|
||||||
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value);
|
|
||||||
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2);
|
|
||||||
Id findCompositeConstant(Op typeClass, Id typeId, const std::vector<Id>& comps);
|
|
||||||
Id findStructConstant(Id typeId, const std::vector<Id>& comps);
|
|
||||||
Id collapseAccessChain();
|
|
||||||
void remapDynamicSwizzle();
|
|
||||||
void transferAccessChainSwizzle(bool dynamic);
|
|
||||||
void simplifyAccessChainSwizzle();
|
|
||||||
void createAndSetNoPredecessorBlock(const char*);
|
|
||||||
void createSelectionMerge(Block* mergeBlock, unsigned int control);
|
|
||||||
void dumpSourceInstructions(std::vector<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 dumpModuleProcesses(std::vector<unsigned int>&) const;
|
|
||||||
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc)
|
|
||||||
const;
|
|
||||||
|
|
||||||
unsigned int spvVersion; // the version of SPIR-V to emit in the header
|
|
||||||
SourceLanguage source;
|
|
||||||
int sourceVersion;
|
|
||||||
spv::Id sourceFileStringId;
|
|
||||||
std::string sourceText;
|
|
||||||
int currentLine;
|
|
||||||
const char* currentFile;
|
|
||||||
bool emitOpLines;
|
|
||||||
std::set<std::string> extensions;
|
|
||||||
std::vector<const char*> sourceExtensions;
|
|
||||||
std::vector<const char*> moduleProcesses;
|
|
||||||
AddressingModel addressModel;
|
|
||||||
MemoryModel memoryModel;
|
|
||||||
std::set<spv::Capability> capabilities;
|
|
||||||
int builderNumber;
|
|
||||||
Module module;
|
|
||||||
Block* buildPoint;
|
|
||||||
Id uniqueId;
|
|
||||||
Function* entryPointFunction;
|
|
||||||
bool generatingOpCodeForSpecConst;
|
|
||||||
AccessChain accessChain;
|
|
||||||
|
|
||||||
// special blocks of instructions for output
|
|
||||||
std::vector<std::unique_ptr<Instruction> > strings;
|
|
||||||
std::vector<std::unique_ptr<Instruction> > imports;
|
|
||||||
std::vector<std::unique_ptr<Instruction> > entryPoints;
|
|
||||||
std::vector<std::unique_ptr<Instruction> > executionModes;
|
|
||||||
std::vector<std::unique_ptr<Instruction> > names;
|
|
||||||
std::vector<std::unique_ptr<Instruction> > decorations;
|
|
||||||
std::vector<std::unique_ptr<Instruction> > constantsTypesGlobals;
|
|
||||||
std::vector<std::unique_ptr<Instruction> > externals;
|
|
||||||
std::vector<std::unique_ptr<Function> > functions;
|
|
||||||
|
|
||||||
// not output, internally used for quick & dirty canonical (unique) creation
|
|
||||||
|
|
||||||
// map type opcodes to constant inst.
|
|
||||||
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;
|
|
||||||
|
|
||||||
// stack of switches
|
|
||||||
std::stack<Block*> switchMerges;
|
|
||||||
|
|
||||||
// Our loop stack.
|
|
||||||
std::stack<LoopBlocks> loops;
|
|
||||||
|
|
||||||
// map from strings to their string ids
|
|
||||||
std::unordered_map<std::string, spv::Id> stringIds;
|
|
||||||
|
|
||||||
// map from include file name ids to their contents
|
|
||||||
std::map<spv::Id, const std::string*> includeFiles;
|
|
||||||
|
|
||||||
// The stream for outputting warnings and errors.
|
|
||||||
SpvBuildLogger* logger;
|
|
||||||
}; // end Builder class
|
|
||||||
|
|
||||||
}; // end spv namespace
|
|
||||||
|
|
||||||
#endif // SpvBuilder_H
|
|
|
@ -1,450 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2018 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
//
|
|
||||||
// Post-processing for SPIR-V IR, in internal form, not standard binary form.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "SpvBuilder.h"
|
|
||||||
|
|
||||||
#include "spirv.hpp"
|
|
||||||
#include "GlslangToSpv.h"
|
|
||||||
#include "SpvBuilder.h"
|
|
||||||
namespace spv {
|
|
||||||
#include "GLSL.std.450.h"
|
|
||||||
#include "GLSL.ext.KHR.h"
|
|
||||||
#include "GLSL.ext.EXT.h"
|
|
||||||
#include "GLSL.ext.AMD.h"
|
|
||||||
#include "GLSL.ext.NV.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
// Hook to visit each operand type and result type of an instruction.
|
|
||||||
// Will be called multiple times for one instruction, once for each typed
|
|
||||||
// operand and the result.
|
|
||||||
void Builder::postProcessType(const Instruction& inst, Id typeId)
|
|
||||||
{
|
|
||||||
// Characterize the type being questioned
|
|
||||||
Id basicTypeOp = getMostBasicTypeClass(typeId);
|
|
||||||
int width = 0;
|
|
||||||
if (basicTypeOp == OpTypeFloat || basicTypeOp == OpTypeInt)
|
|
||||||
width = getScalarTypeWidth(typeId);
|
|
||||||
|
|
||||||
// Do opcode-specific checks
|
|
||||||
switch (inst.getOpCode()) {
|
|
||||||
case OpLoad:
|
|
||||||
case OpStore:
|
|
||||||
if (basicTypeOp == OpTypeStruct) {
|
|
||||||
if (containsType(typeId, OpTypeInt, 8))
|
|
||||||
addCapability(CapabilityInt8);
|
|
||||||
if (containsType(typeId, OpTypeInt, 16))
|
|
||||||
addCapability(CapabilityInt16);
|
|
||||||
if (containsType(typeId, OpTypeFloat, 16))
|
|
||||||
addCapability(CapabilityFloat16);
|
|
||||||
} else {
|
|
||||||
StorageClass storageClass = getStorageClass(inst.getIdOperand(0));
|
|
||||||
if (width == 8) {
|
|
||||||
switch (storageClass) {
|
|
||||||
case StorageClassPhysicalStorageBufferEXT:
|
|
||||||
case StorageClassUniform:
|
|
||||||
case StorageClassStorageBuffer:
|
|
||||||
case StorageClassPushConstant:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
addCapability(CapabilityInt8);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (width == 16) {
|
|
||||||
switch (storageClass) {
|
|
||||||
case StorageClassPhysicalStorageBufferEXT:
|
|
||||||
case StorageClassUniform:
|
|
||||||
case StorageClassStorageBuffer:
|
|
||||||
case StorageClassPushConstant:
|
|
||||||
case StorageClassInput:
|
|
||||||
case StorageClassOutput:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (basicTypeOp == OpTypeInt)
|
|
||||||
addCapability(CapabilityInt16);
|
|
||||||
if (basicTypeOp == OpTypeFloat)
|
|
||||||
addCapability(CapabilityFloat16);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OpAccessChain:
|
|
||||||
case OpPtrAccessChain:
|
|
||||||
case OpCopyObject:
|
|
||||||
break;
|
|
||||||
case OpFConvert:
|
|
||||||
case OpSConvert:
|
|
||||||
case OpUConvert:
|
|
||||||
// Look for any 8/16-bit storage capabilities. If there are none, assume that
|
|
||||||
// the convert instruction requires the Float16/Int8/16 capability.
|
|
||||||
if (containsType(typeId, OpTypeFloat, 16) || containsType(typeId, OpTypeInt, 16)) {
|
|
||||||
bool foundStorage = false;
|
|
||||||
for (auto it = capabilities.begin(); it != capabilities.end(); ++it) {
|
|
||||||
spv::Capability cap = *it;
|
|
||||||
if (cap == spv::CapabilityStorageInputOutput16 ||
|
|
||||||
cap == spv::CapabilityStoragePushConstant16 ||
|
|
||||||
cap == spv::CapabilityStorageUniformBufferBlock16 ||
|
|
||||||
cap == spv::CapabilityStorageUniform16) {
|
|
||||||
foundStorage = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!foundStorage) {
|
|
||||||
if (containsType(typeId, OpTypeFloat, 16))
|
|
||||||
addCapability(CapabilityFloat16);
|
|
||||||
if (containsType(typeId, OpTypeInt, 16))
|
|
||||||
addCapability(CapabilityInt16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (containsType(typeId, OpTypeInt, 8)) {
|
|
||||||
bool foundStorage = false;
|
|
||||||
for (auto it = capabilities.begin(); it != capabilities.end(); ++it) {
|
|
||||||
spv::Capability cap = *it;
|
|
||||||
if (cap == spv::CapabilityStoragePushConstant8 ||
|
|
||||||
cap == spv::CapabilityUniformAndStorageBuffer8BitAccess ||
|
|
||||||
cap == spv::CapabilityStorageBuffer8BitAccess) {
|
|
||||||
foundStorage = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!foundStorage) {
|
|
||||||
addCapability(CapabilityInt8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OpExtInst:
|
|
||||||
switch (inst.getImmediateOperand(1)) {
|
|
||||||
case GLSLstd450Frexp:
|
|
||||||
case GLSLstd450FrexpStruct:
|
|
||||||
if (getSpvVersion() < glslang::EShTargetSpv_1_3 && containsType(typeId, OpTypeInt, 16))
|
|
||||||
addExtension(spv::E_SPV_AMD_gpu_shader_int16);
|
|
||||||
break;
|
|
||||||
case GLSLstd450InterpolateAtCentroid:
|
|
||||||
case GLSLstd450InterpolateAtSample:
|
|
||||||
case GLSLstd450InterpolateAtOffset:
|
|
||||||
if (getSpvVersion() < glslang::EShTargetSpv_1_3 && containsType(typeId, OpTypeFloat, 16))
|
|
||||||
addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (basicTypeOp == OpTypeFloat && width == 16)
|
|
||||||
addCapability(CapabilityFloat16);
|
|
||||||
if (basicTypeOp == OpTypeInt && width == 16)
|
|
||||||
addCapability(CapabilityInt16);
|
|
||||||
if (basicTypeOp == OpTypeInt && width == 8)
|
|
||||||
addCapability(CapabilityInt8);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called for each instruction that resides in a block.
|
|
||||||
void Builder::postProcess(Instruction& inst)
|
|
||||||
{
|
|
||||||
// Add capabilities based simply on the opcode.
|
|
||||||
switch (inst.getOpCode()) {
|
|
||||||
case OpExtInst:
|
|
||||||
switch (inst.getImmediateOperand(1)) {
|
|
||||||
case GLSLstd450InterpolateAtCentroid:
|
|
||||||
case GLSLstd450InterpolateAtSample:
|
|
||||||
case GLSLstd450InterpolateAtOffset:
|
|
||||||
addCapability(CapabilityInterpolationFunction);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OpDPdxFine:
|
|
||||||
case OpDPdyFine:
|
|
||||||
case OpFwidthFine:
|
|
||||||
case OpDPdxCoarse:
|
|
||||||
case OpDPdyCoarse:
|
|
||||||
case OpFwidthCoarse:
|
|
||||||
addCapability(CapabilityDerivativeControl);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OpImageQueryLod:
|
|
||||||
case OpImageQuerySize:
|
|
||||||
case OpImageQuerySizeLod:
|
|
||||||
case OpImageQuerySamples:
|
|
||||||
case OpImageQueryLevels:
|
|
||||||
addCapability(CapabilityImageQuery);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OpGroupNonUniformPartitionNV:
|
|
||||||
addExtension(E_SPV_NV_shader_subgroup_partitioned);
|
|
||||||
addCapability(CapabilityGroupNonUniformPartitionedNV);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OpLoad:
|
|
||||||
case OpStore:
|
|
||||||
{
|
|
||||||
// For any load/store to a PhysicalStorageBufferEXT, walk the accesschain
|
|
||||||
// index list to compute the misalignment. The pre-existing alignment value
|
|
||||||
// (set via Builder::AccessChain::alignment) only accounts for the base of
|
|
||||||
// the reference type and any scalar component selection in the accesschain,
|
|
||||||
// and this function computes the rest from the SPIR-V Offset decorations.
|
|
||||||
Instruction *accessChain = module.getInstruction(inst.getIdOperand(0));
|
|
||||||
if (accessChain->getOpCode() == OpAccessChain) {
|
|
||||||
Instruction *base = module.getInstruction(accessChain->getIdOperand(0));
|
|
||||||
// Get the type of the base of the access chain. It must be a pointer type.
|
|
||||||
Id typeId = base->getTypeId();
|
|
||||||
Instruction *type = module.getInstruction(typeId);
|
|
||||||
assert(type->getOpCode() == OpTypePointer);
|
|
||||||
if (type->getImmediateOperand(0) != StorageClassPhysicalStorageBufferEXT) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Get the pointee type.
|
|
||||||
typeId = type->getIdOperand(1);
|
|
||||||
type = module.getInstruction(typeId);
|
|
||||||
// Walk the index list for the access chain. For each index, find any
|
|
||||||
// misalignment that can apply when accessing the member/element via
|
|
||||||
// Offset/ArrayStride/MatrixStride decorations, and bitwise OR them all
|
|
||||||
// together.
|
|
||||||
int alignment = 0;
|
|
||||||
for (int i = 1; i < accessChain->getNumOperands(); ++i) {
|
|
||||||
Instruction *idx = module.getInstruction(accessChain->getIdOperand(i));
|
|
||||||
if (type->getOpCode() == OpTypeStruct) {
|
|
||||||
assert(idx->getOpCode() == OpConstant);
|
|
||||||
unsigned int c = idx->getImmediateOperand(0);
|
|
||||||
|
|
||||||
const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
|
|
||||||
if (decoration.get()->getOpCode() == OpMemberDecorate &&
|
|
||||||
decoration.get()->getIdOperand(0) == typeId &&
|
|
||||||
decoration.get()->getImmediateOperand(1) == c &&
|
|
||||||
(decoration.get()->getImmediateOperand(2) == DecorationOffset ||
|
|
||||||
decoration.get()->getImmediateOperand(2) == DecorationMatrixStride)) {
|
|
||||||
alignment |= decoration.get()->getImmediateOperand(3);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::for_each(decorations.begin(), decorations.end(), function);
|
|
||||||
// get the next member type
|
|
||||||
typeId = type->getIdOperand(c);
|
|
||||||
type = module.getInstruction(typeId);
|
|
||||||
} else if (type->getOpCode() == OpTypeArray ||
|
|
||||||
type->getOpCode() == OpTypeRuntimeArray) {
|
|
||||||
const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
|
|
||||||
if (decoration.get()->getOpCode() == OpDecorate &&
|
|
||||||
decoration.get()->getIdOperand(0) == typeId &&
|
|
||||||
decoration.get()->getImmediateOperand(1) == DecorationArrayStride) {
|
|
||||||
alignment |= decoration.get()->getImmediateOperand(2);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::for_each(decorations.begin(), decorations.end(), function);
|
|
||||||
// Get the element type
|
|
||||||
typeId = type->getIdOperand(0);
|
|
||||||
type = module.getInstruction(typeId);
|
|
||||||
} else {
|
|
||||||
// Once we get to any non-aggregate type, we're done.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(inst.getNumOperands() >= 3);
|
|
||||||
unsigned int memoryAccess = inst.getImmediateOperand((inst.getOpCode() == OpStore) ? 2 : 1);
|
|
||||||
assert(memoryAccess & MemoryAccessAlignedMask);
|
|
||||||
static_cast<void>(memoryAccess);
|
|
||||||
// Compute the index of the alignment operand.
|
|
||||||
int alignmentIdx = 2;
|
|
||||||
if (inst.getOpCode() == OpStore)
|
|
||||||
alignmentIdx++;
|
|
||||||
// Merge new and old (mis)alignment
|
|
||||||
alignment |= inst.getImmediateOperand(alignmentIdx);
|
|
||||||
// Pick the LSB
|
|
||||||
alignment = alignment & ~(alignment & (alignment-1));
|
|
||||||
// update the Aligned operand
|
|
||||||
inst.setImmediateOperand(alignmentIdx, alignment);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks based on type
|
|
||||||
if (inst.getTypeId() != NoType)
|
|
||||||
postProcessType(inst, inst.getTypeId());
|
|
||||||
for (int op = 0; op < inst.getNumOperands(); ++op) {
|
|
||||||
if (inst.isIdOperand(op)) {
|
|
||||||
// In blocks, these are always result ids, but we are relying on
|
|
||||||
// getTypeId() to return NoType for things like OpLabel.
|
|
||||||
if (getTypeId(inst.getIdOperand(op)) != NoType)
|
|
||||||
postProcessType(inst, getTypeId(inst.getIdOperand(op)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// comment in header
|
|
||||||
void Builder::postProcessCFG()
|
|
||||||
{
|
|
||||||
// reachableBlocks is the set of blockss reached via control flow, or which are
|
|
||||||
// unreachable continue targert or unreachable merge.
|
|
||||||
std::unordered_set<const Block*> reachableBlocks;
|
|
||||||
std::unordered_map<Block*, Block*> headerForUnreachableContinue;
|
|
||||||
std::unordered_set<Block*> unreachableMerges;
|
|
||||||
std::unordered_set<Id> unreachableDefinitions;
|
|
||||||
// Collect IDs defined in unreachable blocks. For each function, label the
|
|
||||||
// reachable blocks first. Then for each unreachable block, collect the
|
|
||||||
// result IDs of the instructions in it.
|
|
||||||
for (auto fi = module.getFunctions().cbegin(); fi != module.getFunctions().cend(); fi++) {
|
|
||||||
Function* f = *fi;
|
|
||||||
Block* entry = f->getEntryBlock();
|
|
||||||
inReadableOrder(entry,
|
|
||||||
[&reachableBlocks, &unreachableMerges, &headerForUnreachableContinue]
|
|
||||||
(Block* b, ReachReason why, Block* header) {
|
|
||||||
reachableBlocks.insert(b);
|
|
||||||
if (why == ReachDeadContinue) headerForUnreachableContinue[b] = header;
|
|
||||||
if (why == ReachDeadMerge) unreachableMerges.insert(b);
|
|
||||||
});
|
|
||||||
for (auto bi = f->getBlocks().cbegin(); bi != f->getBlocks().cend(); bi++) {
|
|
||||||
Block* b = *bi;
|
|
||||||
if (unreachableMerges.count(b) != 0 || headerForUnreachableContinue.count(b) != 0) {
|
|
||||||
auto ii = b->getInstructions().cbegin();
|
|
||||||
++ii; // Keep potential decorations on the label.
|
|
||||||
for (; ii != b->getInstructions().cend(); ++ii)
|
|
||||||
unreachableDefinitions.insert(ii->get()->getResultId());
|
|
||||||
} else if (reachableBlocks.count(b) == 0) {
|
|
||||||
// The normal case for unreachable code. All definitions are considered dead.
|
|
||||||
for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ++ii)
|
|
||||||
unreachableDefinitions.insert(ii->get()->getResultId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modify unreachable merge blocks and unreachable continue targets.
|
|
||||||
// Delete their contents.
|
|
||||||
for (auto mergeIter = unreachableMerges.begin(); mergeIter != unreachableMerges.end(); ++mergeIter) {
|
|
||||||
(*mergeIter)->rewriteAsCanonicalUnreachableMerge();
|
|
||||||
}
|
|
||||||
for (auto continueIter = headerForUnreachableContinue.begin();
|
|
||||||
continueIter != headerForUnreachableContinue.end();
|
|
||||||
++continueIter) {
|
|
||||||
Block* continue_target = continueIter->first;
|
|
||||||
Block* header = continueIter->second;
|
|
||||||
continue_target->rewriteAsCanonicalUnreachableContinue(header);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove unneeded decorations, for unreachable instructions
|
|
||||||
decorations.erase(std::remove_if(decorations.begin(), decorations.end(),
|
|
||||||
[&unreachableDefinitions](std::unique_ptr<Instruction>& I) -> bool {
|
|
||||||
Id decoration_id = I.get()->getIdOperand(0);
|
|
||||||
return unreachableDefinitions.count(decoration_id) != 0;
|
|
||||||
}),
|
|
||||||
decorations.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
// comment in header
|
|
||||||
void Builder::postProcessFeatures() {
|
|
||||||
// Add per-instruction capabilities, extensions, etc.,
|
|
||||||
|
|
||||||
// Look for any 8/16 bit type in physical storage buffer class, and set the
|
|
||||||
// appropriate capability. This happens in createSpvVariable for other storage
|
|
||||||
// classes, but there isn't always a variable for physical storage buffer.
|
|
||||||
for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
|
|
||||||
Instruction* type = groupedTypes[OpTypePointer][t];
|
|
||||||
if (type->getImmediateOperand(0) == (unsigned)StorageClassPhysicalStorageBufferEXT) {
|
|
||||||
if (containsType(type->getIdOperand(1), OpTypeInt, 8)) {
|
|
||||||
addIncorporatedExtension(spv::E_SPV_KHR_8bit_storage, spv::Spv_1_5);
|
|
||||||
addCapability(spv::CapabilityStorageBuffer8BitAccess);
|
|
||||||
}
|
|
||||||
if (containsType(type->getIdOperand(1), OpTypeInt, 16) ||
|
|
||||||
containsType(type->getIdOperand(1), OpTypeFloat, 16)) {
|
|
||||||
addIncorporatedExtension(spv::E_SPV_KHR_16bit_storage, spv::Spv_1_3);
|
|
||||||
addCapability(spv::CapabilityStorageBuffer16BitAccess);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// process all block-contained instructions
|
|
||||||
for (auto fi = module.getFunctions().cbegin(); fi != module.getFunctions().cend(); fi++) {
|
|
||||||
Function* f = *fi;
|
|
||||||
for (auto bi = f->getBlocks().cbegin(); bi != f->getBlocks().cend(); bi++) {
|
|
||||||
Block* b = *bi;
|
|
||||||
for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ii++)
|
|
||||||
postProcess(*ii->get());
|
|
||||||
|
|
||||||
// For all local variables that contain pointers to PhysicalStorageBufferEXT, check whether
|
|
||||||
// there is an existing restrict/aliased decoration. If we don't find one, add Aliased as the
|
|
||||||
// default.
|
|
||||||
for (auto vi = b->getLocalVariables().cbegin(); vi != b->getLocalVariables().cend(); vi++) {
|
|
||||||
const Instruction& inst = *vi->get();
|
|
||||||
Id resultId = inst.getResultId();
|
|
||||||
if (containsPhysicalStorageBufferOrArray(getDerefTypeId(resultId))) {
|
|
||||||
bool foundDecoration = false;
|
|
||||||
const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
|
|
||||||
if (decoration.get()->getIdOperand(0) == resultId &&
|
|
||||||
decoration.get()->getOpCode() == OpDecorate &&
|
|
||||||
(decoration.get()->getImmediateOperand(1) == spv::DecorationAliasedPointerEXT ||
|
|
||||||
decoration.get()->getImmediateOperand(1) == spv::DecorationRestrictPointerEXT)) {
|
|
||||||
foundDecoration = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::for_each(decorations.begin(), decorations.end(), function);
|
|
||||||
if (!foundDecoration) {
|
|
||||||
addDecoration(resultId, spv::DecorationAliasedPointerEXT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// comment in header
|
|
||||||
void Builder::postProcess() {
|
|
||||||
postProcessCFG();
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
postProcessFeatures();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // end spv namespace
|
|
|
@ -1,217 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2014-2016 LunarG, Inc.
|
|
||||||
// Copyright (C) 2018-2020 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call into SPIRV-Tools to disassemble, validate, and optimize.
|
|
||||||
//
|
|
||||||
|
|
||||||
#if ENABLE_OPT
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "SpvTools.h"
|
|
||||||
#include "spirv-tools/optimizer.hpp"
|
|
||||||
#include "spirv-tools/libspirv.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
// Translate glslang's view of target versioning to what SPIRV-Tools uses.
|
|
||||||
spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLogger* logger)
|
|
||||||
{
|
|
||||||
switch (spvVersion.vulkan) {
|
|
||||||
case glslang::EShTargetVulkan_1_0:
|
|
||||||
return spv_target_env::SPV_ENV_VULKAN_1_0;
|
|
||||||
case glslang::EShTargetVulkan_1_1:
|
|
||||||
switch (spvVersion.spv) {
|
|
||||||
case EShTargetSpv_1_0:
|
|
||||||
case EShTargetSpv_1_1:
|
|
||||||
case EShTargetSpv_1_2:
|
|
||||||
case EShTargetSpv_1_3:
|
|
||||||
return spv_target_env::SPV_ENV_VULKAN_1_1;
|
|
||||||
case EShTargetSpv_1_4:
|
|
||||||
return spv_target_env::SPV_ENV_VULKAN_1_1_SPIRV_1_4;
|
|
||||||
default:
|
|
||||||
logger->missingFunctionality("Target version for SPIRV-Tools validator");
|
|
||||||
return spv_target_env::SPV_ENV_VULKAN_1_1;
|
|
||||||
}
|
|
||||||
case glslang::EShTargetVulkan_1_2:
|
|
||||||
return spv_target_env::SPV_ENV_VULKAN_1_2;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spvVersion.openGl > 0)
|
|
||||||
return spv_target_env::SPV_ENV_OPENGL_4_5;
|
|
||||||
|
|
||||||
logger->missingFunctionality("Target version for SPIRV-Tools validator");
|
|
||||||
return spv_target_env::SPV_ENV_UNIVERSAL_1_0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Use the SPIRV-Tools disassembler to print SPIR-V.
|
|
||||||
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
|
|
||||||
{
|
|
||||||
// disassemble
|
|
||||||
spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3);
|
|
||||||
spv_text text;
|
|
||||||
spv_diagnostic diagnostic = nullptr;
|
|
||||||
spvBinaryToText(context, spirv.data(), spirv.size(),
|
|
||||||
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT,
|
|
||||||
&text, &diagnostic);
|
|
||||||
|
|
||||||
// dump
|
|
||||||
if (diagnostic == nullptr)
|
|
||||||
out << text->str;
|
|
||||||
else
|
|
||||||
spvDiagnosticPrint(diagnostic);
|
|
||||||
|
|
||||||
// teardown
|
|
||||||
spvDiagnosticDestroy(diagnostic);
|
|
||||||
spvContextDestroy(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply the SPIRV-Tools validator to generated SPIR-V.
|
|
||||||
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
|
||||||
spv::SpvBuildLogger* logger, bool prelegalization)
|
|
||||||
{
|
|
||||||
// validate
|
|
||||||
spv_context context = spvContextCreate(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
|
|
||||||
spv_const_binary_t binary = { spirv.data(), spirv.size() };
|
|
||||||
spv_diagnostic diagnostic = nullptr;
|
|
||||||
spv_validator_options options = spvValidatorOptionsCreate();
|
|
||||||
spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
|
|
||||||
spvValidatorOptionsSetBeforeHlslLegalization(options, prelegalization);
|
|
||||||
spvValidateWithOptions(context, options, &binary, &diagnostic);
|
|
||||||
|
|
||||||
// report
|
|
||||||
if (diagnostic != nullptr) {
|
|
||||||
logger->error("SPIRV-Tools Validation Errors");
|
|
||||||
logger->error(diagnostic->error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tear down
|
|
||||||
spvValidatorOptionsDestroy(options);
|
|
||||||
spvDiagnosticDestroy(diagnostic);
|
|
||||||
spvContextDestroy(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
|
|
||||||
// legalizing HLSL SPIR-V.
|
|
||||||
void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
|
||||||
spv::SpvBuildLogger* logger, const SpvOptions* options)
|
|
||||||
{
|
|
||||||
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
|
|
||||||
|
|
||||||
spvtools::Optimizer optimizer(target_env);
|
|
||||||
optimizer.SetMessageConsumer(
|
|
||||||
[](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
|
|
||||||
// line information into all SPIR-V instructions. This avoids loss of
|
|
||||||
// information when instructions are deleted or moved. Later, remove
|
|
||||||
// redundant information to minimize final SPRIR-V size.
|
|
||||||
if (options->generateDebugInfo) {
|
|
||||||
optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass());
|
|
||||||
}
|
|
||||||
optimizer.RegisterPass(spvtools::CreateWrapOpKillPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateMergeReturnPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateEliminateDeadFunctionsPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateScalarReplacementPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateSimplificationPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateVectorDCEPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateBlockMergePass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateIfConversionPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateSimplificationPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateVectorDCEPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass());
|
|
||||||
if (options->optimizeSize) {
|
|
||||||
optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass());
|
|
||||||
}
|
|
||||||
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
|
|
||||||
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
|
|
||||||
if (options->generateDebugInfo) {
|
|
||||||
optimizer.RegisterPass(spvtools::CreateRedundantLineInfoElimPass());
|
|
||||||
}
|
|
||||||
|
|
||||||
spvtools::OptimizerOptions spvOptOptions;
|
|
||||||
optimizer.SetTargetEnv(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
|
|
||||||
spvOptOptions.set_run_validator(false); // The validator may run as a separate step later on
|
|
||||||
optimizer.Run(spirv.data(), spirv.size(), &spirv, spvOptOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // end namespace glslang
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,82 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2014-2016 LunarG, Inc.
|
|
||||||
// Copyright (C) 2018 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call into SPIRV-Tools to disassemble, validate, and optimize.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef GLSLANG_SPV_TOOLS_H
|
|
||||||
#define GLSLANG_SPV_TOOLS_H
|
|
||||||
|
|
||||||
#ifdef ENABLE_OPT
|
|
||||||
#include <vector>
|
|
||||||
#include <ostream>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "glslang/MachineIndependent/localintermediate.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
struct SpvOptions {
|
|
||||||
SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
|
|
||||||
optimizeSize(false), disassemble(false), validate(false) { }
|
|
||||||
bool generateDebugInfo;
|
|
||||||
bool disableOptimizer;
|
|
||||||
bool optimizeSize;
|
|
||||||
bool disassemble;
|
|
||||||
bool validate;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef ENABLE_OPT
|
|
||||||
|
|
||||||
// Use the SPIRV-Tools disassembler to print SPIR-V.
|
|
||||||
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
|
|
||||||
|
|
||||||
// Apply the SPIRV-Tools validator to generated SPIR-V.
|
|
||||||
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
|
||||||
spv::SpvBuildLogger*, bool prelegalization);
|
|
||||||
|
|
||||||
// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
|
|
||||||
// legalizing HLSL SPIR-V.
|
|
||||||
void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
|
|
||||||
spv::SpvBuildLogger*, const SpvOptions*);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // GLSLANG_SPV_TOOLS_H
|
|
|
@ -1,81 +0,0 @@
|
||||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#ifndef LIBSPIRV_UTIL_BITUTILS_H_
|
|
||||||
#define LIBSPIRV_UTIL_BITUTILS_H_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace spvutils {
|
|
||||||
|
|
||||||
// Performs a bitwise copy of source to the destination type Dest.
|
|
||||||
template <typename Dest, typename Src>
|
|
||||||
Dest BitwiseCast(Src source) {
|
|
||||||
Dest dest;
|
|
||||||
static_assert(sizeof(source) == sizeof(dest),
|
|
||||||
"BitwiseCast: Source and destination must have the same size");
|
|
||||||
std::memcpy(static_cast<void*>(&dest), &source, sizeof(dest));
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetBits<T, First, Num> returns an integer of type <T> with bits set
|
|
||||||
// for position <First> through <First + Num - 1>, counting from the least
|
|
||||||
// significant bit. In particular when Num == 0, no positions are set to 1.
|
|
||||||
// A static assert will be triggered if First + Num > sizeof(T) * 8, that is,
|
|
||||||
// a bit that will not fit in the underlying type is set.
|
|
||||||
template <typename T, size_t First = 0, size_t Num = 0>
|
|
||||||
struct SetBits {
|
|
||||||
static_assert(First < sizeof(T) * 8,
|
|
||||||
"Tried to set a bit that is shifted too far.");
|
|
||||||
const static T get = (T(1) << First) | SetBits<T, First + 1, Num - 1>::get;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, size_t Last>
|
|
||||||
struct SetBits<T, Last, 0> {
|
|
||||||
const static T get = T(0);
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is all compile-time so we can put our tests right here.
|
|
||||||
static_assert(SetBits<uint32_t, 0, 0>::get == uint32_t(0x00000000),
|
|
||||||
"SetBits failed");
|
|
||||||
static_assert(SetBits<uint32_t, 0, 1>::get == uint32_t(0x00000001),
|
|
||||||
"SetBits failed");
|
|
||||||
static_assert(SetBits<uint32_t, 31, 1>::get == uint32_t(0x80000000),
|
|
||||||
"SetBits failed");
|
|
||||||
static_assert(SetBits<uint32_t, 1, 2>::get == uint32_t(0x00000006),
|
|
||||||
"SetBits failed");
|
|
||||||
static_assert(SetBits<uint32_t, 30, 2>::get == uint32_t(0xc0000000),
|
|
||||||
"SetBits failed");
|
|
||||||
static_assert(SetBits<uint32_t, 0, 31>::get == uint32_t(0x7FFFFFFF),
|
|
||||||
"SetBits failed");
|
|
||||||
static_assert(SetBits<uint32_t, 0, 32>::get == uint32_t(0xFFFFFFFF),
|
|
||||||
"SetBits failed");
|
|
||||||
static_assert(SetBits<uint32_t, 16, 16>::get == uint32_t(0xFFFF0000),
|
|
||||||
"SetBits failed");
|
|
||||||
|
|
||||||
static_assert(SetBits<uint64_t, 0, 1>::get == uint64_t(0x0000000000000001LL),
|
|
||||||
"SetBits failed");
|
|
||||||
static_assert(SetBits<uint64_t, 63, 1>::get == uint64_t(0x8000000000000000LL),
|
|
||||||
"SetBits failed");
|
|
||||||
static_assert(SetBits<uint64_t, 62, 2>::get == uint64_t(0xc000000000000000LL),
|
|
||||||
"SetBits failed");
|
|
||||||
static_assert(SetBits<uint64_t, 31, 1>::get == uint64_t(0x0000000080000000LL),
|
|
||||||
"SetBits failed");
|
|
||||||
static_assert(SetBits<uint64_t, 16, 16>::get == uint64_t(0x00000000FFFF0000LL),
|
|
||||||
"SetBits failed");
|
|
||||||
|
|
||||||
} // namespace spvutils
|
|
||||||
|
|
||||||
#endif // LIBSPIRV_UTIL_BITUTILS_H_
|
|
|
@ -1,743 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2014-2015 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
//
|
|
||||||
// Disassembler for SPIR-V.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cassert>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <stack>
|
|
||||||
#include <sstream>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "disassemble.h"
|
|
||||||
#include "doc.h"
|
|
||||||
#include "SpvTools.h"
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
extern "C" {
|
|
||||||
// Include C-based headers that don't have a namespace
|
|
||||||
#include "GLSL.std.450.h"
|
|
||||||
#include "GLSL.ext.AMD.h"
|
|
||||||
#include "GLSL.ext.NV.h"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const char* GlslStd450DebugNames[spv::GLSLstd450Count];
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
|
|
||||||
static const char* GLSLextAMDGetDebugNames(const char*, unsigned);
|
|
||||||
static const char* GLSLextNVGetDebugNames(const char*, unsigned);
|
|
||||||
|
|
||||||
static void Kill(std::ostream& out, const char* message)
|
|
||||||
{
|
|
||||||
out << std::endl << "Disassembly failed: " << message << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// used to identify the extended instruction library imported when printing
|
|
||||||
enum ExtInstSet {
|
|
||||||
GLSL450Inst,
|
|
||||||
GLSLextAMDInst,
|
|
||||||
GLSLextNVInst,
|
|
||||||
OpenCLExtInst,
|
|
||||||
NonSemanticDebugPrintfExtInst,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Container class for a single instance of a SPIR-V stream, with methods for disassembly.
|
|
||||||
class SpirvStream {
|
|
||||||
public:
|
|
||||||
SpirvStream(std::ostream& out, const std::vector<unsigned int>& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { }
|
|
||||||
virtual ~SpirvStream() { }
|
|
||||||
|
|
||||||
void validate();
|
|
||||||
void processInstructions();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
SpirvStream(const SpirvStream&);
|
|
||||||
SpirvStream& operator=(const SpirvStream&);
|
|
||||||
Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; }
|
|
||||||
|
|
||||||
// Output methods
|
|
||||||
void outputIndent();
|
|
||||||
void formatId(Id id, std::stringstream&);
|
|
||||||
void outputResultId(Id id);
|
|
||||||
void outputTypeId(Id id);
|
|
||||||
void outputId(Id id);
|
|
||||||
void outputMask(OperandClass operandClass, unsigned mask);
|
|
||||||
void disassembleImmediates(int numOperands);
|
|
||||||
void disassembleIds(int numOperands);
|
|
||||||
int disassembleString();
|
|
||||||
void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
|
|
||||||
|
|
||||||
// Data
|
|
||||||
std::ostream& out; // where to write the disassembly
|
|
||||||
const std::vector<unsigned int>& stream; // the actual word stream
|
|
||||||
int size; // the size of the word stream
|
|
||||||
int word; // the next word of the stream to read
|
|
||||||
|
|
||||||
// map each <id> to the instruction that created it
|
|
||||||
Id bound;
|
|
||||||
std::vector<unsigned int> idInstruction; // the word offset into the stream where the instruction for result [id] starts; 0 if not yet seen (forward reference or function parameter)
|
|
||||||
|
|
||||||
std::vector<std::string> idDescriptor; // the best text string known for explaining the <id>
|
|
||||||
|
|
||||||
// schema
|
|
||||||
unsigned int schema;
|
|
||||||
|
|
||||||
// stack of structured-merge points
|
|
||||||
std::stack<Id> nestedControl;
|
|
||||||
Id nextNestedControl; // need a slight delay for when we are nested
|
|
||||||
};
|
|
||||||
|
|
||||||
void SpirvStream::validate()
|
|
||||||
{
|
|
||||||
size = (int)stream.size();
|
|
||||||
if (size < 4)
|
|
||||||
Kill(out, "stream is too short");
|
|
||||||
|
|
||||||
// Magic number
|
|
||||||
if (stream[word++] != MagicNumber) {
|
|
||||||
out << "Bad magic number";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version
|
|
||||||
out << "// Module Version " << std::hex << stream[word++] << std::endl;
|
|
||||||
|
|
||||||
// Generator's magic number
|
|
||||||
out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl;
|
|
||||||
|
|
||||||
// Result <id> bound
|
|
||||||
bound = stream[word++];
|
|
||||||
idInstruction.resize(bound);
|
|
||||||
idDescriptor.resize(bound);
|
|
||||||
out << "// Id's are bound by " << bound << std::endl;
|
|
||||||
out << std::endl;
|
|
||||||
|
|
||||||
// Reserved schema, must be 0 for now
|
|
||||||
schema = stream[word++];
|
|
||||||
if (schema != 0)
|
|
||||||
Kill(out, "bad schema, must be 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop over all the instructions, in order, processing each.
|
|
||||||
// Boiler plate for each is handled here directly, the rest is dispatched.
|
|
||||||
void SpirvStream::processInstructions()
|
|
||||||
{
|
|
||||||
// Instructions
|
|
||||||
while (word < size) {
|
|
||||||
int instructionStart = word;
|
|
||||||
|
|
||||||
// Instruction wordCount and opcode
|
|
||||||
unsigned int firstWord = stream[word];
|
|
||||||
unsigned wordCount = firstWord >> WordCountShift;
|
|
||||||
Op opCode = (Op)(firstWord & OpCodeMask);
|
|
||||||
int nextInst = word + wordCount;
|
|
||||||
++word;
|
|
||||||
|
|
||||||
// Presence of full instruction
|
|
||||||
if (nextInst > size)
|
|
||||||
Kill(out, "stream instruction terminated too early");
|
|
||||||
|
|
||||||
// Base for computing number of operands; will be updated as more is learned
|
|
||||||
unsigned numOperands = wordCount - 1;
|
|
||||||
|
|
||||||
// Type <id>
|
|
||||||
Id typeId = 0;
|
|
||||||
if (InstructionDesc[opCode].hasType()) {
|
|
||||||
typeId = stream[word++];
|
|
||||||
--numOperands;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Result <id>
|
|
||||||
Id resultId = 0;
|
|
||||||
if (InstructionDesc[opCode].hasResult()) {
|
|
||||||
resultId = stream[word++];
|
|
||||||
--numOperands;
|
|
||||||
|
|
||||||
// save instruction for future reference
|
|
||||||
idInstruction[resultId] = instructionStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
outputResultId(resultId);
|
|
||||||
outputTypeId(typeId);
|
|
||||||
outputIndent();
|
|
||||||
|
|
||||||
// Hand off the Op and all its operands
|
|
||||||
disassembleInstruction(resultId, typeId, opCode, numOperands);
|
|
||||||
if (word != nextInst) {
|
|
||||||
out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;
|
|
||||||
word = nextInst;
|
|
||||||
}
|
|
||||||
out << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStream::outputIndent()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < (int)nestedControl.size(); ++i)
|
|
||||||
out << " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStream::formatId(Id id, std::stringstream& idStream)
|
|
||||||
{
|
|
||||||
if (id != 0) {
|
|
||||||
// On instructions with no IDs, this is called with "0", which does not
|
|
||||||
// have to be within ID bounds on null shaders.
|
|
||||||
if (id >= bound)
|
|
||||||
Kill(out, "Bad <id>");
|
|
||||||
|
|
||||||
idStream << id;
|
|
||||||
if (idDescriptor[id].size() > 0)
|
|
||||||
idStream << "(" << idDescriptor[id] << ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStream::outputResultId(Id id)
|
|
||||||
{
|
|
||||||
const int width = 16;
|
|
||||||
std::stringstream idStream;
|
|
||||||
formatId(id, idStream);
|
|
||||||
out << std::setw(width) << std::right << idStream.str();
|
|
||||||
if (id != 0)
|
|
||||||
out << ":";
|
|
||||||
else
|
|
||||||
out << " ";
|
|
||||||
|
|
||||||
if (nestedControl.size() && id == nestedControl.top())
|
|
||||||
nestedControl.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStream::outputTypeId(Id id)
|
|
||||||
{
|
|
||||||
const int width = 12;
|
|
||||||
std::stringstream idStream;
|
|
||||||
formatId(id, idStream);
|
|
||||||
out << std::setw(width) << std::right << idStream.str() << " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStream::outputId(Id id)
|
|
||||||
{
|
|
||||||
if (id >= bound)
|
|
||||||
Kill(out, "Bad <id>");
|
|
||||||
|
|
||||||
out << id;
|
|
||||||
if (idDescriptor[id].size() > 0)
|
|
||||||
out << "(" << idDescriptor[id] << ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStream::outputMask(OperandClass operandClass, unsigned mask)
|
|
||||||
{
|
|
||||||
if (mask == 0)
|
|
||||||
out << "None";
|
|
||||||
else {
|
|
||||||
for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {
|
|
||||||
if (mask & (1 << m))
|
|
||||||
out << OperandClassParams[operandClass].getName(m) << " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStream::disassembleImmediates(int numOperands)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < numOperands; ++i) {
|
|
||||||
out << stream[word++];
|
|
||||||
if (i < numOperands - 1)
|
|
||||||
out << " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStream::disassembleIds(int numOperands)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < numOperands; ++i) {
|
|
||||||
outputId(stream[word++]);
|
|
||||||
if (i < numOperands - 1)
|
|
||||||
out << " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the number of operands consumed by the string
|
|
||||||
int SpirvStream::disassembleString()
|
|
||||||
{
|
|
||||||
int startWord = word;
|
|
||||||
|
|
||||||
out << " \"";
|
|
||||||
|
|
||||||
const char* wordString;
|
|
||||||
bool done = false;
|
|
||||||
do {
|
|
||||||
unsigned int content = stream[word];
|
|
||||||
wordString = (const char*)&content;
|
|
||||||
for (int charCount = 0; charCount < 4; ++charCount) {
|
|
||||||
if (*wordString == 0) {
|
|
||||||
done = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
out << *(wordString++);
|
|
||||||
}
|
|
||||||
++word;
|
|
||||||
} while (! done);
|
|
||||||
|
|
||||||
out << "\"";
|
|
||||||
|
|
||||||
return word - startWord;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
|
|
||||||
{
|
|
||||||
// Process the opcode
|
|
||||||
|
|
||||||
out << (OpcodeString(opCode) + 2); // leave out the "Op"
|
|
||||||
|
|
||||||
if (opCode == OpLoopMerge || opCode == OpSelectionMerge)
|
|
||||||
nextNestedControl = stream[word];
|
|
||||||
else if (opCode == OpBranchConditional || opCode == OpSwitch) {
|
|
||||||
if (nextNestedControl) {
|
|
||||||
nestedControl.push(nextNestedControl);
|
|
||||||
nextNestedControl = 0;
|
|
||||||
}
|
|
||||||
} else if (opCode == OpExtInstImport) {
|
|
||||||
idDescriptor[resultId] = (const char*)(&stream[word]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (resultId != 0 && idDescriptor[resultId].size() == 0) {
|
|
||||||
switch (opCode) {
|
|
||||||
case OpTypeInt:
|
|
||||||
switch (stream[word]) {
|
|
||||||
case 8: idDescriptor[resultId] = "int8_t"; break;
|
|
||||||
case 16: idDescriptor[resultId] = "int16_t"; break;
|
|
||||||
default: assert(0); // fallthrough
|
|
||||||
case 32: idDescriptor[resultId] = "int"; break;
|
|
||||||
case 64: idDescriptor[resultId] = "int64_t"; break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OpTypeFloat:
|
|
||||||
switch (stream[word]) {
|
|
||||||
case 16: idDescriptor[resultId] = "float16_t"; break;
|
|
||||||
default: assert(0); // fallthrough
|
|
||||||
case 32: idDescriptor[resultId] = "float"; break;
|
|
||||||
case 64: idDescriptor[resultId] = "float64_t"; break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OpTypeBool:
|
|
||||||
idDescriptor[resultId] = "bool";
|
|
||||||
break;
|
|
||||||
case OpTypeStruct:
|
|
||||||
idDescriptor[resultId] = "struct";
|
|
||||||
break;
|
|
||||||
case OpTypePointer:
|
|
||||||
idDescriptor[resultId] = "ptr";
|
|
||||||
break;
|
|
||||||
case OpTypeVector:
|
|
||||||
if (idDescriptor[stream[word]].size() > 0) {
|
|
||||||
idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1);
|
|
||||||
if (strstr(idDescriptor[stream[word]].c_str(), "8")) {
|
|
||||||
idDescriptor[resultId].append("8");
|
|
||||||
}
|
|
||||||
if (strstr(idDescriptor[stream[word]].c_str(), "16")) {
|
|
||||||
idDescriptor[resultId].append("16");
|
|
||||||
}
|
|
||||||
if (strstr(idDescriptor[stream[word]].c_str(), "64")) {
|
|
||||||
idDescriptor[resultId].append("64");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
idDescriptor[resultId].append("vec");
|
|
||||||
switch (stream[word + 1]) {
|
|
||||||
case 2: idDescriptor[resultId].append("2"); break;
|
|
||||||
case 3: idDescriptor[resultId].append("3"); break;
|
|
||||||
case 4: idDescriptor[resultId].append("4"); break;
|
|
||||||
case 8: idDescriptor[resultId].append("8"); break;
|
|
||||||
case 16: idDescriptor[resultId].append("16"); break;
|
|
||||||
case 32: idDescriptor[resultId].append("32"); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process the operands. Note, a new context-dependent set could be
|
|
||||||
// swapped in mid-traversal.
|
|
||||||
|
|
||||||
// Handle images specially, so can put out helpful strings.
|
|
||||||
if (opCode == OpTypeImage) {
|
|
||||||
out << " ";
|
|
||||||
disassembleIds(1);
|
|
||||||
out << " " << DimensionString((Dim)stream[word++]);
|
|
||||||
out << (stream[word++] != 0 ? " depth" : "");
|
|
||||||
out << (stream[word++] != 0 ? " array" : "");
|
|
||||||
out << (stream[word++] != 0 ? " multi-sampled" : "");
|
|
||||||
switch (stream[word++]) {
|
|
||||||
case 0: out << " runtime"; break;
|
|
||||||
case 1: out << " sampled"; break;
|
|
||||||
case 2: out << " nonsampled"; break;
|
|
||||||
}
|
|
||||||
out << " format:" << ImageFormatString((ImageFormat)stream[word++]);
|
|
||||||
|
|
||||||
if (numOperands == 8) {
|
|
||||||
out << " " << AccessQualifierString(stream[word++]);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle all the parameterized operands
|
|
||||||
for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) {
|
|
||||||
out << " ";
|
|
||||||
OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op);
|
|
||||||
switch (operandClass) {
|
|
||||||
case OperandId:
|
|
||||||
case OperandScope:
|
|
||||||
case OperandMemorySemantics:
|
|
||||||
disassembleIds(1);
|
|
||||||
--numOperands;
|
|
||||||
// Get names for printing "(XXX)" for readability, *after* this id
|
|
||||||
if (opCode == OpName)
|
|
||||||
idDescriptor[stream[word - 1]] = (const char*)(&stream[word]);
|
|
||||||
break;
|
|
||||||
case OperandVariableIds:
|
|
||||||
disassembleIds(numOperands);
|
|
||||||
return;
|
|
||||||
case OperandImageOperands:
|
|
||||||
outputMask(OperandImageOperands, stream[word++]);
|
|
||||||
--numOperands;
|
|
||||||
disassembleIds(numOperands);
|
|
||||||
return;
|
|
||||||
case OperandOptionalLiteral:
|
|
||||||
case OperandVariableLiterals:
|
|
||||||
if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) ||
|
|
||||||
(opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) {
|
|
||||||
out << BuiltInString(stream[word++]);
|
|
||||||
--numOperands;
|
|
||||||
++op;
|
|
||||||
}
|
|
||||||
disassembleImmediates(numOperands);
|
|
||||||
return;
|
|
||||||
case OperandVariableIdLiteral:
|
|
||||||
while (numOperands > 0) {
|
|
||||||
out << std::endl;
|
|
||||||
outputResultId(0);
|
|
||||||
outputTypeId(0);
|
|
||||||
outputIndent();
|
|
||||||
out << " Type ";
|
|
||||||
disassembleIds(1);
|
|
||||||
out << ", member ";
|
|
||||||
disassembleImmediates(1);
|
|
||||||
numOperands -= 2;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case OperandVariableLiteralId:
|
|
||||||
while (numOperands > 0) {
|
|
||||||
out << std::endl;
|
|
||||||
outputResultId(0);
|
|
||||||
outputTypeId(0);
|
|
||||||
outputIndent();
|
|
||||||
out << " case ";
|
|
||||||
disassembleImmediates(1);
|
|
||||||
out << ": ";
|
|
||||||
disassembleIds(1);
|
|
||||||
numOperands -= 2;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case OperandLiteralNumber:
|
|
||||||
disassembleImmediates(1);
|
|
||||||
--numOperands;
|
|
||||||
if (opCode == OpExtInst) {
|
|
||||||
ExtInstSet extInstSet = GLSL450Inst;
|
|
||||||
const char* name = idDescriptor[stream[word - 2]].c_str();
|
|
||||||
if (strcmp("OpenCL.std", name) == 0) {
|
|
||||||
extInstSet = OpenCLExtInst;
|
|
||||||
} else if (strcmp("OpenCL.DebugInfo.100", name) == 0) {
|
|
||||||
extInstSet = OpenCLExtInst;
|
|
||||||
} else if (strcmp("NonSemantic.DebugPrintf", name) == 0) {
|
|
||||||
extInstSet = NonSemanticDebugPrintfExtInst;
|
|
||||||
} else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
|
|
||||||
strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
|
|
||||||
strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
|
|
||||||
strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) {
|
|
||||||
extInstSet = GLSLextAMDInst;
|
|
||||||
} else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||
|
|
||||||
strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 ||
|
|
||||||
strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 ||
|
|
||||||
strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 ||
|
|
||||||
strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 ||
|
|
||||||
strcmp(spv::E_SPV_NV_mesh_shader, name) == 0) {
|
|
||||||
extInstSet = GLSLextNVInst;
|
|
||||||
}
|
|
||||||
unsigned entrypoint = stream[word - 1];
|
|
||||||
if (extInstSet == GLSL450Inst) {
|
|
||||||
if (entrypoint < GLSLstd450Count) {
|
|
||||||
out << "(" << GlslStd450DebugNames[entrypoint] << ")";
|
|
||||||
}
|
|
||||||
} else if (extInstSet == GLSLextAMDInst) {
|
|
||||||
out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")";
|
|
||||||
}
|
|
||||||
else if (extInstSet == GLSLextNVInst) {
|
|
||||||
out << "(" << GLSLextNVGetDebugNames(name, entrypoint) << ")";
|
|
||||||
} else if (extInstSet == NonSemanticDebugPrintfExtInst) {
|
|
||||||
out << "(DebugPrintf)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case OperandOptionalLiteralString:
|
|
||||||
case OperandLiteralString:
|
|
||||||
numOperands -= disassembleString();
|
|
||||||
break;
|
|
||||||
case OperandMemoryAccess:
|
|
||||||
outputMask(OperandMemoryAccess, stream[word++]);
|
|
||||||
--numOperands;
|
|
||||||
// Aligned is the only memory access operand that uses an immediate
|
|
||||||
// value, and it is also the first operand that uses a value at all.
|
|
||||||
if (stream[word-1] & MemoryAccessAlignedMask) {
|
|
||||||
disassembleImmediates(1);
|
|
||||||
numOperands--;
|
|
||||||
if (numOperands)
|
|
||||||
out << " ";
|
|
||||||
}
|
|
||||||
disassembleIds(numOperands);
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
assert(operandClass >= OperandSource && operandClass < OperandOpcode);
|
|
||||||
|
|
||||||
if (OperandClassParams[operandClass].bitmask)
|
|
||||||
outputMask(operandClass, stream[word++]);
|
|
||||||
else
|
|
||||||
out << OperandClassParams[operandClass].getName(stream[word++]);
|
|
||||||
--numOperands;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void GLSLstd450GetDebugNames(const char** names)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < GLSLstd450Count; ++i)
|
|
||||||
names[i] = "Unknown";
|
|
||||||
|
|
||||||
names[GLSLstd450Round] = "Round";
|
|
||||||
names[GLSLstd450RoundEven] = "RoundEven";
|
|
||||||
names[GLSLstd450Trunc] = "Trunc";
|
|
||||||
names[GLSLstd450FAbs] = "FAbs";
|
|
||||||
names[GLSLstd450SAbs] = "SAbs";
|
|
||||||
names[GLSLstd450FSign] = "FSign";
|
|
||||||
names[GLSLstd450SSign] = "SSign";
|
|
||||||
names[GLSLstd450Floor] = "Floor";
|
|
||||||
names[GLSLstd450Ceil] = "Ceil";
|
|
||||||
names[GLSLstd450Fract] = "Fract";
|
|
||||||
names[GLSLstd450Radians] = "Radians";
|
|
||||||
names[GLSLstd450Degrees] = "Degrees";
|
|
||||||
names[GLSLstd450Sin] = "Sin";
|
|
||||||
names[GLSLstd450Cos] = "Cos";
|
|
||||||
names[GLSLstd450Tan] = "Tan";
|
|
||||||
names[GLSLstd450Asin] = "Asin";
|
|
||||||
names[GLSLstd450Acos] = "Acos";
|
|
||||||
names[GLSLstd450Atan] = "Atan";
|
|
||||||
names[GLSLstd450Sinh] = "Sinh";
|
|
||||||
names[GLSLstd450Cosh] = "Cosh";
|
|
||||||
names[GLSLstd450Tanh] = "Tanh";
|
|
||||||
names[GLSLstd450Asinh] = "Asinh";
|
|
||||||
names[GLSLstd450Acosh] = "Acosh";
|
|
||||||
names[GLSLstd450Atanh] = "Atanh";
|
|
||||||
names[GLSLstd450Atan2] = "Atan2";
|
|
||||||
names[GLSLstd450Pow] = "Pow";
|
|
||||||
names[GLSLstd450Exp] = "Exp";
|
|
||||||
names[GLSLstd450Log] = "Log";
|
|
||||||
names[GLSLstd450Exp2] = "Exp2";
|
|
||||||
names[GLSLstd450Log2] = "Log2";
|
|
||||||
names[GLSLstd450Sqrt] = "Sqrt";
|
|
||||||
names[GLSLstd450InverseSqrt] = "InverseSqrt";
|
|
||||||
names[GLSLstd450Determinant] = "Determinant";
|
|
||||||
names[GLSLstd450MatrixInverse] = "MatrixInverse";
|
|
||||||
names[GLSLstd450Modf] = "Modf";
|
|
||||||
names[GLSLstd450ModfStruct] = "ModfStruct";
|
|
||||||
names[GLSLstd450FMin] = "FMin";
|
|
||||||
names[GLSLstd450SMin] = "SMin";
|
|
||||||
names[GLSLstd450UMin] = "UMin";
|
|
||||||
names[GLSLstd450FMax] = "FMax";
|
|
||||||
names[GLSLstd450SMax] = "SMax";
|
|
||||||
names[GLSLstd450UMax] = "UMax";
|
|
||||||
names[GLSLstd450FClamp] = "FClamp";
|
|
||||||
names[GLSLstd450SClamp] = "SClamp";
|
|
||||||
names[GLSLstd450UClamp] = "UClamp";
|
|
||||||
names[GLSLstd450FMix] = "FMix";
|
|
||||||
names[GLSLstd450Step] = "Step";
|
|
||||||
names[GLSLstd450SmoothStep] = "SmoothStep";
|
|
||||||
names[GLSLstd450Fma] = "Fma";
|
|
||||||
names[GLSLstd450Frexp] = "Frexp";
|
|
||||||
names[GLSLstd450FrexpStruct] = "FrexpStruct";
|
|
||||||
names[GLSLstd450Ldexp] = "Ldexp";
|
|
||||||
names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8";
|
|
||||||
names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8";
|
|
||||||
names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16";
|
|
||||||
names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16";
|
|
||||||
names[GLSLstd450PackHalf2x16] = "PackHalf2x16";
|
|
||||||
names[GLSLstd450PackDouble2x32] = "PackDouble2x32";
|
|
||||||
names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16";
|
|
||||||
names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16";
|
|
||||||
names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16";
|
|
||||||
names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8";
|
|
||||||
names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8";
|
|
||||||
names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32";
|
|
||||||
names[GLSLstd450Length] = "Length";
|
|
||||||
names[GLSLstd450Distance] = "Distance";
|
|
||||||
names[GLSLstd450Cross] = "Cross";
|
|
||||||
names[GLSLstd450Normalize] = "Normalize";
|
|
||||||
names[GLSLstd450FaceForward] = "FaceForward";
|
|
||||||
names[GLSLstd450Reflect] = "Reflect";
|
|
||||||
names[GLSLstd450Refract] = "Refract";
|
|
||||||
names[GLSLstd450FindILsb] = "FindILsb";
|
|
||||||
names[GLSLstd450FindSMsb] = "FindSMsb";
|
|
||||||
names[GLSLstd450FindUMsb] = "FindUMsb";
|
|
||||||
names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid";
|
|
||||||
names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample";
|
|
||||||
names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset";
|
|
||||||
names[GLSLstd450NMin] = "NMin";
|
|
||||||
names[GLSLstd450NMax] = "NMax";
|
|
||||||
names[GLSLstd450NClamp] = "NClamp";
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint)
|
|
||||||
{
|
|
||||||
if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) {
|
|
||||||
switch (entrypoint) {
|
|
||||||
case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD";
|
|
||||||
case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD";
|
|
||||||
case WriteInvocationAMD: return "WriteInvocationAMD";
|
|
||||||
case MbcntAMD: return "MbcntAMD";
|
|
||||||
default: return "Bad";
|
|
||||||
}
|
|
||||||
} else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) {
|
|
||||||
switch (entrypoint) {
|
|
||||||
case FMin3AMD: return "FMin3AMD";
|
|
||||||
case UMin3AMD: return "UMin3AMD";
|
|
||||||
case SMin3AMD: return "SMin3AMD";
|
|
||||||
case FMax3AMD: return "FMax3AMD";
|
|
||||||
case UMax3AMD: return "UMax3AMD";
|
|
||||||
case SMax3AMD: return "SMax3AMD";
|
|
||||||
case FMid3AMD: return "FMid3AMD";
|
|
||||||
case UMid3AMD: return "UMid3AMD";
|
|
||||||
case SMid3AMD: return "SMid3AMD";
|
|
||||||
default: return "Bad";
|
|
||||||
}
|
|
||||||
} else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) {
|
|
||||||
switch (entrypoint) {
|
|
||||||
case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD";
|
|
||||||
default: return "Bad";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) {
|
|
||||||
switch (entrypoint) {
|
|
||||||
case CubeFaceIndexAMD: return "CubeFaceIndexAMD";
|
|
||||||
case CubeFaceCoordAMD: return "CubeFaceCoordAMD";
|
|
||||||
case TimeAMD: return "TimeAMD";
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Bad";
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)
|
|
||||||
{
|
|
||||||
if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 ||
|
|
||||||
strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 ||
|
|
||||||
strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 ||
|
|
||||||
strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 ||
|
|
||||||
strcmp(name, spv::E_SPV_NVX_multiview_per_view_attributes) == 0 ||
|
|
||||||
strcmp(name, spv::E_SPV_NV_fragment_shader_barycentric) == 0 ||
|
|
||||||
strcmp(name, spv::E_SPV_NV_mesh_shader) == 0 ||
|
|
||||||
strcmp(name, spv::E_SPV_NV_shader_image_footprint) == 0) {
|
|
||||||
switch (entrypoint) {
|
|
||||||
// NV builtins
|
|
||||||
case BuiltInViewportMaskNV: return "ViewportMaskNV";
|
|
||||||
case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
|
|
||||||
case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
|
|
||||||
case BuiltInPositionPerViewNV: return "PositionPerViewNV";
|
|
||||||
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
|
|
||||||
case BuiltInBaryCoordNV: return "BaryCoordNV";
|
|
||||||
case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
|
|
||||||
case BuiltInTaskCountNV: return "TaskCountNV";
|
|
||||||
case BuiltInPrimitiveCountNV: return "PrimitiveCountNV";
|
|
||||||
case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV";
|
|
||||||
case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV";
|
|
||||||
case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV";
|
|
||||||
case BuiltInLayerPerViewNV: return "LayerPerViewNV";
|
|
||||||
case BuiltInMeshViewCountNV: return "MeshViewCountNV";
|
|
||||||
case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV";
|
|
||||||
|
|
||||||
// NV Capabilities
|
|
||||||
case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";
|
|
||||||
case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV";
|
|
||||||
case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV";
|
|
||||||
case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
|
|
||||||
case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
|
|
||||||
case CapabilityMeshShadingNV: return "MeshShadingNV";
|
|
||||||
case CapabilityImageFootprintNV: return "ImageFootprintNV";
|
|
||||||
case CapabilitySampleMaskOverrideCoverageNV:return "SampleMaskOverrideCoverageNV";
|
|
||||||
|
|
||||||
// NV Decorations
|
|
||||||
case DecorationOverrideCoverageNV: return "OverrideCoverageNV";
|
|
||||||
case DecorationPassthroughNV: return "PassthroughNV";
|
|
||||||
case DecorationViewportRelativeNV: return "ViewportRelativeNV";
|
|
||||||
case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";
|
|
||||||
case DecorationPerVertexNV: return "PerVertexNV";
|
|
||||||
case DecorationPerPrimitiveNV: return "PerPrimitiveNV";
|
|
||||||
case DecorationPerViewNV: return "PerViewNV";
|
|
||||||
case DecorationPerTaskNV: return "PerTaskNV";
|
|
||||||
|
|
||||||
default: return "Bad";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "Bad";
|
|
||||||
}
|
|
||||||
|
|
||||||
void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
|
|
||||||
{
|
|
||||||
SpirvStream SpirvStream(out, stream);
|
|
||||||
spv::Parameterize();
|
|
||||||
GLSLstd450GetDebugNames(GlslStd450DebugNames);
|
|
||||||
SpirvStream.validate();
|
|
||||||
SpirvStream.processInstructions();
|
|
||||||
}
|
|
||||||
|
|
||||||
}; // end namespace spv
|
|
|
@ -1,53 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2014-2015 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
//
|
|
||||||
// Disassembler for SPIR-V.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef disassembler_H
|
|
||||||
#define disassembler_H
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
|
|
||||||
// disassemble with glslang custom disassembler
|
|
||||||
void Disassemble(std::ostream& out, const std::vector<unsigned int>&);
|
|
||||||
|
|
||||||
} // end namespace spv
|
|
||||||
|
|
||||||
#endif // disassembler_H
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,258 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2014-2015 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
//
|
|
||||||
// Parameterize the SPIR-V enumerants.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "spirv.hpp"
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
|
|
||||||
// Fill in all the parameters
|
|
||||||
void Parameterize();
|
|
||||||
|
|
||||||
// Return the English names of all the enums.
|
|
||||||
const char* SourceString(int);
|
|
||||||
const char* AddressingString(int);
|
|
||||||
const char* MemoryString(int);
|
|
||||||
const char* ExecutionModelString(int);
|
|
||||||
const char* ExecutionModeString(int);
|
|
||||||
const char* StorageClassString(int);
|
|
||||||
const char* DecorationString(int);
|
|
||||||
const char* BuiltInString(int);
|
|
||||||
const char* DimensionString(int);
|
|
||||||
const char* SelectControlString(int);
|
|
||||||
const char* LoopControlString(int);
|
|
||||||
const char* FunctionControlString(int);
|
|
||||||
const char* SamplerAddressingModeString(int);
|
|
||||||
const char* SamplerFilterModeString(int);
|
|
||||||
const char* ImageFormatString(int);
|
|
||||||
const char* ImageChannelOrderString(int);
|
|
||||||
const char* ImageChannelTypeString(int);
|
|
||||||
const char* ImageChannelDataTypeString(int type);
|
|
||||||
const char* ImageOperandsString(int format);
|
|
||||||
const char* ImageOperands(int);
|
|
||||||
const char* FPFastMathString(int);
|
|
||||||
const char* FPRoundingModeString(int);
|
|
||||||
const char* LinkageTypeString(int);
|
|
||||||
const char* FuncParamAttrString(int);
|
|
||||||
const char* AccessQualifierString(int);
|
|
||||||
const char* MemorySemanticsString(int);
|
|
||||||
const char* MemoryAccessString(int);
|
|
||||||
const char* ExecutionScopeString(int);
|
|
||||||
const char* GroupOperationString(int);
|
|
||||||
const char* KernelEnqueueFlagsString(int);
|
|
||||||
const char* KernelProfilingInfoString(int);
|
|
||||||
const char* CapabilityString(int);
|
|
||||||
const char* OpcodeString(int);
|
|
||||||
const char* ScopeString(int mem);
|
|
||||||
|
|
||||||
// For grouping opcodes into subsections
|
|
||||||
enum OpcodeClass {
|
|
||||||
OpClassMisc,
|
|
||||||
OpClassDebug,
|
|
||||||
OpClassAnnotate,
|
|
||||||
OpClassExtension,
|
|
||||||
OpClassMode,
|
|
||||||
OpClassType,
|
|
||||||
OpClassConstant,
|
|
||||||
OpClassMemory,
|
|
||||||
OpClassFunction,
|
|
||||||
OpClassImage,
|
|
||||||
OpClassConvert,
|
|
||||||
OpClassComposite,
|
|
||||||
OpClassArithmetic,
|
|
||||||
OpClassBit,
|
|
||||||
OpClassRelationalLogical,
|
|
||||||
OpClassDerivative,
|
|
||||||
OpClassFlowControl,
|
|
||||||
OpClassAtomic,
|
|
||||||
OpClassPrimitive,
|
|
||||||
OpClassBarrier,
|
|
||||||
OpClassGroup,
|
|
||||||
OpClassDeviceSideEnqueue,
|
|
||||||
OpClassPipe,
|
|
||||||
|
|
||||||
OpClassCount,
|
|
||||||
OpClassMissing // all instructions start out as missing
|
|
||||||
};
|
|
||||||
|
|
||||||
// For parameterizing operands.
|
|
||||||
enum OperandClass {
|
|
||||||
OperandNone,
|
|
||||||
OperandId,
|
|
||||||
OperandVariableIds,
|
|
||||||
OperandOptionalLiteral,
|
|
||||||
OperandOptionalLiteralString,
|
|
||||||
OperandVariableLiterals,
|
|
||||||
OperandVariableIdLiteral,
|
|
||||||
OperandVariableLiteralId,
|
|
||||||
OperandLiteralNumber,
|
|
||||||
OperandLiteralString,
|
|
||||||
OperandSource,
|
|
||||||
OperandExecutionModel,
|
|
||||||
OperandAddressing,
|
|
||||||
OperandMemory,
|
|
||||||
OperandExecutionMode,
|
|
||||||
OperandStorage,
|
|
||||||
OperandDimensionality,
|
|
||||||
OperandSamplerAddressingMode,
|
|
||||||
OperandSamplerFilterMode,
|
|
||||||
OperandSamplerImageFormat,
|
|
||||||
OperandImageChannelOrder,
|
|
||||||
OperandImageChannelDataType,
|
|
||||||
OperandImageOperands,
|
|
||||||
OperandFPFastMath,
|
|
||||||
OperandFPRoundingMode,
|
|
||||||
OperandLinkageType,
|
|
||||||
OperandAccessQualifier,
|
|
||||||
OperandFuncParamAttr,
|
|
||||||
OperandDecoration,
|
|
||||||
OperandBuiltIn,
|
|
||||||
OperandSelect,
|
|
||||||
OperandLoop,
|
|
||||||
OperandFunction,
|
|
||||||
OperandMemorySemantics,
|
|
||||||
OperandMemoryAccess,
|
|
||||||
OperandScope,
|
|
||||||
OperandGroupOperation,
|
|
||||||
OperandKernelEnqueueFlags,
|
|
||||||
OperandKernelProfilingInfo,
|
|
||||||
OperandCapability,
|
|
||||||
|
|
||||||
OperandOpcode,
|
|
||||||
|
|
||||||
OperandCount
|
|
||||||
};
|
|
||||||
|
|
||||||
// Any specific enum can have a set of capabilities that allow it:
|
|
||||||
typedef std::vector<Capability> EnumCaps;
|
|
||||||
|
|
||||||
// Parameterize a set of operands with their OperandClass(es) and descriptions.
|
|
||||||
class OperandParameters {
|
|
||||||
public:
|
|
||||||
OperandParameters() { }
|
|
||||||
void push(OperandClass oc, const char* d, bool opt = false)
|
|
||||||
{
|
|
||||||
opClass.push_back(oc);
|
|
||||||
desc.push_back(d);
|
|
||||||
optional.push_back(opt);
|
|
||||||
}
|
|
||||||
void setOptional();
|
|
||||||
OperandClass getClass(int op) const { return opClass[op]; }
|
|
||||||
const char* getDesc(int op) const { return desc[op]; }
|
|
||||||
bool isOptional(int op) const { return optional[op]; }
|
|
||||||
int getNum() const { return (int)opClass.size(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::vector<OperandClass> opClass;
|
|
||||||
std::vector<const char*> desc;
|
|
||||||
std::vector<bool> optional;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parameterize an enumerant
|
|
||||||
class EnumParameters {
|
|
||||||
public:
|
|
||||||
EnumParameters() : desc(0) { }
|
|
||||||
const char* desc;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parameterize a set of enumerants that form an enum
|
|
||||||
class EnumDefinition : public EnumParameters {
|
|
||||||
public:
|
|
||||||
EnumDefinition() :
|
|
||||||
ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { }
|
|
||||||
void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false)
|
|
||||||
{
|
|
||||||
ceiling = ceil;
|
|
||||||
getName = name;
|
|
||||||
bitmask = mask;
|
|
||||||
enumParams = ep;
|
|
||||||
}
|
|
||||||
void setOperands(OperandParameters* op) { operandParams = op; }
|
|
||||||
int ceiling; // ceiling of enumerants
|
|
||||||
bool bitmask; // true if these enumerants combine into a bitmask
|
|
||||||
const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift)
|
|
||||||
EnumParameters* enumParams; // parameters for each individual enumerant
|
|
||||||
OperandParameters* operandParams; // sets of operands
|
|
||||||
};
|
|
||||||
|
|
||||||
// Parameterize an instruction's logical format, including its known set of operands,
|
|
||||||
// per OperandParameters above.
|
|
||||||
class InstructionParameters {
|
|
||||||
public:
|
|
||||||
InstructionParameters() :
|
|
||||||
opDesc("TBD"),
|
|
||||||
opClass(OpClassMissing),
|
|
||||||
typePresent(true), // most normal, only exceptions have to be spelled out
|
|
||||||
resultPresent(true) // most normal, only exceptions have to be spelled out
|
|
||||||
{ }
|
|
||||||
|
|
||||||
void setResultAndType(bool r, bool t)
|
|
||||||
{
|
|
||||||
resultPresent = r;
|
|
||||||
typePresent = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasResult() const { return resultPresent != 0; }
|
|
||||||
bool hasType() const { return typePresent != 0; }
|
|
||||||
|
|
||||||
const char* opDesc;
|
|
||||||
OpcodeClass opClass;
|
|
||||||
OperandParameters operands;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int typePresent : 1;
|
|
||||||
int resultPresent : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// The set of objects that hold all the instruction/operand
|
|
||||||
// parameterization information.
|
|
||||||
extern InstructionParameters InstructionDesc[];
|
|
||||||
|
|
||||||
// These hold definitions of the enumerants used for operands
|
|
||||||
extern EnumDefinition OperandClassParams[];
|
|
||||||
|
|
||||||
const char* GetOperandDesc(OperandClass operand);
|
|
||||||
void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false);
|
|
||||||
const char* AccessQualifierString(int attr);
|
|
||||||
|
|
||||||
void PrintOperands(const OperandParameters& operands, int reservedOperands);
|
|
||||||
|
|
||||||
} // end namespace spv
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,485 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2014 LunarG, Inc.
|
|
||||||
// Copyright (C) 2015-2018 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
// SPIRV-IR
|
|
||||||
//
|
|
||||||
// Simple in-memory representation (IR) of SPIRV. Just for holding
|
|
||||||
// Each function's CFG of blocks. Has this hierarchy:
|
|
||||||
// - Module, which is a list of
|
|
||||||
// - Function, which is a list of
|
|
||||||
// - Block, which is a list of
|
|
||||||
// - Instruction
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef spvIR_H
|
|
||||||
#define spvIR_H
|
|
||||||
|
|
||||||
#include "spirv.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cassert>
|
|
||||||
#include <functional>
|
|
||||||
#include <iostream>
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace spv {
|
|
||||||
|
|
||||||
class Block;
|
|
||||||
class Function;
|
|
||||||
class Module;
|
|
||||||
|
|
||||||
const Id NoResult = 0;
|
|
||||||
const Id NoType = 0;
|
|
||||||
|
|
||||||
const Decoration NoPrecision = DecorationMax;
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
# define POTENTIALLY_UNUSED __attribute__((unused))
|
|
||||||
#else
|
|
||||||
# define POTENTIALLY_UNUSED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
POTENTIALLY_UNUSED
|
|
||||||
const MemorySemanticsMask MemorySemanticsAllMemory =
|
|
||||||
(MemorySemanticsMask)(MemorySemanticsUniformMemoryMask |
|
|
||||||
MemorySemanticsWorkgroupMemoryMask |
|
|
||||||
MemorySemanticsAtomicCounterMemoryMask |
|
|
||||||
MemorySemanticsImageMemoryMask);
|
|
||||||
|
|
||||||
struct IdImmediate {
|
|
||||||
bool isId; // true if word is an Id, false if word is an immediate
|
|
||||||
unsigned word;
|
|
||||||
IdImmediate(bool i, unsigned w) : isId(i), word(w) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// SPIR-V IR instruction.
|
|
||||||
//
|
|
||||||
|
|
||||||
class Instruction {
|
|
||||||
public:
|
|
||||||
Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { }
|
|
||||||
explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { }
|
|
||||||
virtual ~Instruction() {}
|
|
||||||
void addIdOperand(Id id) {
|
|
||||||
operands.push_back(id);
|
|
||||||
idOperand.push_back(true);
|
|
||||||
}
|
|
||||||
void addImmediateOperand(unsigned int immediate) {
|
|
||||||
operands.push_back(immediate);
|
|
||||||
idOperand.push_back(false);
|
|
||||||
}
|
|
||||||
void setImmediateOperand(unsigned idx, unsigned int immediate) {
|
|
||||||
assert(!idOperand[idx]);
|
|
||||||
operands[idx] = immediate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void addStringOperand(const char* str)
|
|
||||||
{
|
|
||||||
unsigned int word;
|
|
||||||
char* wordString = (char*)&word;
|
|
||||||
char* wordPtr = wordString;
|
|
||||||
int charCount = 0;
|
|
||||||
char c;
|
|
||||||
do {
|
|
||||||
c = *(str++);
|
|
||||||
*(wordPtr++) = c;
|
|
||||||
++charCount;
|
|
||||||
if (charCount == 4) {
|
|
||||||
addImmediateOperand(word);
|
|
||||||
wordPtr = wordString;
|
|
||||||
charCount = 0;
|
|
||||||
}
|
|
||||||
} while (c != 0);
|
|
||||||
|
|
||||||
// deal with partial last word
|
|
||||||
if (charCount > 0) {
|
|
||||||
// pad with 0s
|
|
||||||
for (; charCount < 4; ++charCount)
|
|
||||||
*(wordPtr++) = 0;
|
|
||||||
addImmediateOperand(word);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool isIdOperand(int op) const { return idOperand[op]; }
|
|
||||||
void setBlock(Block* b) { block = b; }
|
|
||||||
Block* getBlock() const { return block; }
|
|
||||||
Op getOpCode() const { return opCode; }
|
|
||||||
int getNumOperands() const
|
|
||||||
{
|
|
||||||
assert(operands.size() == idOperand.size());
|
|
||||||
return (int)operands.size();
|
|
||||||
}
|
|
||||||
Id getResultId() const { return resultId; }
|
|
||||||
Id getTypeId() const { return typeId; }
|
|
||||||
Id getIdOperand(int op) const {
|
|
||||||
assert(idOperand[op]);
|
|
||||||
return operands[op];
|
|
||||||
}
|
|
||||||
unsigned int getImmediateOperand(int op) const {
|
|
||||||
assert(!idOperand[op]);
|
|
||||||
return operands[op];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write out the binary form.
|
|
||||||
void dump(std::vector<unsigned int>& out) const
|
|
||||||
{
|
|
||||||
// Compute the wordCount
|
|
||||||
unsigned int wordCount = 1;
|
|
||||||
if (typeId)
|
|
||||||
++wordCount;
|
|
||||||
if (resultId)
|
|
||||||
++wordCount;
|
|
||||||
wordCount += (unsigned int)operands.size();
|
|
||||||
|
|
||||||
// Write out the beginning of the instruction
|
|
||||||
out.push_back(((wordCount) << WordCountShift) | opCode);
|
|
||||||
if (typeId)
|
|
||||||
out.push_back(typeId);
|
|
||||||
if (resultId)
|
|
||||||
out.push_back(resultId);
|
|
||||||
|
|
||||||
// Write out the operands
|
|
||||||
for (int op = 0; op < (int)operands.size(); ++op)
|
|
||||||
out.push_back(operands[op]);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Instruction(const Instruction&);
|
|
||||||
Id resultId;
|
|
||||||
Id typeId;
|
|
||||||
Op opCode;
|
|
||||||
std::vector<Id> operands; // operands, both <id> and immediates (both are unsigned int)
|
|
||||||
std::vector<bool> idOperand; // true for operands that are <id>, false for immediates
|
|
||||||
Block* block;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// SPIR-V IR block.
|
|
||||||
//
|
|
||||||
|
|
||||||
class Block {
|
|
||||||
public:
|
|
||||||
Block(Id id, Function& parent);
|
|
||||||
virtual ~Block()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Id getId() { return instructions.front()->getResultId(); }
|
|
||||||
|
|
||||||
Function& getParent() const { return parent; }
|
|
||||||
void addInstruction(std::unique_ptr<Instruction> inst);
|
|
||||||
void addPredecessor(Block* pred) { predecessors.push_back(pred); pred->successors.push_back(this);}
|
|
||||||
void addLocalVariable(std::unique_ptr<Instruction> inst) { localVariables.push_back(std::move(inst)); }
|
|
||||||
const std::vector<Block*>& getPredecessors() const { return predecessors; }
|
|
||||||
const std::vector<Block*>& getSuccessors() const { return successors; }
|
|
||||||
const std::vector<std::unique_ptr<Instruction> >& getInstructions() const {
|
|
||||||
return instructions;
|
|
||||||
}
|
|
||||||
const std::vector<std::unique_ptr<Instruction> >& getLocalVariables() const { return localVariables; }
|
|
||||||
void setUnreachable() { unreachable = true; }
|
|
||||||
bool isUnreachable() const { return unreachable; }
|
|
||||||
// Returns the block's merge instruction, if one exists (otherwise null).
|
|
||||||
const Instruction* getMergeInstruction() const {
|
|
||||||
if (instructions.size() < 2) return nullptr;
|
|
||||||
const Instruction* nextToLast = (instructions.cend() - 2)->get();
|
|
||||||
switch (nextToLast->getOpCode()) {
|
|
||||||
case OpSelectionMerge:
|
|
||||||
case OpLoopMerge:
|
|
||||||
return nextToLast;
|
|
||||||
default:
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change this block into a canonical dead merge block. Delete instructions
|
|
||||||
// as necessary. A canonical dead merge block has only an OpLabel and an
|
|
||||||
// OpUnreachable.
|
|
||||||
void rewriteAsCanonicalUnreachableMerge() {
|
|
||||||
assert(localVariables.empty());
|
|
||||||
// Delete all instructions except for the label.
|
|
||||||
assert(instructions.size() > 0);
|
|
||||||
instructions.resize(1);
|
|
||||||
successors.clear();
|
|
||||||
addInstruction(std::unique_ptr<Instruction>(new Instruction(OpUnreachable)));
|
|
||||||
}
|
|
||||||
// Change this block into a canonical dead continue target branching to the
|
|
||||||
// given header ID. Delete instructions as necessary. A canonical dead continue
|
|
||||||
// target has only an OpLabel and an unconditional branch back to the corresponding
|
|
||||||
// header.
|
|
||||||
void rewriteAsCanonicalUnreachableContinue(Block* header) {
|
|
||||||
assert(localVariables.empty());
|
|
||||||
// Delete all instructions except for the label.
|
|
||||||
assert(instructions.size() > 0);
|
|
||||||
instructions.resize(1);
|
|
||||||
successors.clear();
|
|
||||||
// Add OpBranch back to the header.
|
|
||||||
assert(header != nullptr);
|
|
||||||
Instruction* branch = new Instruction(OpBranch);
|
|
||||||
branch->addIdOperand(header->getId());
|
|
||||||
addInstruction(std::unique_ptr<Instruction>(branch));
|
|
||||||
successors.push_back(header);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isTerminated() const
|
|
||||||
{
|
|
||||||
switch (instructions.back()->getOpCode()) {
|
|
||||||
case OpBranch:
|
|
||||||
case OpBranchConditional:
|
|
||||||
case OpSwitch:
|
|
||||||
case OpKill:
|
|
||||||
case OpReturn:
|
|
||||||
case OpReturnValue:
|
|
||||||
case OpUnreachable:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump(std::vector<unsigned int>& out) const
|
|
||||||
{
|
|
||||||
instructions[0]->dump(out);
|
|
||||||
for (int i = 0; i < (int)localVariables.size(); ++i)
|
|
||||||
localVariables[i]->dump(out);
|
|
||||||
for (int i = 1; i < (int)instructions.size(); ++i)
|
|
||||||
instructions[i]->dump(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Block(const Block&);
|
|
||||||
Block& operator=(Block&);
|
|
||||||
|
|
||||||
// To enforce keeping parent and ownership in sync:
|
|
||||||
friend Function;
|
|
||||||
|
|
||||||
std::vector<std::unique_ptr<Instruction> > instructions;
|
|
||||||
std::vector<Block*> predecessors, successors;
|
|
||||||
std::vector<std::unique_ptr<Instruction> > localVariables;
|
|
||||||
Function& parent;
|
|
||||||
|
|
||||||
// track whether this block is known to be uncreachable (not necessarily
|
|
||||||
// true for all unreachable blocks, but should be set at least
|
|
||||||
// for the extraneous ones introduced by the builder).
|
|
||||||
bool unreachable;
|
|
||||||
};
|
|
||||||
|
|
||||||
// The different reasons for reaching a block in the inReadableOrder traversal.
|
|
||||||
enum ReachReason {
|
|
||||||
// Reachable from the entry block via transfers of control, i.e. branches.
|
|
||||||
ReachViaControlFlow = 0,
|
|
||||||
// A continue target that is not reachable via control flow.
|
|
||||||
ReachDeadContinue,
|
|
||||||
// A merge block that is not reachable via control flow.
|
|
||||||
ReachDeadMerge
|
|
||||||
};
|
|
||||||
|
|
||||||
// Traverses the control-flow graph rooted at root in an order suited for
|
|
||||||
// readable code generation. Invokes callback at every node in the traversal
|
|
||||||
// order. The callback arguments are:
|
|
||||||
// - the block,
|
|
||||||
// - the reason we reached the block,
|
|
||||||
// - if the reason was that block is an unreachable continue or unreachable merge block
|
|
||||||
// then the last parameter is the corresponding header block.
|
|
||||||
void inReadableOrder(Block* root, std::function<void(Block*, ReachReason, Block* header)> callback);
|
|
||||||
|
|
||||||
//
|
|
||||||
// SPIR-V IR Function.
|
|
||||||
//
|
|
||||||
|
|
||||||
class Function {
|
|
||||||
public:
|
|
||||||
Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent);
|
|
||||||
virtual ~Function()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < (int)parameterInstructions.size(); ++i)
|
|
||||||
delete parameterInstructions[i];
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)blocks.size(); ++i)
|
|
||||||
delete blocks[i];
|
|
||||||
}
|
|
||||||
Id getId() const { return functionInstruction.getResultId(); }
|
|
||||||
Id getParamId(int p) const { return parameterInstructions[p]->getResultId(); }
|
|
||||||
Id getParamType(int p) const { return parameterInstructions[p]->getTypeId(); }
|
|
||||||
|
|
||||||
void addBlock(Block* block) { blocks.push_back(block); }
|
|
||||||
void removeBlock(Block* block)
|
|
||||||
{
|
|
||||||
auto found = find(blocks.begin(), blocks.end(), block);
|
|
||||||
assert(found != blocks.end());
|
|
||||||
blocks.erase(found);
|
|
||||||
delete block;
|
|
||||||
}
|
|
||||||
|
|
||||||
Module& getParent() const { return parent; }
|
|
||||||
Block* getEntryBlock() const { return blocks.front(); }
|
|
||||||
Block* getLastBlock() const { return blocks.back(); }
|
|
||||||
const std::vector<Block*>& getBlocks() const { return blocks; }
|
|
||||||
void addLocalVariable(std::unique_ptr<Instruction> inst);
|
|
||||||
Id getReturnType() const { return functionInstruction.getTypeId(); }
|
|
||||||
|
|
||||||
void setImplicitThis() { implicitThis = true; }
|
|
||||||
bool hasImplicitThis() const { return implicitThis; }
|
|
||||||
|
|
||||||
void dump(std::vector<unsigned int>& out) const
|
|
||||||
{
|
|
||||||
// OpFunction
|
|
||||||
functionInstruction.dump(out);
|
|
||||||
|
|
||||||
// OpFunctionParameter
|
|
||||||
for (int p = 0; p < (int)parameterInstructions.size(); ++p)
|
|
||||||
parameterInstructions[p]->dump(out);
|
|
||||||
|
|
||||||
// Blocks
|
|
||||||
inReadableOrder(blocks[0], [&out](const Block* b, ReachReason, Block*) { b->dump(out); });
|
|
||||||
Instruction end(0, 0, OpFunctionEnd);
|
|
||||||
end.dump(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Function(const Function&);
|
|
||||||
Function& operator=(Function&);
|
|
||||||
|
|
||||||
Module& parent;
|
|
||||||
Instruction functionInstruction;
|
|
||||||
std::vector<Instruction*> parameterInstructions;
|
|
||||||
std::vector<Block*> blocks;
|
|
||||||
bool implicitThis; // true if this is a member function expecting to be passed a 'this' as the first argument
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// SPIR-V IR Module.
|
|
||||||
//
|
|
||||||
|
|
||||||
class Module {
|
|
||||||
public:
|
|
||||||
Module() {}
|
|
||||||
virtual ~Module()
|
|
||||||
{
|
|
||||||
// TODO delete things
|
|
||||||
}
|
|
||||||
|
|
||||||
void addFunction(Function *fun) { functions.push_back(fun); }
|
|
||||||
|
|
||||||
void mapInstruction(Instruction *instruction)
|
|
||||||
{
|
|
||||||
spv::Id resultId = instruction->getResultId();
|
|
||||||
// map the instruction's result id
|
|
||||||
if (resultId >= idToInstruction.size())
|
|
||||||
idToInstruction.resize(resultId + 16);
|
|
||||||
idToInstruction[resultId] = instruction;
|
|
||||||
}
|
|
||||||
|
|
||||||
Instruction* getInstruction(Id id) const { return idToInstruction[id]; }
|
|
||||||
const std::vector<Function*>& getFunctions() const { return functions; }
|
|
||||||
spv::Id getTypeId(Id resultId) const {
|
|
||||||
return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId();
|
|
||||||
}
|
|
||||||
StorageClass getStorageClass(Id typeId) const
|
|
||||||
{
|
|
||||||
assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer);
|
|
||||||
return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dump(std::vector<unsigned int>& out) const
|
|
||||||
{
|
|
||||||
for (int f = 0; f < (int)functions.size(); ++f)
|
|
||||||
functions[f]->dump(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Module(const Module&);
|
|
||||||
std::vector<Function*> functions;
|
|
||||||
|
|
||||||
// map from result id to instruction having that result id
|
|
||||||
std::vector<Instruction*> idToInstruction;
|
|
||||||
|
|
||||||
// map from a result id to its type id
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Implementation (it's here due to circular type definitions).
|
|
||||||
//
|
|
||||||
|
|
||||||
// Add both
|
|
||||||
// - the OpFunction instruction
|
|
||||||
// - all the OpFunctionParameter instructions
|
|
||||||
__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
|
|
||||||
: parent(parent), functionInstruction(id, resultType, OpFunction), implicitThis(false)
|
|
||||||
{
|
|
||||||
// OpFunction
|
|
||||||
functionInstruction.addImmediateOperand(FunctionControlMaskNone);
|
|
||||||
functionInstruction.addIdOperand(functionType);
|
|
||||||
parent.mapInstruction(&functionInstruction);
|
|
||||||
parent.addFunction(this);
|
|
||||||
|
|
||||||
// OpFunctionParameter
|
|
||||||
Instruction* typeInst = parent.getInstruction(functionType);
|
|
||||||
int numParams = typeInst->getNumOperands() - 1;
|
|
||||||
for (int p = 0; p < numParams; ++p) {
|
|
||||||
Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter);
|
|
||||||
parent.mapInstruction(param);
|
|
||||||
parameterInstructions.push_back(param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__inline void Function::addLocalVariable(std::unique_ptr<Instruction> inst)
|
|
||||||
{
|
|
||||||
Instruction* raw_instruction = inst.get();
|
|
||||||
blocks[0]->addLocalVariable(std::move(inst));
|
|
||||||
parent.mapInstruction(raw_instruction);
|
|
||||||
}
|
|
||||||
|
|
||||||
__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false)
|
|
||||||
{
|
|
||||||
instructions.push_back(std::unique_ptr<Instruction>(new Instruction(id, NoType, OpLabel)));
|
|
||||||
instructions.back()->setBlock(this);
|
|
||||||
parent.getParent().mapInstruction(instructions.back().get());
|
|
||||||
}
|
|
||||||
|
|
||||||
__inline void Block::addInstruction(std::unique_ptr<Instruction> inst)
|
|
||||||
{
|
|
||||||
Instruction* raw_instruction = inst.get();
|
|
||||||
instructions.push_back(std::move(inst));
|
|
||||||
raw_instruction->setBlock(this);
|
|
||||||
if (raw_instruction->getResultId())
|
|
||||||
parent.getParent().mapInstruction(raw_instruction);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end spv namespace
|
|
||||||
|
|
||||||
#endif // spvIR_H
|
|
|
@ -1,141 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2017 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <fstream>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "./../glslang/Public/ShaderLang.h"
|
|
||||||
|
|
||||||
// Default include class for normal include convention of search backward
|
|
||||||
// through the stack of active include paths (for nested includes).
|
|
||||||
// Can be overridden to customize.
|
|
||||||
class DirStackFileIncluder : public glslang::TShader::Includer {
|
|
||||||
public:
|
|
||||||
DirStackFileIncluder() : externalLocalDirectoryCount(0) { }
|
|
||||||
|
|
||||||
virtual IncludeResult* includeLocal(const char* headerName,
|
|
||||||
const char* includerName,
|
|
||||||
size_t inclusionDepth) override
|
|
||||||
{
|
|
||||||
return readLocalPath(headerName, includerName, (int)inclusionDepth);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual IncludeResult* includeSystem(const char* headerName,
|
|
||||||
const char* /*includerName*/,
|
|
||||||
size_t /*inclusionDepth*/) override
|
|
||||||
{
|
|
||||||
return readSystemPath(headerName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Externally set directories. E.g., from a command-line -I<dir>.
|
|
||||||
// - Most-recently pushed are checked first.
|
|
||||||
// - All these are checked after the parse-time stack of local directories
|
|
||||||
// is checked.
|
|
||||||
// - This only applies to the "local" form of #include.
|
|
||||||
// - Makes its own copy of the path.
|
|
||||||
virtual void pushExternalLocalDirectory(const std::string& dir)
|
|
||||||
{
|
|
||||||
directoryStack.push_back(dir);
|
|
||||||
externalLocalDirectoryCount = (int)directoryStack.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void releaseInclude(IncludeResult* result) override
|
|
||||||
{
|
|
||||||
if (result != nullptr) {
|
|
||||||
delete [] static_cast<tUserDataElement*>(result->userData);
|
|
||||||
delete result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~DirStackFileIncluder() override { }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
typedef char tUserDataElement;
|
|
||||||
std::vector<std::string> directoryStack;
|
|
||||||
int externalLocalDirectoryCount;
|
|
||||||
|
|
||||||
// Search for a valid "local" path based on combining the stack of include
|
|
||||||
// directories and the nominal name of the header.
|
|
||||||
virtual IncludeResult* readLocalPath(const char* headerName, const char* includerName, int depth)
|
|
||||||
{
|
|
||||||
// Discard popped include directories, and
|
|
||||||
// initialize when at parse-time first level.
|
|
||||||
directoryStack.resize(depth + externalLocalDirectoryCount);
|
|
||||||
if (depth == 1)
|
|
||||||
directoryStack.back() = getDirectory(includerName);
|
|
||||||
|
|
||||||
// Find a directory that works, using a reverse search of the include stack.
|
|
||||||
for (auto it = directoryStack.rbegin(); it != directoryStack.rend(); ++it) {
|
|
||||||
std::string path = *it + '/' + headerName;
|
|
||||||
std::replace(path.begin(), path.end(), '\\', '/');
|
|
||||||
std::ifstream file(path, std::ios_base::binary | std::ios_base::ate);
|
|
||||||
if (file) {
|
|
||||||
directoryStack.push_back(getDirectory(path));
|
|
||||||
return newIncludeResult(path, file, (int)file.tellg());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search for a valid <system> path.
|
|
||||||
// Not implemented yet; returning nullptr signals failure to find.
|
|
||||||
virtual IncludeResult* readSystemPath(const char* /*headerName*/) const
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do actual reading of the file, filling in a new include result.
|
|
||||||
virtual IncludeResult* newIncludeResult(const std::string& path, std::ifstream& file, int length) const
|
|
||||||
{
|
|
||||||
char* content = new tUserDataElement [length];
|
|
||||||
file.seekg(0, file.beg);
|
|
||||||
file.read(content, length);
|
|
||||||
return new IncludeResult(path, content, length, content);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no path markers, return current working directory.
|
|
||||||
// Otherwise, strip file name and return path leading up to it.
|
|
||||||
virtual std::string getDirectory(const std::string path) const
|
|
||||||
{
|
|
||||||
size_t last = path.find_last_of("/\\");
|
|
||||||
return last == std::string::npos ? "." : path.substr(0, last);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,496 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2016 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <sstream>
|
|
||||||
#include <cctype>
|
|
||||||
|
|
||||||
#include "ResourceLimits.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
const TBuiltInResource DefaultTBuiltInResource = {
|
|
||||||
/* .MaxLights = */ 32,
|
|
||||||
/* .MaxClipPlanes = */ 6,
|
|
||||||
/* .MaxTextureUnits = */ 32,
|
|
||||||
/* .MaxTextureCoords = */ 32,
|
|
||||||
/* .MaxVertexAttribs = */ 64,
|
|
||||||
/* .MaxVertexUniformComponents = */ 4096,
|
|
||||||
/* .MaxVaryingFloats = */ 64,
|
|
||||||
/* .MaxVertexTextureImageUnits = */ 32,
|
|
||||||
/* .MaxCombinedTextureImageUnits = */ 80,
|
|
||||||
/* .MaxTextureImageUnits = */ 32,
|
|
||||||
/* .MaxFragmentUniformComponents = */ 4096,
|
|
||||||
/* .MaxDrawBuffers = */ 32,
|
|
||||||
/* .MaxVertexUniformVectors = */ 128,
|
|
||||||
/* .MaxVaryingVectors = */ 8,
|
|
||||||
/* .MaxFragmentUniformVectors = */ 16,
|
|
||||||
/* .MaxVertexOutputVectors = */ 16,
|
|
||||||
/* .MaxFragmentInputVectors = */ 15,
|
|
||||||
/* .MinProgramTexelOffset = */ -8,
|
|
||||||
/* .MaxProgramTexelOffset = */ 7,
|
|
||||||
/* .MaxClipDistances = */ 8,
|
|
||||||
/* .MaxComputeWorkGroupCountX = */ 65535,
|
|
||||||
/* .MaxComputeWorkGroupCountY = */ 65535,
|
|
||||||
/* .MaxComputeWorkGroupCountZ = */ 65535,
|
|
||||||
/* .MaxComputeWorkGroupSizeX = */ 1024,
|
|
||||||
/* .MaxComputeWorkGroupSizeY = */ 1024,
|
|
||||||
/* .MaxComputeWorkGroupSizeZ = */ 64,
|
|
||||||
/* .MaxComputeUniformComponents = */ 1024,
|
|
||||||
/* .MaxComputeTextureImageUnits = */ 16,
|
|
||||||
/* .MaxComputeImageUniforms = */ 8,
|
|
||||||
/* .MaxComputeAtomicCounters = */ 8,
|
|
||||||
/* .MaxComputeAtomicCounterBuffers = */ 1,
|
|
||||||
/* .MaxVaryingComponents = */ 60,
|
|
||||||
/* .MaxVertexOutputComponents = */ 64,
|
|
||||||
/* .MaxGeometryInputComponents = */ 64,
|
|
||||||
/* .MaxGeometryOutputComponents = */ 128,
|
|
||||||
/* .MaxFragmentInputComponents = */ 128,
|
|
||||||
/* .MaxImageUnits = */ 8,
|
|
||||||
/* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8,
|
|
||||||
/* .MaxCombinedShaderOutputResources = */ 8,
|
|
||||||
/* .MaxImageSamples = */ 0,
|
|
||||||
/* .MaxVertexImageUniforms = */ 0,
|
|
||||||
/* .MaxTessControlImageUniforms = */ 0,
|
|
||||||
/* .MaxTessEvaluationImageUniforms = */ 0,
|
|
||||||
/* .MaxGeometryImageUniforms = */ 0,
|
|
||||||
/* .MaxFragmentImageUniforms = */ 8,
|
|
||||||
/* .MaxCombinedImageUniforms = */ 8,
|
|
||||||
/* .MaxGeometryTextureImageUnits = */ 16,
|
|
||||||
/* .MaxGeometryOutputVertices = */ 256,
|
|
||||||
/* .MaxGeometryTotalOutputComponents = */ 1024,
|
|
||||||
/* .MaxGeometryUniformComponents = */ 1024,
|
|
||||||
/* .MaxGeometryVaryingComponents = */ 64,
|
|
||||||
/* .MaxTessControlInputComponents = */ 128,
|
|
||||||
/* .MaxTessControlOutputComponents = */ 128,
|
|
||||||
/* .MaxTessControlTextureImageUnits = */ 16,
|
|
||||||
/* .MaxTessControlUniformComponents = */ 1024,
|
|
||||||
/* .MaxTessControlTotalOutputComponents = */ 4096,
|
|
||||||
/* .MaxTessEvaluationInputComponents = */ 128,
|
|
||||||
/* .MaxTessEvaluationOutputComponents = */ 128,
|
|
||||||
/* .MaxTessEvaluationTextureImageUnits = */ 16,
|
|
||||||
/* .MaxTessEvaluationUniformComponents = */ 1024,
|
|
||||||
/* .MaxTessPatchComponents = */ 120,
|
|
||||||
/* .MaxPatchVertices = */ 32,
|
|
||||||
/* .MaxTessGenLevel = */ 64,
|
|
||||||
/* .MaxViewports = */ 16,
|
|
||||||
/* .MaxVertexAtomicCounters = */ 0,
|
|
||||||
/* .MaxTessControlAtomicCounters = */ 0,
|
|
||||||
/* .MaxTessEvaluationAtomicCounters = */ 0,
|
|
||||||
/* .MaxGeometryAtomicCounters = */ 0,
|
|
||||||
/* .MaxFragmentAtomicCounters = */ 8,
|
|
||||||
/* .MaxCombinedAtomicCounters = */ 8,
|
|
||||||
/* .MaxAtomicCounterBindings = */ 1,
|
|
||||||
/* .MaxVertexAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxTessControlAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxTessEvaluationAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxGeometryAtomicCounterBuffers = */ 0,
|
|
||||||
/* .MaxFragmentAtomicCounterBuffers = */ 1,
|
|
||||||
/* .MaxCombinedAtomicCounterBuffers = */ 1,
|
|
||||||
/* .MaxAtomicCounterBufferSize = */ 16384,
|
|
||||||
/* .MaxTransformFeedbackBuffers = */ 4,
|
|
||||||
/* .MaxTransformFeedbackInterleavedComponents = */ 64,
|
|
||||||
/* .MaxCullDistances = */ 8,
|
|
||||||
/* .MaxCombinedClipAndCullDistances = */ 8,
|
|
||||||
/* .MaxSamples = */ 4,
|
|
||||||
/* .maxMeshOutputVerticesNV = */ 256,
|
|
||||||
/* .maxMeshOutputPrimitivesNV = */ 512,
|
|
||||||
/* .maxMeshWorkGroupSizeX_NV = */ 32,
|
|
||||||
/* .maxMeshWorkGroupSizeY_NV = */ 1,
|
|
||||||
/* .maxMeshWorkGroupSizeZ_NV = */ 1,
|
|
||||||
/* .maxTaskWorkGroupSizeX_NV = */ 32,
|
|
||||||
/* .maxTaskWorkGroupSizeY_NV = */ 1,
|
|
||||||
/* .maxTaskWorkGroupSizeZ_NV = */ 1,
|
|
||||||
/* .maxMeshViewCountNV = */ 4,
|
|
||||||
/* .maxDualSourceDrawBuffersEXT = */ 1,
|
|
||||||
|
|
||||||
/* .limits = */ {
|
|
||||||
/* .nonInductiveForLoops = */ 1,
|
|
||||||
/* .whileLoops = */ 1,
|
|
||||||
/* .doWhileLoops = */ 1,
|
|
||||||
/* .generalUniformIndexing = */ 1,
|
|
||||||
/* .generalAttributeMatrixVectorIndexing = */ 1,
|
|
||||||
/* .generalVaryingIndexing = */ 1,
|
|
||||||
/* .generalSamplerIndexing = */ 1,
|
|
||||||
/* .generalVariableIndexing = */ 1,
|
|
||||||
/* .generalConstantMatrixVectorIndexing = */ 1,
|
|
||||||
}};
|
|
||||||
|
|
||||||
std::string GetDefaultTBuiltInResourceString()
|
|
||||||
{
|
|
||||||
std::ostringstream ostream;
|
|
||||||
|
|
||||||
ostream << "MaxLights " << DefaultTBuiltInResource.maxLights << "\n"
|
|
||||||
<< "MaxClipPlanes " << DefaultTBuiltInResource.maxClipPlanes << "\n"
|
|
||||||
<< "MaxTextureUnits " << DefaultTBuiltInResource.maxTextureUnits << "\n"
|
|
||||||
<< "MaxTextureCoords " << DefaultTBuiltInResource.maxTextureCoords << "\n"
|
|
||||||
<< "MaxVertexAttribs " << DefaultTBuiltInResource.maxVertexAttribs << "\n"
|
|
||||||
<< "MaxVertexUniformComponents " << DefaultTBuiltInResource.maxVertexUniformComponents << "\n"
|
|
||||||
<< "MaxVaryingFloats " << DefaultTBuiltInResource.maxVaryingFloats << "\n"
|
|
||||||
<< "MaxVertexTextureImageUnits " << DefaultTBuiltInResource.maxVertexTextureImageUnits << "\n"
|
|
||||||
<< "MaxCombinedTextureImageUnits " << DefaultTBuiltInResource.maxCombinedTextureImageUnits << "\n"
|
|
||||||
<< "MaxTextureImageUnits " << DefaultTBuiltInResource.maxTextureImageUnits << "\n"
|
|
||||||
<< "MaxFragmentUniformComponents " << DefaultTBuiltInResource.maxFragmentUniformComponents << "\n"
|
|
||||||
<< "MaxDrawBuffers " << DefaultTBuiltInResource.maxDrawBuffers << "\n"
|
|
||||||
<< "MaxVertexUniformVectors " << DefaultTBuiltInResource.maxVertexUniformVectors << "\n"
|
|
||||||
<< "MaxVaryingVectors " << DefaultTBuiltInResource.maxVaryingVectors << "\n"
|
|
||||||
<< "MaxFragmentUniformVectors " << DefaultTBuiltInResource.maxFragmentUniformVectors << "\n"
|
|
||||||
<< "MaxVertexOutputVectors " << DefaultTBuiltInResource.maxVertexOutputVectors << "\n"
|
|
||||||
<< "MaxFragmentInputVectors " << DefaultTBuiltInResource.maxFragmentInputVectors << "\n"
|
|
||||||
<< "MinProgramTexelOffset " << DefaultTBuiltInResource.minProgramTexelOffset << "\n"
|
|
||||||
<< "MaxProgramTexelOffset " << DefaultTBuiltInResource.maxProgramTexelOffset << "\n"
|
|
||||||
<< "MaxClipDistances " << DefaultTBuiltInResource.maxClipDistances << "\n"
|
|
||||||
<< "MaxComputeWorkGroupCountX " << DefaultTBuiltInResource.maxComputeWorkGroupCountX << "\n"
|
|
||||||
<< "MaxComputeWorkGroupCountY " << DefaultTBuiltInResource.maxComputeWorkGroupCountY << "\n"
|
|
||||||
<< "MaxComputeWorkGroupCountZ " << DefaultTBuiltInResource.maxComputeWorkGroupCountZ << "\n"
|
|
||||||
<< "MaxComputeWorkGroupSizeX " << DefaultTBuiltInResource.maxComputeWorkGroupSizeX << "\n"
|
|
||||||
<< "MaxComputeWorkGroupSizeY " << DefaultTBuiltInResource.maxComputeWorkGroupSizeY << "\n"
|
|
||||||
<< "MaxComputeWorkGroupSizeZ " << DefaultTBuiltInResource.maxComputeWorkGroupSizeZ << "\n"
|
|
||||||
<< "MaxComputeUniformComponents " << DefaultTBuiltInResource.maxComputeUniformComponents << "\n"
|
|
||||||
<< "MaxComputeTextureImageUnits " << DefaultTBuiltInResource.maxComputeTextureImageUnits << "\n"
|
|
||||||
<< "MaxComputeImageUniforms " << DefaultTBuiltInResource.maxComputeImageUniforms << "\n"
|
|
||||||
<< "MaxComputeAtomicCounters " << DefaultTBuiltInResource.maxComputeAtomicCounters << "\n"
|
|
||||||
<< "MaxComputeAtomicCounterBuffers " << DefaultTBuiltInResource.maxComputeAtomicCounterBuffers << "\n"
|
|
||||||
<< "MaxVaryingComponents " << DefaultTBuiltInResource.maxVaryingComponents << "\n"
|
|
||||||
<< "MaxVertexOutputComponents " << DefaultTBuiltInResource.maxVertexOutputComponents << "\n"
|
|
||||||
<< "MaxGeometryInputComponents " << DefaultTBuiltInResource.maxGeometryInputComponents << "\n"
|
|
||||||
<< "MaxGeometryOutputComponents " << DefaultTBuiltInResource.maxGeometryOutputComponents << "\n"
|
|
||||||
<< "MaxFragmentInputComponents " << DefaultTBuiltInResource.maxFragmentInputComponents << "\n"
|
|
||||||
<< "MaxImageUnits " << DefaultTBuiltInResource.maxImageUnits << "\n"
|
|
||||||
<< "MaxCombinedImageUnitsAndFragmentOutputs " << DefaultTBuiltInResource.maxCombinedImageUnitsAndFragmentOutputs << "\n"
|
|
||||||
<< "MaxCombinedShaderOutputResources " << DefaultTBuiltInResource.maxCombinedShaderOutputResources << "\n"
|
|
||||||
<< "MaxImageSamples " << DefaultTBuiltInResource.maxImageSamples << "\n"
|
|
||||||
<< "MaxVertexImageUniforms " << DefaultTBuiltInResource.maxVertexImageUniforms << "\n"
|
|
||||||
<< "MaxTessControlImageUniforms " << DefaultTBuiltInResource.maxTessControlImageUniforms << "\n"
|
|
||||||
<< "MaxTessEvaluationImageUniforms " << DefaultTBuiltInResource.maxTessEvaluationImageUniforms << "\n"
|
|
||||||
<< "MaxGeometryImageUniforms " << DefaultTBuiltInResource.maxGeometryImageUniforms << "\n"
|
|
||||||
<< "MaxFragmentImageUniforms " << DefaultTBuiltInResource.maxFragmentImageUniforms << "\n"
|
|
||||||
<< "MaxCombinedImageUniforms " << DefaultTBuiltInResource.maxCombinedImageUniforms << "\n"
|
|
||||||
<< "MaxGeometryTextureImageUnits " << DefaultTBuiltInResource.maxGeometryTextureImageUnits << "\n"
|
|
||||||
<< "MaxGeometryOutputVertices " << DefaultTBuiltInResource.maxGeometryOutputVertices << "\n"
|
|
||||||
<< "MaxGeometryTotalOutputComponents " << DefaultTBuiltInResource.maxGeometryTotalOutputComponents << "\n"
|
|
||||||
<< "MaxGeometryUniformComponents " << DefaultTBuiltInResource.maxGeometryUniformComponents << "\n"
|
|
||||||
<< "MaxGeometryVaryingComponents " << DefaultTBuiltInResource.maxGeometryVaryingComponents << "\n"
|
|
||||||
<< "MaxTessControlInputComponents " << DefaultTBuiltInResource.maxTessControlInputComponents << "\n"
|
|
||||||
<< "MaxTessControlOutputComponents " << DefaultTBuiltInResource.maxTessControlOutputComponents << "\n"
|
|
||||||
<< "MaxTessControlTextureImageUnits " << DefaultTBuiltInResource.maxTessControlTextureImageUnits << "\n"
|
|
||||||
<< "MaxTessControlUniformComponents " << DefaultTBuiltInResource.maxTessControlUniformComponents << "\n"
|
|
||||||
<< "MaxTessControlTotalOutputComponents " << DefaultTBuiltInResource.maxTessControlTotalOutputComponents << "\n"
|
|
||||||
<< "MaxTessEvaluationInputComponents " << DefaultTBuiltInResource.maxTessEvaluationInputComponents << "\n"
|
|
||||||
<< "MaxTessEvaluationOutputComponents " << DefaultTBuiltInResource.maxTessEvaluationOutputComponents << "\n"
|
|
||||||
<< "MaxTessEvaluationTextureImageUnits " << DefaultTBuiltInResource.maxTessEvaluationTextureImageUnits << "\n"
|
|
||||||
<< "MaxTessEvaluationUniformComponents " << DefaultTBuiltInResource.maxTessEvaluationUniformComponents << "\n"
|
|
||||||
<< "MaxTessPatchComponents " << DefaultTBuiltInResource.maxTessPatchComponents << "\n"
|
|
||||||
<< "MaxPatchVertices " << DefaultTBuiltInResource.maxPatchVertices << "\n"
|
|
||||||
<< "MaxTessGenLevel " << DefaultTBuiltInResource.maxTessGenLevel << "\n"
|
|
||||||
<< "MaxViewports " << DefaultTBuiltInResource.maxViewports << "\n"
|
|
||||||
<< "MaxVertexAtomicCounters " << DefaultTBuiltInResource.maxVertexAtomicCounters << "\n"
|
|
||||||
<< "MaxTessControlAtomicCounters " << DefaultTBuiltInResource.maxTessControlAtomicCounters << "\n"
|
|
||||||
<< "MaxTessEvaluationAtomicCounters " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounters << "\n"
|
|
||||||
<< "MaxGeometryAtomicCounters " << DefaultTBuiltInResource.maxGeometryAtomicCounters << "\n"
|
|
||||||
<< "MaxFragmentAtomicCounters " << DefaultTBuiltInResource.maxFragmentAtomicCounters << "\n"
|
|
||||||
<< "MaxCombinedAtomicCounters " << DefaultTBuiltInResource.maxCombinedAtomicCounters << "\n"
|
|
||||||
<< "MaxAtomicCounterBindings " << DefaultTBuiltInResource.maxAtomicCounterBindings << "\n"
|
|
||||||
<< "MaxVertexAtomicCounterBuffers " << DefaultTBuiltInResource.maxVertexAtomicCounterBuffers << "\n"
|
|
||||||
<< "MaxTessControlAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessControlAtomicCounterBuffers << "\n"
|
|
||||||
<< "MaxTessEvaluationAtomicCounterBuffers " << DefaultTBuiltInResource.maxTessEvaluationAtomicCounterBuffers << "\n"
|
|
||||||
<< "MaxGeometryAtomicCounterBuffers " << DefaultTBuiltInResource.maxGeometryAtomicCounterBuffers << "\n"
|
|
||||||
<< "MaxFragmentAtomicCounterBuffers " << DefaultTBuiltInResource.maxFragmentAtomicCounterBuffers << "\n"
|
|
||||||
<< "MaxCombinedAtomicCounterBuffers " << DefaultTBuiltInResource.maxCombinedAtomicCounterBuffers << "\n"
|
|
||||||
<< "MaxAtomicCounterBufferSize " << DefaultTBuiltInResource.maxAtomicCounterBufferSize << "\n"
|
|
||||||
<< "MaxTransformFeedbackBuffers " << DefaultTBuiltInResource.maxTransformFeedbackBuffers << "\n"
|
|
||||||
<< "MaxTransformFeedbackInterleavedComponents " << DefaultTBuiltInResource.maxTransformFeedbackInterleavedComponents << "\n"
|
|
||||||
<< "MaxCullDistances " << DefaultTBuiltInResource.maxCullDistances << "\n"
|
|
||||||
<< "MaxCombinedClipAndCullDistances " << DefaultTBuiltInResource.maxCombinedClipAndCullDistances << "\n"
|
|
||||||
<< "MaxSamples " << DefaultTBuiltInResource.maxSamples << "\n"
|
|
||||||
<< "MaxMeshOutputVerticesNV " << DefaultTBuiltInResource.maxMeshOutputVerticesNV << "\n"
|
|
||||||
<< "MaxMeshOutputPrimitivesNV " << DefaultTBuiltInResource.maxMeshOutputPrimitivesNV << "\n"
|
|
||||||
<< "MaxMeshWorkGroupSizeX_NV " << DefaultTBuiltInResource.maxMeshWorkGroupSizeX_NV << "\n"
|
|
||||||
<< "MaxMeshWorkGroupSizeY_NV " << DefaultTBuiltInResource.maxMeshWorkGroupSizeY_NV << "\n"
|
|
||||||
<< "MaxMeshWorkGroupSizeZ_NV " << DefaultTBuiltInResource.maxMeshWorkGroupSizeZ_NV << "\n"
|
|
||||||
<< "MaxTaskWorkGroupSizeX_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeX_NV << "\n"
|
|
||||||
<< "MaxTaskWorkGroupSizeY_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeY_NV << "\n"
|
|
||||||
<< "MaxTaskWorkGroupSizeZ_NV " << DefaultTBuiltInResource.maxTaskWorkGroupSizeZ_NV << "\n"
|
|
||||||
<< "MaxMeshViewCountNV " << DefaultTBuiltInResource.maxMeshViewCountNV << "\n"
|
|
||||||
<< "MaxDualSourceDrawBuffersEXT " << DefaultTBuiltInResource.maxDualSourceDrawBuffersEXT << "\n"
|
|
||||||
<< "nonInductiveForLoops " << DefaultTBuiltInResource.limits.nonInductiveForLoops << "\n"
|
|
||||||
<< "whileLoops " << DefaultTBuiltInResource.limits.whileLoops << "\n"
|
|
||||||
<< "doWhileLoops " << DefaultTBuiltInResource.limits.doWhileLoops << "\n"
|
|
||||||
<< "generalUniformIndexing " << DefaultTBuiltInResource.limits.generalUniformIndexing << "\n"
|
|
||||||
<< "generalAttributeMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalAttributeMatrixVectorIndexing << "\n"
|
|
||||||
<< "generalVaryingIndexing " << DefaultTBuiltInResource.limits.generalVaryingIndexing << "\n"
|
|
||||||
<< "generalSamplerIndexing " << DefaultTBuiltInResource.limits.generalSamplerIndexing << "\n"
|
|
||||||
<< "generalVariableIndexing " << DefaultTBuiltInResource.limits.generalVariableIndexing << "\n"
|
|
||||||
<< "generalConstantMatrixVectorIndexing " << DefaultTBuiltInResource.limits.generalConstantMatrixVectorIndexing << "\n"
|
|
||||||
;
|
|
||||||
|
|
||||||
return ostream.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DecodeResourceLimits(TBuiltInResource* resources, char* config)
|
|
||||||
{
|
|
||||||
static const char* delims = " \t\n\r";
|
|
||||||
|
|
||||||
size_t pos = 0;
|
|
||||||
std::string configStr(config);
|
|
||||||
|
|
||||||
while ((pos = configStr.find_first_not_of(delims, pos)) != std::string::npos) {
|
|
||||||
const size_t token_s = pos;
|
|
||||||
const size_t token_e = configStr.find_first_of(delims, token_s);
|
|
||||||
const size_t value_s = configStr.find_first_not_of(delims, token_e);
|
|
||||||
const size_t value_e = configStr.find_first_of(delims, value_s);
|
|
||||||
pos = value_e;
|
|
||||||
|
|
||||||
// Faster to use compare(), but prefering readability.
|
|
||||||
const std::string tokenStr = configStr.substr(token_s, token_e-token_s);
|
|
||||||
const std::string valueStr = configStr.substr(value_s, value_e-value_s);
|
|
||||||
|
|
||||||
if (value_s == std::string::npos || ! (valueStr[0] == '-' || isdigit(valueStr[0]))) {
|
|
||||||
printf("Error: '%s' bad .conf file. Each name must be followed by one number.\n",
|
|
||||||
valueStr.c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int value = std::atoi(valueStr.c_str());
|
|
||||||
|
|
||||||
if (tokenStr == "MaxLights")
|
|
||||||
resources->maxLights = value;
|
|
||||||
else if (tokenStr == "MaxClipPlanes")
|
|
||||||
resources->maxClipPlanes = value;
|
|
||||||
else if (tokenStr == "MaxTextureUnits")
|
|
||||||
resources->maxTextureUnits = value;
|
|
||||||
else if (tokenStr == "MaxTextureCoords")
|
|
||||||
resources->maxTextureCoords = value;
|
|
||||||
else if (tokenStr == "MaxVertexAttribs")
|
|
||||||
resources->maxVertexAttribs = value;
|
|
||||||
else if (tokenStr == "MaxVertexUniformComponents")
|
|
||||||
resources->maxVertexUniformComponents = value;
|
|
||||||
else if (tokenStr == "MaxVaryingFloats")
|
|
||||||
resources->maxVaryingFloats = value;
|
|
||||||
else if (tokenStr == "MaxVertexTextureImageUnits")
|
|
||||||
resources->maxVertexTextureImageUnits = value;
|
|
||||||
else if (tokenStr == "MaxCombinedTextureImageUnits")
|
|
||||||
resources->maxCombinedTextureImageUnits = value;
|
|
||||||
else if (tokenStr == "MaxTextureImageUnits")
|
|
||||||
resources->maxTextureImageUnits = value;
|
|
||||||
else if (tokenStr == "MaxFragmentUniformComponents")
|
|
||||||
resources->maxFragmentUniformComponents = value;
|
|
||||||
else if (tokenStr == "MaxDrawBuffers")
|
|
||||||
resources->maxDrawBuffers = value;
|
|
||||||
else if (tokenStr == "MaxVertexUniformVectors")
|
|
||||||
resources->maxVertexUniformVectors = value;
|
|
||||||
else if (tokenStr == "MaxVaryingVectors")
|
|
||||||
resources->maxVaryingVectors = value;
|
|
||||||
else if (tokenStr == "MaxFragmentUniformVectors")
|
|
||||||
resources->maxFragmentUniformVectors = value;
|
|
||||||
else if (tokenStr == "MaxVertexOutputVectors")
|
|
||||||
resources->maxVertexOutputVectors = value;
|
|
||||||
else if (tokenStr == "MaxFragmentInputVectors")
|
|
||||||
resources->maxFragmentInputVectors = value;
|
|
||||||
else if (tokenStr == "MinProgramTexelOffset")
|
|
||||||
resources->minProgramTexelOffset = value;
|
|
||||||
else if (tokenStr == "MaxProgramTexelOffset")
|
|
||||||
resources->maxProgramTexelOffset = value;
|
|
||||||
else if (tokenStr == "MaxClipDistances")
|
|
||||||
resources->maxClipDistances = value;
|
|
||||||
else if (tokenStr == "MaxComputeWorkGroupCountX")
|
|
||||||
resources->maxComputeWorkGroupCountX = value;
|
|
||||||
else if (tokenStr == "MaxComputeWorkGroupCountY")
|
|
||||||
resources->maxComputeWorkGroupCountY = value;
|
|
||||||
else if (tokenStr == "MaxComputeWorkGroupCountZ")
|
|
||||||
resources->maxComputeWorkGroupCountZ = value;
|
|
||||||
else if (tokenStr == "MaxComputeWorkGroupSizeX")
|
|
||||||
resources->maxComputeWorkGroupSizeX = value;
|
|
||||||
else if (tokenStr == "MaxComputeWorkGroupSizeY")
|
|
||||||
resources->maxComputeWorkGroupSizeY = value;
|
|
||||||
else if (tokenStr == "MaxComputeWorkGroupSizeZ")
|
|
||||||
resources->maxComputeWorkGroupSizeZ = value;
|
|
||||||
else if (tokenStr == "MaxComputeUniformComponents")
|
|
||||||
resources->maxComputeUniformComponents = value;
|
|
||||||
else if (tokenStr == "MaxComputeTextureImageUnits")
|
|
||||||
resources->maxComputeTextureImageUnits = value;
|
|
||||||
else if (tokenStr == "MaxComputeImageUniforms")
|
|
||||||
resources->maxComputeImageUniforms = value;
|
|
||||||
else if (tokenStr == "MaxComputeAtomicCounters")
|
|
||||||
resources->maxComputeAtomicCounters = value;
|
|
||||||
else if (tokenStr == "MaxComputeAtomicCounterBuffers")
|
|
||||||
resources->maxComputeAtomicCounterBuffers = value;
|
|
||||||
else if (tokenStr == "MaxVaryingComponents")
|
|
||||||
resources->maxVaryingComponents = value;
|
|
||||||
else if (tokenStr == "MaxVertexOutputComponents")
|
|
||||||
resources->maxVertexOutputComponents = value;
|
|
||||||
else if (tokenStr == "MaxGeometryInputComponents")
|
|
||||||
resources->maxGeometryInputComponents = value;
|
|
||||||
else if (tokenStr == "MaxGeometryOutputComponents")
|
|
||||||
resources->maxGeometryOutputComponents = value;
|
|
||||||
else if (tokenStr == "MaxFragmentInputComponents")
|
|
||||||
resources->maxFragmentInputComponents = value;
|
|
||||||
else if (tokenStr == "MaxImageUnits")
|
|
||||||
resources->maxImageUnits = value;
|
|
||||||
else if (tokenStr == "MaxCombinedImageUnitsAndFragmentOutputs")
|
|
||||||
resources->maxCombinedImageUnitsAndFragmentOutputs = value;
|
|
||||||
else if (tokenStr == "MaxCombinedShaderOutputResources")
|
|
||||||
resources->maxCombinedShaderOutputResources = value;
|
|
||||||
else if (tokenStr == "MaxImageSamples")
|
|
||||||
resources->maxImageSamples = value;
|
|
||||||
else if (tokenStr == "MaxVertexImageUniforms")
|
|
||||||
resources->maxVertexImageUniforms = value;
|
|
||||||
else if (tokenStr == "MaxTessControlImageUniforms")
|
|
||||||
resources->maxTessControlImageUniforms = value;
|
|
||||||
else if (tokenStr == "MaxTessEvaluationImageUniforms")
|
|
||||||
resources->maxTessEvaluationImageUniforms = value;
|
|
||||||
else if (tokenStr == "MaxGeometryImageUniforms")
|
|
||||||
resources->maxGeometryImageUniforms = value;
|
|
||||||
else if (tokenStr == "MaxFragmentImageUniforms")
|
|
||||||
resources->maxFragmentImageUniforms = value;
|
|
||||||
else if (tokenStr == "MaxCombinedImageUniforms")
|
|
||||||
resources->maxCombinedImageUniforms = value;
|
|
||||||
else if (tokenStr == "MaxGeometryTextureImageUnits")
|
|
||||||
resources->maxGeometryTextureImageUnits = value;
|
|
||||||
else if (tokenStr == "MaxGeometryOutputVertices")
|
|
||||||
resources->maxGeometryOutputVertices = value;
|
|
||||||
else if (tokenStr == "MaxGeometryTotalOutputComponents")
|
|
||||||
resources->maxGeometryTotalOutputComponents = value;
|
|
||||||
else if (tokenStr == "MaxGeometryUniformComponents")
|
|
||||||
resources->maxGeometryUniformComponents = value;
|
|
||||||
else if (tokenStr == "MaxGeometryVaryingComponents")
|
|
||||||
resources->maxGeometryVaryingComponents = value;
|
|
||||||
else if (tokenStr == "MaxTessControlInputComponents")
|
|
||||||
resources->maxTessControlInputComponents = value;
|
|
||||||
else if (tokenStr == "MaxTessControlOutputComponents")
|
|
||||||
resources->maxTessControlOutputComponents = value;
|
|
||||||
else if (tokenStr == "MaxTessControlTextureImageUnits")
|
|
||||||
resources->maxTessControlTextureImageUnits = value;
|
|
||||||
else if (tokenStr == "MaxTessControlUniformComponents")
|
|
||||||
resources->maxTessControlUniformComponents = value;
|
|
||||||
else if (tokenStr == "MaxTessControlTotalOutputComponents")
|
|
||||||
resources->maxTessControlTotalOutputComponents = value;
|
|
||||||
else if (tokenStr == "MaxTessEvaluationInputComponents")
|
|
||||||
resources->maxTessEvaluationInputComponents = value;
|
|
||||||
else if (tokenStr == "MaxTessEvaluationOutputComponents")
|
|
||||||
resources->maxTessEvaluationOutputComponents = value;
|
|
||||||
else if (tokenStr == "MaxTessEvaluationTextureImageUnits")
|
|
||||||
resources->maxTessEvaluationTextureImageUnits = value;
|
|
||||||
else if (tokenStr == "MaxTessEvaluationUniformComponents")
|
|
||||||
resources->maxTessEvaluationUniformComponents = value;
|
|
||||||
else if (tokenStr == "MaxTessPatchComponents")
|
|
||||||
resources->maxTessPatchComponents = value;
|
|
||||||
else if (tokenStr == "MaxPatchVertices")
|
|
||||||
resources->maxPatchVertices = value;
|
|
||||||
else if (tokenStr == "MaxTessGenLevel")
|
|
||||||
resources->maxTessGenLevel = value;
|
|
||||||
else if (tokenStr == "MaxViewports")
|
|
||||||
resources->maxViewports = value;
|
|
||||||
else if (tokenStr == "MaxVertexAtomicCounters")
|
|
||||||
resources->maxVertexAtomicCounters = value;
|
|
||||||
else if (tokenStr == "MaxTessControlAtomicCounters")
|
|
||||||
resources->maxTessControlAtomicCounters = value;
|
|
||||||
else if (tokenStr == "MaxTessEvaluationAtomicCounters")
|
|
||||||
resources->maxTessEvaluationAtomicCounters = value;
|
|
||||||
else if (tokenStr == "MaxGeometryAtomicCounters")
|
|
||||||
resources->maxGeometryAtomicCounters = value;
|
|
||||||
else if (tokenStr == "MaxFragmentAtomicCounters")
|
|
||||||
resources->maxFragmentAtomicCounters = value;
|
|
||||||
else if (tokenStr == "MaxCombinedAtomicCounters")
|
|
||||||
resources->maxCombinedAtomicCounters = value;
|
|
||||||
else if (tokenStr == "MaxAtomicCounterBindings")
|
|
||||||
resources->maxAtomicCounterBindings = value;
|
|
||||||
else if (tokenStr == "MaxVertexAtomicCounterBuffers")
|
|
||||||
resources->maxVertexAtomicCounterBuffers = value;
|
|
||||||
else if (tokenStr == "MaxTessControlAtomicCounterBuffers")
|
|
||||||
resources->maxTessControlAtomicCounterBuffers = value;
|
|
||||||
else if (tokenStr == "MaxTessEvaluationAtomicCounterBuffers")
|
|
||||||
resources->maxTessEvaluationAtomicCounterBuffers = value;
|
|
||||||
else if (tokenStr == "MaxGeometryAtomicCounterBuffers")
|
|
||||||
resources->maxGeometryAtomicCounterBuffers = value;
|
|
||||||
else if (tokenStr == "MaxFragmentAtomicCounterBuffers")
|
|
||||||
resources->maxFragmentAtomicCounterBuffers = value;
|
|
||||||
else if (tokenStr == "MaxCombinedAtomicCounterBuffers")
|
|
||||||
resources->maxCombinedAtomicCounterBuffers = value;
|
|
||||||
else if (tokenStr == "MaxAtomicCounterBufferSize")
|
|
||||||
resources->maxAtomicCounterBufferSize = value;
|
|
||||||
else if (tokenStr == "MaxTransformFeedbackBuffers")
|
|
||||||
resources->maxTransformFeedbackBuffers = value;
|
|
||||||
else if (tokenStr == "MaxTransformFeedbackInterleavedComponents")
|
|
||||||
resources->maxTransformFeedbackInterleavedComponents = value;
|
|
||||||
else if (tokenStr == "MaxCullDistances")
|
|
||||||
resources->maxCullDistances = value;
|
|
||||||
else if (tokenStr == "MaxCombinedClipAndCullDistances")
|
|
||||||
resources->maxCombinedClipAndCullDistances = value;
|
|
||||||
else if (tokenStr == "MaxSamples")
|
|
||||||
resources->maxSamples = value;
|
|
||||||
else if (tokenStr == "MaxMeshOutputVerticesNV")
|
|
||||||
resources->maxMeshOutputVerticesNV = value;
|
|
||||||
else if (tokenStr == "MaxMeshOutputPrimitivesNV")
|
|
||||||
resources->maxMeshOutputPrimitivesNV = value;
|
|
||||||
else if (tokenStr == "MaxMeshWorkGroupSizeX_NV")
|
|
||||||
resources->maxMeshWorkGroupSizeX_NV = value;
|
|
||||||
else if (tokenStr == "MaxMeshWorkGroupSizeY_NV")
|
|
||||||
resources->maxMeshWorkGroupSizeY_NV = value;
|
|
||||||
else if (tokenStr == "MaxMeshWorkGroupSizeZ_NV")
|
|
||||||
resources->maxMeshWorkGroupSizeZ_NV = value;
|
|
||||||
else if (tokenStr == "MaxTaskWorkGroupSizeX_NV")
|
|
||||||
resources->maxTaskWorkGroupSizeX_NV = value;
|
|
||||||
else if (tokenStr == "MaxTaskWorkGroupSizeY_NV")
|
|
||||||
resources->maxTaskWorkGroupSizeY_NV = value;
|
|
||||||
else if (tokenStr == "MaxTaskWorkGroupSizeZ_NV")
|
|
||||||
resources->maxTaskWorkGroupSizeZ_NV = value;
|
|
||||||
else if (tokenStr == "MaxMeshViewCountNV")
|
|
||||||
resources->maxMeshViewCountNV = value;
|
|
||||||
else if (tokenStr == "nonInductiveForLoops")
|
|
||||||
resources->limits.nonInductiveForLoops = (value != 0);
|
|
||||||
else if (tokenStr == "whileLoops")
|
|
||||||
resources->limits.whileLoops = (value != 0);
|
|
||||||
else if (tokenStr == "doWhileLoops")
|
|
||||||
resources->limits.doWhileLoops = (value != 0);
|
|
||||||
else if (tokenStr == "generalUniformIndexing")
|
|
||||||
resources->limits.generalUniformIndexing = (value != 0);
|
|
||||||
else if (tokenStr == "generalAttributeMatrixVectorIndexing")
|
|
||||||
resources->limits.generalAttributeMatrixVectorIndexing = (value != 0);
|
|
||||||
else if (tokenStr == "generalVaryingIndexing")
|
|
||||||
resources->limits.generalVaryingIndexing = (value != 0);
|
|
||||||
else if (tokenStr == "generalSamplerIndexing")
|
|
||||||
resources->limits.generalSamplerIndexing = (value != 0);
|
|
||||||
else if (tokenStr == "generalVariableIndexing")
|
|
||||||
resources->limits.generalVariableIndexing = (value != 0);
|
|
||||||
else if (tokenStr == "generalConstantMatrixVectorIndexing")
|
|
||||||
resources->limits.generalConstantMatrixVectorIndexing = (value != 0);
|
|
||||||
else
|
|
||||||
printf("Warning: unrecognized limit (%s) in configuration file.\n", tokenStr.c_str());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
|
@ -1,57 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2016 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of Google Inc. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
#ifndef _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_
|
|
||||||
#define _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "../glslang/Include/ResourceLimits.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
// These are the default resources for TBuiltInResources, used for both
|
|
||||||
// - parsing this string for the case where the user didn't supply one,
|
|
||||||
// - dumping out a template for user construction of a config file.
|
|
||||||
extern const TBuiltInResource DefaultTBuiltInResource;
|
|
||||||
|
|
||||||
// Returns the DefaultTBuiltInResource as a human-readable string.
|
|
||||||
std::string GetDefaultTBuiltInResourceString();
|
|
||||||
|
|
||||||
// Decodes the resource limits from |config| to |resources|.
|
|
||||||
void DecodeResourceLimits(TBuiltInResource* resources, char* config);
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _STAND_ALONE_RESOURCE_LIMITS_INCLUDED_
|
|
|
@ -1,95 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
#ifndef WORKLIST_H_INCLUDED
|
|
||||||
#define WORKLIST_H_INCLUDED
|
|
||||||
|
|
||||||
#include "../glslang/OSDependent/osinclude.h"
|
|
||||||
#include <list>
|
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
class TWorkItem {
|
|
||||||
public:
|
|
||||||
TWorkItem() { }
|
|
||||||
explicit TWorkItem(const std::string& s) :
|
|
||||||
name(s) { }
|
|
||||||
std::string name;
|
|
||||||
std::string results;
|
|
||||||
std::string resultsIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TWorklist {
|
|
||||||
public:
|
|
||||||
TWorklist() { }
|
|
||||||
virtual ~TWorklist() { }
|
|
||||||
|
|
||||||
void add(TWorkItem* item)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> guard(mutex);
|
|
||||||
worklist.push_back(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool remove(TWorkItem*& item)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> guard(mutex);
|
|
||||||
|
|
||||||
if (worklist.empty())
|
|
||||||
return false;
|
|
||||||
item = worklist.front();
|
|
||||||
worklist.pop_front();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int size()
|
|
||||||
{
|
|
||||||
return (int)worklist.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty()
|
|
||||||
{
|
|
||||||
return worklist.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::mutex mutex;
|
|
||||||
std::list<TWorkItem*> worklist;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // WORKLIST_H_INCLUDED
|
|
|
@ -1,65 +0,0 @@
|
||||||
/**
|
|
||||||
BSD 2-Clause License
|
|
||||||
|
|
||||||
Copyright (c) 2020, Travis Fort
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include "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);
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
/**
|
|
||||||
BSD 2-Clause License
|
|
||||||
|
|
||||||
Copyright (c) 2020, Travis Fort
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_
|
|
||||||
#define _STAND_ALONE_RESOURCE_LIMITS_C_INCLUDED_
|
|
||||||
|
|
||||||
#include "../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_
|
|
|
@ -1,123 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="..\msvc\vsprops\Configurations.props" />
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="glslang\CInterface\glslang_c_interface.cpp" />
|
|
||||||
<ClCompile Include="glslang\GenericCodeGen\CodeGen.cpp" />
|
|
||||||
<ClCompile Include="glslang\GenericCodeGen\Link.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\attribute.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\Constant.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\glslang_tab.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\InfoSink.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\Initialize.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\Intermediate.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\intermOut.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\IntermTraverse.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\iomapper.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\limits.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\linkValidate.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\parseConst.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\ParseContextBase.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\ParseHelper.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\PoolAlloc.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\Pp.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpAtom.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpContext.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpScanner.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpTokens.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\propagateNoContraction.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\reflection.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\RemoveTree.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\Scan.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\ShaderLang.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\SymbolTable.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\Versions.cpp" />
|
|
||||||
<ClCompile Include="glslang\OSDependent\Windows\ossource.cpp" />
|
|
||||||
<ClCompile Include="OGLCompilersDLL\InitializeDll.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\disassemble.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\doc.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\GlslangToSpv.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\InReadableOrder.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\Logger.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\SpvBuilder.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\SpvPostProcess.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\SPVRemapper.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\SpvTools.cpp" />
|
|
||||||
<ClCompile Include="StandAlone\ResourceLimits.cpp" />
|
|
||||||
<ClCompile Include="StandAlone\resource_limits_c.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="glslang\Include\arrays.h" />
|
|
||||||
<ClInclude Include="glslang\Include\BaseTypes.h" />
|
|
||||||
<ClInclude Include="glslang\Include\Common.h" />
|
|
||||||
<ClInclude Include="glslang\Include\ConstantUnion.h" />
|
|
||||||
<ClInclude Include="glslang\Include\glslang_c_interface.h" />
|
|
||||||
<ClInclude Include="glslang\Include\glslang_c_shader_types.h" />
|
|
||||||
<ClInclude Include="glslang\Include\InfoSink.h" />
|
|
||||||
<ClInclude Include="glslang\Include\InitializeGlobals.h" />
|
|
||||||
<ClInclude Include="glslang\Include\intermediate.h" />
|
|
||||||
<ClInclude Include="glslang\Include\PoolAlloc.h" />
|
|
||||||
<ClInclude Include="glslang\Include\ResourceLimits.h" />
|
|
||||||
<ClInclude Include="glslang\Include\revision.h" />
|
|
||||||
<ClInclude Include="glslang\Include\ShHandle.h" />
|
|
||||||
<ClInclude Include="glslang\Include\Types.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\attribute.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\glslang_tab.cpp.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\gl_types.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\Initialize.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\iomapper.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\LiveTraverser.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\localintermediate.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\ParseHelper.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\parseVersions.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\preprocessor\PpContext.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\preprocessor\PpTokens.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\propagateNoContraction.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\reflection.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\RemoveTree.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\Scan.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\ScanContext.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\SymbolTable.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\Versions.h" />
|
|
||||||
<ClInclude Include="glslang\OSDependent\osinclude.h" />
|
|
||||||
<ClInclude Include="glslang\Public\ShaderLang.h" />
|
|
||||||
<ClInclude Include="OGLCompilersDLL\InitializeDll.h" />
|
|
||||||
<ClInclude Include="SPIRV\bitutils.h" />
|
|
||||||
<ClInclude Include="SPIRV\disassemble.h" />
|
|
||||||
<ClInclude Include="SPIRV\doc.h" />
|
|
||||||
<ClInclude Include="SPIRV\GLSL.ext.AMD.h" />
|
|
||||||
<ClInclude Include="SPIRV\GLSL.ext.EXT.h" />
|
|
||||||
<ClInclude Include="SPIRV\GLSL.ext.KHR.h" />
|
|
||||||
<ClInclude Include="SPIRV\GLSL.ext.NV.h" />
|
|
||||||
<ClInclude Include="SPIRV\GLSL.std.450.h" />
|
|
||||||
<ClInclude Include="SPIRV\GlslangToSpv.h" />
|
|
||||||
<ClInclude Include="SPIRV\hex_float.h" />
|
|
||||||
<ClInclude Include="SPIRV\Logger.h" />
|
|
||||||
<ClInclude Include="SPIRV\NonSemanticDebugPrintf.h" />
|
|
||||||
<ClInclude Include="SPIRV\spirv.hpp" />
|
|
||||||
<ClInclude Include="SPIRV\SpvBuilder.h" />
|
|
||||||
<ClInclude Include="SPIRV\spvIR.h" />
|
|
||||||
<ClInclude Include="SPIRV\SPVRemapper.h" />
|
|
||||||
<ClInclude Include="SPIRV\SpvTools.h" />
|
|
||||||
<ClInclude Include="StandAlone\DirStackFileIncluder.h" />
|
|
||||||
<ClInclude Include="StandAlone\ResourceLimits.h" />
|
|
||||||
<ClInclude Include="StandAlone\resource_limits_c.h" />
|
|
||||||
<ClInclude Include="StandAlone\Worklist.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>{7F909E29-4808-4BD9-A60C-56C51A3AAEC2}</ProjectGuid>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<Import Project="..\msvc\vsprops\StaticLibrary.props" />
|
|
||||||
|
|
||||||
<ItemDefinitionGroup>
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
|
|
||||||
<Import Project="..\msvc\vsprops\Targets.props" />
|
|
||||||
</Project>
|
|
|
@ -1,106 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="glslang\CInterface\glslang_c_interface.cpp" />
|
|
||||||
<ClCompile Include="glslang\GenericCodeGen\Link.cpp" />
|
|
||||||
<ClCompile Include="glslang\GenericCodeGen\CodeGen.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\ParseHelper.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\PoolAlloc.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\propagateNoContraction.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\reflection.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\RemoveTree.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\Scan.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\ShaderLang.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\SymbolTable.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\Versions.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\attribute.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\Constant.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\glslang_tab.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\InfoSink.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\Initialize.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\Intermediate.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\intermOut.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\IntermTraverse.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\iomapper.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\limits.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\linkValidate.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\parseConst.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\ParseContextBase.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpTokens.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\Pp.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpAtom.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpContext.cpp" />
|
|
||||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpScanner.cpp" />
|
|
||||||
<ClCompile Include="glslang\OSDependent\Windows\ossource.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\GlslangToSpv.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\InReadableOrder.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\Logger.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\SpvBuilder.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\SpvPostProcess.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\SPVRemapper.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\disassemble.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\doc.cpp" />
|
|
||||||
<ClCompile Include="StandAlone\ResourceLimits.cpp" />
|
|
||||||
<ClCompile Include="StandAlone\resource_limits_c.cpp" />
|
|
||||||
<ClCompile Include="SPIRV\SpvTools.cpp" />
|
|
||||||
<ClCompile Include="OGLCompilersDLL\InitializeDll.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="glslang\Include\glslang_c_interface.h" />
|
|
||||||
<ClInclude Include="glslang\Include\glslang_c_shader_types.h" />
|
|
||||||
<ClInclude Include="glslang\Include\InfoSink.h" />
|
|
||||||
<ClInclude Include="glslang\Include\InitializeGlobals.h" />
|
|
||||||
<ClInclude Include="glslang\Include\intermediate.h" />
|
|
||||||
<ClInclude Include="glslang\Include\PoolAlloc.h" />
|
|
||||||
<ClInclude Include="glslang\Include\ResourceLimits.h" />
|
|
||||||
<ClInclude Include="glslang\Include\revision.h" />
|
|
||||||
<ClInclude Include="glslang\Include\ShHandle.h" />
|
|
||||||
<ClInclude Include="glslang\Include\Types.h" />
|
|
||||||
<ClInclude Include="glslang\Include\arrays.h" />
|
|
||||||
<ClInclude Include="glslang\Include\BaseTypes.h" />
|
|
||||||
<ClInclude Include="glslang\Include\Common.h" />
|
|
||||||
<ClInclude Include="glslang\Include\ConstantUnion.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\ParseHelper.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\parseVersions.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\propagateNoContraction.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\reflection.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\RemoveTree.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\Scan.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\ScanContext.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\SymbolTable.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\Versions.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\attribute.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\gl_types.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\glslang_tab.cpp.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\Initialize.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\iomapper.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\LiveTraverser.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\localintermediate.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\preprocessor\PpTokens.h" />
|
|
||||||
<ClInclude Include="glslang\MachineIndependent\preprocessor\PpContext.h" />
|
|
||||||
<ClInclude Include="glslang\OSDependent\osinclude.h" />
|
|
||||||
<ClInclude Include="glslang\Public\ShaderLang.h" />
|
|
||||||
<ClInclude Include="SPIRV\GlslangToSpv.h" />
|
|
||||||
<ClInclude Include="SPIRV\hex_float.h" />
|
|
||||||
<ClInclude Include="SPIRV\Logger.h" />
|
|
||||||
<ClInclude Include="SPIRV\NonSemanticDebugPrintf.h" />
|
|
||||||
<ClInclude Include="SPIRV\spirv.hpp" />
|
|
||||||
<ClInclude Include="SPIRV\SpvBuilder.h" />
|
|
||||||
<ClInclude Include="SPIRV\spvIR.h" />
|
|
||||||
<ClInclude Include="SPIRV\SPVRemapper.h" />
|
|
||||||
<ClInclude Include="SPIRV\bitutils.h" />
|
|
||||||
<ClInclude Include="SPIRV\disassemble.h" />
|
|
||||||
<ClInclude Include="SPIRV\doc.h" />
|
|
||||||
<ClInclude Include="SPIRV\GLSL.ext.AMD.h" />
|
|
||||||
<ClInclude Include="SPIRV\GLSL.ext.EXT.h" />
|
|
||||||
<ClInclude Include="SPIRV\GLSL.ext.KHR.h" />
|
|
||||||
<ClInclude Include="SPIRV\GLSL.ext.NV.h" />
|
|
||||||
<ClInclude Include="SPIRV\GLSL.std.450.h" />
|
|
||||||
<ClInclude Include="StandAlone\ResourceLimits.h" />
|
|
||||||
<ClInclude Include="StandAlone\Worklist.h" />
|
|
||||||
<ClInclude Include="StandAlone\DirStackFileIncluder.h" />
|
|
||||||
<ClInclude Include="StandAlone\resource_limits_c.h" />
|
|
||||||
<ClInclude Include="SPIRV\SpvTools.h" />
|
|
||||||
<ClInclude Include="OGLCompilersDLL\InitializeDll.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
|
@ -1,461 +0,0 @@
|
||||||
/**
|
|
||||||
This code is based on the glslang_c_interface implementation by Viktor Latypov
|
|
||||||
**/
|
|
||||||
|
|
||||||
/**
|
|
||||||
BSD 2-Clause License
|
|
||||||
|
|
||||||
Copyright (c) 2019, Viktor Latypov
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#include "glslang/Include/glslang_c_interface.h"
|
|
||||||
|
|
||||||
#include "SPIRV/GlslangToSpv.h"
|
|
||||||
#include "SPIRV/Logger.h"
|
|
||||||
#include "SPIRV/SpvTools.h"
|
|
||||||
#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;
|
|
||||||
};
|
|
||||||
|
|
||||||
int glslang_initialize_process() { return static_cast<int>(glslang::InitializeProcess()); }
|
|
||||||
|
|
||||||
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;
|
|
||||||
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_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_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader)
|
|
||||||
{
|
|
||||||
return shader->preprocessedGLSL.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* glslang_shader_get_info_log(glslang_shader_t* shader) { return shader->shader->getInfoLog(); }
|
|
||||||
|
|
||||||
const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader) { return shader->shader->getInfoDebugLog(); }
|
|
||||||
|
|
||||||
void glslang_shader_delete(glslang_shader_t* shader)
|
|
||||||
{
|
|
||||||
if (!shader)
|
|
||||||
return;
|
|
||||||
|
|
||||||
delete (shader->shader);
|
|
||||||
delete (shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
glslang_program_t* glslang_program_create()
|
|
||||||
{
|
|
||||||
glslang_program_t* p = new glslang_program_t();
|
|
||||||
p->program = new glslang::TProgram();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t glslang_program_SPIRV_get_size(glslang_program_t* program) { return program->spirv.size(); }
|
|
||||||
|
|
||||||
void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int* out)
|
|
||||||
{
|
|
||||||
memcpy(out, program->spirv.data(), program->spirv.size() * sizeof(unsigned int));
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program)
|
|
||||||
{
|
|
||||||
return program->spirv.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* glslang_program_SPIRV_get_messages(glslang_program_t* program)
|
|
||||||
{
|
|
||||||
return program->loggerMessages.empty() ? nullptr : program->loggerMessages.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void glslang_program_delete(glslang_program_t* program)
|
|
||||||
{
|
|
||||||
if (!program)
|
|
||||||
return;
|
|
||||||
|
|
||||||
delete (program->program);
|
|
||||||
delete (program);
|
|
||||||
}
|
|
||||||
|
|
||||||
void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader)
|
|
||||||
{
|
|
||||||
program->program->addShader(shader->shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
int glslang_program_link(glslang_program_t* program, int messages)
|
|
||||||
{
|
|
||||||
return (int)program->program->link((EShMessages)messages);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* glslang_program_get_info_log(glslang_program_t* program)
|
|
||||||
{
|
|
||||||
return program->program->getInfoLog();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* glslang_program_get_info_debug_log(glslang_program_t* program)
|
|
||||||
{
|
|
||||||
return program->program->getInfoDebugLog();
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "../Include/Common.h"
|
|
||||||
#include "../Include/ShHandle.h"
|
|
||||||
#include "../MachineIndependent/Versions.h"
|
|
||||||
|
|
||||||
//
|
|
||||||
// Here is where real machine specific high-level data would be defined.
|
|
||||||
//
|
|
||||||
class TGenericCompiler : public TCompiler {
|
|
||||||
public:
|
|
||||||
TGenericCompiler(EShLanguage l, int dOptions) : TCompiler(l, infoSink), debugOptions(dOptions) { }
|
|
||||||
virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile);
|
|
||||||
TInfoSink infoSink;
|
|
||||||
int debugOptions;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// This function must be provided to create the actual
|
|
||||||
// compile object used by higher level code. It returns
|
|
||||||
// a subclass of TCompiler.
|
|
||||||
//
|
|
||||||
TCompiler* ConstructCompiler(EShLanguage language, int debugOptions)
|
|
||||||
{
|
|
||||||
return new TGenericCompiler(language, debugOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Delete the compiler made by ConstructCompiler
|
|
||||||
//
|
|
||||||
void DeleteCompiler(TCompiler* compiler)
|
|
||||||
{
|
|
||||||
delete compiler;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Generate code from the given parse tree
|
|
||||||
//
|
|
||||||
bool TGenericCompiler::compile(TIntermNode* /*root*/, int /*version*/, EProfile /*profile*/)
|
|
||||||
{
|
|
||||||
haveValidObjectCode = true;
|
|
||||||
|
|
||||||
return haveValidObjectCode;
|
|
||||||
}
|
|
|
@ -1,91 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// The top level algorithms for linking multiple
|
|
||||||
// shaders together.
|
|
||||||
//
|
|
||||||
#include "../Include/Common.h"
|
|
||||||
#include "../Include/ShHandle.h"
|
|
||||||
|
|
||||||
//
|
|
||||||
// Actual link object, derived from the shader handle base classes.
|
|
||||||
//
|
|
||||||
class TGenericLinker : public TLinker {
|
|
||||||
public:
|
|
||||||
TGenericLinker(EShExecutable e, int dOptions) : TLinker(e, infoSink), debugOptions(dOptions) { }
|
|
||||||
bool link(TCompilerList&, TUniformMap*) { return true; }
|
|
||||||
void getAttributeBindings(ShBindingTable const **) const { }
|
|
||||||
TInfoSink infoSink;
|
|
||||||
int debugOptions;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// The internal view of a uniform/float object exchanged with the driver.
|
|
||||||
//
|
|
||||||
class TUniformLinkedMap : public TUniformMap {
|
|
||||||
public:
|
|
||||||
TUniformLinkedMap() { }
|
|
||||||
virtual int getLocation(const char*) { return 0; }
|
|
||||||
};
|
|
||||||
|
|
||||||
TShHandleBase* ConstructLinker(EShExecutable executable, int debugOptions)
|
|
||||||
{
|
|
||||||
return new TGenericLinker(executable, debugOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeleteLinker(TShHandleBase* linker)
|
|
||||||
{
|
|
||||||
delete linker;
|
|
||||||
}
|
|
||||||
|
|
||||||
TUniformMap* ConstructUniformMap()
|
|
||||||
{
|
|
||||||
return new TUniformLinkedMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeleteUniformMap(TUniformMap* map)
|
|
||||||
{
|
|
||||||
delete map;
|
|
||||||
}
|
|
||||||
|
|
||||||
TShHandleBase* ConstructBindings()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeleteBindingList(TShHandleBase* bindingList)
|
|
||||||
{
|
|
||||||
delete bindingList;
|
|
||||||
}
|
|
|
@ -1,571 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
|
||||||
// Copyright (C) 2017 ARM Limited.
|
|
||||||
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _BASICTYPES_INCLUDED_
|
|
||||||
#define _BASICTYPES_INCLUDED_
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Basic type. Arrays, vectors, sampler details, etc., are orthogonal to this.
|
|
||||||
//
|
|
||||||
enum TBasicType {
|
|
||||||
EbtVoid,
|
|
||||||
EbtFloat,
|
|
||||||
EbtDouble,
|
|
||||||
EbtFloat16,
|
|
||||||
EbtInt8,
|
|
||||||
EbtUint8,
|
|
||||||
EbtInt16,
|
|
||||||
EbtUint16,
|
|
||||||
EbtInt,
|
|
||||||
EbtUint,
|
|
||||||
EbtInt64,
|
|
||||||
EbtUint64,
|
|
||||||
EbtBool,
|
|
||||||
EbtAtomicUint,
|
|
||||||
EbtSampler,
|
|
||||||
EbtStruct,
|
|
||||||
EbtBlock,
|
|
||||||
EbtAccStruct,
|
|
||||||
EbtReference,
|
|
||||||
EbtRayQuery,
|
|
||||||
|
|
||||||
// HLSL types that live only temporarily.
|
|
||||||
EbtString,
|
|
||||||
|
|
||||||
EbtNumTypes
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Storage qualifiers. Should align with different kinds of storage or
|
|
||||||
// resource or GLSL storage qualifier. Expansion is deprecated.
|
|
||||||
//
|
|
||||||
// N.B.: You probably DON'T want to add anything here, but rather just add it
|
|
||||||
// to the built-in variables. See the comment above TBuiltInVariable.
|
|
||||||
//
|
|
||||||
// A new built-in variable will normally be an existing qualifier, like 'in', 'out', etc.
|
|
||||||
// DO NOT follow the design pattern of, say EvqInstanceId, etc.
|
|
||||||
//
|
|
||||||
enum TStorageQualifier {
|
|
||||||
EvqTemporary, // For temporaries (within a function), read/write
|
|
||||||
EvqGlobal, // For globals read/write
|
|
||||||
EvqConst, // User-defined constant values, will be semantically constant and constant folded
|
|
||||||
EvqVaryingIn, // pipeline input, read only, also supercategory for all built-ins not included in this enum (see TBuiltInVariable)
|
|
||||||
EvqVaryingOut, // pipeline output, read/write, also supercategory for all built-ins not included in this enum (see TBuiltInVariable)
|
|
||||||
EvqUniform, // read only, shared with app
|
|
||||||
EvqBuffer, // read/write, shared with app
|
|
||||||
EvqShared, // compute shader's read/write 'shared' qualifier
|
|
||||||
|
|
||||||
EvqPayload,
|
|
||||||
EvqPayloadIn,
|
|
||||||
EvqHitAttr,
|
|
||||||
EvqCallableData,
|
|
||||||
EvqCallableDataIn,
|
|
||||||
|
|
||||||
// parameters
|
|
||||||
EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
|
|
||||||
EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter
|
|
||||||
EvqInOut,
|
|
||||||
EvqConstReadOnly, // input; also other read-only types having neither a constant value nor constant-value semantics
|
|
||||||
|
|
||||||
// built-ins read by vertex shader
|
|
||||||
EvqVertexId,
|
|
||||||
EvqInstanceId,
|
|
||||||
|
|
||||||
// built-ins written by vertex shader
|
|
||||||
EvqPosition,
|
|
||||||
EvqPointSize,
|
|
||||||
EvqClipVertex,
|
|
||||||
|
|
||||||
// built-ins read by fragment shader
|
|
||||||
EvqFace,
|
|
||||||
EvqFragCoord,
|
|
||||||
EvqPointCoord,
|
|
||||||
|
|
||||||
// built-ins written by fragment shader
|
|
||||||
EvqFragColor,
|
|
||||||
EvqFragDepth,
|
|
||||||
|
|
||||||
// end of list
|
|
||||||
EvqLast
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Subcategories of the TStorageQualifier, simply to give a direct mapping
|
|
||||||
// between built-in variable names and an numerical value (the enum).
|
|
||||||
//
|
|
||||||
// For backward compatibility, there is some redundancy between the
|
|
||||||
// TStorageQualifier and these. Existing members should both be maintained accurately.
|
|
||||||
// However, any new built-in variable (and any existing non-redundant one)
|
|
||||||
// must follow the pattern that the specific built-in is here, and only its
|
|
||||||
// general qualifier is in TStorageQualifier.
|
|
||||||
//
|
|
||||||
// Something like gl_Position, which is sometimes 'in' and sometimes 'out'
|
|
||||||
// shows up as two different built-in variables in a single stage, but
|
|
||||||
// only has a single enum in TBuiltInVariable, so both the
|
|
||||||
// TStorageQualifier and the TBuitinVariable are needed to distinguish
|
|
||||||
// between them.
|
|
||||||
//
|
|
||||||
enum TBuiltInVariable {
|
|
||||||
EbvNone,
|
|
||||||
EbvNumWorkGroups,
|
|
||||||
EbvWorkGroupSize,
|
|
||||||
EbvWorkGroupId,
|
|
||||||
EbvLocalInvocationId,
|
|
||||||
EbvGlobalInvocationId,
|
|
||||||
EbvLocalInvocationIndex,
|
|
||||||
EbvNumSubgroups,
|
|
||||||
EbvSubgroupID,
|
|
||||||
EbvSubGroupSize,
|
|
||||||
EbvSubGroupInvocation,
|
|
||||||
EbvSubGroupEqMask,
|
|
||||||
EbvSubGroupGeMask,
|
|
||||||
EbvSubGroupGtMask,
|
|
||||||
EbvSubGroupLeMask,
|
|
||||||
EbvSubGroupLtMask,
|
|
||||||
EbvSubgroupSize2,
|
|
||||||
EbvSubgroupInvocation2,
|
|
||||||
EbvSubgroupEqMask2,
|
|
||||||
EbvSubgroupGeMask2,
|
|
||||||
EbvSubgroupGtMask2,
|
|
||||||
EbvSubgroupLeMask2,
|
|
||||||
EbvSubgroupLtMask2,
|
|
||||||
EbvVertexId,
|
|
||||||
EbvInstanceId,
|
|
||||||
EbvVertexIndex,
|
|
||||||
EbvInstanceIndex,
|
|
||||||
EbvBaseVertex,
|
|
||||||
EbvBaseInstance,
|
|
||||||
EbvDrawId,
|
|
||||||
EbvPosition,
|
|
||||||
EbvPointSize,
|
|
||||||
EbvClipVertex,
|
|
||||||
EbvClipDistance,
|
|
||||||
EbvCullDistance,
|
|
||||||
EbvNormal,
|
|
||||||
EbvVertex,
|
|
||||||
EbvMultiTexCoord0,
|
|
||||||
EbvMultiTexCoord1,
|
|
||||||
EbvMultiTexCoord2,
|
|
||||||
EbvMultiTexCoord3,
|
|
||||||
EbvMultiTexCoord4,
|
|
||||||
EbvMultiTexCoord5,
|
|
||||||
EbvMultiTexCoord6,
|
|
||||||
EbvMultiTexCoord7,
|
|
||||||
EbvFrontColor,
|
|
||||||
EbvBackColor,
|
|
||||||
EbvFrontSecondaryColor,
|
|
||||||
EbvBackSecondaryColor,
|
|
||||||
EbvTexCoord,
|
|
||||||
EbvFogFragCoord,
|
|
||||||
EbvInvocationId,
|
|
||||||
EbvPrimitiveId,
|
|
||||||
EbvLayer,
|
|
||||||
EbvViewportIndex,
|
|
||||||
EbvPatchVertices,
|
|
||||||
EbvTessLevelOuter,
|
|
||||||
EbvTessLevelInner,
|
|
||||||
EbvBoundingBox,
|
|
||||||
EbvTessCoord,
|
|
||||||
EbvColor,
|
|
||||||
EbvSecondaryColor,
|
|
||||||
EbvFace,
|
|
||||||
EbvFragCoord,
|
|
||||||
EbvPointCoord,
|
|
||||||
EbvFragColor,
|
|
||||||
EbvFragData,
|
|
||||||
EbvFragDepth,
|
|
||||||
EbvFragStencilRef,
|
|
||||||
EbvSampleId,
|
|
||||||
EbvSamplePosition,
|
|
||||||
EbvSampleMask,
|
|
||||||
EbvHelperInvocation,
|
|
||||||
|
|
||||||
EbvBaryCoordNoPersp,
|
|
||||||
EbvBaryCoordNoPerspCentroid,
|
|
||||||
EbvBaryCoordNoPerspSample,
|
|
||||||
EbvBaryCoordSmooth,
|
|
||||||
EbvBaryCoordSmoothCentroid,
|
|
||||||
EbvBaryCoordSmoothSample,
|
|
||||||
EbvBaryCoordPullModel,
|
|
||||||
|
|
||||||
EbvViewIndex,
|
|
||||||
EbvDeviceIndex,
|
|
||||||
|
|
||||||
EbvFragSizeEXT,
|
|
||||||
EbvFragInvocationCountEXT,
|
|
||||||
|
|
||||||
EbvSecondaryFragDataEXT,
|
|
||||||
EbvSecondaryFragColorEXT,
|
|
||||||
|
|
||||||
EbvViewportMaskNV,
|
|
||||||
EbvSecondaryPositionNV,
|
|
||||||
EbvSecondaryViewportMaskNV,
|
|
||||||
EbvPositionPerViewNV,
|
|
||||||
EbvViewportMaskPerViewNV,
|
|
||||||
EbvFragFullyCoveredNV,
|
|
||||||
EbvFragmentSizeNV,
|
|
||||||
EbvInvocationsPerPixelNV,
|
|
||||||
// ray tracing
|
|
||||||
EbvLaunchId,
|
|
||||||
EbvLaunchSize,
|
|
||||||
EbvInstanceCustomIndex,
|
|
||||||
EbvGeometryIndex,
|
|
||||||
EbvWorldRayOrigin,
|
|
||||||
EbvWorldRayDirection,
|
|
||||||
EbvObjectRayOrigin,
|
|
||||||
EbvObjectRayDirection,
|
|
||||||
EbvRayTmin,
|
|
||||||
EbvRayTmax,
|
|
||||||
EbvHitT,
|
|
||||||
EbvHitKind,
|
|
||||||
EbvObjectToWorld,
|
|
||||||
EbvObjectToWorld3x4,
|
|
||||||
EbvWorldToObject,
|
|
||||||
EbvWorldToObject3x4,
|
|
||||||
EbvIncomingRayFlags,
|
|
||||||
// barycentrics
|
|
||||||
EbvBaryCoordNV,
|
|
||||||
EbvBaryCoordNoPerspNV,
|
|
||||||
// mesh shaders
|
|
||||||
EbvTaskCountNV,
|
|
||||||
EbvPrimitiveCountNV,
|
|
||||||
EbvPrimitiveIndicesNV,
|
|
||||||
EbvClipDistancePerViewNV,
|
|
||||||
EbvCullDistancePerViewNV,
|
|
||||||
EbvLayerPerViewNV,
|
|
||||||
EbvMeshViewCountNV,
|
|
||||||
EbvMeshViewIndicesNV,
|
|
||||||
|
|
||||||
// sm builtins
|
|
||||||
EbvWarpsPerSM,
|
|
||||||
EbvSMCount,
|
|
||||||
EbvWarpID,
|
|
||||||
EbvSMID,
|
|
||||||
|
|
||||||
// HLSL built-ins that live only temporarily, until they get remapped
|
|
||||||
// to one of the above.
|
|
||||||
EbvFragDepthGreater,
|
|
||||||
EbvFragDepthLesser,
|
|
||||||
EbvGsOutputStream,
|
|
||||||
EbvOutputPatch,
|
|
||||||
EbvInputPatch,
|
|
||||||
|
|
||||||
// structbuffer types
|
|
||||||
EbvAppendConsume, // no need to differentiate append and consume
|
|
||||||
EbvRWStructuredBuffer,
|
|
||||||
EbvStructuredBuffer,
|
|
||||||
EbvByteAddressBuffer,
|
|
||||||
EbvRWByteAddressBuffer,
|
|
||||||
|
|
||||||
EbvLast
|
|
||||||
};
|
|
||||||
|
|
||||||
// In this enum, order matters; users can assume higher precision is a bigger value
|
|
||||||
// and EpqNone is 0.
|
|
||||||
enum TPrecisionQualifier {
|
|
||||||
EpqNone = 0,
|
|
||||||
EpqLow,
|
|
||||||
EpqMedium,
|
|
||||||
EpqHigh
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef GLSLANG_WEB
|
|
||||||
__inline const char* GetStorageQualifierString(TStorageQualifier q) { return ""; }
|
|
||||||
__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p) { return ""; }
|
|
||||||
#else
|
|
||||||
// These will show up in error messages
|
|
||||||
__inline const char* GetStorageQualifierString(TStorageQualifier q)
|
|
||||||
{
|
|
||||||
switch (q) {
|
|
||||||
case EvqTemporary: return "temp"; break;
|
|
||||||
case EvqGlobal: return "global"; break;
|
|
||||||
case EvqConst: return "const"; break;
|
|
||||||
case EvqConstReadOnly: return "const (read only)"; break;
|
|
||||||
case EvqVaryingIn: return "in"; break;
|
|
||||||
case EvqVaryingOut: return "out"; break;
|
|
||||||
case EvqUniform: return "uniform"; break;
|
|
||||||
case EvqBuffer: return "buffer"; break;
|
|
||||||
case EvqShared: return "shared"; break;
|
|
||||||
case EvqIn: return "in"; break;
|
|
||||||
case EvqOut: return "out"; break;
|
|
||||||
case EvqInOut: return "inout"; break;
|
|
||||||
case EvqVertexId: return "gl_VertexId"; break;
|
|
||||||
case EvqInstanceId: return "gl_InstanceId"; break;
|
|
||||||
case EvqPosition: return "gl_Position"; break;
|
|
||||||
case EvqPointSize: return "gl_PointSize"; break;
|
|
||||||
case EvqClipVertex: return "gl_ClipVertex"; break;
|
|
||||||
case EvqFace: return "gl_FrontFacing"; break;
|
|
||||||
case EvqFragCoord: return "gl_FragCoord"; break;
|
|
||||||
case EvqPointCoord: return "gl_PointCoord"; break;
|
|
||||||
case EvqFragColor: return "fragColor"; break;
|
|
||||||
case EvqFragDepth: return "gl_FragDepth"; break;
|
|
||||||
case EvqPayload: return "rayPayloadNV"; break;
|
|
||||||
case EvqPayloadIn: return "rayPayloadInNV"; break;
|
|
||||||
case EvqHitAttr: return "hitAttributeNV"; break;
|
|
||||||
case EvqCallableData: return "callableDataNV"; break;
|
|
||||||
case EvqCallableDataIn: return "callableDataInNV"; break;
|
|
||||||
default: return "unknown qualifier";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__inline const char* GetBuiltInVariableString(TBuiltInVariable v)
|
|
||||||
{
|
|
||||||
switch (v) {
|
|
||||||
case EbvNone: return "";
|
|
||||||
case EbvNumWorkGroups: return "NumWorkGroups";
|
|
||||||
case EbvWorkGroupSize: return "WorkGroupSize";
|
|
||||||
case EbvWorkGroupId: return "WorkGroupID";
|
|
||||||
case EbvLocalInvocationId: return "LocalInvocationID";
|
|
||||||
case EbvGlobalInvocationId: return "GlobalInvocationID";
|
|
||||||
case EbvLocalInvocationIndex: return "LocalInvocationIndex";
|
|
||||||
case EbvNumSubgroups: return "NumSubgroups";
|
|
||||||
case EbvSubgroupID: return "SubgroupID";
|
|
||||||
case EbvSubGroupSize: return "SubGroupSize";
|
|
||||||
case EbvSubGroupInvocation: return "SubGroupInvocation";
|
|
||||||
case EbvSubGroupEqMask: return "SubGroupEqMask";
|
|
||||||
case EbvSubGroupGeMask: return "SubGroupGeMask";
|
|
||||||
case EbvSubGroupGtMask: return "SubGroupGtMask";
|
|
||||||
case EbvSubGroupLeMask: return "SubGroupLeMask";
|
|
||||||
case EbvSubGroupLtMask: return "SubGroupLtMask";
|
|
||||||
case EbvSubgroupSize2: return "SubgroupSize";
|
|
||||||
case EbvSubgroupInvocation2: return "SubgroupInvocationID";
|
|
||||||
case EbvSubgroupEqMask2: return "SubgroupEqMask";
|
|
||||||
case EbvSubgroupGeMask2: return "SubgroupGeMask";
|
|
||||||
case EbvSubgroupGtMask2: return "SubgroupGtMask";
|
|
||||||
case EbvSubgroupLeMask2: return "SubgroupLeMask";
|
|
||||||
case EbvSubgroupLtMask2: return "SubgroupLtMask";
|
|
||||||
case EbvVertexId: return "VertexId";
|
|
||||||
case EbvInstanceId: return "InstanceId";
|
|
||||||
case EbvVertexIndex: return "VertexIndex";
|
|
||||||
case EbvInstanceIndex: return "InstanceIndex";
|
|
||||||
case EbvBaseVertex: return "BaseVertex";
|
|
||||||
case EbvBaseInstance: return "BaseInstance";
|
|
||||||
case EbvDrawId: return "DrawId";
|
|
||||||
case EbvPosition: return "Position";
|
|
||||||
case EbvPointSize: return "PointSize";
|
|
||||||
case EbvClipVertex: return "ClipVertex";
|
|
||||||
case EbvClipDistance: return "ClipDistance";
|
|
||||||
case EbvCullDistance: return "CullDistance";
|
|
||||||
case EbvNormal: return "Normal";
|
|
||||||
case EbvVertex: return "Vertex";
|
|
||||||
case EbvMultiTexCoord0: return "MultiTexCoord0";
|
|
||||||
case EbvMultiTexCoord1: return "MultiTexCoord1";
|
|
||||||
case EbvMultiTexCoord2: return "MultiTexCoord2";
|
|
||||||
case EbvMultiTexCoord3: return "MultiTexCoord3";
|
|
||||||
case EbvMultiTexCoord4: return "MultiTexCoord4";
|
|
||||||
case EbvMultiTexCoord5: return "MultiTexCoord5";
|
|
||||||
case EbvMultiTexCoord6: return "MultiTexCoord6";
|
|
||||||
case EbvMultiTexCoord7: return "MultiTexCoord7";
|
|
||||||
case EbvFrontColor: return "FrontColor";
|
|
||||||
case EbvBackColor: return "BackColor";
|
|
||||||
case EbvFrontSecondaryColor: return "FrontSecondaryColor";
|
|
||||||
case EbvBackSecondaryColor: return "BackSecondaryColor";
|
|
||||||
case EbvTexCoord: return "TexCoord";
|
|
||||||
case EbvFogFragCoord: return "FogFragCoord";
|
|
||||||
case EbvInvocationId: return "InvocationID";
|
|
||||||
case EbvPrimitiveId: return "PrimitiveID";
|
|
||||||
case EbvLayer: return "Layer";
|
|
||||||
case EbvViewportIndex: return "ViewportIndex";
|
|
||||||
case EbvPatchVertices: return "PatchVertices";
|
|
||||||
case EbvTessLevelOuter: return "TessLevelOuter";
|
|
||||||
case EbvTessLevelInner: return "TessLevelInner";
|
|
||||||
case EbvBoundingBox: return "BoundingBox";
|
|
||||||
case EbvTessCoord: return "TessCoord";
|
|
||||||
case EbvColor: return "Color";
|
|
||||||
case EbvSecondaryColor: return "SecondaryColor";
|
|
||||||
case EbvFace: return "Face";
|
|
||||||
case EbvFragCoord: return "FragCoord";
|
|
||||||
case EbvPointCoord: return "PointCoord";
|
|
||||||
case EbvFragColor: return "FragColor";
|
|
||||||
case EbvFragData: return "FragData";
|
|
||||||
case EbvFragDepth: return "FragDepth";
|
|
||||||
case EbvFragStencilRef: return "FragStencilRef";
|
|
||||||
case EbvSampleId: return "SampleId";
|
|
||||||
case EbvSamplePosition: return "SamplePosition";
|
|
||||||
case EbvSampleMask: return "SampleMaskIn";
|
|
||||||
case EbvHelperInvocation: return "HelperInvocation";
|
|
||||||
|
|
||||||
case EbvBaryCoordNoPersp: return "BaryCoordNoPersp";
|
|
||||||
case EbvBaryCoordNoPerspCentroid: return "BaryCoordNoPerspCentroid";
|
|
||||||
case EbvBaryCoordNoPerspSample: return "BaryCoordNoPerspSample";
|
|
||||||
case EbvBaryCoordSmooth: return "BaryCoordSmooth";
|
|
||||||
case EbvBaryCoordSmoothCentroid: return "BaryCoordSmoothCentroid";
|
|
||||||
case EbvBaryCoordSmoothSample: return "BaryCoordSmoothSample";
|
|
||||||
case EbvBaryCoordPullModel: return "BaryCoordPullModel";
|
|
||||||
|
|
||||||
case EbvViewIndex: return "ViewIndex";
|
|
||||||
case EbvDeviceIndex: return "DeviceIndex";
|
|
||||||
|
|
||||||
case EbvFragSizeEXT: return "FragSizeEXT";
|
|
||||||
case EbvFragInvocationCountEXT: return "FragInvocationCountEXT";
|
|
||||||
|
|
||||||
case EbvSecondaryFragDataEXT: return "SecondaryFragDataEXT";
|
|
||||||
case EbvSecondaryFragColorEXT: return "SecondaryFragColorEXT";
|
|
||||||
|
|
||||||
case EbvViewportMaskNV: return "ViewportMaskNV";
|
|
||||||
case EbvSecondaryPositionNV: return "SecondaryPositionNV";
|
|
||||||
case EbvSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
|
|
||||||
case EbvPositionPerViewNV: return "PositionPerViewNV";
|
|
||||||
case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
|
|
||||||
case EbvFragFullyCoveredNV: return "FragFullyCoveredNV";
|
|
||||||
case EbvFragmentSizeNV: return "FragmentSizeNV";
|
|
||||||
case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV";
|
|
||||||
case EbvLaunchId: return "LaunchIdNV";
|
|
||||||
case EbvLaunchSize: return "LaunchSizeNV";
|
|
||||||
case EbvInstanceCustomIndex: return "InstanceCustomIndexNV";
|
|
||||||
case EbvGeometryIndex: return "GeometryIndexEXT";
|
|
||||||
case EbvWorldRayOrigin: return "WorldRayOriginNV";
|
|
||||||
case EbvWorldRayDirection: return "WorldRayDirectionNV";
|
|
||||||
case EbvObjectRayOrigin: return "ObjectRayOriginNV";
|
|
||||||
case EbvObjectRayDirection: return "ObjectRayDirectionNV";
|
|
||||||
case EbvRayTmin: return "ObjectRayTminNV";
|
|
||||||
case EbvRayTmax: return "ObjectRayTmaxNV";
|
|
||||||
case EbvHitT: return "HitTNV";
|
|
||||||
case EbvHitKind: return "HitKindNV";
|
|
||||||
case EbvIncomingRayFlags: return "IncomingRayFlagsNV";
|
|
||||||
case EbvObjectToWorld: return "ObjectToWorldNV";
|
|
||||||
case EbvWorldToObject: return "WorldToObjectNV";
|
|
||||||
|
|
||||||
case EbvBaryCoordNV: return "BaryCoordNV";
|
|
||||||
case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
|
|
||||||
|
|
||||||
case EbvTaskCountNV: return "TaskCountNV";
|
|
||||||
case EbvPrimitiveCountNV: return "PrimitiveCountNV";
|
|
||||||
case EbvPrimitiveIndicesNV: return "PrimitiveIndicesNV";
|
|
||||||
case EbvClipDistancePerViewNV: return "ClipDistancePerViewNV";
|
|
||||||
case EbvCullDistancePerViewNV: return "CullDistancePerViewNV";
|
|
||||||
case EbvLayerPerViewNV: return "LayerPerViewNV";
|
|
||||||
case EbvMeshViewCountNV: return "MeshViewCountNV";
|
|
||||||
case EbvMeshViewIndicesNV: return "MeshViewIndicesNV";
|
|
||||||
|
|
||||||
case EbvWarpsPerSM: return "WarpsPerSMNV";
|
|
||||||
case EbvSMCount: return "SMCountNV";
|
|
||||||
case EbvWarpID: return "WarpIDNV";
|
|
||||||
case EbvSMID: return "SMIDNV";
|
|
||||||
|
|
||||||
default: return "unknown built-in variable";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__inline const char* GetPrecisionQualifierString(TPrecisionQualifier p)
|
|
||||||
{
|
|
||||||
switch (p) {
|
|
||||||
case EpqNone: return ""; break;
|
|
||||||
case EpqLow: return "lowp"; break;
|
|
||||||
case EpqMedium: return "mediump"; break;
|
|
||||||
case EpqHigh: return "highp"; break;
|
|
||||||
default: return "unknown precision qualifier";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
__inline bool isTypeSignedInt(TBasicType type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case EbtInt8:
|
|
||||||
case EbtInt16:
|
|
||||||
case EbtInt:
|
|
||||||
case EbtInt64:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__inline bool isTypeUnsignedInt(TBasicType type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case EbtUint8:
|
|
||||||
case EbtUint16:
|
|
||||||
case EbtUint:
|
|
||||||
case EbtUint64:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__inline bool isTypeInt(TBasicType type)
|
|
||||||
{
|
|
||||||
return isTypeSignedInt(type) || isTypeUnsignedInt(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
__inline bool isTypeFloat(TBasicType type)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case EbtFloat:
|
|
||||||
case EbtDouble:
|
|
||||||
case EbtFloat16:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__inline int getTypeRank(TBasicType type)
|
|
||||||
{
|
|
||||||
int res = -1;
|
|
||||||
switch(type) {
|
|
||||||
case EbtInt8:
|
|
||||||
case EbtUint8:
|
|
||||||
res = 0;
|
|
||||||
break;
|
|
||||||
case EbtInt16:
|
|
||||||
case EbtUint16:
|
|
||||||
res = 1;
|
|
||||||
break;
|
|
||||||
case EbtInt:
|
|
||||||
case EbtUint:
|
|
||||||
res = 2;
|
|
||||||
break;
|
|
||||||
case EbtInt64:
|
|
||||||
case EbtUint64:
|
|
||||||
res = 3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _BASICTYPES_INCLUDED_
|
|
|
@ -1,292 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _COMMON_INCLUDED_
|
|
||||||
#define _COMMON_INCLUDED_
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__ANDROID__) || (defined(_MSC_VER) && _MSC_VER < 1700)
|
|
||||||
#include <sstream>
|
|
||||||
namespace std {
|
|
||||||
template<typename T>
|
|
||||||
std::string to_string(const T& val) {
|
|
||||||
std::ostringstream os;
|
|
||||||
os << val;
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (defined(_MSC_VER) && _MSC_VER < 1900 /*vs2015*/) || defined MINGW_HAS_SECURE_API
|
|
||||||
#include <basetsd.h>
|
|
||||||
#ifndef snprintf
|
|
||||||
#define snprintf sprintf_s
|
|
||||||
#endif
|
|
||||||
#define safe_vsprintf(buf,max,format,args) vsnprintf_s((buf), (max), (max), (format), (args))
|
|
||||||
#elif defined (solaris)
|
|
||||||
#define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args))
|
|
||||||
#include <sys/int_types.h>
|
|
||||||
#define UINT_PTR uintptr_t
|
|
||||||
#else
|
|
||||||
#define safe_vsprintf(buf,max,format,args) vsnprintf((buf), (max), (format), (args))
|
|
||||||
#include <stdint.h>
|
|
||||||
#define UINT_PTR uintptr_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
|
||||||
#include <stdlib.h>
|
|
||||||
inline long long int strtoll (const char* str, char** endptr, int base)
|
|
||||||
{
|
|
||||||
return _strtoi64(str, endptr, base);
|
|
||||||
}
|
|
||||||
inline unsigned long long int strtoull (const char* str, char** endptr, int base)
|
|
||||||
{
|
|
||||||
return _strtoui64(str, endptr, base);
|
|
||||||
}
|
|
||||||
inline long long int atoll (const char* str)
|
|
||||||
{
|
|
||||||
return strtoll(str, NULL, 10);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#define strdup _strdup
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* windows only pragma */
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable : 4786) // Don't warn about too long identifiers
|
|
||||||
#pragma warning(disable : 4514) // unused inline method
|
|
||||||
#pragma warning(disable : 4201) // nameless union
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <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"
|
|
||||||
|
|
||||||
//
|
|
||||||
// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
|
|
||||||
//
|
|
||||||
#define POOL_ALLOCATOR_NEW_DELETE(A) \
|
|
||||||
void* operator new(size_t s) { return (A).allocate(s); } \
|
|
||||||
void* operator new(size_t, void *_Where) { return (_Where); } \
|
|
||||||
void operator delete(void*) { } \
|
|
||||||
void operator delete(void *, void *) { } \
|
|
||||||
void* operator new[](size_t s) { return (A).allocate(s); } \
|
|
||||||
void* operator new[](size_t, void *_Where) { return (_Where); } \
|
|
||||||
void operator delete[](void*) { } \
|
|
||||||
void operator delete[](void *, void *) { }
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Pool version of string.
|
|
||||||
//
|
|
||||||
typedef pool_allocator<char> TStringAllocator;
|
|
||||||
typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
// Repackage the std::hash for use by unordered map/set with a TString key.
|
|
||||||
namespace std {
|
|
||||||
|
|
||||||
template<> struct hash<glslang::TString> {
|
|
||||||
std::size_t operator()(const glslang::TString& s) const
|
|
||||||
{
|
|
||||||
const unsigned _FNV_offset_basis = 2166136261U;
|
|
||||||
const unsigned _FNV_prime = 16777619U;
|
|
||||||
unsigned _Val = _FNV_offset_basis;
|
|
||||||
size_t _Count = s.size();
|
|
||||||
const char* _First = s.c_str();
|
|
||||||
for (size_t _Next = 0; _Next < _Count; ++_Next)
|
|
||||||
{
|
|
||||||
_Val ^= (unsigned)_First[_Next];
|
|
||||||
_Val *= _FNV_prime;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _Val;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
inline TString* NewPoolTString(const char* s)
|
|
||||||
{
|
|
||||||
void* memory = GetThreadPoolAllocator().allocate(sizeof(TString));
|
|
||||||
return new(memory) TString(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T> inline T* NewPoolObject(T*)
|
|
||||||
{
|
|
||||||
return new(GetThreadPoolAllocator().allocate(sizeof(T))) T;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T> inline T* NewPoolObject(T, int instances)
|
|
||||||
{
|
|
||||||
return new(GetThreadPoolAllocator().allocate(instances * sizeof(T))) T[instances];
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Pool allocator versions of vectors, lists, and maps
|
|
||||||
//
|
|
||||||
template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
|
|
||||||
public:
|
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
|
||||||
|
|
||||||
typedef typename std::vector<T, pool_allocator<T> >::size_type size_type;
|
|
||||||
TVector() : std::vector<T, pool_allocator<T> >() {}
|
|
||||||
TVector(const pool_allocator<T>& a) : std::vector<T, pool_allocator<T> >(a) {}
|
|
||||||
TVector(size_type i) : std::vector<T, pool_allocator<T> >(i) {}
|
|
||||||
TVector(size_type i, const T& val) : std::vector<T, pool_allocator<T> >(i, val) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T> class TList : public std::list<T, pool_allocator<T> > {
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class K, class D, class CMP = std::less<K> >
|
|
||||||
class TMap : public std::map<K, D, CMP, pool_allocator<std::pair<K const, D> > > {
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class K, class D, class HASH = std::hash<K>, class PRED = std::equal_to<K> >
|
|
||||||
class TUnorderedMap : public std::unordered_map<K, D, HASH, PRED, pool_allocator<std::pair<K const, D> > > {
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Persistent string memory. Should only be used for strings that survive
|
|
||||||
// across compiles/links.
|
|
||||||
//
|
|
||||||
typedef std::basic_string<char> TPersistString;
|
|
||||||
|
|
||||||
//
|
|
||||||
// templatized min and max functions.
|
|
||||||
//
|
|
||||||
template <class T> T Min(const T a, const T b) { return a < b ? a : b; }
|
|
||||||
template <class T> T Max(const T a, const T b) { return a > b ? a : b; }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Create a TString object from an integer.
|
|
||||||
//
|
|
||||||
#if defined _MSC_VER || defined MINGW_HAS_SECURE_API
|
|
||||||
inline const TString String(const int i, const int base = 10)
|
|
||||||
{
|
|
||||||
char text[16]; // 32 bit ints are at most 10 digits in base 10
|
|
||||||
_itoa_s(i, text, sizeof(text), base);
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
inline const TString String(const int i, const int /*base*/ = 10)
|
|
||||||
{
|
|
||||||
char text[16]; // 32 bit ints are at most 10 digits in base 10
|
|
||||||
|
|
||||||
// we assume base 10 for all cases
|
|
||||||
snprintf(text, sizeof(text), "%d", i);
|
|
||||||
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct TSourceLoc {
|
|
||||||
void init()
|
|
||||||
{
|
|
||||||
name = nullptr; string = 0; line = 0; column = 0;
|
|
||||||
}
|
|
||||||
void init(int stringNum) { init(); string = stringNum; }
|
|
||||||
// Returns the name if it exists. Otherwise, returns the string number.
|
|
||||||
std::string getStringNameOrNum(bool quoteStringName = true) const
|
|
||||||
{
|
|
||||||
if (name != nullptr) {
|
|
||||||
TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name;
|
|
||||||
std::string ret_str(qstr.c_str());
|
|
||||||
return ret_str;
|
|
||||||
}
|
|
||||||
return std::to_string((long long)string);
|
|
||||||
}
|
|
||||||
const char* getFilename() const
|
|
||||||
{
|
|
||||||
if (name == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
return name->c_str();
|
|
||||||
}
|
|
||||||
const char* getFilenameStr() const { return name == nullptr ? "" : name->c_str(); }
|
|
||||||
TString* name; // descriptive name for this string, when a textual name is available, otherwise nullptr
|
|
||||||
int string;
|
|
||||||
int line;
|
|
||||||
int column;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TPragmaTable : public TMap<TString, TString> {
|
|
||||||
public:
|
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
|
||||||
};
|
|
||||||
|
|
||||||
const int MaxTokenLength = 1024;
|
|
||||||
|
|
||||||
template <class T> bool IsPow2(T powerOf2)
|
|
||||||
{
|
|
||||||
if (powerOf2 <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return (powerOf2 & (powerOf2 - 1)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Round number up to a multiple of the given powerOf2, which is not
|
|
||||||
// a power, just a number that must be a power of 2.
|
|
||||||
template <class T> void RoundToPow2(T& number, int powerOf2)
|
|
||||||
{
|
|
||||||
assert(IsPow2(powerOf2));
|
|
||||||
number = (number + powerOf2 - 1) & ~(powerOf2 - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T> bool IsMultipleOfPow2(T number, int powerOf2)
|
|
||||||
{
|
|
||||||
assert(IsPow2(powerOf2));
|
|
||||||
return ! (number & (powerOf2 - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _COMMON_INCLUDED_
|
|
|
@ -1,974 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
// Copyright (C) 2017 ARM Limited.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _CONSTANT_UNION_INCLUDED_
|
|
||||||
#define _CONSTANT_UNION_INCLUDED_
|
|
||||||
|
|
||||||
#include "../Include/Common.h"
|
|
||||||
#include "../Include/BaseTypes.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
class TConstUnion {
|
|
||||||
public:
|
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
|
||||||
|
|
||||||
TConstUnion() : iConst(0), type(EbtInt) { }
|
|
||||||
|
|
||||||
void setI8Const(signed char i)
|
|
||||||
{
|
|
||||||
i8Const = i;
|
|
||||||
type = EbtInt8;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setU8Const(unsigned char u)
|
|
||||||
{
|
|
||||||
u8Const = u;
|
|
||||||
type = EbtUint8;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setI16Const(signed short i)
|
|
||||||
{
|
|
||||||
i16Const = i;
|
|
||||||
type = EbtInt16;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setU16Const(unsigned short u)
|
|
||||||
{
|
|
||||||
u16Const = u;
|
|
||||||
type = EbtUint16;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setIConst(int i)
|
|
||||||
{
|
|
||||||
iConst = i;
|
|
||||||
type = EbtInt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUConst(unsigned int u)
|
|
||||||
{
|
|
||||||
uConst = u;
|
|
||||||
type = EbtUint;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setI64Const(long long i64)
|
|
||||||
{
|
|
||||||
i64Const = i64;
|
|
||||||
type = EbtInt64;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setU64Const(unsigned long long u64)
|
|
||||||
{
|
|
||||||
u64Const = u64;
|
|
||||||
type = EbtUint64;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDConst(double d)
|
|
||||||
{
|
|
||||||
dConst = d;
|
|
||||||
type = EbtDouble;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBConst(bool b)
|
|
||||||
{
|
|
||||||
bConst = b;
|
|
||||||
type = EbtBool;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSConst(const TString* s)
|
|
||||||
{
|
|
||||||
sConst = s;
|
|
||||||
type = EbtString;
|
|
||||||
}
|
|
||||||
|
|
||||||
signed char getI8Const() const { return i8Const; }
|
|
||||||
unsigned char getU8Const() const { return u8Const; }
|
|
||||||
signed short getI16Const() const { return i16Const; }
|
|
||||||
unsigned short getU16Const() const { return u16Const; }
|
|
||||||
int getIConst() const { return iConst; }
|
|
||||||
unsigned int getUConst() const { return uConst; }
|
|
||||||
long long getI64Const() const { return i64Const; }
|
|
||||||
unsigned long long getU64Const() const { return u64Const; }
|
|
||||||
double getDConst() const { return dConst; }
|
|
||||||
bool getBConst() const { return bConst; }
|
|
||||||
const TString* getSConst() const { return sConst; }
|
|
||||||
|
|
||||||
bool operator==(const signed char i) const
|
|
||||||
{
|
|
||||||
if (i == i8Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const unsigned char u) const
|
|
||||||
{
|
|
||||||
if (u == u8Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const signed short i) const
|
|
||||||
{
|
|
||||||
if (i == i16Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const unsigned short u) const
|
|
||||||
{
|
|
||||||
if (u == u16Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const int i) const
|
|
||||||
{
|
|
||||||
if (i == iConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const unsigned int u) const
|
|
||||||
{
|
|
||||||
if (u == uConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const long long i64) const
|
|
||||||
{
|
|
||||||
if (i64 == i64Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const unsigned long long u64) const
|
|
||||||
{
|
|
||||||
if (u64 == u64Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const double d) const
|
|
||||||
{
|
|
||||||
if (d == dConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const bool b) const
|
|
||||||
{
|
|
||||||
if (b == bConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
if (constant.type != type)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case EbtInt:
|
|
||||||
if (constant.iConst == iConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case EbtUint:
|
|
||||||
if (constant.uConst == uConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case EbtBool:
|
|
||||||
if (constant.bConst == bConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case EbtDouble:
|
|
||||||
if (constant.dConst == dConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt16:
|
|
||||||
if (constant.i16Const == i16Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case EbtUint16:
|
|
||||||
if (constant.u16Const == u16Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case EbtInt8:
|
|
||||||
if (constant.i8Const == i8Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case EbtUint8:
|
|
||||||
if (constant.u8Const == u8Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case EbtInt64:
|
|
||||||
if (constant.i64Const == i64Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case EbtUint64:
|
|
||||||
if (constant.u64Const == u64Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const signed char i) const
|
|
||||||
{
|
|
||||||
return !operator==(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const unsigned char u) const
|
|
||||||
{
|
|
||||||
return !operator==(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const signed short i) const
|
|
||||||
{
|
|
||||||
return !operator==(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const unsigned short u) const
|
|
||||||
{
|
|
||||||
return !operator==(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const int i) const
|
|
||||||
{
|
|
||||||
return !operator==(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const unsigned int u) const
|
|
||||||
{
|
|
||||||
return !operator==(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const long long i) const
|
|
||||||
{
|
|
||||||
return !operator==(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const unsigned long long u) const
|
|
||||||
{
|
|
||||||
return !operator==(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const float f) const
|
|
||||||
{
|
|
||||||
return !operator==(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const bool b) const
|
|
||||||
{
|
|
||||||
return !operator==(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
return !operator==(constant);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator>(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
assert(type == constant.type);
|
|
||||||
switch (type) {
|
|
||||||
case EbtInt:
|
|
||||||
if (iConst > constant.iConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtUint:
|
|
||||||
if (uConst > constant.uConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtDouble:
|
|
||||||
if (dConst > constant.dConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8:
|
|
||||||
if (i8Const > constant.i8Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtUint8:
|
|
||||||
if (u8Const > constant.u8Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtInt16:
|
|
||||||
if (i16Const > constant.i16Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtUint16:
|
|
||||||
if (u16Const > constant.u16Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtInt64:
|
|
||||||
if (i64Const > constant.i64Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtUint64:
|
|
||||||
if (u64Const > constant.u64Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
assert(false && "Default missing");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
assert(type == constant.type);
|
|
||||||
switch (type) {
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8:
|
|
||||||
if (i8Const < constant.i8Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtUint8:
|
|
||||||
if (u8Const < constant.u8Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtInt16:
|
|
||||||
if (i16Const < constant.i16Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtUint16:
|
|
||||||
if (u16Const < constant.u16Const)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
case EbtInt64:
|
|
||||||
if (i64Const < constant.i64Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtUint64:
|
|
||||||
if (u64Const < constant.u64Const)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
case EbtDouble:
|
|
||||||
if (dConst < constant.dConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtInt:
|
|
||||||
if (iConst < constant.iConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
case EbtUint:
|
|
||||||
if (uConst < constant.uConst)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
assert(false && "Default missing");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator+(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
assert(type == constant.type);
|
|
||||||
switch (type) {
|
|
||||||
case EbtInt: returnValue.setIConst(iConst + constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setUConst(uConst + constant.uConst); break;
|
|
||||||
case EbtDouble: returnValue.setDConst(dConst + constant.dConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setI8Const(i8Const + constant.i8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI16Const(i16Const + constant.i16Const); break;
|
|
||||||
case EbtInt64: returnValue.setI64Const(i64Const + constant.i64Const); break;
|
|
||||||
case EbtUint8: returnValue.setU8Const(u8Const + constant.u8Const); break;
|
|
||||||
case EbtUint16: returnValue.setU16Const(u16Const + constant.u16Const); break;
|
|
||||||
case EbtUint64: returnValue.setU64Const(u64Const + constant.u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator-(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
assert(type == constant.type);
|
|
||||||
switch (type) {
|
|
||||||
case EbtInt: returnValue.setIConst(iConst - constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setUConst(uConst - constant.uConst); break;
|
|
||||||
case EbtDouble: returnValue.setDConst(dConst - constant.dConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setI8Const(i8Const - constant.i8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI16Const(i16Const - constant.i16Const); break;
|
|
||||||
case EbtInt64: returnValue.setI64Const(i64Const - constant.i64Const); break;
|
|
||||||
case EbtUint8: returnValue.setU8Const(u8Const - constant.u8Const); break;
|
|
||||||
case EbtUint16: returnValue.setU16Const(u16Const - constant.u16Const); break;
|
|
||||||
case EbtUint64: returnValue.setU64Const(u64Const - constant.u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator*(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
assert(type == constant.type);
|
|
||||||
switch (type) {
|
|
||||||
case EbtInt: returnValue.setIConst(iConst * constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setUConst(uConst * constant.uConst); break;
|
|
||||||
case EbtDouble: returnValue.setDConst(dConst * constant.dConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setI8Const(i8Const * constant.i8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI16Const(i16Const * constant.i16Const); break;
|
|
||||||
case EbtInt64: returnValue.setI64Const(i64Const * constant.i64Const); break;
|
|
||||||
case EbtUint8: returnValue.setU8Const(u8Const * constant.u8Const); break;
|
|
||||||
case EbtUint16: returnValue.setU16Const(u16Const * constant.u16Const); break;
|
|
||||||
case EbtUint64: returnValue.setU64Const(u64Const * constant.u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator%(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
assert(type == constant.type);
|
|
||||||
switch (type) {
|
|
||||||
case EbtInt: returnValue.setIConst(iConst % constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setUConst(uConst % constant.uConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setI8Const(i8Const % constant.i8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI8Const(i8Const % constant.i16Const); break;
|
|
||||||
case EbtInt64: returnValue.setI64Const(i64Const % constant.i64Const); break;
|
|
||||||
case EbtUint8: returnValue.setU8Const(u8Const % constant.u8Const); break;
|
|
||||||
case EbtUint16: returnValue.setU16Const(u16Const % constant.u16Const); break;
|
|
||||||
case EbtUint64: returnValue.setU64Const(u64Const % constant.u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator>>(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
switch (type) {
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setI8Const(i8Const >> constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setI8Const(i8Const >> constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI8Const(i8Const >> constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setI8Const(i8Const >> constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setI8Const(i8Const >> constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setI8Const(i8Const >> constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setI8Const(i8Const >> constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setI8Const(i8Const >> constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EbtUint8:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setU8Const(u8Const >> constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setU8Const(u8Const >> constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setU8Const(u8Const >> constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setU8Const(u8Const >> constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setU8Const(u8Const >> constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setU8Const(u8Const >> constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setU8Const(u8Const >> constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setU8Const(u8Const >> constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EbtInt16:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setI16Const(i16Const >> constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setI16Const(i16Const >> constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI16Const(i16Const >> constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setI16Const(i16Const >> constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setI16Const(i16Const >> constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setI16Const(i16Const >> constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setI16Const(i16Const >> constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setI16Const(i16Const >> constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EbtUint16:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setU16Const(u16Const >> constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setU16Const(u16Const >> constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setU16Const(u16Const >> constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setU16Const(u16Const >> constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setU16Const(u16Const >> constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setU16Const(u16Const >> constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setU16Const(u16Const >> constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setU16Const(u16Const >> constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case EbtInt:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setIConst(iConst >> constant.uConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setIConst(iConst >> constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setIConst(iConst >> constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setIConst(iConst >> constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setIConst(iConst >> constant.u16Const); break;
|
|
||||||
case EbtInt64: returnValue.setIConst(iConst >> constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setIConst(iConst >> constant.u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EbtUint:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt: returnValue.setUConst(uConst >> constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setUConst(uConst >> constant.uConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setUConst(uConst >> constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setUConst(uConst >> constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setUConst(uConst >> constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setUConst(uConst >> constant.u16Const); break;
|
|
||||||
case EbtInt64: returnValue.setUConst(uConst >> constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setUConst(uConst >> constant.u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt64:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setI64Const(i64Const >> constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setI64Const(i64Const >> constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI64Const(i64Const >> constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setI64Const(i64Const >> constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setI64Const(i64Const >> constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setI64Const(i64Const >> constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setI64Const(i64Const >> constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setI64Const(i64Const >> constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EbtUint64:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setU64Const(u64Const >> constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setU64Const(u64Const >> constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setU64Const(u64Const >> constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setU64Const(u64Const >> constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setU64Const(u64Const >> constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setU64Const(u64Const >> constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setU64Const(u64Const >> constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setU64Const(u64Const >> constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator<<(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
switch (type) {
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setI8Const(i8Const << constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setI8Const(i8Const << constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI8Const(i8Const << constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setI8Const(i8Const << constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setI8Const(i8Const << constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setI8Const(i8Const << constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setI8Const(i8Const << constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setI8Const(i8Const << constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EbtUint8:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setU8Const(u8Const << constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setU8Const(u8Const << constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setU8Const(u8Const << constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setU8Const(u8Const << constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setU8Const(u8Const << constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setU8Const(u8Const << constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setU8Const(u8Const << constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setU8Const(u8Const << constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EbtInt16:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setI16Const(i16Const << constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setI16Const(i16Const << constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI16Const(i16Const << constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setI16Const(i16Const << constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setI16Const(i16Const << constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setI16Const(i16Const << constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setI16Const(i16Const << constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setI16Const(i16Const << constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EbtUint16:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setU16Const(u16Const << constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setU16Const(u16Const << constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setU16Const(u16Const << constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setU16Const(u16Const << constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setU16Const(u16Const << constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setU16Const(u16Const << constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setU16Const(u16Const << constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setU16Const(u16Const << constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EbtInt64:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setI64Const(i64Const << constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setI64Const(i64Const << constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI64Const(i64Const << constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setI64Const(i64Const << constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setI64Const(i64Const << constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setI64Const(i64Const << constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setI64Const(i64Const << constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setI64Const(i64Const << constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EbtUint64:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt8: returnValue.setU64Const(u64Const << constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setU64Const(u64Const << constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setU64Const(u64Const << constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setU64Const(u64Const << constant.u16Const); break;
|
|
||||||
case EbtInt: returnValue.setU64Const(u64Const << constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setU64Const(u64Const << constant.uConst); break;
|
|
||||||
case EbtInt64: returnValue.setU64Const(u64Const << constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setU64Const(u64Const << constant.u64Const); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case EbtInt:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setIConst(iConst << constant.uConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setIConst(iConst << constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setIConst(iConst << constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setIConst(iConst << constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setIConst(iConst << constant.u16Const); break;
|
|
||||||
case EbtInt64: returnValue.setIConst(iConst << constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setIConst(iConst << constant.u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case EbtUint:
|
|
||||||
switch (constant.type) {
|
|
||||||
case EbtInt: returnValue.setUConst(uConst << constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setUConst(uConst << constant.uConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setUConst(uConst << constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setUConst(uConst << constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setUConst(uConst << constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setUConst(uConst << constant.u16Const); break;
|
|
||||||
case EbtInt64: returnValue.setUConst(uConst << constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setUConst(uConst << constant.u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator&(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
assert(type == constant.type);
|
|
||||||
switch (type) {
|
|
||||||
case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setUConst(uConst & constant.uConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setI8Const(i8Const & constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setU8Const(u8Const & constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI16Const(i16Const & constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setU16Const(u16Const & constant.u16Const); break;
|
|
||||||
case EbtInt64: returnValue.setI64Const(i64Const & constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setU64Const(u64Const & constant.u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator|(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
assert(type == constant.type);
|
|
||||||
switch (type) {
|
|
||||||
case EbtInt: returnValue.setIConst(iConst | constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setUConst(uConst | constant.uConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setI8Const(i8Const | constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setU8Const(u8Const | constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI16Const(i16Const | constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setU16Const(u16Const | constant.u16Const); break;
|
|
||||||
case EbtInt64: returnValue.setI64Const(i64Const | constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setU64Const(u64Const | constant.u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator^(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
assert(type == constant.type);
|
|
||||||
switch (type) {
|
|
||||||
case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break;
|
|
||||||
case EbtUint: returnValue.setUConst(uConst ^ constant.uConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setI8Const(i8Const ^ constant.i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setU8Const(u8Const ^ constant.u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI16Const(i16Const ^ constant.i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setU16Const(u16Const ^ constant.u16Const); break;
|
|
||||||
case EbtInt64: returnValue.setI64Const(i64Const ^ constant.i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setU64Const(u64Const ^ constant.u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator~() const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
switch (type) {
|
|
||||||
case EbtInt: returnValue.setIConst(~iConst); break;
|
|
||||||
case EbtUint: returnValue.setUConst(~uConst); break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtInt8: returnValue.setI8Const(~i8Const); break;
|
|
||||||
case EbtUint8: returnValue.setU8Const(~u8Const); break;
|
|
||||||
case EbtInt16: returnValue.setI16Const(~i16Const); break;
|
|
||||||
case EbtUint16: returnValue.setU16Const(~u16Const); break;
|
|
||||||
case EbtInt64: returnValue.setI64Const(~i64Const); break;
|
|
||||||
case EbtUint64: returnValue.setU64Const(~u64Const); break;
|
|
||||||
#endif
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator&&(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
assert(type == constant.type);
|
|
||||||
switch (type) {
|
|
||||||
case EbtBool: returnValue.setBConst(bConst && constant.bConst); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TConstUnion operator||(const TConstUnion& constant) const
|
|
||||||
{
|
|
||||||
TConstUnion returnValue;
|
|
||||||
assert(type == constant.type);
|
|
||||||
switch (type) {
|
|
||||||
case EbtBool: returnValue.setBConst(bConst || constant.bConst); break;
|
|
||||||
default: assert(false && "Default missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
TBasicType getType() const { return type; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
union {
|
|
||||||
signed char i8Const; // used for i8vec, scalar int8s
|
|
||||||
unsigned char u8Const; // used for u8vec, scalar uint8s
|
|
||||||
signed short i16Const; // used for i16vec, scalar int16s
|
|
||||||
unsigned short u16Const; // used for u16vec, scalar uint16s
|
|
||||||
int iConst; // used for ivec, scalar ints
|
|
||||||
unsigned int uConst; // used for uvec, scalar uints
|
|
||||||
long long i64Const; // used for i64vec, scalar int64s
|
|
||||||
unsigned long long u64Const; // used for u64vec, scalar uint64s
|
|
||||||
bool bConst; // used for bvec, scalar bools
|
|
||||||
double dConst; // used for vec, dvec, mat, dmat, scalar floats and doubles
|
|
||||||
const TString* sConst; // string constant
|
|
||||||
};
|
|
||||||
|
|
||||||
TBasicType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Encapsulate having a pointer to an array of TConstUnion,
|
|
||||||
// which only needs to be allocated if its size is going to be
|
|
||||||
// bigger than 0.
|
|
||||||
//
|
|
||||||
// One convenience is being able to use [] to go inside the array, instead
|
|
||||||
// of C++ assuming it as an array of pointers to vectors.
|
|
||||||
//
|
|
||||||
// General usage is that the size is known up front, and it is
|
|
||||||
// created once with the proper size.
|
|
||||||
//
|
|
||||||
class TConstUnionArray {
|
|
||||||
public:
|
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
|
||||||
|
|
||||||
TConstUnionArray() : unionArray(nullptr) { }
|
|
||||||
virtual ~TConstUnionArray() { }
|
|
||||||
|
|
||||||
explicit TConstUnionArray(int size)
|
|
||||||
{
|
|
||||||
if (size == 0)
|
|
||||||
unionArray = nullptr;
|
|
||||||
else
|
|
||||||
unionArray = new TConstUnionVector(size);
|
|
||||||
}
|
|
||||||
TConstUnionArray(const TConstUnionArray& a) = default;
|
|
||||||
TConstUnionArray(const TConstUnionArray& a, int start, int size)
|
|
||||||
{
|
|
||||||
unionArray = new TConstUnionVector(size);
|
|
||||||
for (int i = 0; i < size; ++i)
|
|
||||||
(*unionArray)[i] = a[start + i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use this constructor for a smear operation
|
|
||||||
TConstUnionArray(int size, const TConstUnion& val)
|
|
||||||
{
|
|
||||||
unionArray = new TConstUnionVector(size, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
int size() const { return unionArray ? (int)unionArray->size() : 0; }
|
|
||||||
TConstUnion& operator[](size_t index) { return (*unionArray)[index]; }
|
|
||||||
const TConstUnion& operator[](size_t index) const { return (*unionArray)[index]; }
|
|
||||||
bool operator==(const TConstUnionArray& rhs) const
|
|
||||||
{
|
|
||||||
// this includes the case that both are unallocated
|
|
||||||
if (unionArray == rhs.unionArray)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (! unionArray || ! rhs.unionArray)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return *unionArray == *rhs.unionArray;
|
|
||||||
}
|
|
||||||
bool operator!=(const TConstUnionArray& rhs) const { return ! operator==(rhs); }
|
|
||||||
|
|
||||||
double dot(const TConstUnionArray& rhs)
|
|
||||||
{
|
|
||||||
assert(rhs.unionArray->size() == unionArray->size());
|
|
||||||
double sum = 0.0;
|
|
||||||
|
|
||||||
for (size_t comp = 0; comp < unionArray->size(); ++comp)
|
|
||||||
sum += (*this)[comp].getDConst() * rhs[comp].getDConst();
|
|
||||||
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool empty() const { return unionArray == nullptr; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
typedef TVector<TConstUnion> TConstUnionVector;
|
|
||||||
TConstUnionVector* unionArray;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _CONSTANT_UNION_INCLUDED_
|
|
|
@ -1,144 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _INFOSINK_INCLUDED_
|
|
||||||
#define _INFOSINK_INCLUDED_
|
|
||||||
|
|
||||||
#include "../Include/Common.h"
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// TPrefixType is used to centralize how info log messages start.
|
|
||||||
// See below.
|
|
||||||
//
|
|
||||||
enum TPrefixType {
|
|
||||||
EPrefixNone,
|
|
||||||
EPrefixWarning,
|
|
||||||
EPrefixError,
|
|
||||||
EPrefixInternalError,
|
|
||||||
EPrefixUnimplemented,
|
|
||||||
EPrefixNote
|
|
||||||
};
|
|
||||||
|
|
||||||
enum TOutputStream {
|
|
||||||
ENull = 0,
|
|
||||||
EDebugger = 0x01,
|
|
||||||
EStdOut = 0x02,
|
|
||||||
EString = 0x04,
|
|
||||||
};
|
|
||||||
//
|
|
||||||
// Encapsulate info logs for all objects that have them.
|
|
||||||
//
|
|
||||||
// The methods are a general set of tools for getting a variety of
|
|
||||||
// messages and types inserted into the log.
|
|
||||||
//
|
|
||||||
class TInfoSinkBase {
|
|
||||||
public:
|
|
||||||
TInfoSinkBase() : outputStream(4) {}
|
|
||||||
void erase() { sink.erase(); }
|
|
||||||
TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; }
|
|
||||||
TInfoSinkBase& operator<<(char c) { append(1, c); return *this; }
|
|
||||||
TInfoSinkBase& operator<<(const char* s) { append(s); return *this; }
|
|
||||||
TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; }
|
|
||||||
TInfoSinkBase& operator<<(unsigned int n) { append(String(n)); return *this; }
|
|
||||||
TInfoSinkBase& operator<<(float n) { const int size = 40; char buf[size];
|
|
||||||
snprintf(buf, size, (fabs(n) > 1e-8 && fabs(n) < 1e8) || n == 0.0f ? "%f" : "%g", n);
|
|
||||||
append(buf);
|
|
||||||
return *this; }
|
|
||||||
TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; }
|
|
||||||
TInfoSinkBase& operator+(const TString& t) { append(t); return *this; }
|
|
||||||
TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; }
|
|
||||||
TInfoSinkBase& operator+(const char* s) { append(s); return *this; }
|
|
||||||
const char* c_str() const { return sink.c_str(); }
|
|
||||||
void prefix(TPrefixType message) {
|
|
||||||
switch(message) {
|
|
||||||
case EPrefixNone: break;
|
|
||||||
case EPrefixWarning: append("WARNING: "); break;
|
|
||||||
case EPrefixError: append("ERROR: "); break;
|
|
||||||
case EPrefixInternalError: append("INTERNAL ERROR: "); break;
|
|
||||||
case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break;
|
|
||||||
case EPrefixNote: append("NOTE: "); break;
|
|
||||||
default: append("UNKNOWN ERROR: "); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void location(const TSourceLoc& loc) {
|
|
||||||
const int maxSize = 24;
|
|
||||||
char locText[maxSize];
|
|
||||||
snprintf(locText, maxSize, ":%d", loc.line);
|
|
||||||
append(loc.getStringNameOrNum(false).c_str());
|
|
||||||
append(locText);
|
|
||||||
append(": ");
|
|
||||||
}
|
|
||||||
void message(TPrefixType message, const char* s) {
|
|
||||||
prefix(message);
|
|
||||||
append(s);
|
|
||||||
append("\n");
|
|
||||||
}
|
|
||||||
void message(TPrefixType message, const char* s, const TSourceLoc& loc) {
|
|
||||||
prefix(message);
|
|
||||||
location(loc);
|
|
||||||
append(s);
|
|
||||||
append("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOutputStream(int output = 4)
|
|
||||||
{
|
|
||||||
outputStream = output;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void append(const char* s);
|
|
||||||
|
|
||||||
void append(int count, char c);
|
|
||||||
void append(const TPersistString& t);
|
|
||||||
void append(const TString& t);
|
|
||||||
|
|
||||||
void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2)
|
|
||||||
sink.reserve(sink.capacity() + sink.capacity() / 2); }
|
|
||||||
void appendToStream(const char* s);
|
|
||||||
TPersistString sink;
|
|
||||||
int outputStream;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
class TInfoSink {
|
|
||||||
public:
|
|
||||||
glslang::TInfoSinkBase info;
|
|
||||||
glslang::TInfoSinkBase debug;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _INFOSINK_INCLUDED_
|
|
|
@ -1,45 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef __INITIALIZE_GLOBALS_INCLUDED_
|
|
||||||
#define __INITIALIZE_GLOBALS_INCLUDED_
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
bool InitializePoolIndex();
|
|
||||||
bool DeinitializePoolIndex();
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // __INITIALIZE_GLOBALS_INCLUDED_
|
|
|
@ -1,316 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _POOLALLOC_INCLUDED_
|
|
||||||
#define _POOLALLOC_INCLUDED_
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
# define GUARD_BLOCKS // define to enable guard block sanity checking
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// This header defines an allocator that can be used to efficiently
|
|
||||||
// allocate a large number of small requests for heap memory, with the
|
|
||||||
// intention that they are not individually deallocated, but rather
|
|
||||||
// collectively deallocated at one time.
|
|
||||||
//
|
|
||||||
// This simultaneously
|
|
||||||
//
|
|
||||||
// * Makes each individual allocation much more efficient; the
|
|
||||||
// typical allocation is trivial.
|
|
||||||
// * Completely avoids the cost of doing individual deallocation.
|
|
||||||
// * Saves the trouble of tracking down and plugging a large class of leaks.
|
|
||||||
//
|
|
||||||
// Individual classes can use this allocator by supplying their own
|
|
||||||
// new and delete methods.
|
|
||||||
//
|
|
||||||
// STL containers can use this allocator by using the pool_allocator
|
|
||||||
// class as the allocator (second) template argument.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstring>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
// If we are using guard blocks, we must track each individual
|
|
||||||
// allocation. If we aren't using guard blocks, these
|
|
||||||
// never get instantiated, so won't have any impact.
|
|
||||||
//
|
|
||||||
|
|
||||||
class TAllocation {
|
|
||||||
public:
|
|
||||||
TAllocation(size_t size, unsigned char* mem, TAllocation* prev = 0) :
|
|
||||||
size(size), mem(mem), prevAlloc(prev) {
|
|
||||||
// Allocations are bracketed:
|
|
||||||
// [allocationHeader][initialGuardBlock][userData][finalGuardBlock]
|
|
||||||
// This would be cleaner with if (guardBlockSize)..., but that
|
|
||||||
// makes the compiler print warnings about 0 length memsets,
|
|
||||||
// even with the if() protecting them.
|
|
||||||
# ifdef GUARD_BLOCKS
|
|
||||||
memset(preGuard(), guardBlockBeginVal, guardBlockSize);
|
|
||||||
memset(data(), userDataFill, size);
|
|
||||||
memset(postGuard(), guardBlockEndVal, guardBlockSize);
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void check() const {
|
|
||||||
checkGuardBlock(preGuard(), guardBlockBeginVal, "before");
|
|
||||||
checkGuardBlock(postGuard(), guardBlockEndVal, "after");
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkAllocList() const;
|
|
||||||
|
|
||||||
// Return total size needed to accommodate user buffer of 'size',
|
|
||||||
// plus our tracking data.
|
|
||||||
inline static size_t allocationSize(size_t size) {
|
|
||||||
return size + 2 * guardBlockSize + headerSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offset from surrounding buffer to get to user data buffer.
|
|
||||||
inline static unsigned char* offsetAllocation(unsigned char* m) {
|
|
||||||
return m + guardBlockSize + headerSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const;
|
|
||||||
|
|
||||||
// Find offsets to pre and post guard blocks, and user data buffer
|
|
||||||
unsigned char* preGuard() const { return mem + headerSize(); }
|
|
||||||
unsigned char* data() const { return preGuard() + guardBlockSize; }
|
|
||||||
unsigned char* postGuard() const { return data() + size; }
|
|
||||||
|
|
||||||
size_t size; // size of the user data area
|
|
||||||
unsigned char* mem; // beginning of our allocation (pts to header)
|
|
||||||
TAllocation* prevAlloc; // prior allocation in the chain
|
|
||||||
|
|
||||||
const static unsigned char guardBlockBeginVal;
|
|
||||||
const static unsigned char guardBlockEndVal;
|
|
||||||
const static unsigned char userDataFill;
|
|
||||||
|
|
||||||
const static size_t guardBlockSize;
|
|
||||||
# ifdef GUARD_BLOCKS
|
|
||||||
inline static size_t headerSize() { return sizeof(TAllocation); }
|
|
||||||
# else
|
|
||||||
inline static size_t headerSize() { return 0; }
|
|
||||||
# endif
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// There are several stacks. One is to track the pushing and popping
|
|
||||||
// of the user, and not yet implemented. The others are simply a
|
|
||||||
// repositories of free pages or used pages.
|
|
||||||
//
|
|
||||||
// Page stacks are linked together with a simple header at the beginning
|
|
||||||
// of each allocation obtained from the underlying OS. Multi-page allocations
|
|
||||||
// are returned to the OS. Individual page allocations are kept for future
|
|
||||||
// re-use.
|
|
||||||
//
|
|
||||||
// The "page size" used is not, nor must it match, the underlying OS
|
|
||||||
// page size. But, having it be about that size or equal to a set of
|
|
||||||
// pages is likely most optimal.
|
|
||||||
//
|
|
||||||
class TPoolAllocator {
|
|
||||||
public:
|
|
||||||
TPoolAllocator(int growthIncrement = 8*1024, int allocationAlignment = 16);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Don't call the destructor just to free up the memory, call pop()
|
|
||||||
//
|
|
||||||
~TPoolAllocator();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call push() to establish a new place to pop memory too. Does not
|
|
||||||
// have to be called to get things started.
|
|
||||||
//
|
|
||||||
void push();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call pop() to free all memory allocated since the last call to push(),
|
|
||||||
// or if no last call to push, frees all memory since first allocation.
|
|
||||||
//
|
|
||||||
void pop();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call popAll() to free all memory allocated.
|
|
||||||
//
|
|
||||||
void popAll();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Call allocate() to actually acquire memory. Returns 0 if no memory
|
|
||||||
// available, otherwise a properly aligned pointer to 'numBytes' of memory.
|
|
||||||
//
|
|
||||||
void* allocate(size_t numBytes);
|
|
||||||
|
|
||||||
//
|
|
||||||
// There is no deallocate. The point of this class is that
|
|
||||||
// deallocation can be skipped by the user of it, as the model
|
|
||||||
// of use is to simultaneously deallocate everything at once
|
|
||||||
// by calling pop(), and to not have to solve memory leak problems.
|
|
||||||
//
|
|
||||||
|
|
||||||
protected:
|
|
||||||
friend struct tHeader;
|
|
||||||
|
|
||||||
struct tHeader {
|
|
||||||
tHeader(tHeader* nextPage, size_t pageCount) :
|
|
||||||
#ifdef GUARD_BLOCKS
|
|
||||||
lastAllocation(0),
|
|
||||||
#endif
|
|
||||||
nextPage(nextPage), pageCount(pageCount) { }
|
|
||||||
|
|
||||||
~tHeader() {
|
|
||||||
#ifdef GUARD_BLOCKS
|
|
||||||
if (lastAllocation)
|
|
||||||
lastAllocation->checkAllocList();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef GUARD_BLOCKS
|
|
||||||
TAllocation* lastAllocation;
|
|
||||||
#endif
|
|
||||||
tHeader* nextPage;
|
|
||||||
size_t pageCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct tAllocState {
|
|
||||||
size_t offset;
|
|
||||||
tHeader* page;
|
|
||||||
};
|
|
||||||
typedef std::vector<tAllocState> tAllocStack;
|
|
||||||
|
|
||||||
// Track allocations if and only if we're using guard blocks
|
|
||||||
#ifndef GUARD_BLOCKS
|
|
||||||
void* initializeAllocation(tHeader*, unsigned char* memory, size_t) {
|
|
||||||
#else
|
|
||||||
void* initializeAllocation(tHeader* block, unsigned char* memory, size_t numBytes) {
|
|
||||||
new(memory) TAllocation(numBytes, memory, block->lastAllocation);
|
|
||||||
block->lastAllocation = reinterpret_cast<TAllocation*>(memory);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// This is optimized entirely away if GUARD_BLOCKS is not defined.
|
|
||||||
return TAllocation::offsetAllocation(memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t pageSize; // granularity of allocation from the OS
|
|
||||||
size_t alignment; // all returned allocations will be aligned at
|
|
||||||
// this granularity, which will be a power of 2
|
|
||||||
size_t alignmentMask;
|
|
||||||
size_t headerSkip; // amount of memory to skip to make room for the
|
|
||||||
// header (basically, size of header, rounded
|
|
||||||
// up to make it aligned
|
|
||||||
size_t currentPageOffset; // next offset in top of inUseList to allocate from
|
|
||||||
tHeader* freeList; // list of popped memory
|
|
||||||
tHeader* inUseList; // list of all memory currently being used
|
|
||||||
tAllocStack stack; // stack of where to allocate from, to partition pool
|
|
||||||
|
|
||||||
int numCalls; // just an interesting statistic
|
|
||||||
size_t totalBytes; // just an interesting statistic
|
|
||||||
private:
|
|
||||||
TPoolAllocator& operator=(const TPoolAllocator&); // don't allow assignment operator
|
|
||||||
TPoolAllocator(const TPoolAllocator&); // don't allow default copy constructor
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// There could potentially be many pools with pops happening at
|
|
||||||
// different times. But a simple use is to have a global pop
|
|
||||||
// with everyone using the same global allocator.
|
|
||||||
//
|
|
||||||
extern TPoolAllocator& GetThreadPoolAllocator();
|
|
||||||
void SetThreadPoolAllocator(TPoolAllocator* poolAllocator);
|
|
||||||
|
|
||||||
//
|
|
||||||
// This STL compatible allocator is intended to be used as the allocator
|
|
||||||
// parameter to templatized STL containers, like vector and map.
|
|
||||||
//
|
|
||||||
// It will use the pools for allocation, and not
|
|
||||||
// do any deallocation, but will still do destruction.
|
|
||||||
//
|
|
||||||
template<class T>
|
|
||||||
class pool_allocator {
|
|
||||||
public:
|
|
||||||
typedef size_t size_type;
|
|
||||||
typedef ptrdiff_t difference_type;
|
|
||||||
typedef T *pointer;
|
|
||||||
typedef const T *const_pointer;
|
|
||||||
typedef T& reference;
|
|
||||||
typedef const T& const_reference;
|
|
||||||
typedef T value_type;
|
|
||||||
template<class Other>
|
|
||||||
struct rebind {
|
|
||||||
typedef pool_allocator<Other> other;
|
|
||||||
};
|
|
||||||
pointer address(reference x) const { return &x; }
|
|
||||||
const_pointer address(const_reference x) const { return &x; }
|
|
||||||
|
|
||||||
pool_allocator() : allocator(GetThreadPoolAllocator()) { }
|
|
||||||
pool_allocator(TPoolAllocator& a) : allocator(a) { }
|
|
||||||
pool_allocator(const pool_allocator<T>& p) : allocator(p.allocator) { }
|
|
||||||
|
|
||||||
template<class Other>
|
|
||||||
pool_allocator(const pool_allocator<Other>& p) : allocator(p.getAllocator()) { }
|
|
||||||
|
|
||||||
pointer allocate(size_type n) {
|
|
||||||
return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
|
|
||||||
pointer allocate(size_type n, const void*) {
|
|
||||||
return reinterpret_cast<pointer>(getAllocator().allocate(n * sizeof(T))); }
|
|
||||||
|
|
||||||
void deallocate(void*, size_type) { }
|
|
||||||
void deallocate(pointer, size_type) { }
|
|
||||||
|
|
||||||
pointer _Charalloc(size_t n) {
|
|
||||||
return reinterpret_cast<pointer>(getAllocator().allocate(n)); }
|
|
||||||
|
|
||||||
void construct(pointer p, const T& val) { new ((void *)p) T(val); }
|
|
||||||
void destroy(pointer p) { p->T::~T(); }
|
|
||||||
|
|
||||||
bool operator==(const pool_allocator& rhs) const { return &getAllocator() == &rhs.getAllocator(); }
|
|
||||||
bool operator!=(const pool_allocator& rhs) const { return &getAllocator() != &rhs.getAllocator(); }
|
|
||||||
|
|
||||||
size_type max_size() const { return static_cast<size_type>(-1) / sizeof(T); }
|
|
||||||
size_type max_size(int size) const { return static_cast<size_type>(-1) / size; }
|
|
||||||
|
|
||||||
TPoolAllocator& getAllocator() const { return allocator; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
pool_allocator& operator=(const pool_allocator&) { return *this; }
|
|
||||||
TPoolAllocator& allocator;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _POOLALLOC_INCLUDED_
|
|
|
@ -1,150 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _RESOURCE_LIMITS_INCLUDED_
|
|
||||||
#define _RESOURCE_LIMITS_INCLUDED_
|
|
||||||
|
|
||||||
struct TLimits {
|
|
||||||
bool nonInductiveForLoops;
|
|
||||||
bool whileLoops;
|
|
||||||
bool doWhileLoops;
|
|
||||||
bool generalUniformIndexing;
|
|
||||||
bool generalAttributeMatrixVectorIndexing;
|
|
||||||
bool generalVaryingIndexing;
|
|
||||||
bool generalSamplerIndexing;
|
|
||||||
bool generalVariableIndexing;
|
|
||||||
bool generalConstantMatrixVectorIndexing;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TBuiltInResource {
|
|
||||||
int maxLights;
|
|
||||||
int maxClipPlanes;
|
|
||||||
int maxTextureUnits;
|
|
||||||
int maxTextureCoords;
|
|
||||||
int maxVertexAttribs;
|
|
||||||
int maxVertexUniformComponents;
|
|
||||||
int maxVaryingFloats;
|
|
||||||
int maxVertexTextureImageUnits;
|
|
||||||
int maxCombinedTextureImageUnits;
|
|
||||||
int maxTextureImageUnits;
|
|
||||||
int maxFragmentUniformComponents;
|
|
||||||
int maxDrawBuffers;
|
|
||||||
int maxVertexUniformVectors;
|
|
||||||
int maxVaryingVectors;
|
|
||||||
int maxFragmentUniformVectors;
|
|
||||||
int maxVertexOutputVectors;
|
|
||||||
int maxFragmentInputVectors;
|
|
||||||
int minProgramTexelOffset;
|
|
||||||
int maxProgramTexelOffset;
|
|
||||||
int maxClipDistances;
|
|
||||||
int maxComputeWorkGroupCountX;
|
|
||||||
int maxComputeWorkGroupCountY;
|
|
||||||
int maxComputeWorkGroupCountZ;
|
|
||||||
int maxComputeWorkGroupSizeX;
|
|
||||||
int maxComputeWorkGroupSizeY;
|
|
||||||
int maxComputeWorkGroupSizeZ;
|
|
||||||
int maxComputeUniformComponents;
|
|
||||||
int maxComputeTextureImageUnits;
|
|
||||||
int maxComputeImageUniforms;
|
|
||||||
int maxComputeAtomicCounters;
|
|
||||||
int maxComputeAtomicCounterBuffers;
|
|
||||||
int maxVaryingComponents;
|
|
||||||
int maxVertexOutputComponents;
|
|
||||||
int maxGeometryInputComponents;
|
|
||||||
int maxGeometryOutputComponents;
|
|
||||||
int maxFragmentInputComponents;
|
|
||||||
int maxImageUnits;
|
|
||||||
int maxCombinedImageUnitsAndFragmentOutputs;
|
|
||||||
int maxCombinedShaderOutputResources;
|
|
||||||
int maxImageSamples;
|
|
||||||
int maxVertexImageUniforms;
|
|
||||||
int maxTessControlImageUniforms;
|
|
||||||
int maxTessEvaluationImageUniforms;
|
|
||||||
int maxGeometryImageUniforms;
|
|
||||||
int maxFragmentImageUniforms;
|
|
||||||
int maxCombinedImageUniforms;
|
|
||||||
int maxGeometryTextureImageUnits;
|
|
||||||
int maxGeometryOutputVertices;
|
|
||||||
int maxGeometryTotalOutputComponents;
|
|
||||||
int maxGeometryUniformComponents;
|
|
||||||
int maxGeometryVaryingComponents;
|
|
||||||
int maxTessControlInputComponents;
|
|
||||||
int maxTessControlOutputComponents;
|
|
||||||
int maxTessControlTextureImageUnits;
|
|
||||||
int maxTessControlUniformComponents;
|
|
||||||
int maxTessControlTotalOutputComponents;
|
|
||||||
int maxTessEvaluationInputComponents;
|
|
||||||
int maxTessEvaluationOutputComponents;
|
|
||||||
int maxTessEvaluationTextureImageUnits;
|
|
||||||
int maxTessEvaluationUniformComponents;
|
|
||||||
int maxTessPatchComponents;
|
|
||||||
int maxPatchVertices;
|
|
||||||
int maxTessGenLevel;
|
|
||||||
int maxViewports;
|
|
||||||
int maxVertexAtomicCounters;
|
|
||||||
int maxTessControlAtomicCounters;
|
|
||||||
int maxTessEvaluationAtomicCounters;
|
|
||||||
int maxGeometryAtomicCounters;
|
|
||||||
int maxFragmentAtomicCounters;
|
|
||||||
int maxCombinedAtomicCounters;
|
|
||||||
int maxAtomicCounterBindings;
|
|
||||||
int maxVertexAtomicCounterBuffers;
|
|
||||||
int maxTessControlAtomicCounterBuffers;
|
|
||||||
int maxTessEvaluationAtomicCounterBuffers;
|
|
||||||
int maxGeometryAtomicCounterBuffers;
|
|
||||||
int maxFragmentAtomicCounterBuffers;
|
|
||||||
int maxCombinedAtomicCounterBuffers;
|
|
||||||
int maxAtomicCounterBufferSize;
|
|
||||||
int maxTransformFeedbackBuffers;
|
|
||||||
int maxTransformFeedbackInterleavedComponents;
|
|
||||||
int maxCullDistances;
|
|
||||||
int maxCombinedClipAndCullDistances;
|
|
||||||
int maxSamples;
|
|
||||||
int maxMeshOutputVerticesNV;
|
|
||||||
int maxMeshOutputPrimitivesNV;
|
|
||||||
int maxMeshWorkGroupSizeX_NV;
|
|
||||||
int maxMeshWorkGroupSizeY_NV;
|
|
||||||
int maxMeshWorkGroupSizeZ_NV;
|
|
||||||
int maxTaskWorkGroupSizeX_NV;
|
|
||||||
int maxTaskWorkGroupSizeY_NV;
|
|
||||||
int maxTaskWorkGroupSizeZ_NV;
|
|
||||||
int maxMeshViewCountNV;
|
|
||||||
int maxDualSourceDrawBuffersEXT;
|
|
||||||
|
|
||||||
TLimits limits;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _RESOURCE_LIMITS_INCLUDED_
|
|
|
@ -1,176 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _SHHANDLE_INCLUDED_
|
|
||||||
#define _SHHANDLE_INCLUDED_
|
|
||||||
|
|
||||||
//
|
|
||||||
// Machine independent part of the compiler private objects
|
|
||||||
// sent as ShHandle to the driver.
|
|
||||||
//
|
|
||||||
// This should not be included by driver code.
|
|
||||||
//
|
|
||||||
|
|
||||||
#define SH_EXPORTING
|
|
||||||
#include "../Public/ShaderLang.h"
|
|
||||||
#include "../MachineIndependent/Versions.h"
|
|
||||||
#include "InfoSink.h"
|
|
||||||
|
|
||||||
class TCompiler;
|
|
||||||
class TLinker;
|
|
||||||
class TUniformMap;
|
|
||||||
|
|
||||||
//
|
|
||||||
// The base class used to back handles returned to the driver.
|
|
||||||
//
|
|
||||||
class TShHandleBase {
|
|
||||||
public:
|
|
||||||
TShHandleBase() { pool = new glslang::TPoolAllocator; }
|
|
||||||
virtual ~TShHandleBase() { delete pool; }
|
|
||||||
virtual TCompiler* getAsCompiler() { return 0; }
|
|
||||||
virtual TLinker* getAsLinker() { return 0; }
|
|
||||||
virtual TUniformMap* getAsUniformMap() { return 0; }
|
|
||||||
virtual glslang::TPoolAllocator* getPool() const { return pool; }
|
|
||||||
private:
|
|
||||||
glslang::TPoolAllocator* pool;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// The base class for the machine dependent linker to derive from
|
|
||||||
// for managing where uniforms live.
|
|
||||||
//
|
|
||||||
class TUniformMap : public TShHandleBase {
|
|
||||||
public:
|
|
||||||
TUniformMap() { }
|
|
||||||
virtual ~TUniformMap() { }
|
|
||||||
virtual TUniformMap* getAsUniformMap() { return this; }
|
|
||||||
virtual int getLocation(const char* name) = 0;
|
|
||||||
virtual TInfoSink& getInfoSink() { return infoSink; }
|
|
||||||
TInfoSink infoSink;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TIntermNode;
|
|
||||||
|
|
||||||
//
|
|
||||||
// The base class for the machine dependent compiler to derive from
|
|
||||||
// for managing object code from the compile.
|
|
||||||
//
|
|
||||||
class TCompiler : public TShHandleBase {
|
|
||||||
public:
|
|
||||||
TCompiler(EShLanguage l, TInfoSink& sink) : infoSink(sink) , language(l), haveValidObjectCode(false) { }
|
|
||||||
virtual ~TCompiler() { }
|
|
||||||
EShLanguage getLanguage() { return language; }
|
|
||||||
virtual TInfoSink& getInfoSink() { return infoSink; }
|
|
||||||
|
|
||||||
virtual bool compile(TIntermNode* root, int version = 0, EProfile profile = ENoProfile) = 0;
|
|
||||||
|
|
||||||
virtual TCompiler* getAsCompiler() { return this; }
|
|
||||||
virtual bool linkable() { return haveValidObjectCode; }
|
|
||||||
|
|
||||||
TInfoSink& infoSink;
|
|
||||||
protected:
|
|
||||||
TCompiler& operator=(TCompiler&);
|
|
||||||
|
|
||||||
EShLanguage language;
|
|
||||||
bool haveValidObjectCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Link operations are based on a list of compile results...
|
|
||||||
//
|
|
||||||
typedef glslang::TVector<TCompiler*> TCompilerList;
|
|
||||||
typedef glslang::TVector<TShHandleBase*> THandleList;
|
|
||||||
|
|
||||||
//
|
|
||||||
// The base class for the machine dependent linker to derive from
|
|
||||||
// to manage the resulting executable.
|
|
||||||
//
|
|
||||||
|
|
||||||
class TLinker : public TShHandleBase {
|
|
||||||
public:
|
|
||||||
TLinker(EShExecutable e, TInfoSink& iSink) :
|
|
||||||
infoSink(iSink),
|
|
||||||
executable(e),
|
|
||||||
haveReturnableObjectCode(false),
|
|
||||||
appAttributeBindings(0),
|
|
||||||
fixedAttributeBindings(0),
|
|
||||||
excludedAttributes(0),
|
|
||||||
excludedCount(0),
|
|
||||||
uniformBindings(0) { }
|
|
||||||
virtual TLinker* getAsLinker() { return this; }
|
|
||||||
virtual ~TLinker() { }
|
|
||||||
virtual bool link(TCompilerList&, TUniformMap*) = 0;
|
|
||||||
virtual bool link(THandleList&) { return false; }
|
|
||||||
virtual void setAppAttributeBindings(const ShBindingTable* t) { appAttributeBindings = t; }
|
|
||||||
virtual void setFixedAttributeBindings(const ShBindingTable* t) { fixedAttributeBindings = t; }
|
|
||||||
virtual void getAttributeBindings(ShBindingTable const **t) const = 0;
|
|
||||||
virtual void setExcludedAttributes(const int* attributes, int count) { excludedAttributes = attributes; excludedCount = count; }
|
|
||||||
virtual ShBindingTable* getUniformBindings() const { return uniformBindings; }
|
|
||||||
virtual const void* getObjectCode() const { return 0; } // a real compiler would be returning object code here
|
|
||||||
virtual TInfoSink& getInfoSink() { return infoSink; }
|
|
||||||
TInfoSink& infoSink;
|
|
||||||
protected:
|
|
||||||
TLinker& operator=(TLinker&);
|
|
||||||
EShExecutable executable;
|
|
||||||
bool haveReturnableObjectCode; // true when objectCode is acceptable to send to driver
|
|
||||||
|
|
||||||
const ShBindingTable* appAttributeBindings;
|
|
||||||
const ShBindingTable* fixedAttributeBindings;
|
|
||||||
const int* excludedAttributes;
|
|
||||||
int excludedCount;
|
|
||||||
ShBindingTable* uniformBindings; // created by the linker
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// This is the interface between the machine independent code
|
|
||||||
// and the machine dependent code.
|
|
||||||
//
|
|
||||||
// The machine dependent code should derive from the classes
|
|
||||||
// above. Then Construct*() and Delete*() will create and
|
|
||||||
// destroy the machine dependent objects, which contain the
|
|
||||||
// above machine independent information.
|
|
||||||
//
|
|
||||||
TCompiler* ConstructCompiler(EShLanguage, int);
|
|
||||||
|
|
||||||
TShHandleBase* ConstructLinker(EShExecutable, int);
|
|
||||||
TShHandleBase* ConstructBindings();
|
|
||||||
void DeleteLinker(TShHandleBase*);
|
|
||||||
void DeleteBindingList(TShHandleBase* bindingList);
|
|
||||||
|
|
||||||
TUniformMap* ConstructUniformMap();
|
|
||||||
void DeleteCompiler(TCompiler*);
|
|
||||||
|
|
||||||
void DeleteUniformMap(TUniformMap*);
|
|
||||||
|
|
||||||
#endif // _SHHANDLE_INCLUDED_
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,341 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Implement types for tracking GLSL arrays, arrays of arrays, etc.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _ARRAYS_INCLUDED
|
|
||||||
#define _ARRAYS_INCLUDED
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
// This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else.
|
|
||||||
const int UnsizedArraySize = 0;
|
|
||||||
|
|
||||||
class TIntermTyped;
|
|
||||||
extern bool SameSpecializationConstants(TIntermTyped*, TIntermTyped*);
|
|
||||||
|
|
||||||
// Specialization constants need both a nominal size and a node that defines
|
|
||||||
// the specialization constant being used. Array types are the same when their
|
|
||||||
// size and specialization constant nodes are the same.
|
|
||||||
struct TArraySize {
|
|
||||||
unsigned int size;
|
|
||||||
TIntermTyped* node; // nullptr means no specialization constant node
|
|
||||||
bool operator==(const TArraySize& rhs) const
|
|
||||||
{
|
|
||||||
if (size != rhs.size)
|
|
||||||
return false;
|
|
||||||
if (node == nullptr || rhs.node == nullptr)
|
|
||||||
return node == rhs.node;
|
|
||||||
|
|
||||||
return SameSpecializationConstants(node, rhs.node);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// TSmallArrayVector is used as the container for the set of sizes in TArraySizes.
|
|
||||||
// It has generic-container semantics, while TArraySizes has array-of-array semantics.
|
|
||||||
// That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy.
|
|
||||||
//
|
|
||||||
struct TSmallArrayVector {
|
|
||||||
//
|
|
||||||
// TODO: memory: TSmallArrayVector is intended to be smaller.
|
|
||||||
// Almost all arrays could be handled by two sizes each fitting
|
|
||||||
// in 16 bits, needing a real vector only in the cases where there
|
|
||||||
// are more than 3 sizes or a size needing more than 16 bits.
|
|
||||||
//
|
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
|
||||||
|
|
||||||
TSmallArrayVector() : sizes(nullptr) { }
|
|
||||||
virtual ~TSmallArrayVector() { dealloc(); }
|
|
||||||
|
|
||||||
// For breaking into two non-shared copies, independently modifiable.
|
|
||||||
TSmallArrayVector& operator=(const TSmallArrayVector& from)
|
|
||||||
{
|
|
||||||
if (from.sizes == nullptr)
|
|
||||||
sizes = nullptr;
|
|
||||||
else {
|
|
||||||
alloc();
|
|
||||||
*sizes = *from.sizes;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
int size() const
|
|
||||||
{
|
|
||||||
if (sizes == nullptr)
|
|
||||||
return 0;
|
|
||||||
return (int)sizes->size();
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int frontSize() const
|
|
||||||
{
|
|
||||||
assert(sizes != nullptr && sizes->size() > 0);
|
|
||||||
return sizes->front().size;
|
|
||||||
}
|
|
||||||
|
|
||||||
TIntermTyped* frontNode() const
|
|
||||||
{
|
|
||||||
assert(sizes != nullptr && sizes->size() > 0);
|
|
||||||
return sizes->front().node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeFront(unsigned int s)
|
|
||||||
{
|
|
||||||
assert(sizes != nullptr);
|
|
||||||
// this should only happen for implicitly sized arrays, not specialization constants
|
|
||||||
assert(sizes->front().node == nullptr);
|
|
||||||
sizes->front().size = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
void push_back(unsigned int e, TIntermTyped* n)
|
|
||||||
{
|
|
||||||
alloc();
|
|
||||||
TArraySize pair = { e, n };
|
|
||||||
sizes->push_back(pair);
|
|
||||||
}
|
|
||||||
|
|
||||||
void push_back(const TSmallArrayVector& newDims)
|
|
||||||
{
|
|
||||||
alloc();
|
|
||||||
sizes->insert(sizes->end(), newDims.sizes->begin(), newDims.sizes->end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop_front()
|
|
||||||
{
|
|
||||||
assert(sizes != nullptr && sizes->size() > 0);
|
|
||||||
if (sizes->size() == 1)
|
|
||||||
dealloc();
|
|
||||||
else
|
|
||||||
sizes->erase(sizes->begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
// 'this' should currently not be holding anything, and copyNonFront
|
|
||||||
// will make it hold a copy of all but the first element of rhs.
|
|
||||||
// (This would be useful for making a type that is dereferenced by
|
|
||||||
// one dimension.)
|
|
||||||
void copyNonFront(const TSmallArrayVector& rhs)
|
|
||||||
{
|
|
||||||
assert(sizes == nullptr);
|
|
||||||
if (rhs.size() > 1) {
|
|
||||||
alloc();
|
|
||||||
sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int getDimSize(int i) const
|
|
||||||
{
|
|
||||||
assert(sizes != nullptr && (int)sizes->size() > i);
|
|
||||||
return (*sizes)[i].size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setDimSize(int i, unsigned int size) const
|
|
||||||
{
|
|
||||||
assert(sizes != nullptr && (int)sizes->size() > i);
|
|
||||||
assert((*sizes)[i].node == nullptr);
|
|
||||||
(*sizes)[i].size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
TIntermTyped* getDimNode(int i) const
|
|
||||||
{
|
|
||||||
assert(sizes != nullptr && (int)sizes->size() > i);
|
|
||||||
return (*sizes)[i].node;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const TSmallArrayVector& rhs) const
|
|
||||||
{
|
|
||||||
if (sizes == nullptr && rhs.sizes == nullptr)
|
|
||||||
return true;
|
|
||||||
if (sizes == nullptr || rhs.sizes == nullptr)
|
|
||||||
return false;
|
|
||||||
return *sizes == *rhs.sizes;
|
|
||||||
}
|
|
||||||
bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TSmallArrayVector(const TSmallArrayVector&);
|
|
||||||
|
|
||||||
void alloc()
|
|
||||||
{
|
|
||||||
if (sizes == nullptr)
|
|
||||||
sizes = new TVector<TArraySize>;
|
|
||||||
}
|
|
||||||
void dealloc()
|
|
||||||
{
|
|
||||||
delete sizes;
|
|
||||||
sizes = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
TVector<TArraySize>* sizes; // will either hold such a pointer, or in the future, hold the two array sizes
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Represent an array, or array of arrays, to arbitrary depth. This is not
|
|
||||||
// done through a hierarchy of types in a type tree, rather all contiguous arrayness
|
|
||||||
// in the type hierarchy is localized into this single cumulative object.
|
|
||||||
//
|
|
||||||
// The arrayness in TTtype is a pointer, so that it can be non-allocated and zero
|
|
||||||
// for the vast majority of types that are non-array types.
|
|
||||||
//
|
|
||||||
// Order Policy: these are all identical:
|
|
||||||
// - left to right order within a contiguous set of ...[..][..][..]... in the source language
|
|
||||||
// - index order 0, 1, 2, ... within the 'sizes' member below
|
|
||||||
// - outer-most to inner-most
|
|
||||||
//
|
|
||||||
struct TArraySizes {
|
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
|
||||||
|
|
||||||
TArraySizes() : implicitArraySize(1), variablyIndexed(false) { }
|
|
||||||
|
|
||||||
// For breaking into two non-shared copies, independently modifiable.
|
|
||||||
TArraySizes& operator=(const TArraySizes& from)
|
|
||||||
{
|
|
||||||
implicitArraySize = from.implicitArraySize;
|
|
||||||
variablyIndexed = from.variablyIndexed;
|
|
||||||
sizes = from.sizes;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// translate from array-of-array semantics to container semantics
|
|
||||||
int getNumDims() const { return sizes.size(); }
|
|
||||||
int getDimSize(int dim) const { return sizes.getDimSize(dim); }
|
|
||||||
TIntermTyped* getDimNode(int dim) const { return sizes.getDimNode(dim); }
|
|
||||||
void setDimSize(int dim, int size) { sizes.setDimSize(dim, size); }
|
|
||||||
int getOuterSize() const { return sizes.frontSize(); }
|
|
||||||
TIntermTyped* getOuterNode() const { return sizes.frontNode(); }
|
|
||||||
int getCumulativeSize() const
|
|
||||||
{
|
|
||||||
int size = 1;
|
|
||||||
for (int d = 0; d < sizes.size(); ++d) {
|
|
||||||
// this only makes sense in paths that have a known array size
|
|
||||||
assert(sizes.getDimSize(d) != UnsizedArraySize);
|
|
||||||
size *= sizes.getDimSize(d);
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
void addInnerSize() { addInnerSize((unsigned)UnsizedArraySize); }
|
|
||||||
void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); }
|
|
||||||
void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); }
|
|
||||||
void addInnerSize(TArraySize pair) {
|
|
||||||
sizes.push_back(pair.size, pair.node);
|
|
||||||
}
|
|
||||||
void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); }
|
|
||||||
void changeOuterSize(int s) { sizes.changeFront((unsigned)s); }
|
|
||||||
int getImplicitSize() const { return implicitArraySize; }
|
|
||||||
void updateImplicitSize(int s) { implicitArraySize = std::max(implicitArraySize, s); }
|
|
||||||
bool isInnerUnsized() const
|
|
||||||
{
|
|
||||||
for (int d = 1; d < sizes.size(); ++d) {
|
|
||||||
if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool clearInnerUnsized()
|
|
||||||
{
|
|
||||||
for (int d = 1; d < sizes.size(); ++d) {
|
|
||||||
if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
|
|
||||||
setDimSize(d, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool isInnerSpecialization() const
|
|
||||||
{
|
|
||||||
for (int d = 1; d < sizes.size(); ++d) {
|
|
||||||
if (sizes.getDimNode(d) != nullptr)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool isOuterSpecialization()
|
|
||||||
{
|
|
||||||
return sizes.getDimNode(0) != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); }
|
|
||||||
bool isSized() const { return getOuterSize() != UnsizedArraySize; }
|
|
||||||
void dereference() { sizes.pop_front(); }
|
|
||||||
void copyDereferenced(const TArraySizes& rhs)
|
|
||||||
{
|
|
||||||
assert(sizes.size() == 0);
|
|
||||||
if (rhs.sizes.size() > 1)
|
|
||||||
sizes.copyNonFront(rhs.sizes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sameInnerArrayness(const TArraySizes& rhs) const
|
|
||||||
{
|
|
||||||
if (sizes.size() != rhs.sizes.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (int d = 1; d < sizes.size(); ++d) {
|
|
||||||
if (sizes.getDimSize(d) != rhs.sizes.getDimSize(d) ||
|
|
||||||
sizes.getDimNode(d) != rhs.sizes.getDimNode(d))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setVariablyIndexed() { variablyIndexed = true; }
|
|
||||||
bool isVariablyIndexed() const { return variablyIndexed; }
|
|
||||||
|
|
||||||
bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; }
|
|
||||||
bool operator!=(const TArraySizes& rhs) const { return sizes != rhs.sizes; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TSmallArrayVector sizes;
|
|
||||||
|
|
||||||
TArraySizes(const TArraySizes&);
|
|
||||||
|
|
||||||
// For tracking maximum referenced compile-time constant index.
|
|
||||||
// Applies only to the outer-most dimension. Potentially becomes
|
|
||||||
// the implicit size of the array, if not variably indexed and
|
|
||||||
// otherwise legal.
|
|
||||||
int implicitArraySize;
|
|
||||||
bool variablyIndexed; // true if array is indexed with a non compile-time constant
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _ARRAYS_INCLUDED_
|
|
|
@ -1,233 +0,0 @@
|
||||||
/**
|
|
||||||
This code is based on the glslang_c_interface implementation by Viktor Latypov
|
|
||||||
**/
|
|
||||||
|
|
||||||
/**
|
|
||||||
BSD 2-Clause License
|
|
||||||
|
|
||||||
Copyright (c) 2019, Viktor Latypov
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef GLSLANG_C_IFACE_H_INCLUDED
|
|
||||||
#define GLSLANG_C_IFACE_H_INCLUDED
|
|
||||||
|
|
||||||
#include <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
|
|
||||||
|
|
||||||
int glslang_initialize_process();
|
|
||||||
void glslang_finalize_process();
|
|
||||||
|
|
||||||
glslang_shader_t* glslang_shader_create(const glslang_input_t* input);
|
|
||||||
void glslang_shader_delete(glslang_shader_t* shader);
|
|
||||||
int glslang_shader_preprocess(glslang_shader_t* shader, const glslang_input_t* input);
|
|
||||||
int glslang_shader_parse(glslang_shader_t* shader, const glslang_input_t* input);
|
|
||||||
const char* glslang_shader_get_preprocessed_code(glslang_shader_t* shader);
|
|
||||||
const char* glslang_shader_get_info_log(glslang_shader_t* shader);
|
|
||||||
const char* glslang_shader_get_info_debug_log(glslang_shader_t* shader);
|
|
||||||
|
|
||||||
glslang_program_t* glslang_program_create();
|
|
||||||
void glslang_program_delete(glslang_program_t* program);
|
|
||||||
void glslang_program_add_shader(glslang_program_t* program, glslang_shader_t* shader);
|
|
||||||
int glslang_program_link(glslang_program_t* program, int messages); // glslang_messages_t
|
|
||||||
void glslang_program_SPIRV_generate(glslang_program_t* program, glslang_stage_t stage);
|
|
||||||
size_t glslang_program_SPIRV_get_size(glslang_program_t* program);
|
|
||||||
void glslang_program_SPIRV_get(glslang_program_t* program, unsigned int*);
|
|
||||||
unsigned int* glslang_program_SPIRV_get_ptr(glslang_program_t* program);
|
|
||||||
const char* glslang_program_SPIRV_get_messages(glslang_program_t* program);
|
|
||||||
const char* glslang_program_get_info_log(glslang_program_t* program);
|
|
||||||
const char* glslang_program_get_info_debug_log(glslang_program_t* program);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* #ifdef GLSLANG_C_IFACE_INCLUDED */
|
|
|
@ -1,183 +0,0 @@
|
||||||
/**
|
|
||||||
This code is based on the glslang_c_interface implementation by Viktor Latypov
|
|
||||||
**/
|
|
||||||
|
|
||||||
/**
|
|
||||||
BSD 2-Clause License
|
|
||||||
|
|
||||||
Copyright (c) 2019, Viktor Latypov
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**/
|
|
||||||
|
|
||||||
#ifndef C_SHADER_TYPES_H_INCLUDED
|
|
||||||
#define C_SHADER_TYPES_H_INCLUDED
|
|
||||||
|
|
||||||
#define LAST_ELEMENT_MARKER(x) x
|
|
||||||
|
|
||||||
/* EShLanguage counterpart */
|
|
||||||
typedef enum {
|
|
||||||
GLSLANG_STAGE_VERTEX,
|
|
||||||
GLSLANG_STAGE_TESSCONTROL,
|
|
||||||
GLSLANG_STAGE_TESSEVALUATION,
|
|
||||||
GLSLANG_STAGE_GEOMETRY,
|
|
||||||
GLSLANG_STAGE_FRAGMENT,
|
|
||||||
GLSLANG_STAGE_COMPUTE,
|
|
||||||
GLSLANG_STAGE_RAYGEN_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_OPENGL_450 = 450,
|
|
||||||
LAST_ELEMENT_MARKER(GLSLANG_TARGET_CLIENT_VERSION_COUNT),
|
|
||||||
} 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),
|
|
||||||
LAST_ELEMENT_MARKER(GLSLANG_TARGET_LANGUAGE_VERSION_COUNT),
|
|
||||||
} glslang_target_language_version_t;
|
|
||||||
|
|
||||||
/* EShExecutable counterpart */
|
|
||||||
typedef enum { GLSLANG_EX_VERTEX_FRAGMENT, GLSLANG_EX_FRAGMENT } glslang_executable_t;
|
|
||||||
|
|
||||||
/* EShOptimizationLevel counterpart */
|
|
||||||
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),
|
|
||||||
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_SHARED_STD140_BLOCKS_BIT = (1 << 6),
|
|
||||||
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;
|
|
||||||
|
|
||||||
#undef LAST_ELEMENT_MARKER
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,3 +0,0 @@
|
||||||
// This header is generated by the make-revision script.
|
|
||||||
|
|
||||||
#define GLSLANG_PATCH_LEVEL 3766
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,113 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "../Include/InfoSink.h"
|
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
void TInfoSinkBase::append(const char* s)
|
|
||||||
{
|
|
||||||
if (outputStream & EString) {
|
|
||||||
if (s == nullptr)
|
|
||||||
sink.append("(null)");
|
|
||||||
else {
|
|
||||||
checkMem(strlen(s));
|
|
||||||
sink.append(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//#ifdef _WIN32
|
|
||||||
// if (outputStream & EDebugger)
|
|
||||||
// OutputDebugString(s);
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
if (outputStream & EStdOut)
|
|
||||||
fprintf(stdout, "%s", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TInfoSinkBase::append(int count, char c)
|
|
||||||
{
|
|
||||||
if (outputStream & EString) {
|
|
||||||
checkMem(count);
|
|
||||||
sink.append(count, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
//#ifdef _WIN32
|
|
||||||
// if (outputStream & EDebugger) {
|
|
||||||
// char str[2];
|
|
||||||
// str[0] = c;
|
|
||||||
// str[1] = '\0';
|
|
||||||
// OutputDebugString(str);
|
|
||||||
// }
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
if (outputStream & EStdOut)
|
|
||||||
fprintf(stdout, "%c", c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TInfoSinkBase::append(const TPersistString& t)
|
|
||||||
{
|
|
||||||
if (outputStream & EString) {
|
|
||||||
checkMem(t.size());
|
|
||||||
sink.append(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
//#ifdef _WIN32
|
|
||||||
// if (outputStream & EDebugger)
|
|
||||||
// OutputDebugString(t.c_str());
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
if (outputStream & EStdOut)
|
|
||||||
fprintf(stdout, "%s", t.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void TInfoSinkBase::append(const TString& t)
|
|
||||||
{
|
|
||||||
if (outputStream & EString) {
|
|
||||||
checkMem(t.size());
|
|
||||||
sink.append(t.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
//#ifdef _WIN32
|
|
||||||
// if (outputStream & EDebugger)
|
|
||||||
// OutputDebugString(t.c_str());
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
if (outputStream & EStdOut)
|
|
||||||
fprintf(stdout, "%s", t.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,112 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2013-2016 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _INITIALIZE_INCLUDED_
|
|
||||||
#define _INITIALIZE_INCLUDED_
|
|
||||||
|
|
||||||
#include "../Include/ResourceLimits.h"
|
|
||||||
#include "../Include/Common.h"
|
|
||||||
#include "../Include/ShHandle.h"
|
|
||||||
#include "SymbolTable.h"
|
|
||||||
#include "Versions.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// This is made to hold parseable strings for almost all the built-in
|
|
||||||
// functions and variables for one specific combination of version
|
|
||||||
// and profile. (Some still need to be added programmatically.)
|
|
||||||
// This is a base class for language-specific derivations, which
|
|
||||||
// can be used for language independent builtins.
|
|
||||||
//
|
|
||||||
// The strings are organized by
|
|
||||||
// commonBuiltins: intersection of all stages' built-ins, processed just once
|
|
||||||
// stageBuiltins[]: anything a stage needs that's not in commonBuiltins
|
|
||||||
//
|
|
||||||
class TBuiltInParseables {
|
|
||||||
public:
|
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
|
||||||
TBuiltInParseables();
|
|
||||||
virtual ~TBuiltInParseables();
|
|
||||||
virtual void initialize(int version, EProfile, const SpvVersion& spvVersion) = 0;
|
|
||||||
virtual void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage) = 0;
|
|
||||||
virtual const TString& getCommonString() const { return commonBuiltins; }
|
|
||||||
virtual const TString& getStageString(EShLanguage language) const { return stageBuiltins[language]; }
|
|
||||||
|
|
||||||
virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) = 0;
|
|
||||||
virtual void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TString commonBuiltins;
|
|
||||||
TString stageBuiltins[EShLangCount];
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// This is a GLSL specific derivation of TBuiltInParseables. To present a stable
|
|
||||||
// interface and match other similar code, it is called TBuiltIns, rather
|
|
||||||
// than TBuiltInParseablesGlsl.
|
|
||||||
//
|
|
||||||
class TBuiltIns : public TBuiltInParseables {
|
|
||||||
public:
|
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
|
||||||
TBuiltIns();
|
|
||||||
virtual ~TBuiltIns();
|
|
||||||
void initialize(int version, EProfile, const SpvVersion& spvVersion);
|
|
||||||
void initialize(const TBuiltInResource& resources, int version, EProfile, const SpvVersion& spvVersion, EShLanguage);
|
|
||||||
|
|
||||||
void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable);
|
|
||||||
void identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion);
|
|
||||||
void relateTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage, TSymbolTable&);
|
|
||||||
void add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion);
|
|
||||||
void addSubpassSampling(TSampler, const TString& typeName, int version, EProfile profile);
|
|
||||||
void addQueryFunctions(TSampler, const TString& typeName, int version, EProfile profile);
|
|
||||||
void addImageFunctions(TSampler, const TString& typeName, int version, EProfile profile);
|
|
||||||
void addSamplingFunctions(TSampler, const TString& typeName, int version, EProfile profile);
|
|
||||||
void addGatherFunctions(TSampler, const TString& typeName, int version, EProfile profile);
|
|
||||||
|
|
||||||
// Helpers for making textual representations of the permutations
|
|
||||||
// of texturing/imaging functions.
|
|
||||||
const char* postfixes[5];
|
|
||||||
const char* prefixes[EbtNumTypes];
|
|
||||||
int dimMap[EsdNumDims];
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _INITIALIZE_INCLUDED_
|
|
|
@ -1,302 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
// Copyright (c) 2002-2010 The ANGLE Project Authors.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "../Include/intermediate.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Traverse the intermediate representation tree, and
|
|
||||||
// call a node type specific function for each node.
|
|
||||||
// Done recursively through the member function Traverse().
|
|
||||||
// Node types can be skipped if their function to call is 0,
|
|
||||||
// but their subtree will still be traversed.
|
|
||||||
// Nodes with children can have their whole subtree skipped
|
|
||||||
// if preVisit is turned on and the type specific function
|
|
||||||
// returns false.
|
|
||||||
//
|
|
||||||
// preVisit, postVisit, and rightToLeft control what order
|
|
||||||
// nodes are visited in.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Traversal functions for terminals are straightforward....
|
|
||||||
//
|
|
||||||
void TIntermMethod::traverse(TIntermTraverser*)
|
|
||||||
{
|
|
||||||
// Tree should always resolve all methods as a non-method.
|
|
||||||
}
|
|
||||||
|
|
||||||
void TIntermSymbol::traverse(TIntermTraverser *it)
|
|
||||||
{
|
|
||||||
it->visitSymbol(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TIntermConstantUnion::traverse(TIntermTraverser *it)
|
|
||||||
{
|
|
||||||
it->visitConstantUnion(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Traverse a binary node.
|
|
||||||
//
|
|
||||||
void TIntermBinary::traverse(TIntermTraverser *it)
|
|
||||||
{
|
|
||||||
bool visit = true;
|
|
||||||
|
|
||||||
//
|
|
||||||
// visit the node before children if pre-visiting.
|
|
||||||
//
|
|
||||||
if (it->preVisit)
|
|
||||||
visit = it->visitBinary(EvPreVisit, this);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Visit the children, in the right order.
|
|
||||||
//
|
|
||||||
if (visit) {
|
|
||||||
it->incrementDepth(this);
|
|
||||||
|
|
||||||
if (it->rightToLeft) {
|
|
||||||
if (right)
|
|
||||||
right->traverse(it);
|
|
||||||
|
|
||||||
if (it->inVisit)
|
|
||||||
visit = it->visitBinary(EvInVisit, this);
|
|
||||||
|
|
||||||
if (visit && left)
|
|
||||||
left->traverse(it);
|
|
||||||
} else {
|
|
||||||
if (left)
|
|
||||||
left->traverse(it);
|
|
||||||
|
|
||||||
if (it->inVisit)
|
|
||||||
visit = it->visitBinary(EvInVisit, this);
|
|
||||||
|
|
||||||
if (visit && right)
|
|
||||||
right->traverse(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
it->decrementDepth();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Visit the node after the children, if requested and the traversal
|
|
||||||
// hasn't been canceled yet.
|
|
||||||
//
|
|
||||||
if (visit && it->postVisit)
|
|
||||||
it->visitBinary(EvPostVisit, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Traverse a unary node. Same comments in binary node apply here.
|
|
||||||
//
|
|
||||||
void TIntermUnary::traverse(TIntermTraverser *it)
|
|
||||||
{
|
|
||||||
bool visit = true;
|
|
||||||
|
|
||||||
if (it->preVisit)
|
|
||||||
visit = it->visitUnary(EvPreVisit, this);
|
|
||||||
|
|
||||||
if (visit) {
|
|
||||||
it->incrementDepth(this);
|
|
||||||
operand->traverse(it);
|
|
||||||
it->decrementDepth();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visit && it->postVisit)
|
|
||||||
it->visitUnary(EvPostVisit, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Traverse an aggregate node. Same comments in binary node apply here.
|
|
||||||
//
|
|
||||||
void TIntermAggregate::traverse(TIntermTraverser *it)
|
|
||||||
{
|
|
||||||
bool visit = true;
|
|
||||||
|
|
||||||
if (it->preVisit)
|
|
||||||
visit = it->visitAggregate(EvPreVisit, this);
|
|
||||||
|
|
||||||
if (visit) {
|
|
||||||
it->incrementDepth(this);
|
|
||||||
|
|
||||||
if (it->rightToLeft) {
|
|
||||||
for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) {
|
|
||||||
(*sit)->traverse(it);
|
|
||||||
|
|
||||||
if (visit && it->inVisit) {
|
|
||||||
if (*sit != sequence.front())
|
|
||||||
visit = it->visitAggregate(EvInVisit, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) {
|
|
||||||
(*sit)->traverse(it);
|
|
||||||
|
|
||||||
if (visit && it->inVisit) {
|
|
||||||
if (*sit != sequence.back())
|
|
||||||
visit = it->visitAggregate(EvInVisit, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
it->decrementDepth();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visit && it->postVisit)
|
|
||||||
it->visitAggregate(EvPostVisit, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Traverse a selection node. Same comments in binary node apply here.
|
|
||||||
//
|
|
||||||
void TIntermSelection::traverse(TIntermTraverser *it)
|
|
||||||
{
|
|
||||||
bool visit = true;
|
|
||||||
|
|
||||||
if (it->preVisit)
|
|
||||||
visit = it->visitSelection(EvPreVisit, this);
|
|
||||||
|
|
||||||
if (visit) {
|
|
||||||
it->incrementDepth(this);
|
|
||||||
if (it->rightToLeft) {
|
|
||||||
if (falseBlock)
|
|
||||||
falseBlock->traverse(it);
|
|
||||||
if (trueBlock)
|
|
||||||
trueBlock->traverse(it);
|
|
||||||
condition->traverse(it);
|
|
||||||
} else {
|
|
||||||
condition->traverse(it);
|
|
||||||
if (trueBlock)
|
|
||||||
trueBlock->traverse(it);
|
|
||||||
if (falseBlock)
|
|
||||||
falseBlock->traverse(it);
|
|
||||||
}
|
|
||||||
it->decrementDepth();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visit && it->postVisit)
|
|
||||||
it->visitSelection(EvPostVisit, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Traverse a loop node. Same comments in binary node apply here.
|
|
||||||
//
|
|
||||||
void TIntermLoop::traverse(TIntermTraverser *it)
|
|
||||||
{
|
|
||||||
bool visit = true;
|
|
||||||
|
|
||||||
if (it->preVisit)
|
|
||||||
visit = it->visitLoop(EvPreVisit, this);
|
|
||||||
|
|
||||||
if (visit) {
|
|
||||||
it->incrementDepth(this);
|
|
||||||
|
|
||||||
if (it->rightToLeft) {
|
|
||||||
if (terminal)
|
|
||||||
terminal->traverse(it);
|
|
||||||
|
|
||||||
if (body)
|
|
||||||
body->traverse(it);
|
|
||||||
|
|
||||||
if (test)
|
|
||||||
test->traverse(it);
|
|
||||||
} else {
|
|
||||||
if (test)
|
|
||||||
test->traverse(it);
|
|
||||||
|
|
||||||
if (body)
|
|
||||||
body->traverse(it);
|
|
||||||
|
|
||||||
if (terminal)
|
|
||||||
terminal->traverse(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
it->decrementDepth();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visit && it->postVisit)
|
|
||||||
it->visitLoop(EvPostVisit, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Traverse a branch node. Same comments in binary node apply here.
|
|
||||||
//
|
|
||||||
void TIntermBranch::traverse(TIntermTraverser *it)
|
|
||||||
{
|
|
||||||
bool visit = true;
|
|
||||||
|
|
||||||
if (it->preVisit)
|
|
||||||
visit = it->visitBranch(EvPreVisit, this);
|
|
||||||
|
|
||||||
if (visit && expression) {
|
|
||||||
it->incrementDepth(this);
|
|
||||||
expression->traverse(it);
|
|
||||||
it->decrementDepth();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visit && it->postVisit)
|
|
||||||
it->visitBranch(EvPostVisit, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Traverse a switch node.
|
|
||||||
//
|
|
||||||
void TIntermSwitch::traverse(TIntermTraverser* it)
|
|
||||||
{
|
|
||||||
bool visit = true;
|
|
||||||
|
|
||||||
if (it->preVisit)
|
|
||||||
visit = it->visitSwitch(EvPreVisit, this);
|
|
||||||
|
|
||||||
if (visit) {
|
|
||||||
it->incrementDepth(this);
|
|
||||||
if (it->rightToLeft) {
|
|
||||||
body->traverse(it);
|
|
||||||
condition->traverse(it);
|
|
||||||
} else {
|
|
||||||
condition->traverse(it);
|
|
||||||
body->traverse(it);
|
|
||||||
}
|
|
||||||
it->decrementDepth();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visit && it->postVisit)
|
|
||||||
it->visitSwitch(EvPostVisit, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,138 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2016 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "../Include/Common.h"
|
|
||||||
#include "reflection.h"
|
|
||||||
#include "localintermediate.h"
|
|
||||||
|
|
||||||
#include "gl_types.h"
|
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// The traverser: mostly pass through, except
|
|
||||||
// - processing function-call nodes to push live functions onto the stack of functions to process
|
|
||||||
// - processing selection nodes to trim semantically dead code
|
|
||||||
//
|
|
||||||
// This is in the glslang namespace directly so it can be a friend of TReflection.
|
|
||||||
// This can be derived from to implement reflection database traversers or
|
|
||||||
// binding mappers: anything that wants to traverse the live subset of the tree.
|
|
||||||
//
|
|
||||||
|
|
||||||
class TLiveTraverser : public TIntermTraverser {
|
|
||||||
public:
|
|
||||||
TLiveTraverser(const TIntermediate& i, bool traverseAll = false,
|
|
||||||
bool preVisit = true, bool inVisit = false, bool postVisit = false) :
|
|
||||||
TIntermTraverser(preVisit, inVisit, postVisit),
|
|
||||||
intermediate(i), traverseAll(traverseAll)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
//
|
|
||||||
// Given a function name, find its subroot in the tree, and push it onto the stack of
|
|
||||||
// functions left to process.
|
|
||||||
//
|
|
||||||
void pushFunction(const TString& name)
|
|
||||||
{
|
|
||||||
TIntermSequence& globals = intermediate.getTreeRoot()->getAsAggregate()->getSequence();
|
|
||||||
for (unsigned int f = 0; f < globals.size(); ++f) {
|
|
||||||
TIntermAggregate* candidate = globals[f]->getAsAggregate();
|
|
||||||
if (candidate && candidate->getOp() == EOpFunction && candidate->getName() == name) {
|
|
||||||
functions.push_back(candidate);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef std::list<TIntermAggregate*> TFunctionStack;
|
|
||||||
TFunctionStack functions;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// To catch which function calls are not dead, and hence which functions must be visited.
|
|
||||||
virtual bool visitAggregate(TVisit, TIntermAggregate* node)
|
|
||||||
{
|
|
||||||
if (!traverseAll)
|
|
||||||
if (node->getOp() == EOpFunctionCall)
|
|
||||||
addFunctionCall(node);
|
|
||||||
|
|
||||||
return true; // traverse this subtree
|
|
||||||
}
|
|
||||||
|
|
||||||
// To prune semantically dead paths.
|
|
||||||
virtual bool visitSelection(TVisit /* visit */, TIntermSelection* node)
|
|
||||||
{
|
|
||||||
if (traverseAll)
|
|
||||||
return true; // traverse all code
|
|
||||||
|
|
||||||
TIntermConstantUnion* constant = node->getCondition()->getAsConstantUnion();
|
|
||||||
if (constant) {
|
|
||||||
// cull the path that is dead
|
|
||||||
if (constant->getConstArray()[0].getBConst() == true && node->getTrueBlock())
|
|
||||||
node->getTrueBlock()->traverse(this);
|
|
||||||
if (constant->getConstArray()[0].getBConst() == false && node->getFalseBlock())
|
|
||||||
node->getFalseBlock()->traverse(this);
|
|
||||||
|
|
||||||
return false; // don't traverse any more, we did it all above
|
|
||||||
} else
|
|
||||||
return true; // traverse the whole subtree
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track live functions as well as uniforms, so that we don't visit dead functions
|
|
||||||
// and only visit each function once.
|
|
||||||
void addFunctionCall(TIntermAggregate* call)
|
|
||||||
{
|
|
||||||
// // just use the map to ensure we process each function at most once
|
|
||||||
if (liveFunctions.find(call->getName()) == liveFunctions.end()) {
|
|
||||||
liveFunctions.insert(call->getName());
|
|
||||||
pushFunction(call->getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const TIntermediate& intermediate;
|
|
||||||
typedef std::unordered_set<TString> TLiveFunctions;
|
|
||||||
TLiveFunctions liveFunctions;
|
|
||||||
bool traverseAll;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// prevent copy & copy construct
|
|
||||||
TLiveTraverser(TLiveTraverser&);
|
|
||||||
TLiveTraverser& operator=(TLiveTraverser&);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace glslang
|
|
|
@ -1,641 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2016 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
// Implement the TParseContextBase class.
|
|
||||||
|
|
||||||
#include <cstdarg>
|
|
||||||
|
|
||||||
#include "ParseHelper.h"
|
|
||||||
|
|
||||||
extern int yyparse(glslang::TParseContext*);
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Used to output syntax, parsing, and semantic errors.
|
|
||||||
//
|
|
||||||
|
|
||||||
void TParseContextBase::outputMessage(const TSourceLoc& loc, const char* szReason,
|
|
||||||
const char* szToken,
|
|
||||||
const char* szExtraInfoFormat,
|
|
||||||
TPrefixType prefix, va_list args)
|
|
||||||
{
|
|
||||||
const int maxSize = MaxTokenLength + 200;
|
|
||||||
char szExtraInfo[maxSize];
|
|
||||||
|
|
||||||
safe_vsprintf(szExtraInfo, maxSize, szExtraInfoFormat, args);
|
|
||||||
|
|
||||||
infoSink.info.prefix(prefix);
|
|
||||||
infoSink.info.location(loc);
|
|
||||||
infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n";
|
|
||||||
|
|
||||||
if (prefix == EPrefixError) {
|
|
||||||
++numErrors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL)
|
|
||||||
|
|
||||||
void C_DECL TParseContextBase::error(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...)
|
|
||||||
{
|
|
||||||
if (messages & EShMsgOnlyPreprocessor)
|
|
||||||
return;
|
|
||||||
va_list args;
|
|
||||||
va_start(args, szExtraInfoFormat);
|
|
||||||
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
if ((messages & EShMsgCascadingErrors) == 0)
|
|
||||||
currentScanner->setEndOfInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
void C_DECL TParseContextBase::warn(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...)
|
|
||||||
{
|
|
||||||
if (suppressWarnings())
|
|
||||||
return;
|
|
||||||
va_list args;
|
|
||||||
va_start(args, szExtraInfoFormat);
|
|
||||||
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
void C_DECL TParseContextBase::ppError(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, szExtraInfoFormat);
|
|
||||||
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixError, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
if ((messages & EShMsgCascadingErrors) == 0)
|
|
||||||
currentScanner->setEndOfInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, szExtraInfoFormat);
|
|
||||||
outputMessage(loc, szReason, szToken, szExtraInfoFormat, EPrefixWarning, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Both test and if necessary, spit out an error, to see if the node is really
|
|
||||||
// an l-value that can be operated on this way.
|
|
||||||
//
|
|
||||||
// Returns true if there was an error.
|
|
||||||
//
|
|
||||||
bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
|
|
||||||
{
|
|
||||||
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
|
||||||
|
|
||||||
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;
|
|
||||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
|
||||||
if (symNode != nullptr)
|
|
||||||
symbol = symNode->getName().c_str();
|
|
||||||
|
|
||||||
const char* message = nullptr;
|
|
||||||
switch (node->getQualifier().storage) {
|
|
||||||
case EvqConst: message = "can't modify a const"; break;
|
|
||||||
case EvqConstReadOnly: message = "can't modify a const"; break;
|
|
||||||
case EvqUniform: message = "can't modify a uniform"; break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EvqBuffer:
|
|
||||||
if (node->getQualifier().isReadOnly())
|
|
||||||
message = "can't modify a readonly buffer";
|
|
||||||
if (node->getQualifier().isShaderRecord())
|
|
||||||
message = "can't modify a shaderrecordnv qualified buffer";
|
|
||||||
break;
|
|
||||||
case EvqHitAttr:
|
|
||||||
if (language != EShLangIntersect)
|
|
||||||
message = "cannot modify hitAttributeNV in this stage";
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
//
|
|
||||||
// Type that can't be written to?
|
|
||||||
//
|
|
||||||
switch (node->getBasicType()) {
|
|
||||||
case EbtSampler:
|
|
||||||
message = "can't modify a sampler";
|
|
||||||
break;
|
|
||||||
case EbtVoid:
|
|
||||||
message = "can't modify void";
|
|
||||||
break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtAtomicUint:
|
|
||||||
message = "can't modify an atomic_uint";
|
|
||||||
break;
|
|
||||||
case EbtAccStruct:
|
|
||||||
message = "can't modify accelerationStructureNV";
|
|
||||||
break;
|
|
||||||
case EbtRayQuery:
|
|
||||||
message = "can't modify rayQueryEXT";
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
|
|
||||||
error(loc, " l-value required", op, "", "");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Everything else is okay, no error.
|
|
||||||
//
|
|
||||||
if (message == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
//
|
|
||||||
// If we get here, we have an error and a message.
|
|
||||||
//
|
|
||||||
if (symNode)
|
|
||||||
error(loc, " l-value required", op, "\"%s\" (%s)", symbol, message);
|
|
||||||
else
|
|
||||||
error(loc, " l-value required", op, "(%s)", message);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test for and give an error if the node can't be read from.
|
|
||||||
void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
|
|
||||||
{
|
|
||||||
if (! node)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
|
||||||
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
|
|
||||||
// are later processed in finish(), at which point the symbol
|
|
||||||
// must still be valid.
|
|
||||||
// It is okay if the symbol's type will be subsequently edited;
|
|
||||||
// the modifications will be tracked.
|
|
||||||
// Order is preserved, to avoid creating novel forward references.
|
|
||||||
void TParseContextBase::trackLinkage(TSymbol& symbol)
|
|
||||||
{
|
|
||||||
if (!parsingBuiltins)
|
|
||||||
linkageSymbols.push_back(&symbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure index is in bounds, correct if necessary.
|
|
||||||
// Give an error if not.
|
|
||||||
void TParseContextBase::checkIndex(const TSourceLoc& loc, const TType& type, int& index)
|
|
||||||
{
|
|
||||||
const auto sizeIsSpecializationExpression = [&type]() {
|
|
||||||
return type.containsSpecializationSize() &&
|
|
||||||
type.getArraySizes()->getOuterNode() != nullptr &&
|
|
||||||
type.getArraySizes()->getOuterNode()->getAsSymbolNode() == nullptr; };
|
|
||||||
|
|
||||||
if (index < 0) {
|
|
||||||
error(loc, "", "[", "index out of range '%d'", index);
|
|
||||||
index = 0;
|
|
||||||
} else if (type.isArray()) {
|
|
||||||
if (type.isSizedArray() && !sizeIsSpecializationExpression() &&
|
|
||||||
index >= type.getOuterArraySize()) {
|
|
||||||
error(loc, "", "[", "array index out of range '%d'", index);
|
|
||||||
index = type.getOuterArraySize() - 1;
|
|
||||||
}
|
|
||||||
} else if (type.isVector()) {
|
|
||||||
if (index >= type.getVectorSize()) {
|
|
||||||
error(loc, "", "[", "vector index out of range '%d'", index);
|
|
||||||
index = type.getVectorSize() - 1;
|
|
||||||
}
|
|
||||||
} else if (type.isMatrix()) {
|
|
||||||
if (index >= type.getMatrixCols()) {
|
|
||||||
error(loc, "", "[", "matrix index out of range '%d'", index);
|
|
||||||
index = type.getMatrixCols() - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a shared symbol have a non-shared version that can be edited by the current
|
|
||||||
// compile, such that editing its type will not change the shared version and will
|
|
||||||
// effect all nodes already sharing it (non-shallow type),
|
|
||||||
// or adopting its full type after being edited (shallow type).
|
|
||||||
void TParseContextBase::makeEditable(TSymbol*& symbol)
|
|
||||||
{
|
|
||||||
// copyUp() does a deep copy of the type.
|
|
||||||
symbol = symbolTable.copyUp(symbol);
|
|
||||||
|
|
||||||
// Save it (deferred, so it can be edited first) in the AST for linker use.
|
|
||||||
if (symbol)
|
|
||||||
trackLinkage(*symbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return a writable version of the variable 'name'.
|
|
||||||
//
|
|
||||||
// Return nullptr if 'name' is not found. This should mean
|
|
||||||
// something is seriously wrong (e.g., compiler asking self for
|
|
||||||
// built-in that doesn't exist).
|
|
||||||
TVariable* TParseContextBase::getEditableVariable(const char* name)
|
|
||||||
{
|
|
||||||
bool builtIn;
|
|
||||||
TSymbol* symbol = symbolTable.find(name, &builtIn);
|
|
||||||
|
|
||||||
assert(symbol != nullptr);
|
|
||||||
if (symbol == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (builtIn)
|
|
||||||
makeEditable(symbol);
|
|
||||||
|
|
||||||
return symbol->getAsVariable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select the best matching function for 'call' from 'candidateList'.
|
|
||||||
//
|
|
||||||
// Assumptions
|
|
||||||
//
|
|
||||||
// There is no exact match, so a selection algorithm needs to run. That is, the
|
|
||||||
// language-specific handler should check for exact match first, to
|
|
||||||
// decide what to do, before calling this selector.
|
|
||||||
//
|
|
||||||
// Input
|
|
||||||
//
|
|
||||||
// * list of candidate signatures to select from
|
|
||||||
// * the call
|
|
||||||
// * a predicate function convertible(from, to) that says whether or not type
|
|
||||||
// 'from' can implicitly convert to type 'to' (it includes the case of what
|
|
||||||
// the calling language would consider a matching type with no conversion
|
|
||||||
// needed)
|
|
||||||
// * a predicate function better(from1, from2, to1, to2) that says whether or
|
|
||||||
// not a conversion from <-> to2 is considered better than a conversion
|
|
||||||
// from <-> to1 (both in and out directions need testing, as declared by the
|
|
||||||
// formal parameter)
|
|
||||||
//
|
|
||||||
// Output
|
|
||||||
//
|
|
||||||
// * best matching candidate (or none, if no viable candidates found)
|
|
||||||
// * whether there was a tie for the best match (ambiguous overload selection,
|
|
||||||
// caller's choice for how to report)
|
|
||||||
//
|
|
||||||
const TFunction* TParseContextBase::selectFunction(
|
|
||||||
const TVector<const TFunction*> candidateList,
|
|
||||||
const TFunction& call,
|
|
||||||
std::function<bool(const TType& from, const TType& to, TOperator op, int arg)> convertible,
|
|
||||||
std::function<bool(const TType& from, const TType& to1, const TType& to2)> better,
|
|
||||||
/* output */ bool& tie)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Operation
|
|
||||||
//
|
|
||||||
// 1. Prune the input list of candidates down to a list of viable candidates,
|
|
||||||
// where each viable candidate has
|
|
||||||
//
|
|
||||||
// * at least as many parameters as there are calling arguments, with any
|
|
||||||
// remaining parameters being optional or having default values
|
|
||||||
// * each parameter is true under convertible(A, B), where A is the calling
|
|
||||||
// type for in and B is the formal type, and in addition, for out B is the
|
|
||||||
// calling type and A is the formal type
|
|
||||||
//
|
|
||||||
// 2. If there are no viable candidates, return with no match.
|
|
||||||
//
|
|
||||||
// 3. If there is only one viable candidate, it is the best match.
|
|
||||||
//
|
|
||||||
// 4. If there are multiple viable candidates, select the first viable candidate
|
|
||||||
// as the incumbent. Compare the incumbent to the next viable candidate, and if
|
|
||||||
// that candidate is better (bullets below), make it the incumbent. Repeat, with
|
|
||||||
// a linear walk through the viable candidate list. The final incumbent will be
|
|
||||||
// returned as the best match. A viable candidate is better than the incumbent if
|
|
||||||
//
|
|
||||||
// * it has a function argument with a better(...) conversion than the incumbent,
|
|
||||||
// for all directions needed by in and out
|
|
||||||
// * the incumbent has no argument with a better(...) conversion then the
|
|
||||||
// candidate, for either in or out (as needed)
|
|
||||||
//
|
|
||||||
// 5. Check for ambiguity by comparing the best match against all other viable
|
|
||||||
// candidates. If any other viable candidate has a function argument with a
|
|
||||||
// better(...) conversion than the best candidate (for either in or out
|
|
||||||
// directions), return that there was a tie for best.
|
|
||||||
//
|
|
||||||
|
|
||||||
tie = false;
|
|
||||||
|
|
||||||
// 1. prune to viable...
|
|
||||||
TVector<const TFunction*> viableCandidates;
|
|
||||||
for (auto it = candidateList.begin(); it != candidateList.end(); ++it) {
|
|
||||||
const TFunction& candidate = *(*it);
|
|
||||||
|
|
||||||
// to even be a potential match, number of arguments must be >= the number of
|
|
||||||
// fixed (non-default) parameters, and <= the total (including parameter with defaults).
|
|
||||||
if (call.getParamCount() < candidate.getFixedParamCount() ||
|
|
||||||
call.getParamCount() > candidate.getParamCount())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// see if arguments are convertible
|
|
||||||
bool viable = true;
|
|
||||||
|
|
||||||
// The call can have fewer parameters than the candidate, if some have defaults.
|
|
||||||
const int paramCount = std::min(call.getParamCount(), candidate.getParamCount());
|
|
||||||
for (int param = 0; param < paramCount; ++param) {
|
|
||||||
if (candidate[param].type->getQualifier().isParamInput()) {
|
|
||||||
if (! convertible(*call[param].type, *candidate[param].type, candidate.getBuiltInOp(), param)) {
|
|
||||||
viable = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (candidate[param].type->getQualifier().isParamOutput()) {
|
|
||||||
if (! convertible(*candidate[param].type, *call[param].type, candidate.getBuiltInOp(), param)) {
|
|
||||||
viable = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (viable)
|
|
||||||
viableCandidates.push_back(&candidate);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. none viable...
|
|
||||||
if (viableCandidates.size() == 0)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// 3. only one viable...
|
|
||||||
if (viableCandidates.size() == 1)
|
|
||||||
return viableCandidates.front();
|
|
||||||
|
|
||||||
// 4. find best...
|
|
||||||
const auto betterParam = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
|
|
||||||
// is call -> can2 better than call -> can1 for any parameter
|
|
||||||
bool hasBetterParam = false;
|
|
||||||
for (int param = 0; param < call.getParamCount(); ++param) {
|
|
||||||
if (better(*call[param].type, *can1[param].type, *can2[param].type)) {
|
|
||||||
hasBetterParam = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hasBetterParam;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto equivalentParams = [&call, &better](const TFunction& can1, const TFunction& can2) -> bool {
|
|
||||||
// is call -> can2 equivalent to call -> can1 for all the call parameters?
|
|
||||||
for (int param = 0; param < call.getParamCount(); ++param) {
|
|
||||||
if (better(*call[param].type, *can1[param].type, *can2[param].type) ||
|
|
||||||
better(*call[param].type, *can2[param].type, *can1[param].type))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const TFunction* incumbent = viableCandidates.front();
|
|
||||||
for (auto it = viableCandidates.begin() + 1; it != viableCandidates.end(); ++it) {
|
|
||||||
const TFunction& candidate = *(*it);
|
|
||||||
if (betterParam(*incumbent, candidate) && ! betterParam(candidate, *incumbent))
|
|
||||||
incumbent = &candidate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. ambiguity...
|
|
||||||
for (auto it = viableCandidates.begin(); it != viableCandidates.end(); ++it) {
|
|
||||||
if (incumbent == *it)
|
|
||||||
continue;
|
|
||||||
const TFunction& candidate = *(*it);
|
|
||||||
|
|
||||||
// In the case of default parameters, it may have an identical initial set, which is
|
|
||||||
// also ambiguous
|
|
||||||
if (betterParam(*incumbent, candidate) || equivalentParams(*incumbent, candidate))
|
|
||||||
tie = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return incumbent;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Look at a '.' field selector string and change it into numerical selectors
|
|
||||||
// for a vector or scalar.
|
|
||||||
//
|
|
||||||
// Always return some form of swizzle, so the result is always usable.
|
|
||||||
//
|
|
||||||
void TParseContextBase::parseSwizzleSelector(const TSourceLoc& loc, const TString& compString, int vecSize,
|
|
||||||
TSwizzleSelectors<TVectorSelector>& selector)
|
|
||||||
{
|
|
||||||
// Too long?
|
|
||||||
if (compString.size() > MaxSwizzleSelectors)
|
|
||||||
error(loc, "vector swizzle too long", compString.c_str(), "");
|
|
||||||
|
|
||||||
// Use this to test that all swizzle characters are from the same swizzle-namespace-set
|
|
||||||
enum {
|
|
||||||
exyzw,
|
|
||||||
ergba,
|
|
||||||
estpq,
|
|
||||||
} fieldSet[MaxSwizzleSelectors];
|
|
||||||
|
|
||||||
// Decode the swizzle string.
|
|
||||||
int size = std::min(MaxSwizzleSelectors, (int)compString.size());
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
switch (compString[i]) {
|
|
||||||
case 'x':
|
|
||||||
selector.push_back(0);
|
|
||||||
fieldSet[i] = exyzw;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
selector.push_back(0);
|
|
||||||
fieldSet[i] = ergba;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
selector.push_back(0);
|
|
||||||
fieldSet[i] = estpq;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'y':
|
|
||||||
selector.push_back(1);
|
|
||||||
fieldSet[i] = exyzw;
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
selector.push_back(1);
|
|
||||||
fieldSet[i] = ergba;
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
selector.push_back(1);
|
|
||||||
fieldSet[i] = estpq;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'z':
|
|
||||||
selector.push_back(2);
|
|
||||||
fieldSet[i] = exyzw;
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
selector.push_back(2);
|
|
||||||
fieldSet[i] = ergba;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
selector.push_back(2);
|
|
||||||
fieldSet[i] = estpq;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'w':
|
|
||||||
selector.push_back(3);
|
|
||||||
fieldSet[i] = exyzw;
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
selector.push_back(3);
|
|
||||||
fieldSet[i] = ergba;
|
|
||||||
break;
|
|
||||||
case 'q':
|
|
||||||
selector.push_back(3);
|
|
||||||
fieldSet[i] = estpq;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
error(loc, "unknown swizzle selection", compString.c_str(), "");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Additional error checking.
|
|
||||||
for (int i = 0; i < selector.size(); ++i) {
|
|
||||||
if (selector[i] >= vecSize) {
|
|
||||||
error(loc, "vector swizzle selection out of range", compString.c_str(), "");
|
|
||||||
selector.resize(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i > 0 && fieldSet[i] != fieldSet[i-1]) {
|
|
||||||
error(loc, "vector swizzle selectors not from the same set", compString.c_str(), "");
|
|
||||||
selector.resize(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure it is valid.
|
|
||||||
if (selector.size() == 0)
|
|
||||||
selector.push_back(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_HLSL
|
|
||||||
//
|
|
||||||
// Make the passed-in variable information become a member of the
|
|
||||||
// global uniform block. If this doesn't exist yet, make it.
|
|
||||||
//
|
|
||||||
void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList)
|
|
||||||
{
|
|
||||||
// Make the global block, if not yet made.
|
|
||||||
if (globalUniformBlock == nullptr) {
|
|
||||||
TQualifier blockQualifier;
|
|
||||||
blockQualifier.clear();
|
|
||||||
blockQualifier.storage = EvqUniform;
|
|
||||||
TType blockType(new TTypeList, *NewPoolTString(getGlobalUniformBlockName()), blockQualifier);
|
|
||||||
setUniformBlockDefaults(blockType);
|
|
||||||
globalUniformBlock = new TVariable(NewPoolTString(""), blockType, true);
|
|
||||||
firstNewMember = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update with binding and set
|
|
||||||
globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding;
|
|
||||||
globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet;
|
|
||||||
|
|
||||||
// Add the requested member as a member to the global block.
|
|
||||||
TType* type = new TType;
|
|
||||||
type->shallowCopy(memberType);
|
|
||||||
type->setFieldName(memberName);
|
|
||||||
if (typeList)
|
|
||||||
type->setStruct(typeList);
|
|
||||||
TTypeLoc typeLoc = {type, loc};
|
|
||||||
globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc);
|
|
||||||
|
|
||||||
// Insert into the symbol table.
|
|
||||||
if (firstNewMember == 0) {
|
|
||||||
// This is the first request; we need a normal symbol table insert
|
|
||||||
if (symbolTable.insert(*globalUniformBlock))
|
|
||||||
trackLinkage(*globalUniformBlock);
|
|
||||||
else
|
|
||||||
error(loc, "failed to insert the global constant buffer", "uniform", "");
|
|
||||||
} else {
|
|
||||||
// This is a follow-on request; we need to amend the first insert
|
|
||||||
symbolTable.amend(*globalUniformBlock, firstNewMember);
|
|
||||||
}
|
|
||||||
|
|
||||||
++firstNewMember;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void TParseContextBase::finish()
|
|
||||||
{
|
|
||||||
if (parsingBuiltins)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Transfer the linkage symbols to AST nodes, preserving order.
|
|
||||||
TIntermAggregate* linkage = new TIntermAggregate;
|
|
||||||
for (auto i = linkageSymbols.begin(); i != linkageSymbols.end(); ++i)
|
|
||||||
intermediate.addSymbolLinkageNode(linkage, **i);
|
|
||||||
intermediate.addSymbolLinkageNodes(linkage, getLanguage(), symbolTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,532 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
|
||||||
// Copyright (C) 2015-2018 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// This header defines a two-level parse-helper hierarchy, derived from
|
|
||||||
// TParseVersions:
|
|
||||||
// - TParseContextBase: sharable across multiple parsers
|
|
||||||
// - TParseContext: GLSL specific helper
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _PARSER_HELPER_INCLUDED_
|
|
||||||
#define _PARSER_HELPER_INCLUDED_
|
|
||||||
|
|
||||||
#include <cstdarg>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "parseVersions.h"
|
|
||||||
#include "../Include/ShHandle.h"
|
|
||||||
#include "SymbolTable.h"
|
|
||||||
#include "localintermediate.h"
|
|
||||||
#include "Scan.h"
|
|
||||||
#include "attribute.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
struct TPragma {
|
|
||||||
TPragma(bool o, bool d) : optimize(o), debug(d) { }
|
|
||||||
bool optimize;
|
|
||||||
bool debug;
|
|
||||||
TPragmaTable pragmaTable;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TScanContext;
|
|
||||||
class TPpContext;
|
|
||||||
|
|
||||||
typedef std::set<int> TIdSetType;
|
|
||||||
typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Sharable code (as well as what's in TParseVersions) across
|
|
||||||
// parse helpers.
|
|
||||||
//
|
|
||||||
class TParseContextBase : public TParseVersions {
|
|
||||||
public:
|
|
||||||
TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version,
|
|
||||||
EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
|
|
||||||
TInfoSink& infoSink, bool forwardCompatible, EShMessages messages,
|
|
||||||
const TString* entryPoint = nullptr)
|
|
||||||
: TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
|
|
||||||
scopeMangler("::"),
|
|
||||||
symbolTable(symbolTable),
|
|
||||||
statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
|
|
||||||
postEntryPointReturn(false),
|
|
||||||
contextPragma(true, false),
|
|
||||||
beginInvocationInterlockCount(0), endInvocationInterlockCount(0),
|
|
||||||
parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
|
|
||||||
limits(resources.limits),
|
|
||||||
globalUniformBlock(nullptr),
|
|
||||||
globalUniformBinding(TQualifier::layoutBindingEnd),
|
|
||||||
globalUniformSet(TQualifier::layoutSetEnd)
|
|
||||||
{
|
|
||||||
if (entryPoint != nullptr)
|
|
||||||
sourceEntryPointName = *entryPoint;
|
|
||||||
}
|
|
||||||
virtual ~TParseContextBase() { }
|
|
||||||
|
|
||||||
#if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL)
|
|
||||||
virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...);
|
|
||||||
virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...);
|
|
||||||
virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...);
|
|
||||||
virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual void setLimits(const TBuiltInResource&) = 0;
|
|
||||||
|
|
||||||
void checkIndex(const TSourceLoc&, const TType&, int& index);
|
|
||||||
|
|
||||||
EShLanguage getLanguage() const { return language; }
|
|
||||||
void setScanContext(TScanContext* c) { scanContext = c; }
|
|
||||||
TScanContext* getScanContext() const { return scanContext; }
|
|
||||||
void setPpContext(TPpContext* c) { ppContext = c; }
|
|
||||||
TPpContext* getPpContext() const { return ppContext; }
|
|
||||||
|
|
||||||
virtual void setLineCallback(const std::function<void(int, int, bool, int, const char*)>& func) { lineCallback = func; }
|
|
||||||
virtual void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; }
|
|
||||||
virtual void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; }
|
|
||||||
virtual void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; }
|
|
||||||
virtual void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; }
|
|
||||||
|
|
||||||
virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0;
|
|
||||||
virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0;
|
|
||||||
virtual bool lineDirectiveShouldSetNextLine() const = 0;
|
|
||||||
virtual void handlePragma(const TSourceLoc&, const TVector<TString>&) = 0;
|
|
||||||
|
|
||||||
virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0;
|
|
||||||
|
|
||||||
virtual void notifyVersion(int line, int version, const char* type_string)
|
|
||||||
{
|
|
||||||
if (versionCallback)
|
|
||||||
versionCallback(line, version, type_string);
|
|
||||||
}
|
|
||||||
virtual void notifyErrorDirective(int line, const char* error_message)
|
|
||||||
{
|
|
||||||
if (errorCallback)
|
|
||||||
errorCallback(line, error_message);
|
|
||||||
}
|
|
||||||
virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName)
|
|
||||||
{
|
|
||||||
if (lineCallback)
|
|
||||||
lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName);
|
|
||||||
}
|
|
||||||
virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior)
|
|
||||||
{
|
|
||||||
if (extensionCallback)
|
|
||||||
extensionCallback(line, extension, behavior);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_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);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Potentially rename shader entry point function
|
|
||||||
void renameShaderFunction(TString*& name) const
|
|
||||||
{
|
|
||||||
// Replace the entry point name given in the shader with the real entry point name,
|
|
||||||
// if there is a substitution.
|
|
||||||
if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0)
|
|
||||||
name = NewPoolTString(intermediate.getEntryPointName().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
|
||||||
virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
|
|
||||||
|
|
||||||
const char* const scopeMangler;
|
|
||||||
|
|
||||||
// Basic parsing state, easily accessible to the grammar
|
|
||||||
|
|
||||||
TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile
|
|
||||||
int statementNestingLevel; // 0 if outside all flow control or compound statements
|
|
||||||
int loopNestingLevel; // 0 if outside all loops
|
|
||||||
int structNestingLevel; // 0 if outside blocks and structures
|
|
||||||
int controlFlowNestingLevel; // 0 if outside all flow control
|
|
||||||
const TType* currentFunctionType; // the return type of the function that's currently being parsed
|
|
||||||
bool functionReturnsValue; // true if a non-void function has a return
|
|
||||||
// if inside a function, true if the function is the entry point and this is after a return statement
|
|
||||||
bool postEntryPointReturn;
|
|
||||||
// case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting
|
|
||||||
TList<TIntermSequence*> switchSequenceStack;
|
|
||||||
// the statementNestingLevel the current switch statement is at, which must match the level of its case statements
|
|
||||||
TList<int> switchLevel;
|
|
||||||
struct TPragma contextPragma;
|
|
||||||
int beginInvocationInterlockCount;
|
|
||||||
int endInvocationInterlockCount;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TParseContextBase(TParseContextBase&);
|
|
||||||
TParseContextBase& operator=(TParseContextBase&);
|
|
||||||
|
|
||||||
const bool parsingBuiltins; // true if parsing built-in symbols/functions
|
|
||||||
TVector<TSymbol*> linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving
|
|
||||||
TScanContext* scanContext;
|
|
||||||
TPpContext* ppContext;
|
|
||||||
TBuiltInResource resources;
|
|
||||||
TLimits& limits;
|
|
||||||
TString sourceEntryPointName;
|
|
||||||
|
|
||||||
// These, if set, will be called when a line, pragma ... is preprocessed.
|
|
||||||
// They will be called with any parameters to the original directive.
|
|
||||||
std::function<void(int, int, bool, int, const char*)> lineCallback;
|
|
||||||
std::function<void(int, const TVector<TString>&)> pragmaCallback;
|
|
||||||
std::function<void(int, int, const char*)> versionCallback;
|
|
||||||
std::function<void(int, const char*, const char*)> extensionCallback;
|
|
||||||
std::function<void(int, const char*)> errorCallback;
|
|
||||||
|
|
||||||
// see implementation for detail
|
|
||||||
const TFunction* selectFunction(const TVector<const TFunction*>, const TFunction&,
|
|
||||||
std::function<bool(const TType&, const TType&, TOperator, int arg)>,
|
|
||||||
std::function<bool(const TType&, const TType&, const TType&)>,
|
|
||||||
/* output */ bool& tie);
|
|
||||||
|
|
||||||
virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size,
|
|
||||||
TSwizzleSelectors<TVectorSelector>&);
|
|
||||||
|
|
||||||
// Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
|
|
||||||
TVariable* globalUniformBlock; // the actual block, inserted into the symbol table
|
|
||||||
unsigned int globalUniformBinding; // the block's binding number
|
|
||||||
unsigned int globalUniformSet; // the block's set number
|
|
||||||
int firstNewMember; // the index of the first member not yet inserted into the symbol table
|
|
||||||
// override this to set the language-specific name
|
|
||||||
virtual const char* getGlobalUniformBlockName() const { return ""; }
|
|
||||||
virtual void setUniformBlockDefaults(TType&) const { }
|
|
||||||
virtual void finalizeGlobalUniformBlockLayout(TVariable&) { }
|
|
||||||
virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, TPrefixType prefix,
|
|
||||||
va_list args);
|
|
||||||
virtual void trackLinkage(TSymbol& symbol);
|
|
||||||
virtual void makeEditable(TSymbol*&);
|
|
||||||
virtual TVariable* getEditableVariable(const char* name);
|
|
||||||
virtual void finish();
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Manage the state for when to respect precision qualifiers and when to warn about
|
|
||||||
// the defaults being different than might be expected.
|
|
||||||
//
|
|
||||||
class TPrecisionManager {
|
|
||||||
public:
|
|
||||||
TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ }
|
|
||||||
virtual ~TPrecisionManager() {}
|
|
||||||
|
|
||||||
void respectPrecisionQualifiers() { obey = true; }
|
|
||||||
bool respectingPrecisionQualifiers() const { return obey; }
|
|
||||||
bool shouldWarnAboutDefaults() const { return warn; }
|
|
||||||
void defaultWarningGiven() { warn = false; }
|
|
||||||
void warnAboutDefaults() { warn = true; }
|
|
||||||
void explicitIntDefaultSeen()
|
|
||||||
{
|
|
||||||
explicitIntDefault = true;
|
|
||||||
if (explicitFloatDefault)
|
|
||||||
warn = false;
|
|
||||||
}
|
|
||||||
void explicitFloatDefaultSeen()
|
|
||||||
{
|
|
||||||
explicitFloatDefault = true;
|
|
||||||
if (explicitIntDefault)
|
|
||||||
warn = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool obey; // respect precision qualifiers
|
|
||||||
bool warn; // need to give a warning about the defaults
|
|
||||||
bool explicitIntDefault; // user set the default for int/uint
|
|
||||||
bool explicitFloatDefault; // user set the default for float
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// GLSL-specific parse helper. Should have GLSL in the name, but that's
|
|
||||||
// too big of a change for comparing branches at the moment, and perhaps
|
|
||||||
// impacts downstream consumers as well.
|
|
||||||
//
|
|
||||||
class TParseContext : public TParseContextBase {
|
|
||||||
public:
|
|
||||||
TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&,
|
|
||||||
bool forwardCompatible = false, EShMessages messages = EShMsgDefault,
|
|
||||||
const TString* entryPoint = nullptr);
|
|
||||||
virtual ~TParseContext();
|
|
||||||
|
|
||||||
bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); }
|
|
||||||
void setPrecisionDefaults();
|
|
||||||
|
|
||||||
void setLimits(const TBuiltInResource&) override;
|
|
||||||
bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
|
|
||||||
void parserError(const char* s); // for bison's yyerror
|
|
||||||
|
|
||||||
void reservedErrorCheck(const TSourceLoc&, const TString&);
|
|
||||||
void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
|
|
||||||
bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
|
|
||||||
bool lineDirectiveShouldSetNextLine() const override;
|
|
||||||
bool builtInName(const TString&);
|
|
||||||
|
|
||||||
void handlePragma(const TSourceLoc&, const TVector<TString>&) override;
|
|
||||||
TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string);
|
|
||||||
TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
|
|
||||||
void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
void makeEditable(TSymbol*&) override;
|
|
||||||
void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier);
|
|
||||||
#endif
|
|
||||||
bool isIoResizeArray(const TType&) const;
|
|
||||||
void fixIoArraySize(const TSourceLoc&, TType&);
|
|
||||||
void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
|
|
||||||
void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false);
|
|
||||||
int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const;
|
|
||||||
void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
|
|
||||||
|
|
||||||
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
|
|
||||||
TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
|
|
||||||
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
|
||||||
TIntermTyped* handleDotSwizzle(const TSourceLoc&, TIntermTyped* base, const TString& field);
|
|
||||||
void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName);
|
|
||||||
TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
|
|
||||||
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
|
|
||||||
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
|
|
||||||
TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function);
|
|
||||||
void computeBuiltinPrecisions(TIntermTyped&, const TFunction&);
|
|
||||||
TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
|
|
||||||
void checkLocation(const TSourceLoc&, TOperator);
|
|
||||||
TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
|
|
||||||
void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
|
|
||||||
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
|
|
||||||
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
|
|
||||||
void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
|
|
||||||
void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);
|
|
||||||
void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*);
|
|
||||||
TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
|
|
||||||
void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier);
|
|
||||||
void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
|
|
||||||
void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
|
|
||||||
|
|
||||||
void assignError(const TSourceLoc&, const char* op, TString left, TString right);
|
|
||||||
void unaryOpError(const TSourceLoc&, const char* op, TString operand);
|
|
||||||
void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
|
|
||||||
void variableCheck(TIntermTyped*& nodePtr);
|
|
||||||
bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
|
|
||||||
void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
|
|
||||||
void constantValueCheck(TIntermTyped* node, const char* token);
|
|
||||||
void integerCheck(const TIntermTyped* node, const char* token);
|
|
||||||
void globalCheck(const TSourceLoc&, const char* token);
|
|
||||||
bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&);
|
|
||||||
bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&);
|
|
||||||
void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType);
|
|
||||||
bool arrayQualifierError(const TSourceLoc&, const TQualifier&);
|
|
||||||
bool arrayError(const TSourceLoc&, const TType&);
|
|
||||||
void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
|
|
||||||
void structArrayCheck(const TSourceLoc&, const TType& structure);
|
|
||||||
void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember);
|
|
||||||
void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*);
|
|
||||||
bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
|
|
||||||
void boolCheck(const TSourceLoc&, const TIntermTyped*);
|
|
||||||
void boolCheck(const TSourceLoc&, const TPublicType&);
|
|
||||||
void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
|
|
||||||
void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
|
|
||||||
void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
|
|
||||||
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
|
|
||||||
void memberQualifierCheck(glslang::TPublicType&);
|
|
||||||
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
|
|
||||||
void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
|
|
||||||
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
|
|
||||||
void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
|
|
||||||
void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier);
|
|
||||||
int computeSamplerTypeIndex(TSampler&);
|
|
||||||
TPrecisionQualifier getDefaultPrecision(TPublicType&);
|
|
||||||
void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&);
|
|
||||||
void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type);
|
|
||||||
bool containsFieldWithBasicType(const TType& type ,TBasicType basicType);
|
|
||||||
TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&);
|
|
||||||
void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
|
|
||||||
void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type);
|
|
||||||
void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type);
|
|
||||||
void nestedBlockCheck(const TSourceLoc&);
|
|
||||||
void nestedStructCheck(const TSourceLoc&);
|
|
||||||
void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
|
|
||||||
void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
|
|
||||||
void referenceCheck(const TSourceLoc&, const TType&, const char* op);
|
|
||||||
void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op);
|
|
||||||
void specializationCheck(const TSourceLoc&, const TType&, const char* op);
|
|
||||||
void structTypeCheck(const TSourceLoc&, TPublicType&);
|
|
||||||
void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop);
|
|
||||||
void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
|
|
||||||
void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
|
|
||||||
|
|
||||||
void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&);
|
|
||||||
void constantIndexExpressionCheck(TIntermNode*);
|
|
||||||
|
|
||||||
void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
|
|
||||||
void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*);
|
|
||||||
void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
|
|
||||||
void layoutObjectCheck(const TSourceLoc&, const TSymbol&);
|
|
||||||
void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes);
|
|
||||||
void layoutTypeCheck(const TSourceLoc&, const TType&);
|
|
||||||
void layoutQualifierCheck(const TSourceLoc&, const TQualifier&);
|
|
||||||
void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
|
|
||||||
void fixOffset(const TSourceLoc&, TSymbol&);
|
|
||||||
|
|
||||||
const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
|
||||||
const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
|
||||||
const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
|
||||||
const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
|
||||||
const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
|
|
||||||
void declareTypeDefaults(const TSourceLoc&, const TPublicType&);
|
|
||||||
TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0);
|
|
||||||
TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
|
|
||||||
TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
|
|
||||||
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
|
|
||||||
void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
|
|
||||||
void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
|
|
||||||
void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
|
|
||||||
void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
|
|
||||||
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
|
|
||||||
void fixXfbOffsets(TQualifier&, TTypeList&);
|
|
||||||
void fixBlockUniformOffsets(TQualifier&, TTypeList&);
|
|
||||||
void fixBlockUniformLayoutMatrix(TQualifier&, TTypeList*, TTypeList*);
|
|
||||||
void fixBlockUniformLayoutPacking(TQualifier&, TTypeList*, TTypeList*);
|
|
||||||
void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
|
|
||||||
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
|
|
||||||
void invariantCheck(const TSourceLoc&, const TQualifier&);
|
|
||||||
void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
|
|
||||||
void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
|
|
||||||
TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
|
|
||||||
const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*);
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
TAttributeType attributeFromName(const TString& name) const;
|
|
||||||
TAttributes* makeAttributes(const TString& identifier) const;
|
|
||||||
TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const;
|
|
||||||
TAttributes* mergeAttributes(TAttributes*, TAttributes*) const;
|
|
||||||
|
|
||||||
// Determine selection control from attributes
|
|
||||||
void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*);
|
|
||||||
void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*);
|
|
||||||
// Determine loop control from attributes
|
|
||||||
void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
|
|
||||||
void inheritGlobalDefaults(TQualifier& dst) const;
|
|
||||||
TVariable* makeInternalVariable(const char* name, const TType&) const;
|
|
||||||
TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&);
|
|
||||||
void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&);
|
|
||||||
void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&);
|
|
||||||
bool isRuntimeLength(const TIntermTyped&) const;
|
|
||||||
TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
|
|
||||||
TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
void finish() override;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public:
|
|
||||||
//
|
|
||||||
// Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
|
|
||||||
//
|
|
||||||
|
|
||||||
// Current state of parsing
|
|
||||||
bool inMain; // if inside a function, true if the function is main
|
|
||||||
const TString* blockName;
|
|
||||||
TQualifier currentBlockQualifier;
|
|
||||||
TPrecisionQualifier defaultPrecision[EbtNumTypes];
|
|
||||||
TBuiltInResource resources;
|
|
||||||
TLimits& limits;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TParseContext(TParseContext&);
|
|
||||||
TParseContext& operator=(TParseContext&);
|
|
||||||
|
|
||||||
static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex()
|
|
||||||
TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
|
|
||||||
TPrecisionManager precisionManager;
|
|
||||||
TQualifier globalBufferDefaults;
|
|
||||||
TQualifier globalUniformDefaults;
|
|
||||||
TQualifier globalInputDefaults;
|
|
||||||
TQualifier globalOutputDefaults;
|
|
||||||
TString currentCaller; // name of last function body entered (not valid when at global scope)
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point
|
|
||||||
bool anyIndexLimits;
|
|
||||||
TIdSetType inductiveLoopIds;
|
|
||||||
TVector<TIntermTyped*> needsIndexLimitationChecking;
|
|
||||||
TStructRecord matrixFixRecord;
|
|
||||||
TStructRecord packingFixRecord;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Geometry shader input arrays:
|
|
||||||
// - array sizing is based on input primitive and/or explicit size
|
|
||||||
//
|
|
||||||
// Tessellation control output arrays:
|
|
||||||
// - array sizing is based on output layout(vertices=...) and/or explicit size
|
|
||||||
//
|
|
||||||
// Both:
|
|
||||||
// - array sizing is retroactive
|
|
||||||
// - built-in block redeclarations interact with this
|
|
||||||
//
|
|
||||||
// Design:
|
|
||||||
// - use a per-context "resize-list", a list of symbols whose array sizes
|
|
||||||
// can be fixed
|
|
||||||
//
|
|
||||||
// - the resize-list starts empty at beginning of user-shader compilation, it does
|
|
||||||
// not have built-ins in it
|
|
||||||
//
|
|
||||||
// - on built-in array use: copyUp() symbol and add it to the resize-list
|
|
||||||
//
|
|
||||||
// - on user array declaration: add it to the resize-list
|
|
||||||
//
|
|
||||||
// - on block redeclaration: copyUp() symbol and add it to the resize-list
|
|
||||||
// * note, that appropriately gives an error if redeclaring a block that
|
|
||||||
// was already used and hence already copied-up
|
|
||||||
//
|
|
||||||
// - on seeing a layout declaration that sizes the array, fix everything in the
|
|
||||||
// resize-list, giving errors for mismatch
|
|
||||||
//
|
|
||||||
// - on seeing an array size declaration, give errors on mismatch between it and previous
|
|
||||||
// array-sizing declarations
|
|
||||||
//
|
|
||||||
TVector<TSymbol*> ioArraySymbolResizeList;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _PARSER_HELPER_INCLUDED_
|
|
|
@ -1,324 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "../Include/Common.h"
|
|
||||||
#include "../Include/PoolAlloc.h"
|
|
||||||
|
|
||||||
#include "../Include/InitializeGlobals.h"
|
|
||||||
#include "../OSDependent/osinclude.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
// Process-wide TLS index
|
|
||||||
OS_TLSIndex PoolIndex;
|
|
||||||
|
|
||||||
// Return the thread-specific current pool.
|
|
||||||
TPoolAllocator& GetThreadPoolAllocator()
|
|
||||||
{
|
|
||||||
return *static_cast<TPoolAllocator*>(OS_GetTLSValue(PoolIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the thread-specific current pool.
|
|
||||||
void SetThreadPoolAllocator(TPoolAllocator* poolAllocator)
|
|
||||||
{
|
|
||||||
OS_SetTLSValue(PoolIndex, poolAllocator);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process-wide set up of the TLS pool storage.
|
|
||||||
bool InitializePoolIndex()
|
|
||||||
{
|
|
||||||
// Allocate a TLS index.
|
|
||||||
if ((PoolIndex = OS_AllocTLSIndex()) == OS_INVALID_TLS_INDEX)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DeinitializePoolIndex()
|
|
||||||
{
|
|
||||||
if (PoolIndex == OS_INVALID_TLS_INDEX)
|
|
||||||
return false;
|
|
||||||
OS_FreeTLSIndex(PoolIndex);
|
|
||||||
PoolIndex = OS_INVALID_TLS_INDEX;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Implement the functionality of the TPoolAllocator class, which
|
|
||||||
// is documented in PoolAlloc.h.
|
|
||||||
//
|
|
||||||
TPoolAllocator::TPoolAllocator(int growthIncrement, int allocationAlignment) :
|
|
||||||
pageSize(growthIncrement),
|
|
||||||
alignment(allocationAlignment),
|
|
||||||
freeList(nullptr),
|
|
||||||
inUseList(nullptr),
|
|
||||||
numCalls(0)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Don't allow page sizes we know are smaller than all common
|
|
||||||
// OS page sizes.
|
|
||||||
//
|
|
||||||
if (pageSize < 4*1024)
|
|
||||||
pageSize = 4*1024;
|
|
||||||
|
|
||||||
//
|
|
||||||
// A large currentPageOffset indicates a new page needs to
|
|
||||||
// be obtained to allocate memory.
|
|
||||||
//
|
|
||||||
currentPageOffset = pageSize;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Adjust alignment to be at least pointer aligned and
|
|
||||||
// power of 2.
|
|
||||||
//
|
|
||||||
size_t minAlign = sizeof(void*);
|
|
||||||
alignment &= ~(minAlign - 1);
|
|
||||||
if (alignment < minAlign)
|
|
||||||
alignment = minAlign;
|
|
||||||
size_t a = 1;
|
|
||||||
while (a < alignment)
|
|
||||||
a <<= 1;
|
|
||||||
alignment = a;
|
|
||||||
alignmentMask = a - 1;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Align header skip
|
|
||||||
//
|
|
||||||
headerSkip = minAlign;
|
|
||||||
if (headerSkip < sizeof(tHeader)) {
|
|
||||||
headerSkip = (sizeof(tHeader) + alignmentMask) & ~alignmentMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
push();
|
|
||||||
}
|
|
||||||
|
|
||||||
TPoolAllocator::~TPoolAllocator()
|
|
||||||
{
|
|
||||||
while (inUseList) {
|
|
||||||
tHeader* next = inUseList->nextPage;
|
|
||||||
inUseList->~tHeader();
|
|
||||||
delete [] reinterpret_cast<char*>(inUseList);
|
|
||||||
inUseList = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Always delete the free list memory - it can't be being
|
|
||||||
// (correctly) referenced, whether the pool allocator was
|
|
||||||
// global or not. We should not check the guard blocks
|
|
||||||
// here, because we did it already when the block was
|
|
||||||
// placed into the free list.
|
|
||||||
//
|
|
||||||
while (freeList) {
|
|
||||||
tHeader* next = freeList->nextPage;
|
|
||||||
delete [] reinterpret_cast<char*>(freeList);
|
|
||||||
freeList = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned char TAllocation::guardBlockBeginVal = 0xfb;
|
|
||||||
const unsigned char TAllocation::guardBlockEndVal = 0xfe;
|
|
||||||
const unsigned char TAllocation::userDataFill = 0xcd;
|
|
||||||
|
|
||||||
# ifdef GUARD_BLOCKS
|
|
||||||
const size_t TAllocation::guardBlockSize = 16;
|
|
||||||
# else
|
|
||||||
const size_t TAllocation::guardBlockSize = 0;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check a single guard block for damage
|
|
||||||
//
|
|
||||||
#ifdef GUARD_BLOCKS
|
|
||||||
void TAllocation::checkGuardBlock(unsigned char* blockMem, unsigned char val, const char* locText) const
|
|
||||||
#else
|
|
||||||
void TAllocation::checkGuardBlock(unsigned char*, unsigned char, const char*) const
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
#ifdef GUARD_BLOCKS
|
|
||||||
for (size_t x = 0; x < guardBlockSize; x++) {
|
|
||||||
if (blockMem[x] != val) {
|
|
||||||
const int maxSize = 80;
|
|
||||||
char assertMsg[maxSize];
|
|
||||||
|
|
||||||
// We don't print the assert message. It's here just to be helpful.
|
|
||||||
snprintf(assertMsg, maxSize, "PoolAlloc: Damage %s %zu byte allocation at 0x%p\n",
|
|
||||||
locText, size, data());
|
|
||||||
assert(0 && "PoolAlloc: Damage in guard block");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
assert(guardBlockSize == 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void TPoolAllocator::push()
|
|
||||||
{
|
|
||||||
tAllocState state = { currentPageOffset, inUseList };
|
|
||||||
|
|
||||||
stack.push_back(state);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Indicate there is no current page to allocate from.
|
|
||||||
//
|
|
||||||
currentPageOffset = pageSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do a mass-deallocation of all the individual allocations
|
|
||||||
// that have occurred since the last push(), or since the
|
|
||||||
// last pop(), or since the object's creation.
|
|
||||||
//
|
|
||||||
// The deallocated pages are saved for future allocations.
|
|
||||||
//
|
|
||||||
void TPoolAllocator::pop()
|
|
||||||
{
|
|
||||||
if (stack.size() < 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
tHeader* page = stack.back().page;
|
|
||||||
currentPageOffset = stack.back().offset;
|
|
||||||
|
|
||||||
while (inUseList != page) {
|
|
||||||
tHeader* nextInUse = inUseList->nextPage;
|
|
||||||
size_t pageCount = inUseList->pageCount;
|
|
||||||
|
|
||||||
// This technically ends the lifetime of the header as C++ object,
|
|
||||||
// but we will still control the memory and reuse it.
|
|
||||||
inUseList->~tHeader(); // currently, just a debug allocation checker
|
|
||||||
|
|
||||||
if (pageCount > 1) {
|
|
||||||
delete [] reinterpret_cast<char*>(inUseList);
|
|
||||||
} else {
|
|
||||||
inUseList->nextPage = freeList;
|
|
||||||
freeList = inUseList;
|
|
||||||
}
|
|
||||||
inUseList = nextInUse;
|
|
||||||
}
|
|
||||||
|
|
||||||
stack.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do a mass-deallocation of all the individual allocations
|
|
||||||
// that have occurred.
|
|
||||||
//
|
|
||||||
void TPoolAllocator::popAll()
|
|
||||||
{
|
|
||||||
while (stack.size() > 0)
|
|
||||||
pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void* TPoolAllocator::allocate(size_t numBytes)
|
|
||||||
{
|
|
||||||
// If we are using guard blocks, all allocations are bracketed by
|
|
||||||
// them: [guardblock][allocation][guardblock]. numBytes is how
|
|
||||||
// much memory the caller asked for. allocationSize is the total
|
|
||||||
// size including guard blocks. In release build,
|
|
||||||
// guardBlockSize=0 and this all gets optimized away.
|
|
||||||
size_t allocationSize = TAllocation::allocationSize(numBytes);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Just keep some interesting statistics.
|
|
||||||
//
|
|
||||||
++numCalls;
|
|
||||||
totalBytes += numBytes;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do the allocation, most likely case first, for efficiency.
|
|
||||||
// This step could be moved to be inline sometime.
|
|
||||||
//
|
|
||||||
if (currentPageOffset + allocationSize <= pageSize) {
|
|
||||||
//
|
|
||||||
// Safe to allocate from currentPageOffset.
|
|
||||||
//
|
|
||||||
unsigned char* memory = reinterpret_cast<unsigned char*>(inUseList) + currentPageOffset;
|
|
||||||
currentPageOffset += allocationSize;
|
|
||||||
currentPageOffset = (currentPageOffset + alignmentMask) & ~alignmentMask;
|
|
||||||
|
|
||||||
return initializeAllocation(inUseList, memory, numBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allocationSize + headerSkip > pageSize) {
|
|
||||||
//
|
|
||||||
// Do a multi-page allocation. Don't mix these with the others.
|
|
||||||
// The OS is efficient and allocating and free-ing multiple pages.
|
|
||||||
//
|
|
||||||
size_t numBytesToAlloc = allocationSize + headerSkip;
|
|
||||||
tHeader* memory = reinterpret_cast<tHeader*>(::new char[numBytesToAlloc]);
|
|
||||||
if (memory == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Use placement-new to initialize header
|
|
||||||
new(memory) tHeader(inUseList, (numBytesToAlloc + pageSize - 1) / pageSize);
|
|
||||||
inUseList = memory;
|
|
||||||
|
|
||||||
currentPageOffset = pageSize; // make next allocation come from a new page
|
|
||||||
|
|
||||||
// No guard blocks for multi-page allocations (yet)
|
|
||||||
return reinterpret_cast<void*>(reinterpret_cast<UINT_PTR>(memory) + headerSkip);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Need a simple page to allocate from.
|
|
||||||
//
|
|
||||||
tHeader* memory;
|
|
||||||
if (freeList) {
|
|
||||||
memory = freeList;
|
|
||||||
freeList = freeList->nextPage;
|
|
||||||
} else {
|
|
||||||
memory = reinterpret_cast<tHeader*>(::new char[pageSize]);
|
|
||||||
if (memory == 0)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use placement-new to initialize header
|
|
||||||
new(memory) tHeader(inUseList, 1);
|
|
||||||
inUseList = memory;
|
|
||||||
|
|
||||||
unsigned char* ret = reinterpret_cast<unsigned char*>(inUseList) + headerSkip;
|
|
||||||
currentPageOffset = (headerSkip + allocationSize + alignmentMask) & ~alignmentMask;
|
|
||||||
|
|
||||||
return initializeAllocation(inUseList, ret, numBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check all allocations in a list for damage by calling check on each.
|
|
||||||
//
|
|
||||||
void TAllocation::checkAllocList() const
|
|
||||||
{
|
|
||||||
for (const TAllocation* alloc = this; alloc != 0; alloc = alloc->prevAlloc)
|
|
||||||
alloc->check();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
|
@ -1,118 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "../Include/intermediate.h"
|
|
||||||
#include "RemoveTree.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Code to recursively delete the intermediate tree.
|
|
||||||
//
|
|
||||||
struct TRemoveTraverser : TIntermTraverser {
|
|
||||||
TRemoveTraverser() : TIntermTraverser(false, false, true, false) {}
|
|
||||||
|
|
||||||
virtual void visitSymbol(TIntermSymbol* node)
|
|
||||||
{
|
|
||||||
delete node;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool visitBinary(TVisit /* visit*/ , TIntermBinary* node)
|
|
||||||
{
|
|
||||||
delete node;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool visitUnary(TVisit /* visit */, TIntermUnary* node)
|
|
||||||
{
|
|
||||||
delete node;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool visitAggregate(TVisit /* visit*/ , TIntermAggregate* node)
|
|
||||||
{
|
|
||||||
delete node;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool visitSelection(TVisit /* visit*/ , TIntermSelection* node)
|
|
||||||
{
|
|
||||||
delete node;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool visitSwitch(TVisit /* visit*/ , TIntermSwitch* node)
|
|
||||||
{
|
|
||||||
delete node;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void visitConstantUnion(TIntermConstantUnion* node)
|
|
||||||
{
|
|
||||||
delete node;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool visitLoop(TVisit /* visit*/ , TIntermLoop* node)
|
|
||||||
{
|
|
||||||
delete node;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool visitBranch(TVisit /* visit*/ , TIntermBranch* node)
|
|
||||||
{
|
|
||||||
delete node;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Entry point.
|
|
||||||
//
|
|
||||||
void RemoveAllTreeNodes(TIntermNode* root)
|
|
||||||
{
|
|
||||||
TRemoveTraverser it;
|
|
||||||
|
|
||||||
root->traverse(&it);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
|
@ -1,41 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
void RemoveAllTreeNodes(TIntermNode*);
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,276 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
#ifndef _GLSLANG_SCAN_INCLUDED_
|
|
||||||
#define _GLSLANG_SCAN_INCLUDED_
|
|
||||||
|
|
||||||
#include "Versions.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
// Use a global end-of-input character, so no translation is needed across
|
|
||||||
// layers of encapsulation. Characters are all 8 bit, and positive, so there is
|
|
||||||
// no aliasing of character 255 onto -1, for example.
|
|
||||||
const int EndOfInput = -1;
|
|
||||||
|
|
||||||
//
|
|
||||||
// A character scanner that seamlessly, on read-only strings, reads across an
|
|
||||||
// array of strings without assuming null termination.
|
|
||||||
//
|
|
||||||
class TInputScanner {
|
|
||||||
public:
|
|
||||||
TInputScanner(int n, const char* const s[], size_t L[], const char* const* names = nullptr,
|
|
||||||
int b = 0, int f = 0, bool single = false) :
|
|
||||||
numSources(n),
|
|
||||||
// up to this point, common usage is "char*", but now we need positive 8-bit characters
|
|
||||||
sources(reinterpret_cast<const unsigned char* const *>(s)),
|
|
||||||
lengths(L), currentSource(0), currentChar(0), stringBias(b), finale(f), singleLogical(single),
|
|
||||||
endOfFileReached(false)
|
|
||||||
{
|
|
||||||
loc = new TSourceLoc[numSources];
|
|
||||||
for (int i = 0; i < numSources; ++i) {
|
|
||||||
loc[i].init(i - stringBias);
|
|
||||||
}
|
|
||||||
if (names != nullptr) {
|
|
||||||
for (int i = 0; i < numSources; ++i)
|
|
||||||
loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr;
|
|
||||||
}
|
|
||||||
loc[currentSource].line = 1;
|
|
||||||
logicalSourceLoc.init(1);
|
|
||||||
logicalSourceLoc.name = loc[0].name;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~TInputScanner()
|
|
||||||
{
|
|
||||||
delete [] loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrieve the next character and advance one character
|
|
||||||
int get()
|
|
||||||
{
|
|
||||||
int ret = peek();
|
|
||||||
if (ret == EndOfInput)
|
|
||||||
return ret;
|
|
||||||
++loc[currentSource].column;
|
|
||||||
++logicalSourceLoc.column;
|
|
||||||
if (ret == '\n') {
|
|
||||||
++loc[currentSource].line;
|
|
||||||
++logicalSourceLoc.line;
|
|
||||||
logicalSourceLoc.column = 0;
|
|
||||||
loc[currentSource].column = 0;
|
|
||||||
}
|
|
||||||
advance();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrieve the next character, no advance
|
|
||||||
int peek()
|
|
||||||
{
|
|
||||||
if (currentSource >= numSources) {
|
|
||||||
endOfFileReached = true;
|
|
||||||
return EndOfInput;
|
|
||||||
}
|
|
||||||
// Make sure we do not read off the end of a string.
|
|
||||||
// N.B. Sources can have a length of 0.
|
|
||||||
int sourceToRead = currentSource;
|
|
||||||
size_t charToRead = currentChar;
|
|
||||||
while(charToRead >= lengths[sourceToRead]) {
|
|
||||||
charToRead = 0;
|
|
||||||
sourceToRead += 1;
|
|
||||||
if (sourceToRead >= numSources) {
|
|
||||||
return EndOfInput;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Here, we care about making negative valued characters positive
|
|
||||||
return sources[sourceToRead][charToRead];
|
|
||||||
}
|
|
||||||
|
|
||||||
// go back one character
|
|
||||||
void unget()
|
|
||||||
{
|
|
||||||
// Do not roll back once we've reached the end of the file.
|
|
||||||
if (endOfFileReached)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (currentChar > 0) {
|
|
||||||
--currentChar;
|
|
||||||
--loc[currentSource].column;
|
|
||||||
--logicalSourceLoc.column;
|
|
||||||
if (loc[currentSource].column < 0) {
|
|
||||||
// We've moved back past a new line. Find the
|
|
||||||
// previous newline (or start of the file) to compute
|
|
||||||
// the column count on the now current line.
|
|
||||||
size_t chIndex = currentChar;
|
|
||||||
while (chIndex > 0) {
|
|
||||||
if (sources[currentSource][chIndex] == '\n') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
--chIndex;
|
|
||||||
}
|
|
||||||
logicalSourceLoc.column = (int)(currentChar - chIndex);
|
|
||||||
loc[currentSource].column = (int)(currentChar - chIndex);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
do {
|
|
||||||
--currentSource;
|
|
||||||
} while (currentSource > 0 && lengths[currentSource] == 0);
|
|
||||||
if (lengths[currentSource] == 0) {
|
|
||||||
// set to 0 if we've backed up to the start of an empty string
|
|
||||||
currentChar = 0;
|
|
||||||
} else
|
|
||||||
currentChar = lengths[currentSource] - 1;
|
|
||||||
}
|
|
||||||
if (peek() == '\n') {
|
|
||||||
--loc[currentSource].line;
|
|
||||||
--logicalSourceLoc.line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// for #line override
|
|
||||||
void setLine(int newLine)
|
|
||||||
{
|
|
||||||
logicalSourceLoc.line = newLine;
|
|
||||||
loc[getLastValidSourceIndex()].line = newLine;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for #line override in filename based parsing
|
|
||||||
void setFile(const char* filename)
|
|
||||||
{
|
|
||||||
TString* fn_tstr = NewPoolTString(filename);
|
|
||||||
logicalSourceLoc.name = fn_tstr;
|
|
||||||
loc[getLastValidSourceIndex()].name = fn_tstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFile(const char* filename, int i)
|
|
||||||
{
|
|
||||||
TString* fn_tstr = NewPoolTString(filename);
|
|
||||||
if (i == getLastValidSourceIndex()) {
|
|
||||||
logicalSourceLoc.name = fn_tstr;
|
|
||||||
}
|
|
||||||
loc[i].name = fn_tstr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setString(int newString)
|
|
||||||
{
|
|
||||||
logicalSourceLoc.string = newString;
|
|
||||||
loc[getLastValidSourceIndex()].string = newString;
|
|
||||||
logicalSourceLoc.name = nullptr;
|
|
||||||
loc[getLastValidSourceIndex()].name = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// for #include content indentation
|
|
||||||
void setColumn(int col)
|
|
||||||
{
|
|
||||||
logicalSourceLoc.column = col;
|
|
||||||
loc[getLastValidSourceIndex()].column = col;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEndOfInput()
|
|
||||||
{
|
|
||||||
endOfFileReached = true;
|
|
||||||
currentSource = numSources;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool atEndOfInput() const { return endOfFileReached; }
|
|
||||||
|
|
||||||
const TSourceLoc& getSourceLoc() const
|
|
||||||
{
|
|
||||||
if (singleLogical) {
|
|
||||||
return logicalSourceLoc;
|
|
||||||
} else {
|
|
||||||
return loc[std::max(0, std::min(currentSource, numSources - finale - 1))];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Returns the index (starting from 0) of the most recent valid source string we are reading from.
|
|
||||||
int getLastValidSourceIndex() const { return std::min(currentSource, numSources - 1); }
|
|
||||||
|
|
||||||
void consumeWhiteSpace(bool& foundNonSpaceTab);
|
|
||||||
bool consumeComment();
|
|
||||||
void consumeWhitespaceComment(bool& foundNonSpaceTab);
|
|
||||||
bool scanVersion(int& version, EProfile& profile, bool& notFirstToken);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// advance one character
|
|
||||||
void advance()
|
|
||||||
{
|
|
||||||
++currentChar;
|
|
||||||
if (currentChar >= lengths[currentSource]) {
|
|
||||||
++currentSource;
|
|
||||||
if (currentSource < numSources) {
|
|
||||||
loc[currentSource].string = loc[currentSource - 1].string + 1;
|
|
||||||
loc[currentSource].line = 1;
|
|
||||||
loc[currentSource].column = 0;
|
|
||||||
}
|
|
||||||
while (currentSource < numSources && lengths[currentSource] == 0) {
|
|
||||||
++currentSource;
|
|
||||||
if (currentSource < numSources) {
|
|
||||||
loc[currentSource].string = loc[currentSource - 1].string + 1;
|
|
||||||
loc[currentSource].line = 1;
|
|
||||||
loc[currentSource].column = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
currentChar = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int numSources; // number of strings in source
|
|
||||||
const unsigned char* const *sources; // array of strings; must be converted to positive values on use, to avoid aliasing with -1 as EndOfInput
|
|
||||||
const size_t *lengths; // length of each string
|
|
||||||
int currentSource;
|
|
||||||
size_t currentChar;
|
|
||||||
|
|
||||||
// This is for reporting what string/line an error occurred on, and can be overridden by #line.
|
|
||||||
// It remembers the last state of each source string as it is left for the next one, so unget()
|
|
||||||
// can restore that state.
|
|
||||||
TSourceLoc* loc; // an array
|
|
||||||
|
|
||||||
int stringBias; // the first string that is the user's string number 0
|
|
||||||
int finale; // number of internal strings after user's last string
|
|
||||||
|
|
||||||
TSourceLoc logicalSourceLoc;
|
|
||||||
bool singleLogical; // treats the strings as a single logical string.
|
|
||||||
// locations will be reported from the first string.
|
|
||||||
|
|
||||||
// Set to true once peek() returns EndOfFile, so that we won't roll back
|
|
||||||
// once we've reached EndOfFile.
|
|
||||||
bool endOfFileReached;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _GLSLANG_SCAN_INCLUDED_
|
|
|
@ -1,93 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// This holds context specific to the GLSL scanner, which
|
|
||||||
// sits between the preprocessor scanner and parser.
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "ParseHelper.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
class TPpContext;
|
|
||||||
class TPpToken;
|
|
||||||
class TParserToken;
|
|
||||||
|
|
||||||
class TScanContext {
|
|
||||||
public:
|
|
||||||
explicit TScanContext(TParseContextBase& pc) :
|
|
||||||
parseContext(pc),
|
|
||||||
afterType(false), afterStruct(false),
|
|
||||||
field(false), afterBuffer(false) { }
|
|
||||||
virtual ~TScanContext() { }
|
|
||||||
|
|
||||||
static void fillInKeywordMap();
|
|
||||||
static void deleteKeywordMap();
|
|
||||||
|
|
||||||
int tokenize(TPpContext*, TParserToken&);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TScanContext(TScanContext&);
|
|
||||||
TScanContext& operator=(TScanContext&);
|
|
||||||
|
|
||||||
int tokenizeIdentifier();
|
|
||||||
int identifierOrType();
|
|
||||||
int reservedWord();
|
|
||||||
int identifierOrReserved(bool reserved);
|
|
||||||
int es30ReservedFromGLSL(int version);
|
|
||||||
int nonreservedKeyword(int esVersion, int nonEsVersion);
|
|
||||||
int precisionKeyword();
|
|
||||||
int matNxM();
|
|
||||||
int dMat();
|
|
||||||
int firstGenerationImage(bool inEs310);
|
|
||||||
int secondGenerationImage();
|
|
||||||
|
|
||||||
TParseContextBase& parseContext;
|
|
||||||
bool afterType; // true if we've recognized a type, so can only be looking for an identifier
|
|
||||||
bool afterStruct; // true if we've recognized the STRUCT keyword, so can only be looking for an identifier
|
|
||||||
bool field; // true if we're on a field, right after a '.'
|
|
||||||
bool afterBuffer; // true if we've recognized the BUFFER keyword
|
|
||||||
TSourceLoc loc;
|
|
||||||
TParserToken* parserToken;
|
|
||||||
TPpToken* ppToken;
|
|
||||||
|
|
||||||
const char* tokenText;
|
|
||||||
int keyword;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,446 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
|
||||||
// Copyright (C) 2017 ARM Limited.
|
|
||||||
// Copyright (C) 2015-2018 Google, Inc.
|
|
||||||
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Symbol table for parsing. Most functionality and main ideas
|
|
||||||
// are documented in the header file.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "SymbolTable.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// TType helper function needs a place to live.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Recursively generate mangled names.
|
|
||||||
//
|
|
||||||
void TType::buildMangledName(TString& mangledName) const
|
|
||||||
{
|
|
||||||
if (isMatrix())
|
|
||||||
mangledName += 'm';
|
|
||||||
else if (isVector())
|
|
||||||
mangledName += 'v';
|
|
||||||
|
|
||||||
switch (basicType) {
|
|
||||||
case EbtFloat: mangledName += 'f'; break;
|
|
||||||
case EbtInt: mangledName += 'i'; break;
|
|
||||||
case EbtUint: mangledName += 'u'; break;
|
|
||||||
case EbtBool: mangledName += 'b'; break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtDouble: mangledName += 'd'; break;
|
|
||||||
case EbtFloat16: mangledName += "f16"; break;
|
|
||||||
case EbtInt8: mangledName += "i8"; break;
|
|
||||||
case EbtUint8: mangledName += "u8"; break;
|
|
||||||
case EbtInt16: mangledName += "i16"; break;
|
|
||||||
case EbtUint16: mangledName += "u16"; break;
|
|
||||||
case EbtInt64: mangledName += "i64"; break;
|
|
||||||
case EbtUint64: mangledName += "u64"; break;
|
|
||||||
case EbtAtomicUint: mangledName += "au"; break;
|
|
||||||
case EbtAccStruct: mangledName += "as"; break;
|
|
||||||
case EbtRayQuery: mangledName += "rq"; break;
|
|
||||||
#endif
|
|
||||||
case EbtSampler:
|
|
||||||
switch (sampler.type) {
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case EbtFloat16: mangledName += "f16"; break;
|
|
||||||
#endif
|
|
||||||
case EbtInt: mangledName += "i"; break;
|
|
||||||
case EbtUint: mangledName += "u"; break;
|
|
||||||
default: break; // some compilers want this
|
|
||||||
}
|
|
||||||
if (sampler.isImageClass())
|
|
||||||
mangledName += "I"; // a normal image or subpass
|
|
||||||
else if (sampler.isPureSampler())
|
|
||||||
mangledName += "p"; // a "pure" sampler
|
|
||||||
else if (!sampler.isCombined())
|
|
||||||
mangledName += "t"; // a "pure" texture
|
|
||||||
else
|
|
||||||
mangledName += "s"; // traditional combined sampler
|
|
||||||
if (sampler.isArrayed())
|
|
||||||
mangledName += "A";
|
|
||||||
if (sampler.isShadow())
|
|
||||||
mangledName += "S";
|
|
||||||
if (sampler.isExternal())
|
|
||||||
mangledName += "E";
|
|
||||||
if (sampler.isYuv())
|
|
||||||
mangledName += "Y";
|
|
||||||
switch (sampler.dim) {
|
|
||||||
case Esd2D: mangledName += "2"; break;
|
|
||||||
case Esd3D: mangledName += "3"; break;
|
|
||||||
case EsdCube: mangledName += "C"; break;
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
case Esd1D: mangledName += "1"; break;
|
|
||||||
case EsdRect: mangledName += "R2"; break;
|
|
||||||
case EsdBuffer: mangledName += "B"; break;
|
|
||||||
case EsdSubpass: mangledName += "P"; break;
|
|
||||||
#endif
|
|
||||||
default: break; // some compilers want this
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_HLSL
|
|
||||||
if (sampler.hasReturnStruct()) {
|
|
||||||
// Name mangle for sampler return struct uses struct table index.
|
|
||||||
mangledName += "-tx-struct";
|
|
||||||
|
|
||||||
char text[16]; // plenty enough space for the small integers.
|
|
||||||
snprintf(text, sizeof(text), "%u-", sampler.getStructReturnIndex());
|
|
||||||
mangledName += text;
|
|
||||||
} else {
|
|
||||||
switch (sampler.getVectorSize()) {
|
|
||||||
case 1: mangledName += "1"; break;
|
|
||||||
case 2: mangledName += "2"; break;
|
|
||||||
case 3: mangledName += "3"; break;
|
|
||||||
case 4: break; // default to prior name mangle behavior
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (sampler.isMultiSample())
|
|
||||||
mangledName += "M";
|
|
||||||
break;
|
|
||||||
case EbtStruct:
|
|
||||||
case EbtBlock:
|
|
||||||
if (basicType == EbtStruct)
|
|
||||||
mangledName += "struct-";
|
|
||||||
else
|
|
||||||
mangledName += "block-";
|
|
||||||
if (typeName)
|
|
||||||
mangledName += *typeName;
|
|
||||||
for (unsigned int i = 0; i < structure->size(); ++i) {
|
|
||||||
mangledName += '-';
|
|
||||||
(*structure)[i].type->buildMangledName(mangledName);
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getVectorSize() > 0)
|
|
||||||
mangledName += static_cast<char>('0' + getVectorSize());
|
|
||||||
else {
|
|
||||||
mangledName += static_cast<char>('0' + getMatrixCols());
|
|
||||||
mangledName += static_cast<char>('0' + getMatrixRows());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arraySizes) {
|
|
||||||
const int maxSize = 11;
|
|
||||||
char buf[maxSize];
|
|
||||||
for (int i = 0; i < arraySizes->getNumDims(); ++i) {
|
|
||||||
if (arraySizes->getDimNode(i)) {
|
|
||||||
if (arraySizes->getDimNode(i)->getAsSymbolNode())
|
|
||||||
snprintf(buf, maxSize, "s%d", arraySizes->getDimNode(i)->getAsSymbolNode()->getId());
|
|
||||||
else
|
|
||||||
snprintf(buf, maxSize, "s%p", arraySizes->getDimNode(i));
|
|
||||||
} else
|
|
||||||
snprintf(buf, maxSize, "%d", arraySizes->getDimSize(i));
|
|
||||||
mangledName += '[';
|
|
||||||
mangledName += buf;
|
|
||||||
mangledName += ']';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
|
|
||||||
//
|
|
||||||
// Dump functions.
|
|
||||||
//
|
|
||||||
|
|
||||||
void TSymbol::dumpExtensions(TInfoSink& infoSink) const
|
|
||||||
{
|
|
||||||
int numExtensions = getNumExtensions();
|
|
||||||
if (numExtensions) {
|
|
||||||
infoSink.debug << " <";
|
|
||||||
|
|
||||||
for (int i = 0; i < numExtensions; i++)
|
|
||||||
infoSink.debug << getExtensions()[i] << ",";
|
|
||||||
|
|
||||||
infoSink.debug << ">";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TVariable::dump(TInfoSink& infoSink, bool complete) const
|
|
||||||
{
|
|
||||||
if (complete) {
|
|
||||||
infoSink.debug << getName().c_str() << ": " << type.getCompleteString();
|
|
||||||
dumpExtensions(infoSink);
|
|
||||||
} else {
|
|
||||||
infoSink.debug << getName().c_str() << ": " << type.getStorageQualifierString() << " "
|
|
||||||
<< type.getBasicTypeString();
|
|
||||||
|
|
||||||
if (type.isArray())
|
|
||||||
infoSink.debug << "[0]";
|
|
||||||
}
|
|
||||||
|
|
||||||
infoSink.debug << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void TFunction::dump(TInfoSink& infoSink, bool complete) const
|
|
||||||
{
|
|
||||||
if (complete) {
|
|
||||||
infoSink.debug << getName().c_str() << ": " << returnType.getCompleteString() << " " << getName().c_str()
|
|
||||||
<< "(";
|
|
||||||
|
|
||||||
int numParams = getParamCount();
|
|
||||||
for (int i = 0; i < numParams; i++) {
|
|
||||||
const TParameter ¶m = parameters[i];
|
|
||||||
infoSink.debug << param.type->getCompleteString() << " "
|
|
||||||
<< (param.type->isStruct() ? "of " + param.type->getTypeName() + " " : "")
|
|
||||||
<< (param.name ? *param.name : "") << (i < numParams - 1 ? "," : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
infoSink.debug << ")";
|
|
||||||
dumpExtensions(infoSink);
|
|
||||||
} else {
|
|
||||||
infoSink.debug << getName().c_str() << ": " << returnType.getBasicTypeString() << " "
|
|
||||||
<< getMangledName().c_str() << "n";
|
|
||||||
}
|
|
||||||
|
|
||||||
infoSink.debug << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void TAnonMember::dump(TInfoSink& TInfoSink, bool) const
|
|
||||||
{
|
|
||||||
TInfoSink.debug << "anonymous member " << getMemberNumber() << " of " << getAnonContainer().getName().c_str()
|
|
||||||
<< "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
void TSymbolTableLevel::dump(TInfoSink& infoSink, bool complete) const
|
|
||||||
{
|
|
||||||
tLevel::const_iterator it;
|
|
||||||
for (it = level.begin(); it != level.end(); ++it)
|
|
||||||
(*it).second->dump(infoSink, complete);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TSymbolTable::dump(TInfoSink& infoSink, bool complete) const
|
|
||||||
{
|
|
||||||
for (int level = currentLevel(); level >= 0; --level) {
|
|
||||||
infoSink.debug << "LEVEL " << level << "\n";
|
|
||||||
table[level]->dump(infoSink, complete);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Functions have buried pointers to delete.
|
|
||||||
//
|
|
||||||
TFunction::~TFunction()
|
|
||||||
{
|
|
||||||
for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i)
|
|
||||||
delete (*i).type;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Symbol table levels are a map of pointers to symbols that have to be deleted.
|
|
||||||
//
|
|
||||||
TSymbolTableLevel::~TSymbolTableLevel()
|
|
||||||
{
|
|
||||||
for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
|
|
||||||
delete (*it).second;
|
|
||||||
|
|
||||||
delete [] defaultPrecision;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Change all function entries in the table with the non-mangled name
|
|
||||||
// to be related to the provided built-in operation.
|
|
||||||
//
|
|
||||||
void TSymbolTableLevel::relateToOperator(const char* name, TOperator op)
|
|
||||||
{
|
|
||||||
tLevel::const_iterator candidate = level.lower_bound(name);
|
|
||||||
while (candidate != level.end()) {
|
|
||||||
const TString& candidateName = (*candidate).first;
|
|
||||||
TString::size_type parenAt = candidateName.find_first_of('(');
|
|
||||||
if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) {
|
|
||||||
TFunction* function = (*candidate).second->getAsFunction();
|
|
||||||
function->relateToOperator(op);
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
++candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make all function overloads of the given name require an extension(s).
|
|
||||||
// Should only be used for a version/profile that actually needs the extension(s).
|
|
||||||
void TSymbolTableLevel::setFunctionExtensions(const char* name, int num, const char* const extensions[])
|
|
||||||
{
|
|
||||||
tLevel::const_iterator candidate = level.lower_bound(name);
|
|
||||||
while (candidate != level.end()) {
|
|
||||||
const TString& candidateName = (*candidate).first;
|
|
||||||
TString::size_type parenAt = candidateName.find_first_of('(');
|
|
||||||
if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0) {
|
|
||||||
TSymbol* symbol = candidate->second;
|
|
||||||
symbol->setExtensions(num, extensions);
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
++candidate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Make all symbols in this table level read only.
|
|
||||||
//
|
|
||||||
void TSymbolTableLevel::readOnly()
|
|
||||||
{
|
|
||||||
for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
|
|
||||||
(*it).second->makeReadOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Copy a symbol, but the copy is writable; call readOnly() afterward if that's not desired.
|
|
||||||
//
|
|
||||||
TSymbol::TSymbol(const TSymbol& copyOf)
|
|
||||||
{
|
|
||||||
name = NewPoolTString(copyOf.name->c_str());
|
|
||||||
uniqueId = copyOf.uniqueId;
|
|
||||||
writable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf)
|
|
||||||
{
|
|
||||||
type.deepCopy(copyOf.type);
|
|
||||||
userType = copyOf.userType;
|
|
||||||
|
|
||||||
// we don't support specialization-constant subtrees in cloned tables, only extensions
|
|
||||||
constSubtree = nullptr;
|
|
||||||
extensions = nullptr;
|
|
||||||
memberExtensions = nullptr;
|
|
||||||
if (copyOf.getNumExtensions() > 0)
|
|
||||||
setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions());
|
|
||||||
if (copyOf.hasMemberExtensions()) {
|
|
||||||
for (int m = 0; m < (int)copyOf.type.getStruct()->size(); ++m) {
|
|
||||||
if (copyOf.getNumMemberExtensions(m) > 0)
|
|
||||||
setMemberExtensions(m, copyOf.getNumMemberExtensions(m), copyOf.getMemberExtensions(m));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! copyOf.constArray.empty()) {
|
|
||||||
assert(! copyOf.type.isStruct());
|
|
||||||
TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size());
|
|
||||||
constArray = newArray;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TVariable* TVariable::clone() const
|
|
||||||
{
|
|
||||||
TVariable *variable = new TVariable(*this);
|
|
||||||
|
|
||||||
return variable;
|
|
||||||
}
|
|
||||||
|
|
||||||
TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
|
|
||||||
TParameter param;
|
|
||||||
parameters.push_back(param);
|
|
||||||
parameters.back().copyParam(copyOf.parameters[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions = nullptr;
|
|
||||||
if (copyOf.getNumExtensions() > 0)
|
|
||||||
setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions());
|
|
||||||
returnType.deepCopy(copyOf.returnType);
|
|
||||||
mangledName = copyOf.mangledName;
|
|
||||||
op = copyOf.op;
|
|
||||||
defined = copyOf.defined;
|
|
||||||
prototyped = copyOf.prototyped;
|
|
||||||
implicitThis = copyOf.implicitThis;
|
|
||||||
illegalImplicitThis = copyOf.illegalImplicitThis;
|
|
||||||
defaultParamCount = copyOf.defaultParamCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
TFunction* TFunction::clone() const
|
|
||||||
{
|
|
||||||
TFunction *function = new TFunction(*this);
|
|
||||||
|
|
||||||
return function;
|
|
||||||
}
|
|
||||||
|
|
||||||
TAnonMember* TAnonMember::clone() const
|
|
||||||
{
|
|
||||||
// Anonymous members of a given block should be cloned at a higher level,
|
|
||||||
// where they can all be assured to still end up pointing to a single
|
|
||||||
// copy of the original container.
|
|
||||||
assert(0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSymbolTableLevel* TSymbolTableLevel::clone() const
|
|
||||||
{
|
|
||||||
TSymbolTableLevel *symTableLevel = new TSymbolTableLevel();
|
|
||||||
symTableLevel->anonId = anonId;
|
|
||||||
symTableLevel->thisLevel = thisLevel;
|
|
||||||
std::vector<bool> containerCopied(anonId, false);
|
|
||||||
tLevel::const_iterator iter;
|
|
||||||
for (iter = level.begin(); iter != level.end(); ++iter) {
|
|
||||||
const TAnonMember* anon = iter->second->getAsAnonMember();
|
|
||||||
if (anon) {
|
|
||||||
// Insert all the anonymous members of this same container at once,
|
|
||||||
// avoid inserting the remaining members in the future, once this has been done,
|
|
||||||
// allowing them to all be part of the same new container.
|
|
||||||
if (! containerCopied[anon->getAnonId()]) {
|
|
||||||
TVariable* container = anon->getAnonContainer().clone();
|
|
||||||
container->changeName(NewPoolTString(""));
|
|
||||||
// insert the container and all its members
|
|
||||||
symTableLevel->insert(*container, false);
|
|
||||||
containerCopied[anon->getAnonId()] = true;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
symTableLevel->insert(*iter->second->clone(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return symTableLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TSymbolTable::copyTable(const TSymbolTable& copyOf)
|
|
||||||
{
|
|
||||||
assert(adoptedLevels == copyOf.adoptedLevels);
|
|
||||||
|
|
||||||
uniqueId = copyOf.uniqueId;
|
|
||||||
noBuiltInRedeclarations = copyOf.noBuiltInRedeclarations;
|
|
||||||
separateNameSpaces = copyOf.separateNameSpaces;
|
|
||||||
for (unsigned int i = copyOf.adoptedLevels; i < copyOf.table.size(); ++i)
|
|
||||||
table.push_back(copyOf.table[i]->clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
|
@ -1,885 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
// Copyright (C) 2015-2018 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _SYMBOL_TABLE_INCLUDED_
|
|
||||||
#define _SYMBOL_TABLE_INCLUDED_
|
|
||||||
|
|
||||||
//
|
|
||||||
// Symbol table for parsing. Has these design characteristics:
|
|
||||||
//
|
|
||||||
// * Same symbol table can be used to compile many shaders, to preserve
|
|
||||||
// effort of creating and loading with the large numbers of built-in
|
|
||||||
// symbols.
|
|
||||||
//
|
|
||||||
// --> This requires a copy mechanism, so initial pools used to create
|
|
||||||
// the shared information can be popped. Done through "clone"
|
|
||||||
// methods.
|
|
||||||
//
|
|
||||||
// * Name mangling will be used to give each function a unique name
|
|
||||||
// so that symbol table lookups are never ambiguous. This allows
|
|
||||||
// a simpler symbol table structure.
|
|
||||||
//
|
|
||||||
// * Pushing and popping of scope, so symbol table will really be a stack
|
|
||||||
// of symbol tables. Searched from the top, with new inserts going into
|
|
||||||
// the top.
|
|
||||||
//
|
|
||||||
// * Constants: Compile time constant symbols will keep their values
|
|
||||||
// in the symbol table. The parser can substitute constants at parse
|
|
||||||
// time, including doing constant folding and constant propagation.
|
|
||||||
//
|
|
||||||
// * No temporaries: Temporaries made from operations (+, --, .xy, etc.)
|
|
||||||
// are tracked in the intermediate representation, not the symbol table.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "../Include/Common.h"
|
|
||||||
#include "../Include/intermediate.h"
|
|
||||||
#include "../Include/InfoSink.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Symbol base class. (Can build functions or variables out of these...)
|
|
||||||
//
|
|
||||||
|
|
||||||
class TVariable;
|
|
||||||
class TFunction;
|
|
||||||
class TAnonMember;
|
|
||||||
|
|
||||||
typedef TVector<const char*> TExtensionList;
|
|
||||||
|
|
||||||
class TSymbol {
|
|
||||||
public:
|
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
|
||||||
explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { }
|
|
||||||
virtual TSymbol* clone() const = 0;
|
|
||||||
virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool
|
|
||||||
|
|
||||||
virtual const TString& getName() const { return *name; }
|
|
||||||
virtual void changeName(const TString* newName) { name = newName; }
|
|
||||||
virtual void addPrefix(const char* prefix)
|
|
||||||
{
|
|
||||||
TString newName(prefix);
|
|
||||||
newName.append(*name);
|
|
||||||
changeName(NewPoolTString(newName.c_str()));
|
|
||||||
}
|
|
||||||
virtual const TString& getMangledName() const { return getName(); }
|
|
||||||
virtual TFunction* getAsFunction() { return 0; }
|
|
||||||
virtual const TFunction* getAsFunction() const { return 0; }
|
|
||||||
virtual TVariable* getAsVariable() { return 0; }
|
|
||||||
virtual const TVariable* getAsVariable() const { return 0; }
|
|
||||||
virtual const TAnonMember* getAsAnonMember() const { return 0; }
|
|
||||||
virtual const TType& getType() const = 0;
|
|
||||||
virtual TType& getWritableType() = 0;
|
|
||||||
virtual void setUniqueId(int id) { uniqueId = id; }
|
|
||||||
virtual int getUniqueId() const { return uniqueId; }
|
|
||||||
virtual void setExtensions(int numExts, const char* const exts[])
|
|
||||||
{
|
|
||||||
assert(extensions == 0);
|
|
||||||
assert(numExts > 0);
|
|
||||||
extensions = NewPoolObject(extensions);
|
|
||||||
for (int e = 0; e < numExts; ++e)
|
|
||||||
extensions->push_back(exts[e]);
|
|
||||||
}
|
|
||||||
virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); }
|
|
||||||
virtual const char** getExtensions() const { return extensions->data(); }
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0;
|
|
||||||
void dumpExtensions(TInfoSink& infoSink) const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual bool isReadOnly() const { return ! writable; }
|
|
||||||
virtual void makeReadOnly() { writable = false; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit TSymbol(const TSymbol&);
|
|
||||||
TSymbol& operator=(const TSymbol&);
|
|
||||||
|
|
||||||
const TString *name;
|
|
||||||
unsigned int uniqueId; // For cross-scope comparing during code generation
|
|
||||||
|
|
||||||
// For tracking what extensions must be present
|
|
||||||
// (don't use if correct version/profile is present).
|
|
||||||
TExtensionList* extensions; // an array of pointers to existing constant char strings
|
|
||||||
|
|
||||||
//
|
|
||||||
// N.B.: Non-const functions that will be generally used should assert on this,
|
|
||||||
// to avoid overwriting shared symbol-table information.
|
|
||||||
//
|
|
||||||
bool writable;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Variable class, meaning a symbol that's not a function.
|
|
||||||
//
|
|
||||||
// There could be a separate class hierarchy for Constant variables;
|
|
||||||
// Only one of int, bool, or float, (or none) is correct for
|
|
||||||
// any particular use, but it's easy to do this way, and doesn't
|
|
||||||
// seem worth having separate classes, and "getConst" can't simply return
|
|
||||||
// different values for different types polymorphically, so this is
|
|
||||||
// just simple and pragmatic.
|
|
||||||
//
|
|
||||||
class TVariable : public TSymbol {
|
|
||||||
public:
|
|
||||||
TVariable(const TString *name, const TType& t, bool uT = false )
|
|
||||||
: TSymbol(name),
|
|
||||||
userType(uT),
|
|
||||||
constSubtree(nullptr),
|
|
||||||
memberExtensions(nullptr),
|
|
||||||
anonId(-1)
|
|
||||||
{ type.shallowCopy(t); }
|
|
||||||
virtual TVariable* clone() const;
|
|
||||||
virtual ~TVariable() { }
|
|
||||||
|
|
||||||
virtual TVariable* getAsVariable() { return this; }
|
|
||||||
virtual const TVariable* getAsVariable() const { return this; }
|
|
||||||
virtual const TType& getType() const { return type; }
|
|
||||||
virtual TType& getWritableType() { assert(writable); return type; }
|
|
||||||
virtual bool isUserType() const { return userType; }
|
|
||||||
virtual const TConstUnionArray& getConstArray() const { return constArray; }
|
|
||||||
virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; }
|
|
||||||
virtual void setConstArray(const TConstUnionArray& array) { constArray = array; }
|
|
||||||
virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
|
|
||||||
virtual TIntermTyped* getConstSubtree() const { return constSubtree; }
|
|
||||||
virtual void setAnonId(int i) { anonId = i; }
|
|
||||||
virtual int getAnonId() const { return anonId; }
|
|
||||||
|
|
||||||
virtual void setMemberExtensions(int member, int numExts, const char* const exts[])
|
|
||||||
{
|
|
||||||
assert(type.isStruct());
|
|
||||||
assert(numExts > 0);
|
|
||||||
if (memberExtensions == nullptr) {
|
|
||||||
memberExtensions = NewPoolObject(memberExtensions);
|
|
||||||
memberExtensions->resize(type.getStruct()->size());
|
|
||||||
}
|
|
||||||
for (int e = 0; e < numExts; ++e)
|
|
||||||
(*memberExtensions)[member].push_back(exts[e]);
|
|
||||||
}
|
|
||||||
virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; }
|
|
||||||
virtual int getNumMemberExtensions(int member) const
|
|
||||||
{
|
|
||||||
return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size();
|
|
||||||
}
|
|
||||||
virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); }
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
virtual void dump(TInfoSink& infoSink, bool complete = false) const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit TVariable(const TVariable&);
|
|
||||||
TVariable& operator=(const TVariable&);
|
|
||||||
|
|
||||||
TType type;
|
|
||||||
bool userType;
|
|
||||||
|
|
||||||
// we are assuming that Pool Allocator will free the memory allocated to unionArray
|
|
||||||
// when this object is destroyed
|
|
||||||
|
|
||||||
TConstUnionArray constArray; // for compile-time constant value
|
|
||||||
TIntermTyped* constSubtree; // for specialization constant computation
|
|
||||||
TVector<TExtensionList>* memberExtensions; // per-member extension list, allocated only when needed
|
|
||||||
int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// The function sub-class of symbols and the parser will need to
|
|
||||||
// share this definition of a function parameter.
|
|
||||||
//
|
|
||||||
struct TParameter {
|
|
||||||
TString *name;
|
|
||||||
TType* type;
|
|
||||||
TIntermTyped* defaultValue;
|
|
||||||
void copyParam(const TParameter& param)
|
|
||||||
{
|
|
||||||
if (param.name)
|
|
||||||
name = NewPoolTString(param.name->c_str());
|
|
||||||
else
|
|
||||||
name = 0;
|
|
||||||
type = param.type->clone();
|
|
||||||
defaultValue = param.defaultValue;
|
|
||||||
}
|
|
||||||
TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; }
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// The function sub-class of a symbol.
|
|
||||||
//
|
|
||||||
class TFunction : public TSymbol {
|
|
||||||
public:
|
|
||||||
explicit TFunction(TOperator o) :
|
|
||||||
TSymbol(0),
|
|
||||||
op(o),
|
|
||||||
defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { }
|
|
||||||
TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
|
|
||||||
TSymbol(name),
|
|
||||||
mangledName(*name + '('),
|
|
||||||
op(tOp),
|
|
||||||
defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0)
|
|
||||||
{
|
|
||||||
returnType.shallowCopy(retType);
|
|
||||||
declaredBuiltIn = retType.getQualifier().builtIn;
|
|
||||||
}
|
|
||||||
virtual TFunction* clone() const override;
|
|
||||||
virtual ~TFunction();
|
|
||||||
|
|
||||||
virtual TFunction* getAsFunction() override { return this; }
|
|
||||||
virtual const TFunction* getAsFunction() const override { return this; }
|
|
||||||
|
|
||||||
// Install 'p' as the (non-'this') last parameter.
|
|
||||||
// Non-'this' parameters are reflected in both the list of parameters and the
|
|
||||||
// mangled name.
|
|
||||||
virtual void addParameter(TParameter& p)
|
|
||||||
{
|
|
||||||
assert(writable);
|
|
||||||
parameters.push_back(p);
|
|
||||||
p.type->appendMangledName(mangledName);
|
|
||||||
|
|
||||||
if (p.defaultValue != nullptr)
|
|
||||||
defaultParamCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Install 'this' as the first parameter.
|
|
||||||
// 'this' is reflected in the list of parameters, but not the mangled name.
|
|
||||||
virtual void addThisParameter(TType& type, const char* name)
|
|
||||||
{
|
|
||||||
TParameter p = { NewPoolTString(name), new TType, nullptr };
|
|
||||||
p.type->shallowCopy(type);
|
|
||||||
parameters.insert(parameters.begin(), p);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void addPrefix(const char* prefix) override
|
|
||||||
{
|
|
||||||
TSymbol::addPrefix(prefix);
|
|
||||||
mangledName.insert(0, prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void removePrefix(const TString& prefix)
|
|
||||||
{
|
|
||||||
assert(mangledName.compare(0, prefix.size(), prefix) == 0);
|
|
||||||
mangledName.erase(0, prefix.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const TString& getMangledName() const override { return mangledName; }
|
|
||||||
virtual const TType& getType() const override { return returnType; }
|
|
||||||
virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; }
|
|
||||||
virtual TType& getWritableType() override { return returnType; }
|
|
||||||
virtual void relateToOperator(TOperator o) { assert(writable); op = o; }
|
|
||||||
virtual TOperator getBuiltInOp() const { return op; }
|
|
||||||
virtual void setDefined() { assert(writable); defined = true; }
|
|
||||||
virtual bool isDefined() const { return defined; }
|
|
||||||
virtual void setPrototyped() { assert(writable); prototyped = true; }
|
|
||||||
virtual bool isPrototyped() const { return prototyped; }
|
|
||||||
virtual void setImplicitThis() { assert(writable); implicitThis = true; }
|
|
||||||
virtual bool hasImplicitThis() const { return implicitThis; }
|
|
||||||
virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; }
|
|
||||||
virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; }
|
|
||||||
|
|
||||||
// Return total number of parameters
|
|
||||||
virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
|
|
||||||
// Return number of parameters with default values.
|
|
||||||
virtual int getDefaultParamCount() const { return defaultParamCount; }
|
|
||||||
// Return number of fixed parameters (without default values)
|
|
||||||
virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); }
|
|
||||||
|
|
||||||
virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
|
|
||||||
virtual const TParameter& operator[](int i) const { return parameters[i]; }
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit TFunction(const TFunction&);
|
|
||||||
TFunction& operator=(const TFunction&);
|
|
||||||
|
|
||||||
typedef TVector<TParameter> TParamList;
|
|
||||||
TParamList parameters;
|
|
||||||
TType returnType;
|
|
||||||
TBuiltInVariable declaredBuiltIn;
|
|
||||||
|
|
||||||
TString mangledName;
|
|
||||||
TOperator op;
|
|
||||||
bool defined;
|
|
||||||
bool prototyped;
|
|
||||||
bool implicitThis; // True if this function is allowed to see all members of 'this'
|
|
||||||
bool illegalImplicitThis; // True if this function is not supposed to have access to dynamic members of 'this',
|
|
||||||
// even if it finds member variables in the symbol table.
|
|
||||||
// This is important for a static member function that has member variables in scope,
|
|
||||||
// but is not allowed to use them, or see hidden symbols instead.
|
|
||||||
int defaultParamCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Members of anonymous blocks are a kind of TSymbol. They are not hidden in
|
|
||||||
// the symbol table behind a container; rather they are visible and point to
|
|
||||||
// their anonymous container. (The anonymous container is found through the
|
|
||||||
// member, not the other way around.)
|
|
||||||
//
|
|
||||||
class TAnonMember : public TSymbol {
|
|
||||||
public:
|
|
||||||
TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { }
|
|
||||||
virtual TAnonMember* clone() const override;
|
|
||||||
virtual ~TAnonMember() { }
|
|
||||||
|
|
||||||
virtual const TAnonMember* getAsAnonMember() const override { return this; }
|
|
||||||
virtual const TVariable& getAnonContainer() const { return anonContainer; }
|
|
||||||
virtual unsigned int getMemberNumber() const { return memberNumber; }
|
|
||||||
|
|
||||||
virtual const TType& getType() const override
|
|
||||||
{
|
|
||||||
const TTypeList& types = *anonContainer.getType().getStruct();
|
|
||||||
return *types[memberNumber].type;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual TType& getWritableType() override
|
|
||||||
{
|
|
||||||
assert(writable);
|
|
||||||
const TTypeList& types = *anonContainer.getType().getStruct();
|
|
||||||
return *types[memberNumber].type;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setExtensions(int numExts, const char* const exts[]) override
|
|
||||||
{
|
|
||||||
anonContainer.setMemberExtensions(memberNumber, numExts, exts);
|
|
||||||
}
|
|
||||||
virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); }
|
|
||||||
virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); }
|
|
||||||
|
|
||||||
virtual int getAnonId() const { return anonId; }
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit TAnonMember(const TAnonMember&);
|
|
||||||
TAnonMember& operator=(const TAnonMember&);
|
|
||||||
|
|
||||||
TVariable& anonContainer;
|
|
||||||
unsigned int memberNumber;
|
|
||||||
int anonId;
|
|
||||||
};
|
|
||||||
|
|
||||||
class TSymbolTableLevel {
|
|
||||||
public:
|
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
|
||||||
TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { }
|
|
||||||
~TSymbolTableLevel();
|
|
||||||
|
|
||||||
bool insert(TSymbol& symbol, bool separateNameSpaces)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// returning true means symbol was added to the table with no semantic errors
|
|
||||||
//
|
|
||||||
const TString& name = symbol.getName();
|
|
||||||
if (name == "") {
|
|
||||||
symbol.getAsVariable()->setAnonId(anonId++);
|
|
||||||
// An empty name means an anonymous container, exposing its members to the external scope.
|
|
||||||
// Give it a name and insert its members in the symbol table, pointing to the container.
|
|
||||||
char buf[20];
|
|
||||||
snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId());
|
|
||||||
symbol.changeName(NewPoolTString(buf));
|
|
||||||
|
|
||||||
return insertAnonymousMembers(symbol, 0);
|
|
||||||
} else {
|
|
||||||
// Check for redefinition errors:
|
|
||||||
// - STL itself will tell us if there is a direct name collision, with name mangling, at this level
|
|
||||||
// - additionally, check for function-redefining-variable name collisions
|
|
||||||
const TString& insertName = symbol.getMangledName();
|
|
||||||
if (symbol.getAsFunction()) {
|
|
||||||
// make sure there isn't a variable of this name
|
|
||||||
if (! separateNameSpaces && level.find(name) != level.end())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// insert, and whatever happens is okay
|
|
||||||
level.insert(tLevelPair(insertName, &symbol));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else
|
|
||||||
return level.insert(tLevelPair(insertName, &symbol)).second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add more members to an already inserted aggregate object
|
|
||||||
bool amend(TSymbol& symbol, int firstNewMember)
|
|
||||||
{
|
|
||||||
// See insert() for comments on basic explanation of insert.
|
|
||||||
// This operates similarly, but more simply.
|
|
||||||
// Only supporting amend of anonymous blocks so far.
|
|
||||||
if (IsAnonymous(symbol.getName()))
|
|
||||||
return insertAnonymousMembers(symbol, firstNewMember);
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool insertAnonymousMembers(TSymbol& symbol, int firstMember)
|
|
||||||
{
|
|
||||||
const TTypeList& types = *symbol.getAsVariable()->getType().getStruct();
|
|
||||||
for (unsigned int m = firstMember; m < types.size(); ++m) {
|
|
||||||
TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId());
|
|
||||||
if (! level.insert(tLevelPair(member->getMangledName(), member)).second)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSymbol* find(const TString& name) const
|
|
||||||
{
|
|
||||||
tLevel::const_iterator it = level.find(name);
|
|
||||||
if (it == level.end())
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return (*it).second;
|
|
||||||
}
|
|
||||||
|
|
||||||
void findFunctionNameList(const TString& name, TVector<const TFunction*>& list)
|
|
||||||
{
|
|
||||||
size_t parenAt = name.find_first_of('(');
|
|
||||||
TString base(name, 0, parenAt + 1);
|
|
||||||
|
|
||||||
tLevel::const_iterator begin = level.lower_bound(base);
|
|
||||||
base[parenAt] = ')'; // assume ')' is lexically after '('
|
|
||||||
tLevel::const_iterator end = level.upper_bound(base);
|
|
||||||
for (tLevel::const_iterator it = begin; it != end; ++it)
|
|
||||||
list.push_back(it->second->getAsFunction());
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if there is already a function in the table having the given non-function-style name.
|
|
||||||
bool hasFunctionName(const TString& name) const
|
|
||||||
{
|
|
||||||
tLevel::const_iterator candidate = level.lower_bound(name);
|
|
||||||
if (candidate != level.end()) {
|
|
||||||
const TString& candidateName = (*candidate).first;
|
|
||||||
TString::size_type parenAt = candidateName.find_first_of('(');
|
|
||||||
if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0)
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if there is a variable at this level having the given non-function-style name.
|
|
||||||
// Return true if name is found, and set variable to true if the name was a variable.
|
|
||||||
bool findFunctionVariableName(const TString& name, bool& variable) const
|
|
||||||
{
|
|
||||||
tLevel::const_iterator candidate = level.lower_bound(name);
|
|
||||||
if (candidate != level.end()) {
|
|
||||||
const TString& candidateName = (*candidate).first;
|
|
||||||
TString::size_type parenAt = candidateName.find_first_of('(');
|
|
||||||
if (parenAt == candidateName.npos) {
|
|
||||||
// not a mangled name
|
|
||||||
if (candidateName == name) {
|
|
||||||
// found a variable name match
|
|
||||||
variable = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// a mangled name
|
|
||||||
if (candidateName.compare(0, parenAt, name) == 0) {
|
|
||||||
// found a function name match
|
|
||||||
variable = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use this to do a lazy 'push' of precision defaults the first time
|
|
||||||
// a precision statement is seen in a new scope. Leave it at 0 for
|
|
||||||
// when no push was needed. Thus, it is not the current defaults,
|
|
||||||
// it is what to restore the defaults to when popping a level.
|
|
||||||
void setPreviousDefaultPrecisions(const TPrecisionQualifier *p)
|
|
||||||
{
|
|
||||||
// can call multiple times at one scope, will only latch on first call,
|
|
||||||
// as we're tracking the previous scope's values, not the current values
|
|
||||||
if (defaultPrecision != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
defaultPrecision = new TPrecisionQualifier[EbtNumTypes];
|
|
||||||
for (int t = 0; t < EbtNumTypes; ++t)
|
|
||||||
defaultPrecision[t] = p[t];
|
|
||||||
}
|
|
||||||
|
|
||||||
void getPreviousDefaultPrecisions(TPrecisionQualifier *p)
|
|
||||||
{
|
|
||||||
// can be called for table level pops that didn't set the
|
|
||||||
// defaults
|
|
||||||
if (defaultPrecision == 0 || p == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int t = 0; t < EbtNumTypes; ++t)
|
|
||||||
p[t] = defaultPrecision[t];
|
|
||||||
}
|
|
||||||
|
|
||||||
void relateToOperator(const char* name, TOperator op);
|
|
||||||
void setFunctionExtensions(const char* name, int num, const char* const extensions[]);
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
void dump(TInfoSink& infoSink, bool complete = false) const;
|
|
||||||
#endif
|
|
||||||
TSymbolTableLevel* clone() const;
|
|
||||||
void readOnly();
|
|
||||||
|
|
||||||
void setThisLevel() { thisLevel = true; }
|
|
||||||
bool isThisLevel() const { return thisLevel; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit TSymbolTableLevel(TSymbolTableLevel&);
|
|
||||||
TSymbolTableLevel& operator=(TSymbolTableLevel&);
|
|
||||||
|
|
||||||
typedef std::map<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const TString, TSymbol*> > > tLevel;
|
|
||||||
typedef const tLevel::value_type tLevelPair;
|
|
||||||
typedef std::pair<tLevel::iterator, bool> tInsertResult;
|
|
||||||
|
|
||||||
tLevel level; // named mappings
|
|
||||||
TPrecisionQualifier *defaultPrecision;
|
|
||||||
int anonId;
|
|
||||||
bool thisLevel; // True if this level of the symbol table is a structure scope containing member function
|
|
||||||
// that are supposed to see anonymous access to member variables.
|
|
||||||
};
|
|
||||||
|
|
||||||
class TSymbolTable {
|
|
||||||
public:
|
|
||||||
TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// This symbol table cannot be used until push() is called.
|
|
||||||
//
|
|
||||||
}
|
|
||||||
~TSymbolTable()
|
|
||||||
{
|
|
||||||
// this can be called explicitly; safest to code it so it can be called multiple times
|
|
||||||
|
|
||||||
// don't deallocate levels passed in from elsewhere
|
|
||||||
while (table.size() > adoptedLevels)
|
|
||||||
pop(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void adoptLevels(TSymbolTable& symTable)
|
|
||||||
{
|
|
||||||
for (unsigned int level = 0; level < symTable.table.size(); ++level) {
|
|
||||||
table.push_back(symTable.table[level]);
|
|
||||||
++adoptedLevels;
|
|
||||||
}
|
|
||||||
uniqueId = symTable.uniqueId;
|
|
||||||
noBuiltInRedeclarations = symTable.noBuiltInRedeclarations;
|
|
||||||
separateNameSpaces = symTable.separateNameSpaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// While level adopting is generic, the methods below enact a the following
|
|
||||||
// convention for levels:
|
|
||||||
// 0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables
|
|
||||||
// 1: per-stage built-ins, shared across all compiles, but a different copy per stage
|
|
||||||
// 2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins
|
|
||||||
// 3: user-shader globals
|
|
||||||
//
|
|
||||||
protected:
|
|
||||||
static const int globalLevel = 3;
|
|
||||||
bool isSharedLevel(int level) { return level <= 1; } // exclude all per-compile levels
|
|
||||||
bool isBuiltInLevel(int level) { return level <= 2; } // exclude user globals
|
|
||||||
bool isGlobalLevel(int level) { return level <= globalLevel; } // include user globals
|
|
||||||
public:
|
|
||||||
bool isEmpty() { return table.size() == 0; }
|
|
||||||
bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
|
|
||||||
bool atGlobalLevel() { return isGlobalLevel(currentLevel()); }
|
|
||||||
|
|
||||||
void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
|
|
||||||
void setSeparateNameSpaces() { separateNameSpaces = true; }
|
|
||||||
|
|
||||||
void push()
|
|
||||||
{
|
|
||||||
table.push_back(new TSymbolTableLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a new symbol-table level to represent the scope introduced by a structure
|
|
||||||
// containing member functions, such that the member functions can find anonymous
|
|
||||||
// references to member variables.
|
|
||||||
//
|
|
||||||
// 'thisSymbol' should have a name of "" to trigger anonymous structure-member
|
|
||||||
// symbol finds.
|
|
||||||
void pushThis(TSymbol& thisSymbol)
|
|
||||||
{
|
|
||||||
assert(thisSymbol.getName().size() == 0);
|
|
||||||
table.push_back(new TSymbolTableLevel);
|
|
||||||
table.back()->setThisLevel();
|
|
||||||
insert(thisSymbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop(TPrecisionQualifier *p)
|
|
||||||
{
|
|
||||||
table[currentLevel()]->getPreviousDefaultPrecisions(p);
|
|
||||||
delete table.back();
|
|
||||||
table.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Insert a visible symbol into the symbol table so it can
|
|
||||||
// be found later by name.
|
|
||||||
//
|
|
||||||
// Returns false if the was a name collision.
|
|
||||||
//
|
|
||||||
bool insert(TSymbol& symbol)
|
|
||||||
{
|
|
||||||
symbol.setUniqueId(++uniqueId);
|
|
||||||
|
|
||||||
// make sure there isn't a function of this variable name
|
|
||||||
if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// check for not overloading or redefining a built-in function
|
|
||||||
if (noBuiltInRedeclarations) {
|
|
||||||
if (atGlobalLevel() && currentLevel() > 0) {
|
|
||||||
if (table[0]->hasFunctionName(symbol.getName()))
|
|
||||||
return false;
|
|
||||||
if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName()))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return table[currentLevel()]->insert(symbol, separateNameSpaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add more members to an already inserted aggregate object
|
|
||||||
bool amend(TSymbol& symbol, int firstNewMember)
|
|
||||||
{
|
|
||||||
// See insert() for comments on basic explanation of insert.
|
|
||||||
// This operates similarly, but more simply.
|
|
||||||
return table[currentLevel()]->amend(symbol, firstNewMember);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// To allocate an internal temporary, which will need to be uniquely
|
|
||||||
// identified by the consumer of the AST, but never need to
|
|
||||||
// found by doing a symbol table search by name, hence allowed an
|
|
||||||
// arbitrary name in the symbol with no worry of collision.
|
|
||||||
//
|
|
||||||
void makeInternalVariable(TSymbol& symbol)
|
|
||||||
{
|
|
||||||
symbol.setUniqueId(++uniqueId);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Copy a variable or anonymous member's structure from a shared level so that
|
|
||||||
// it can be added (soon after return) to the symbol table where it can be
|
|
||||||
// modified without impacting other users of the shared table.
|
|
||||||
//
|
|
||||||
TSymbol* copyUpDeferredInsert(TSymbol* shared)
|
|
||||||
{
|
|
||||||
if (shared->getAsVariable()) {
|
|
||||||
TSymbol* copy = shared->clone();
|
|
||||||
copy->setUniqueId(shared->getUniqueId());
|
|
||||||
return copy;
|
|
||||||
} else {
|
|
||||||
const TAnonMember* anon = shared->getAsAnonMember();
|
|
||||||
assert(anon);
|
|
||||||
TVariable* container = anon->getAnonContainer().clone();
|
|
||||||
container->changeName(NewPoolTString(""));
|
|
||||||
container->setUniqueId(anon->getAnonContainer().getUniqueId());
|
|
||||||
return container;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TSymbol* copyUp(TSymbol* shared)
|
|
||||||
{
|
|
||||||
TSymbol* copy = copyUpDeferredInsert(shared);
|
|
||||||
table[globalLevel]->insert(*copy, separateNameSpaces);
|
|
||||||
if (shared->getAsVariable())
|
|
||||||
return copy;
|
|
||||||
else {
|
|
||||||
// return the copy of the anonymous member
|
|
||||||
return table[globalLevel]->find(shared->getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normal find of a symbol, that can optionally say whether the symbol was found
|
|
||||||
// at a built-in level or the current top-scope level.
|
|
||||||
TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0)
|
|
||||||
{
|
|
||||||
int level = currentLevel();
|
|
||||||
TSymbol* symbol;
|
|
||||||
int thisDepth = 0;
|
|
||||||
do {
|
|
||||||
if (table[level]->isThisLevel())
|
|
||||||
++thisDepth;
|
|
||||||
symbol = table[level]->find(name);
|
|
||||||
--level;
|
|
||||||
} while (symbol == nullptr && level >= 0);
|
|
||||||
level++;
|
|
||||||
if (builtIn)
|
|
||||||
*builtIn = isBuiltInLevel(level);
|
|
||||||
if (currentScope)
|
|
||||||
*currentScope = isGlobalLevel(currentLevel()) || level == currentLevel(); // consider shared levels as "current scope" WRT user globals
|
|
||||||
if (thisDepthP != nullptr) {
|
|
||||||
if (! table[level]->isThisLevel())
|
|
||||||
thisDepth = 0;
|
|
||||||
*thisDepthP = thisDepth;
|
|
||||||
}
|
|
||||||
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find of a symbol that returns how many layers deep of nested
|
|
||||||
// structures-with-member-functions ('this' scopes) deep the symbol was
|
|
||||||
// found in.
|
|
||||||
TSymbol* find(const TString& name, int& thisDepth)
|
|
||||||
{
|
|
||||||
int level = currentLevel();
|
|
||||||
TSymbol* symbol;
|
|
||||||
thisDepth = 0;
|
|
||||||
do {
|
|
||||||
if (table[level]->isThisLevel())
|
|
||||||
++thisDepth;
|
|
||||||
symbol = table[level]->find(name);
|
|
||||||
--level;
|
|
||||||
} while (symbol == 0 && level >= 0);
|
|
||||||
|
|
||||||
if (! table[level + 1]->isThisLevel())
|
|
||||||
thisDepth = 0;
|
|
||||||
|
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isFunctionNameVariable(const TString& name) const
|
|
||||||
{
|
|
||||||
if (separateNameSpaces)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int level = currentLevel();
|
|
||||||
do {
|
|
||||||
bool variable;
|
|
||||||
bool found = table[level]->findFunctionVariableName(name, variable);
|
|
||||||
if (found)
|
|
||||||
return variable;
|
|
||||||
--level;
|
|
||||||
} while (level >= 0);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void findFunctionNameList(const TString& name, TVector<const TFunction*>& list, bool& builtIn)
|
|
||||||
{
|
|
||||||
// For user levels, return the set found in the first scope with a match
|
|
||||||
builtIn = false;
|
|
||||||
int level = currentLevel();
|
|
||||||
do {
|
|
||||||
table[level]->findFunctionNameList(name, list);
|
|
||||||
--level;
|
|
||||||
} while (list.empty() && level >= globalLevel);
|
|
||||||
|
|
||||||
if (! list.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Gather across all built-in levels; they don't hide each other
|
|
||||||
builtIn = true;
|
|
||||||
do {
|
|
||||||
table[level]->findFunctionNameList(name, list);
|
|
||||||
--level;
|
|
||||||
} while (level >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void relateToOperator(const char* name, TOperator op)
|
|
||||||
{
|
|
||||||
for (unsigned int level = 0; level < table.size(); ++level)
|
|
||||||
table[level]->relateToOperator(name, op);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFunctionExtensions(const char* name, int num, const char* const extensions[])
|
|
||||||
{
|
|
||||||
for (unsigned int level = 0; level < table.size(); ++level)
|
|
||||||
table[level]->setFunctionExtensions(name, num, extensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setVariableExtensions(const char* name, int numExts, const char* const extensions[])
|
|
||||||
{
|
|
||||||
TSymbol* symbol = find(TString(name));
|
|
||||||
if (symbol == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
symbol->setExtensions(numExts, extensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[])
|
|
||||||
{
|
|
||||||
TSymbol* symbol = find(TString(blockName));
|
|
||||||
if (symbol == nullptr)
|
|
||||||
return;
|
|
||||||
TVariable* variable = symbol->getAsVariable();
|
|
||||||
assert(variable != nullptr);
|
|
||||||
|
|
||||||
const TTypeList& structure = *variable->getAsVariable()->getType().getStruct();
|
|
||||||
for (int member = 0; member < (int)structure.size(); ++member) {
|
|
||||||
if (structure[member].type->getFieldName().compare(name) == 0) {
|
|
||||||
variable->setMemberExtensions(member, numExts, extensions);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int getMaxSymbolId() { return uniqueId; }
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
void dump(TInfoSink& infoSink, bool complete = false) const;
|
|
||||||
#endif
|
|
||||||
void copyTable(const TSymbolTable& copyOf);
|
|
||||||
|
|
||||||
void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); }
|
|
||||||
|
|
||||||
void readOnly()
|
|
||||||
{
|
|
||||||
for (unsigned int level = 0; level < table.size(); ++level)
|
|
||||||
table[level]->readOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TSymbolTable(TSymbolTable&);
|
|
||||||
TSymbolTable& operator=(TSymbolTableLevel&);
|
|
||||||
|
|
||||||
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
|
|
||||||
|
|
||||||
std::vector<TSymbolTableLevel*> table;
|
|
||||||
int uniqueId; // for unique identification in code generation
|
|
||||||
bool noBuiltInRedeclarations;
|
|
||||||
bool separateNameSpaces;
|
|
||||||
unsigned int adoptedLevels;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _SYMBOL_TABLE_INCLUDED_
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,331 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2012-2013 LunarG, Inc.
|
|
||||||
// Copyright (C) 2017 ARM Limited.
|
|
||||||
// Copyright (C) 2015-2018 Google, Inc.
|
|
||||||
// Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
#ifndef _VERSIONS_INCLUDED_
|
|
||||||
#define _VERSIONS_INCLUDED_
|
|
||||||
|
|
||||||
#define LAST_ELEMENT_MARKER(x) x
|
|
||||||
|
|
||||||
//
|
|
||||||
// Help manage multiple profiles, versions, extensions etc.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Profiles are set up for masking operations, so queries can be done on multiple
|
|
||||||
// profiles at the same time.
|
|
||||||
//
|
|
||||||
// Don't maintain an ordinal set of enums (0,1,2,3...) to avoid all possible
|
|
||||||
// defects from mixing the two different forms.
|
|
||||||
//
|
|
||||||
typedef enum : unsigned {
|
|
||||||
EBadProfile = 0,
|
|
||||||
ENoProfile = (1 << 0), // only for desktop, before profiles showed up
|
|
||||||
ECoreProfile = (1 << 1),
|
|
||||||
ECompatibilityProfile = (1 << 2),
|
|
||||||
EEsProfile = (1 << 3),
|
|
||||||
LAST_ELEMENT_MARKER(EProfileCount),
|
|
||||||
} EProfile;
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Map from profile enum to externally readable text name.
|
|
||||||
//
|
|
||||||
inline const char* ProfileName(EProfile profile)
|
|
||||||
{
|
|
||||||
switch (profile) {
|
|
||||||
case ENoProfile: return "none";
|
|
||||||
case ECoreProfile: return "core";
|
|
||||||
case ECompatibilityProfile: return "compatibility";
|
|
||||||
case EEsProfile: return "es";
|
|
||||||
default: return "unknown profile";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// What source rules, validation rules, target language, etc. are needed or
|
|
||||||
// desired for SPIR-V?
|
|
||||||
//
|
|
||||||
// 0 means a target or rule set is not enabled (ignore rules from that entity).
|
|
||||||
// Non-0 means to apply semantic rules arising from that version of its rule set.
|
|
||||||
// The union of all requested rule sets will be applied.
|
|
||||||
//
|
|
||||||
struct SpvVersion {
|
|
||||||
SpvVersion() : spv(0), vulkanGlsl(0), vulkan(0), openGl(0) {}
|
|
||||||
unsigned int spv; // the version of SPIR-V to target, as defined by "word 1" of the SPIR-V binary header
|
|
||||||
int vulkanGlsl; // the version of GLSL semantics for Vulkan, from GL_KHR_vulkan_glsl, for "#define VULKAN XXX"
|
|
||||||
int vulkan; // the version of Vulkan, for which SPIR-V execution environment rules to use
|
|
||||||
int openGl; // the version of GLSL semantics for OpenGL, from GL_ARB_gl_spirv, for "#define GL_SPIRV XXX"
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// The behaviors from the GLSL "#extension extension_name : behavior"
|
|
||||||
//
|
|
||||||
typedef enum {
|
|
||||||
EBhMissing = 0,
|
|
||||||
EBhRequire,
|
|
||||||
EBhEnable,
|
|
||||||
EBhWarn,
|
|
||||||
EBhDisable,
|
|
||||||
EBhDisablePartial // use as initial state of an extension that is only partially implemented
|
|
||||||
} TExtensionBehavior;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Symbolic names for extensions. Strings may be directly used when calling the
|
|
||||||
// functions, but better to have the compiler do spelling checks.
|
|
||||||
//
|
|
||||||
const char* const E_GL_OES_texture_3D = "GL_OES_texture_3D";
|
|
||||||
const char* const E_GL_OES_standard_derivatives = "GL_OES_standard_derivatives";
|
|
||||||
const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth";
|
|
||||||
const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external";
|
|
||||||
const char* const E_GL_OES_EGL_image_external_essl3 = "GL_OES_EGL_image_external_essl3";
|
|
||||||
const char* const E_GL_EXT_YUV_target = "GL_EXT_YUV_target";
|
|
||||||
const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod";
|
|
||||||
const char* const E_GL_EXT_shadow_samplers = "GL_EXT_shadow_samplers";
|
|
||||||
|
|
||||||
const char* const E_GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle";
|
|
||||||
const char* const E_GL_3DL_array_objects = "GL_3DL_array_objects";
|
|
||||||
const char* const E_GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack";
|
|
||||||
const char* const E_GL_ARB_texture_gather = "GL_ARB_texture_gather";
|
|
||||||
const char* const E_GL_ARB_gpu_shader5 = "GL_ARB_gpu_shader5";
|
|
||||||
const char* const E_GL_ARB_separate_shader_objects = "GL_ARB_separate_shader_objects";
|
|
||||||
const char* const E_GL_ARB_compute_shader = "GL_ARB_compute_shader";
|
|
||||||
const char* const E_GL_ARB_tessellation_shader = "GL_ARB_tessellation_shader";
|
|
||||||
const char* const E_GL_ARB_enhanced_layouts = "GL_ARB_enhanced_layouts";
|
|
||||||
const char* const E_GL_ARB_texture_cube_map_array = "GL_ARB_texture_cube_map_array";
|
|
||||||
const char* const E_GL_ARB_texture_multisample = "GL_ARB_texture_multisample";
|
|
||||||
const char* const E_GL_ARB_shader_texture_lod = "GL_ARB_shader_texture_lod";
|
|
||||||
const char* const E_GL_ARB_explicit_attrib_location = "GL_ARB_explicit_attrib_location";
|
|
||||||
const char* const E_GL_ARB_explicit_uniform_location = "GL_ARB_explicit_uniform_location";
|
|
||||||
const char* const E_GL_ARB_shader_image_load_store = "GL_ARB_shader_image_load_store";
|
|
||||||
const char* const E_GL_ARB_shader_atomic_counters = "GL_ARB_shader_atomic_counters";
|
|
||||||
const char* const E_GL_ARB_shader_draw_parameters = "GL_ARB_shader_draw_parameters";
|
|
||||||
const char* const E_GL_ARB_shader_group_vote = "GL_ARB_shader_group_vote";
|
|
||||||
const char* const E_GL_ARB_derivative_control = "GL_ARB_derivative_control";
|
|
||||||
const char* const E_GL_ARB_shader_texture_image_samples = "GL_ARB_shader_texture_image_samples";
|
|
||||||
const char* const E_GL_ARB_viewport_array = "GL_ARB_viewport_array";
|
|
||||||
const char* const E_GL_ARB_gpu_shader_int64 = "GL_ARB_gpu_shader_int64";
|
|
||||||
const char* const E_GL_ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64";
|
|
||||||
const char* const E_GL_ARB_shader_ballot = "GL_ARB_shader_ballot";
|
|
||||||
const char* const E_GL_ARB_sparse_texture2 = "GL_ARB_sparse_texture2";
|
|
||||||
const char* const E_GL_ARB_sparse_texture_clamp = "GL_ARB_sparse_texture_clamp";
|
|
||||||
const char* const E_GL_ARB_shader_stencil_export = "GL_ARB_shader_stencil_export";
|
|
||||||
// const char* const E_GL_ARB_cull_distance = "GL_ARB_cull_distance"; // present for 4.5, but need extension control over block members
|
|
||||||
const char* const E_GL_ARB_post_depth_coverage = "GL_ARB_post_depth_coverage";
|
|
||||||
const char* const E_GL_ARB_shader_viewport_layer_array = "GL_ARB_shader_viewport_layer_array";
|
|
||||||
const char* const E_GL_ARB_fragment_shader_interlock = "GL_ARB_fragment_shader_interlock";
|
|
||||||
const char* const E_GL_ARB_shader_clock = "GL_ARB_shader_clock";
|
|
||||||
const char* const E_GL_ARB_uniform_buffer_object = "GL_ARB_uniform_buffer_object";
|
|
||||||
const char* const E_GL_ARB_sample_shading = "GL_ARB_sample_shading";
|
|
||||||
const char* const E_GL_ARB_shader_bit_encoding = "GL_ARB_shader_bit_encoding";
|
|
||||||
const char* const E_GL_ARB_shader_image_size = "GL_ARB_shader_image_size";
|
|
||||||
const char* const E_GL_ARB_shader_storage_buffer_object = "GL_ARB_shader_storage_buffer_object";
|
|
||||||
const char* const E_GL_ARB_shading_language_packing = "GL_ARB_shading_language_packing";
|
|
||||||
const char* const E_GL_ARB_texture_query_lod = "GL_ARB_texture_query_lod";
|
|
||||||
const char* const E_GL_ARB_vertex_attrib_64bit = "GL_ARB_vertex_attrib_64bit";
|
|
||||||
|
|
||||||
const char* const E_GL_KHR_shader_subgroup_basic = "GL_KHR_shader_subgroup_basic";
|
|
||||||
const char* const E_GL_KHR_shader_subgroup_vote = "GL_KHR_shader_subgroup_vote";
|
|
||||||
const char* const E_GL_KHR_shader_subgroup_arithmetic = "GL_KHR_shader_subgroup_arithmetic";
|
|
||||||
const char* const E_GL_KHR_shader_subgroup_ballot = "GL_KHR_shader_subgroup_ballot";
|
|
||||||
const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_subgroup_shuffle";
|
|
||||||
const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative";
|
|
||||||
const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered";
|
|
||||||
const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad";
|
|
||||||
const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics";
|
|
||||||
|
|
||||||
const char* const E_GL_EXT_shader_atomic_int64 = "GL_EXT_shader_atomic_int64";
|
|
||||||
|
|
||||||
const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers";
|
|
||||||
const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted";
|
|
||||||
|
|
||||||
const char* const E_GL_EXT_shader_16bit_storage = "GL_EXT_shader_16bit_storage";
|
|
||||||
const char* const E_GL_EXT_shader_8bit_storage = "GL_EXT_shader_8bit_storage";
|
|
||||||
|
|
||||||
|
|
||||||
// EXT extensions
|
|
||||||
const char* const E_GL_EXT_device_group = "GL_EXT_device_group";
|
|
||||||
const char* const E_GL_EXT_multiview = "GL_EXT_multiview";
|
|
||||||
const char* const E_GL_EXT_post_depth_coverage = "GL_EXT_post_depth_coverage";
|
|
||||||
const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes";
|
|
||||||
const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier";
|
|
||||||
const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions";
|
|
||||||
const char* const E_GL_EXT_scalar_block_layout = "GL_EXT_scalar_block_layout";
|
|
||||||
const char* const E_GL_EXT_fragment_invocation_density = "GL_EXT_fragment_invocation_density";
|
|
||||||
const char* const E_GL_EXT_buffer_reference = "GL_EXT_buffer_reference";
|
|
||||||
const char* const E_GL_EXT_buffer_reference2 = "GL_EXT_buffer_reference2";
|
|
||||||
const char* const E_GL_EXT_buffer_reference_uvec2 = "GL_EXT_buffer_reference_uvec2";
|
|
||||||
const char* const E_GL_EXT_demote_to_helper_invocation = "GL_EXT_demote_to_helper_invocation";
|
|
||||||
const char* const E_GL_EXT_shader_realtime_clock = "GL_EXT_shader_realtime_clock";
|
|
||||||
const char* const E_GL_EXT_debug_printf = "GL_EXT_debug_printf";
|
|
||||||
const char* const E_GL_EXT_ray_tracing = "GL_EXT_ray_tracing";
|
|
||||||
const char* const E_GL_EXT_ray_query = "GL_EXT_ray_query";
|
|
||||||
const char* const E_GL_EXT_ray_flags_primitive_culling = "GL_EXT_ray_flags_primitive_culling";
|
|
||||||
const char* const E_GL_EXT_blend_func_extended = "GL_EXT_blend_func_extended";
|
|
||||||
const char* const E_GL_EXT_shader_implicit_conversions = "GL_EXT_shader_implicit_conversions";
|
|
||||||
|
|
||||||
// Arrays of extensions for the above viewportEXTs duplications
|
|
||||||
|
|
||||||
const char* const post_depth_coverageEXTs[] = { E_GL_ARB_post_depth_coverage, E_GL_EXT_post_depth_coverage };
|
|
||||||
const int Num_post_depth_coverageEXTs = sizeof(post_depth_coverageEXTs) / sizeof(post_depth_coverageEXTs[0]);
|
|
||||||
|
|
||||||
// OVR extensions
|
|
||||||
const char* const E_GL_OVR_multiview = "GL_OVR_multiview";
|
|
||||||
const char* const E_GL_OVR_multiview2 = "GL_OVR_multiview2";
|
|
||||||
|
|
||||||
const char* const OVR_multiview_EXTs[] = { E_GL_OVR_multiview, E_GL_OVR_multiview2 };
|
|
||||||
const int Num_OVR_multiview_EXTs = sizeof(OVR_multiview_EXTs) / sizeof(OVR_multiview_EXTs[0]);
|
|
||||||
|
|
||||||
// #line and #include
|
|
||||||
const char* const E_GL_GOOGLE_cpp_style_line_directive = "GL_GOOGLE_cpp_style_line_directive";
|
|
||||||
const char* const E_GL_GOOGLE_include_directive = "GL_GOOGLE_include_directive";
|
|
||||||
|
|
||||||
const char* const E_GL_AMD_shader_ballot = "GL_AMD_shader_ballot";
|
|
||||||
const char* const E_GL_AMD_shader_trinary_minmax = "GL_AMD_shader_trinary_minmax";
|
|
||||||
const char* const E_GL_AMD_shader_explicit_vertex_parameter = "GL_AMD_shader_explicit_vertex_parameter";
|
|
||||||
const char* const E_GL_AMD_gcn_shader = "GL_AMD_gcn_shader";
|
|
||||||
const char* const E_GL_AMD_gpu_shader_half_float = "GL_AMD_gpu_shader_half_float";
|
|
||||||
const char* const E_GL_AMD_texture_gather_bias_lod = "GL_AMD_texture_gather_bias_lod";
|
|
||||||
const char* const E_GL_AMD_gpu_shader_int16 = "GL_AMD_gpu_shader_int16";
|
|
||||||
const char* const E_GL_AMD_shader_image_load_store_lod = "GL_AMD_shader_image_load_store_lod";
|
|
||||||
const char* const E_GL_AMD_shader_fragment_mask = "GL_AMD_shader_fragment_mask";
|
|
||||||
const char* const E_GL_AMD_gpu_shader_half_float_fetch = "GL_AMD_gpu_shader_half_float_fetch";
|
|
||||||
|
|
||||||
const char* const E_GL_INTEL_shader_integer_functions2 = "GL_INTEL_shader_integer_functions2";
|
|
||||||
|
|
||||||
const char* const E_GL_NV_sample_mask_override_coverage = "GL_NV_sample_mask_override_coverage";
|
|
||||||
const char* const E_SPV_NV_geometry_shader_passthrough = "GL_NV_geometry_shader_passthrough";
|
|
||||||
const char* const E_GL_NV_viewport_array2 = "GL_NV_viewport_array2";
|
|
||||||
const char* const E_GL_NV_stereo_view_rendering = "GL_NV_stereo_view_rendering";
|
|
||||||
const char* const E_GL_NVX_multiview_per_view_attributes = "GL_NVX_multiview_per_view_attributes";
|
|
||||||
const char* const E_GL_NV_shader_atomic_int64 = "GL_NV_shader_atomic_int64";
|
|
||||||
const char* const E_GL_NV_conservative_raster_underestimation = "GL_NV_conservative_raster_underestimation";
|
|
||||||
const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_noperspective_interpolation";
|
|
||||||
const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned";
|
|
||||||
const char* const E_GL_NV_shading_rate_image = "GL_NV_shading_rate_image";
|
|
||||||
const char* const E_GL_NV_ray_tracing = "GL_NV_ray_tracing";
|
|
||||||
const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragment_shader_barycentric";
|
|
||||||
const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives";
|
|
||||||
const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint";
|
|
||||||
const char* const E_GL_NV_mesh_shader = "GL_NV_mesh_shader";
|
|
||||||
|
|
||||||
// Arrays of extensions for the above viewportEXTs duplications
|
|
||||||
|
|
||||||
const char* const viewportEXTs[] = { E_GL_ARB_shader_viewport_layer_array, E_GL_NV_viewport_array2 };
|
|
||||||
const int Num_viewportEXTs = sizeof(viewportEXTs) / sizeof(viewportEXTs[0]);
|
|
||||||
|
|
||||||
const char* const E_GL_NV_cooperative_matrix = "GL_NV_cooperative_matrix";
|
|
||||||
const char* const E_GL_NV_shader_sm_builtins = "GL_NV_shader_sm_builtins";
|
|
||||||
const char* const E_GL_NV_integer_cooperative_matrix = "GL_NV_integer_cooperative_matrix";
|
|
||||||
|
|
||||||
// AEP
|
|
||||||
const char* const E_GL_ANDROID_extension_pack_es31a = "GL_ANDROID_extension_pack_es31a";
|
|
||||||
const char* const E_GL_KHR_blend_equation_advanced = "GL_KHR_blend_equation_advanced";
|
|
||||||
const char* const E_GL_OES_sample_variables = "GL_OES_sample_variables";
|
|
||||||
const char* const E_GL_OES_shader_image_atomic = "GL_OES_shader_image_atomic";
|
|
||||||
const char* const E_GL_OES_shader_multisample_interpolation = "GL_OES_shader_multisample_interpolation";
|
|
||||||
const char* const E_GL_OES_texture_storage_multisample_2d_array = "GL_OES_texture_storage_multisample_2d_array";
|
|
||||||
const char* const E_GL_EXT_geometry_shader = "GL_EXT_geometry_shader";
|
|
||||||
const char* const E_GL_EXT_geometry_point_size = "GL_EXT_geometry_point_size";
|
|
||||||
const char* const E_GL_EXT_gpu_shader5 = "GL_EXT_gpu_shader5";
|
|
||||||
const char* const E_GL_EXT_primitive_bounding_box = "GL_EXT_primitive_bounding_box";
|
|
||||||
const char* const E_GL_EXT_shader_io_blocks = "GL_EXT_shader_io_blocks";
|
|
||||||
const char* const E_GL_EXT_tessellation_shader = "GL_EXT_tessellation_shader";
|
|
||||||
const char* const E_GL_EXT_tessellation_point_size = "GL_EXT_tessellation_point_size";
|
|
||||||
const char* const E_GL_EXT_texture_buffer = "GL_EXT_texture_buffer";
|
|
||||||
const char* const E_GL_EXT_texture_cube_map_array = "GL_EXT_texture_cube_map_array";
|
|
||||||
const char* const E_GL_EXT_shader_integer_mix = "GL_EXT_shader_integer_mix";
|
|
||||||
|
|
||||||
// OES matching AEP
|
|
||||||
const char* const E_GL_OES_geometry_shader = "GL_OES_geometry_shader";
|
|
||||||
const char* const E_GL_OES_geometry_point_size = "GL_OES_geometry_point_size";
|
|
||||||
const char* const E_GL_OES_gpu_shader5 = "GL_OES_gpu_shader5";
|
|
||||||
const char* const E_GL_OES_primitive_bounding_box = "GL_OES_primitive_bounding_box";
|
|
||||||
const char* const E_GL_OES_shader_io_blocks = "GL_OES_shader_io_blocks";
|
|
||||||
const char* const E_GL_OES_tessellation_shader = "GL_OES_tessellation_shader";
|
|
||||||
const char* const E_GL_OES_tessellation_point_size = "GL_OES_tessellation_point_size";
|
|
||||||
const char* const E_GL_OES_texture_buffer = "GL_OES_texture_buffer";
|
|
||||||
const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array";
|
|
||||||
|
|
||||||
// EXT
|
|
||||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types = "GL_EXT_shader_explicit_arithmetic_types";
|
|
||||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_int8 = "GL_EXT_shader_explicit_arithmetic_types_int8";
|
|
||||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_int16 = "GL_EXT_shader_explicit_arithmetic_types_int16";
|
|
||||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_int32 = "GL_EXT_shader_explicit_arithmetic_types_int32";
|
|
||||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_int64 = "GL_EXT_shader_explicit_arithmetic_types_int64";
|
|
||||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_float16 = "GL_EXT_shader_explicit_arithmetic_types_float16";
|
|
||||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_float32 = "GL_EXT_shader_explicit_arithmetic_types_float32";
|
|
||||||
const char* const E_GL_EXT_shader_explicit_arithmetic_types_float64 = "GL_EXT_shader_explicit_arithmetic_types_float64";
|
|
||||||
|
|
||||||
const char* const E_GL_EXT_shader_subgroup_extended_types_int8 = "GL_EXT_shader_subgroup_extended_types_int8";
|
|
||||||
const char* const E_GL_EXT_shader_subgroup_extended_types_int16 = "GL_EXT_shader_subgroup_extended_types_int16";
|
|
||||||
const char* const E_GL_EXT_shader_subgroup_extended_types_int64 = "GL_EXT_shader_subgroup_extended_types_int64";
|
|
||||||
const char* const E_GL_EXT_shader_subgroup_extended_types_float16 = "GL_EXT_shader_subgroup_extended_types_float16";
|
|
||||||
|
|
||||||
// Arrays of extensions for the above AEP duplications
|
|
||||||
|
|
||||||
const char* const AEP_geometry_shader[] = { E_GL_EXT_geometry_shader, E_GL_OES_geometry_shader };
|
|
||||||
const int Num_AEP_geometry_shader = sizeof(AEP_geometry_shader)/sizeof(AEP_geometry_shader[0]);
|
|
||||||
|
|
||||||
const char* const AEP_geometry_point_size[] = { E_GL_EXT_geometry_point_size, E_GL_OES_geometry_point_size };
|
|
||||||
const int Num_AEP_geometry_point_size = sizeof(AEP_geometry_point_size)/sizeof(AEP_geometry_point_size[0]);
|
|
||||||
|
|
||||||
const char* const AEP_gpu_shader5[] = { E_GL_EXT_gpu_shader5, E_GL_OES_gpu_shader5 };
|
|
||||||
const int Num_AEP_gpu_shader5 = sizeof(AEP_gpu_shader5)/sizeof(AEP_gpu_shader5[0]);
|
|
||||||
|
|
||||||
const char* const AEP_primitive_bounding_box[] = { E_GL_EXT_primitive_bounding_box, E_GL_OES_primitive_bounding_box };
|
|
||||||
const int Num_AEP_primitive_bounding_box = sizeof(AEP_primitive_bounding_box)/sizeof(AEP_primitive_bounding_box[0]);
|
|
||||||
|
|
||||||
const char* const AEP_shader_io_blocks[] = { E_GL_EXT_shader_io_blocks, E_GL_OES_shader_io_blocks };
|
|
||||||
const int Num_AEP_shader_io_blocks = sizeof(AEP_shader_io_blocks)/sizeof(AEP_shader_io_blocks[0]);
|
|
||||||
|
|
||||||
const char* const AEP_tessellation_shader[] = { E_GL_EXT_tessellation_shader, E_GL_OES_tessellation_shader };
|
|
||||||
const int Num_AEP_tessellation_shader = sizeof(AEP_tessellation_shader)/sizeof(AEP_tessellation_shader[0]);
|
|
||||||
|
|
||||||
const char* const AEP_tessellation_point_size[] = { E_GL_EXT_tessellation_point_size, E_GL_OES_tessellation_point_size };
|
|
||||||
const int Num_AEP_tessellation_point_size = sizeof(AEP_tessellation_point_size)/sizeof(AEP_tessellation_point_size[0]);
|
|
||||||
|
|
||||||
const char* const AEP_texture_buffer[] = { E_GL_EXT_texture_buffer, E_GL_OES_texture_buffer };
|
|
||||||
const int Num_AEP_texture_buffer = sizeof(AEP_texture_buffer)/sizeof(AEP_texture_buffer[0]);
|
|
||||||
|
|
||||||
const char* const AEP_texture_cube_map_array[] = { E_GL_EXT_texture_cube_map_array, E_GL_OES_texture_cube_map_array };
|
|
||||||
const int Num_AEP_texture_cube_map_array = sizeof(AEP_texture_cube_map_array)/sizeof(AEP_texture_cube_map_array[0]);
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _VERSIONS_INCLUDED_
|
|
|
@ -1,346 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2017 LunarG, Inc.
|
|
||||||
// Copyright (C) 2018 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of Google, Inc., nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
|
|
||||||
#include "attribute.h"
|
|
||||||
#include "../Include/intermediate.h"
|
|
||||||
#include "ParseHelper.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
// extract integers out of attribute arguments stored in attribute aggregate
|
|
||||||
bool TAttributeArgs::getInt(int& value, int argNum) const
|
|
||||||
{
|
|
||||||
const TConstUnion* intConst = getConstUnion(EbtInt, argNum);
|
|
||||||
|
|
||||||
if (intConst == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
value = intConst->getIConst();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// extract strings out of attribute arguments stored in attribute aggregate.
|
|
||||||
// convert to lower case if converToLower is true (for case-insensitive compare convenience)
|
|
||||||
bool TAttributeArgs::getString(TString& value, int argNum, bool convertToLower) const
|
|
||||||
{
|
|
||||||
const TConstUnion* stringConst = getConstUnion(EbtString, argNum);
|
|
||||||
|
|
||||||
if (stringConst == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
value = *stringConst->getSConst();
|
|
||||||
|
|
||||||
// Convenience.
|
|
||||||
if (convertToLower)
|
|
||||||
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// How many arguments were supplied?
|
|
||||||
int TAttributeArgs::size() const
|
|
||||||
{
|
|
||||||
return args == nullptr ? 0 : (int)args->getSequence().size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper to get attribute const union. Returns nullptr on failure.
|
|
||||||
const TConstUnion* TAttributeArgs::getConstUnion(TBasicType basicType, int argNum) const
|
|
||||||
{
|
|
||||||
if (args == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (argNum >= (int)args->getSequence().size())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (args->getSequence()[argNum]->getAsConstantUnion() == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
const TConstUnion* constVal = &args->getSequence()[argNum]->getAsConstantUnion()->getConstArray()[0];
|
|
||||||
if (constVal == nullptr || constVal->getType() != basicType)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return constVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implementation of TParseContext parts of attributes
|
|
||||||
TAttributeType TParseContext::attributeFromName(const TString& name) const
|
|
||||||
{
|
|
||||||
if (name == "branch" || name == "dont_flatten")
|
|
||||||
return EatBranch;
|
|
||||||
else if (name == "flatten")
|
|
||||||
return EatFlatten;
|
|
||||||
else if (name == "unroll")
|
|
||||||
return EatUnroll;
|
|
||||||
else if (name == "loop" || name == "dont_unroll")
|
|
||||||
return EatLoop;
|
|
||||||
else if (name == "dependency_infinite")
|
|
||||||
return EatDependencyInfinite;
|
|
||||||
else if (name == "dependency_length")
|
|
||||||
return EatDependencyLength;
|
|
||||||
else if (name == "min_iterations")
|
|
||||||
return EatMinIterations;
|
|
||||||
else if (name == "max_iterations")
|
|
||||||
return EatMaxIterations;
|
|
||||||
else if (name == "iteration_multiple")
|
|
||||||
return EatIterationMultiple;
|
|
||||||
else if (name == "peel_count")
|
|
||||||
return EatPeelCount;
|
|
||||||
else if (name == "partial_count")
|
|
||||||
return EatPartialCount;
|
|
||||||
else
|
|
||||||
return EatNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make an initial leaf for the grammar from a no-argument attribute
|
|
||||||
TAttributes* TParseContext::makeAttributes(const TString& identifier) const
|
|
||||||
{
|
|
||||||
TAttributes *attributes = nullptr;
|
|
||||||
attributes = NewPoolObject(attributes);
|
|
||||||
TAttributeArgs args = { attributeFromName(identifier), nullptr };
|
|
||||||
attributes->push_back(args);
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make an initial leaf for the grammar from a one-argument attribute
|
|
||||||
TAttributes* TParseContext::makeAttributes(const TString& identifier, TIntermNode* node) const
|
|
||||||
{
|
|
||||||
TAttributes *attributes = nullptr;
|
|
||||||
attributes = NewPoolObject(attributes);
|
|
||||||
|
|
||||||
// for now, node is always a simple single expression, but other code expects
|
|
||||||
// a list, so make it so
|
|
||||||
TIntermAggregate* agg = intermediate.makeAggregate(node);
|
|
||||||
TAttributeArgs args = { attributeFromName(identifier), agg };
|
|
||||||
attributes->push_back(args);
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge two sets of attributes into a single set.
|
|
||||||
// The second argument is destructively consumed.
|
|
||||||
TAttributes* TParseContext::mergeAttributes(TAttributes* attr1, TAttributes* attr2) const
|
|
||||||
{
|
|
||||||
attr1->splice(attr1->end(), *attr2);
|
|
||||||
return attr1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Selection attributes
|
|
||||||
//
|
|
||||||
void TParseContext::handleSelectionAttributes(const TAttributes& attributes, TIntermNode* node)
|
|
||||||
{
|
|
||||||
TIntermSelection* selection = node->getAsSelectionNode();
|
|
||||||
if (selection == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
|
|
||||||
if (it->size() > 0) {
|
|
||||||
warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", "");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (it->name) {
|
|
||||||
case EatFlatten:
|
|
||||||
selection->setFlatten();
|
|
||||||
break;
|
|
||||||
case EatBranch:
|
|
||||||
selection->setDontFlatten();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
warn(node->getLoc(), "attribute does not apply to a selection", "", "");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Switch attributes
|
|
||||||
//
|
|
||||||
void TParseContext::handleSwitchAttributes(const TAttributes& attributes, TIntermNode* node)
|
|
||||||
{
|
|
||||||
TIntermSwitch* selection = node->getAsSwitchNode();
|
|
||||||
if (selection == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
|
|
||||||
if (it->size() > 0) {
|
|
||||||
warn(node->getLoc(), "attribute with arguments not recognized, skipping", "", "");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (it->name) {
|
|
||||||
case EatFlatten:
|
|
||||||
selection->setFlatten();
|
|
||||||
break;
|
|
||||||
case EatBranch:
|
|
||||||
selection->setDontFlatten();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
warn(node->getLoc(), "attribute does not apply to a switch", "", "");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Loop attributes
|
|
||||||
//
|
|
||||||
void TParseContext::handleLoopAttributes(const TAttributes& attributes, TIntermNode* node)
|
|
||||||
{
|
|
||||||
TIntermLoop* loop = node->getAsLoopNode();
|
|
||||||
if (loop == nullptr) {
|
|
||||||
// the actual loop might be part of a sequence
|
|
||||||
TIntermAggregate* agg = node->getAsAggregate();
|
|
||||||
if (agg == nullptr)
|
|
||||||
return;
|
|
||||||
for (auto it = agg->getSequence().begin(); it != agg->getSequence().end(); ++it) {
|
|
||||||
loop = (*it)->getAsLoopNode();
|
|
||||||
if (loop != nullptr)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (loop == nullptr)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto it = attributes.begin(); it != attributes.end(); ++it) {
|
|
||||||
|
|
||||||
const auto noArgument = [&](const char* feature) {
|
|
||||||
if (it->size() > 0) {
|
|
||||||
warn(node->getLoc(), "expected no arguments", feature, "");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto positiveSignedArgument = [&](const char* feature, int& value) {
|
|
||||||
if (it->size() == 1 && it->getInt(value)) {
|
|
||||||
if (value <= 0) {
|
|
||||||
error(node->getLoc(), "must be positive", feature, "");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn(node->getLoc(), "expected a single integer argument", feature, "");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto unsignedArgument = [&](const char* feature, unsigned int& uiValue) {
|
|
||||||
int value;
|
|
||||||
if (!(it->size() == 1 && it->getInt(value))) {
|
|
||||||
warn(node->getLoc(), "expected a single integer argument", feature, "");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uiValue = (unsigned int)value;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto positiveUnsignedArgument = [&](const char* feature, unsigned int& uiValue) {
|
|
||||||
int value;
|
|
||||||
if (it->size() == 1 && it->getInt(value)) {
|
|
||||||
if (value == 0) {
|
|
||||||
error(node->getLoc(), "must be greater than or equal to 1", feature, "");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn(node->getLoc(), "expected a single integer argument", feature, "");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
uiValue = (unsigned int)value;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto spirv14 = [&](const char* feature) {
|
|
||||||
if (spvVersion.spv > 0 && spvVersion.spv < EShTargetSpv_1_4)
|
|
||||||
warn(node->getLoc(), "attribute requires a SPIR-V 1.4 target-env", feature, "");
|
|
||||||
};
|
|
||||||
|
|
||||||
int value = 0;
|
|
||||||
unsigned uiValue = 0;
|
|
||||||
switch (it->name) {
|
|
||||||
case EatUnroll:
|
|
||||||
if (noArgument("unroll"))
|
|
||||||
loop->setUnroll();
|
|
||||||
break;
|
|
||||||
case EatLoop:
|
|
||||||
if (noArgument("dont_unroll"))
|
|
||||||
loop->setDontUnroll();
|
|
||||||
break;
|
|
||||||
case EatDependencyInfinite:
|
|
||||||
if (noArgument("dependency_infinite"))
|
|
||||||
loop->setLoopDependency(TIntermLoop::dependencyInfinite);
|
|
||||||
break;
|
|
||||||
case EatDependencyLength:
|
|
||||||
if (positiveSignedArgument("dependency_length", value))
|
|
||||||
loop->setLoopDependency(value);
|
|
||||||
break;
|
|
||||||
case EatMinIterations:
|
|
||||||
spirv14("min_iterations");
|
|
||||||
if (unsignedArgument("min_iterations", uiValue))
|
|
||||||
loop->setMinIterations(uiValue);
|
|
||||||
break;
|
|
||||||
case EatMaxIterations:
|
|
||||||
spirv14("max_iterations");
|
|
||||||
if (unsignedArgument("max_iterations", uiValue))
|
|
||||||
loop->setMaxIterations(uiValue);
|
|
||||||
break;
|
|
||||||
case EatIterationMultiple:
|
|
||||||
spirv14("iteration_multiple");
|
|
||||||
if (positiveUnsignedArgument("iteration_multiple", uiValue))
|
|
||||||
loop->setIterationMultiple(uiValue);
|
|
||||||
break;
|
|
||||||
case EatPeelCount:
|
|
||||||
spirv14("peel_count");
|
|
||||||
if (unsignedArgument("peel_count", uiValue))
|
|
||||||
loop->setPeelCount(uiValue);
|
|
||||||
break;
|
|
||||||
case EatPartialCount:
|
|
||||||
spirv14("partial_count");
|
|
||||||
if (unsignedArgument("partial_count", uiValue))
|
|
||||||
loop->setPartialCount(uiValue);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
warn(node->getLoc(), "attribute does not apply to a loop", "", "");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // GLSLANG_WEB
|
|
|
@ -1,149 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2017 LunarG, Inc.
|
|
||||||
// Copyright (C) 2018 Google, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef _ATTRIBUTE_INCLUDED_
|
|
||||||
#define _ATTRIBUTE_INCLUDED_
|
|
||||||
|
|
||||||
#include "../Include/Common.h"
|
|
||||||
#include "../Include/ConstantUnion.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
enum TAttributeType {
|
|
||||||
EatNone,
|
|
||||||
EatAllow_uav_condition,
|
|
||||||
EatBranch,
|
|
||||||
EatCall,
|
|
||||||
EatDomain,
|
|
||||||
EatEarlyDepthStencil,
|
|
||||||
EatFastOpt,
|
|
||||||
EatFlatten,
|
|
||||||
EatForceCase,
|
|
||||||
EatInstance,
|
|
||||||
EatMaxTessFactor,
|
|
||||||
EatNumThreads,
|
|
||||||
EatMaxVertexCount,
|
|
||||||
EatOutputControlPoints,
|
|
||||||
EatOutputTopology,
|
|
||||||
EatPartitioning,
|
|
||||||
EatPatchConstantFunc,
|
|
||||||
EatPatchSize,
|
|
||||||
EatUnroll,
|
|
||||||
EatLoop,
|
|
||||||
EatBinding,
|
|
||||||
EatGlobalBinding,
|
|
||||||
EatLocation,
|
|
||||||
EatInputAttachment,
|
|
||||||
EatBuiltIn,
|
|
||||||
EatPushConstant,
|
|
||||||
EatConstantId,
|
|
||||||
EatDependencyInfinite,
|
|
||||||
EatDependencyLength,
|
|
||||||
EatMinIterations,
|
|
||||||
EatMaxIterations,
|
|
||||||
EatIterationMultiple,
|
|
||||||
EatPeelCount,
|
|
||||||
EatPartialCount,
|
|
||||||
EatFormatRgba32f,
|
|
||||||
EatFormatRgba16f,
|
|
||||||
EatFormatR32f,
|
|
||||||
EatFormatRgba8,
|
|
||||||
EatFormatRgba8Snorm,
|
|
||||||
EatFormatRg32f,
|
|
||||||
EatFormatRg16f,
|
|
||||||
EatFormatR11fG11fB10f,
|
|
||||||
EatFormatR16f,
|
|
||||||
EatFormatRgba16,
|
|
||||||
EatFormatRgb10A2,
|
|
||||||
EatFormatRg16,
|
|
||||||
EatFormatRg8,
|
|
||||||
EatFormatR16,
|
|
||||||
EatFormatR8,
|
|
||||||
EatFormatRgba16Snorm,
|
|
||||||
EatFormatRg16Snorm,
|
|
||||||
EatFormatRg8Snorm,
|
|
||||||
EatFormatR16Snorm,
|
|
||||||
EatFormatR8Snorm,
|
|
||||||
EatFormatRgba32i,
|
|
||||||
EatFormatRgba16i,
|
|
||||||
EatFormatRgba8i,
|
|
||||||
EatFormatR32i,
|
|
||||||
EatFormatRg32i,
|
|
||||||
EatFormatRg16i,
|
|
||||||
EatFormatRg8i,
|
|
||||||
EatFormatR16i,
|
|
||||||
EatFormatR8i,
|
|
||||||
EatFormatRgba32ui,
|
|
||||||
EatFormatRgba16ui,
|
|
||||||
EatFormatRgba8ui,
|
|
||||||
EatFormatR32ui,
|
|
||||||
EatFormatRgb10a2ui,
|
|
||||||
EatFormatRg32ui,
|
|
||||||
EatFormatRg16ui,
|
|
||||||
EatFormatRg8ui,
|
|
||||||
EatFormatR16ui,
|
|
||||||
EatFormatR8ui,
|
|
||||||
EatFormatUnknown,
|
|
||||||
EatNonWritable,
|
|
||||||
EatNonReadable
|
|
||||||
};
|
|
||||||
|
|
||||||
class TIntermAggregate;
|
|
||||||
|
|
||||||
struct TAttributeArgs {
|
|
||||||
TAttributeType name;
|
|
||||||
const TIntermAggregate* args;
|
|
||||||
|
|
||||||
// Obtain attribute as integer
|
|
||||||
// Return false if it cannot be obtained
|
|
||||||
bool getInt(int& value, int argNum = 0) const;
|
|
||||||
|
|
||||||
// Obtain attribute as string, with optional to-lower transform
|
|
||||||
// Return false if it cannot be obtained
|
|
||||||
bool getString(TString& value, int argNum = 0, bool convertToLower = true) const;
|
|
||||||
|
|
||||||
// How many arguments were provided to the attribute?
|
|
||||||
int size() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
const TConstUnion* getConstUnion(TBasicType basicType, int argNum) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef TList<TAttributeArgs> TAttributes;
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _ATTRIBUTE_INCLUDED_
|
|
|
@ -1,210 +0,0 @@
|
||||||
/*
|
|
||||||
** Copyright (c) 2013 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
** copy of this software and/or associated documentation files (the
|
|
||||||
** "Materials"), to deal in the Materials without restriction, including
|
|
||||||
** without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
** permit persons to whom the Materials are furnished to do so, subject to
|
|
||||||
** the following conditions:
|
|
||||||
**
|
|
||||||
** The above copyright notice and this permission notice shall be included
|
|
||||||
** in all copies or substantial portions of the Materials.
|
|
||||||
**
|
|
||||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define GL_FLOAT 0x1406
|
|
||||||
#define GL_FLOAT_VEC2 0x8B50
|
|
||||||
#define GL_FLOAT_VEC3 0x8B51
|
|
||||||
#define GL_FLOAT_VEC4 0x8B52
|
|
||||||
|
|
||||||
#define GL_DOUBLE 0x140A
|
|
||||||
#define GL_DOUBLE_VEC2 0x8FFC
|
|
||||||
#define GL_DOUBLE_VEC3 0x8FFD
|
|
||||||
#define GL_DOUBLE_VEC4 0x8FFE
|
|
||||||
|
|
||||||
#define GL_INT 0x1404
|
|
||||||
#define GL_INT_VEC2 0x8B53
|
|
||||||
#define GL_INT_VEC3 0x8B54
|
|
||||||
#define GL_INT_VEC4 0x8B55
|
|
||||||
|
|
||||||
#define GL_UNSIGNED_INT 0x1405
|
|
||||||
#define GL_UNSIGNED_INT_VEC2 0x8DC6
|
|
||||||
#define GL_UNSIGNED_INT_VEC3 0x8DC7
|
|
||||||
#define GL_UNSIGNED_INT_VEC4 0x8DC8
|
|
||||||
|
|
||||||
#define GL_INT64_ARB 0x140E
|
|
||||||
#define GL_INT64_VEC2_ARB 0x8FE9
|
|
||||||
#define GL_INT64_VEC3_ARB 0x8FEA
|
|
||||||
#define GL_INT64_VEC4_ARB 0x8FEB
|
|
||||||
|
|
||||||
#define GL_UNSIGNED_INT64_ARB 0x140F
|
|
||||||
#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FE5
|
|
||||||
#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FE6
|
|
||||||
#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FE7
|
|
||||||
|
|
||||||
#define GL_BOOL 0x8B56
|
|
||||||
#define GL_BOOL_VEC2 0x8B57
|
|
||||||
#define GL_BOOL_VEC3 0x8B58
|
|
||||||
#define GL_BOOL_VEC4 0x8B59
|
|
||||||
|
|
||||||
#define GL_FLOAT_MAT2 0x8B5A
|
|
||||||
#define GL_FLOAT_MAT3 0x8B5B
|
|
||||||
#define GL_FLOAT_MAT4 0x8B5C
|
|
||||||
#define GL_FLOAT_MAT2x3 0x8B65
|
|
||||||
#define GL_FLOAT_MAT2x4 0x8B66
|
|
||||||
#define GL_FLOAT_MAT3x2 0x8B67
|
|
||||||
#define GL_FLOAT_MAT3x4 0x8B68
|
|
||||||
#define GL_FLOAT_MAT4x2 0x8B69
|
|
||||||
#define GL_FLOAT_MAT4x3 0x8B6A
|
|
||||||
|
|
||||||
#define GL_DOUBLE_MAT2 0x8F46
|
|
||||||
#define GL_DOUBLE_MAT3 0x8F47
|
|
||||||
#define GL_DOUBLE_MAT4 0x8F48
|
|
||||||
#define GL_DOUBLE_MAT2x3 0x8F49
|
|
||||||
#define GL_DOUBLE_MAT2x4 0x8F4A
|
|
||||||
#define GL_DOUBLE_MAT3x2 0x8F4B
|
|
||||||
#define GL_DOUBLE_MAT3x4 0x8F4C
|
|
||||||
#define GL_DOUBLE_MAT4x2 0x8F4D
|
|
||||||
#define GL_DOUBLE_MAT4x3 0x8F4E
|
|
||||||
|
|
||||||
// Those constants are borrowed from extension NV_gpu_shader5
|
|
||||||
#define GL_FLOAT16_NV 0x8FF8
|
|
||||||
#define GL_FLOAT16_VEC2_NV 0x8FF9
|
|
||||||
#define GL_FLOAT16_VEC3_NV 0x8FFA
|
|
||||||
#define GL_FLOAT16_VEC4_NV 0x8FFB
|
|
||||||
|
|
||||||
#define GL_FLOAT16_MAT2_AMD 0x91C5
|
|
||||||
#define GL_FLOAT16_MAT3_AMD 0x91C6
|
|
||||||
#define GL_FLOAT16_MAT4_AMD 0x91C7
|
|
||||||
#define GL_FLOAT16_MAT2x3_AMD 0x91C8
|
|
||||||
#define GL_FLOAT16_MAT2x4_AMD 0x91C9
|
|
||||||
#define GL_FLOAT16_MAT3x2_AMD 0x91CA
|
|
||||||
#define GL_FLOAT16_MAT3x4_AMD 0x91CB
|
|
||||||
#define GL_FLOAT16_MAT4x2_AMD 0x91CC
|
|
||||||
#define GL_FLOAT16_MAT4x3_AMD 0x91CD
|
|
||||||
|
|
||||||
#define GL_SAMPLER_1D 0x8B5D
|
|
||||||
#define GL_SAMPLER_2D 0x8B5E
|
|
||||||
#define GL_SAMPLER_3D 0x8B5F
|
|
||||||
#define GL_SAMPLER_CUBE 0x8B60
|
|
||||||
#define GL_SAMPLER_BUFFER 0x8DC2
|
|
||||||
#define GL_SAMPLER_1D_ARRAY 0x8DC0
|
|
||||||
#define GL_SAMPLER_2D_ARRAY 0x8DC1
|
|
||||||
#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
|
|
||||||
#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
|
|
||||||
#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
|
|
||||||
#define GL_SAMPLER_1D_SHADOW 0x8B61
|
|
||||||
#define GL_SAMPLER_2D_SHADOW 0x8B62
|
|
||||||
#define GL_SAMPLER_2D_RECT 0x8B63
|
|
||||||
#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
|
|
||||||
#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
|
|
||||||
#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
|
|
||||||
#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
|
|
||||||
#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
|
|
||||||
#define GL_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900C
|
|
||||||
#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB 0x900D
|
|
||||||
|
|
||||||
#define GL_FLOAT16_SAMPLER_1D_AMD 0x91CE
|
|
||||||
#define GL_FLOAT16_SAMPLER_2D_AMD 0x91CF
|
|
||||||
#define GL_FLOAT16_SAMPLER_3D_AMD 0x91D0
|
|
||||||
#define GL_FLOAT16_SAMPLER_CUBE_AMD 0x91D1
|
|
||||||
#define GL_FLOAT16_SAMPLER_2D_RECT_AMD 0x91D2
|
|
||||||
#define GL_FLOAT16_SAMPLER_1D_ARRAY_AMD 0x91D3
|
|
||||||
#define GL_FLOAT16_SAMPLER_2D_ARRAY_AMD 0x91D4
|
|
||||||
#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_AMD 0x91D5
|
|
||||||
#define GL_FLOAT16_SAMPLER_BUFFER_AMD 0x91D6
|
|
||||||
#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_AMD 0x91D7
|
|
||||||
#define GL_FLOAT16_SAMPLER_2D_MULTISAMPLE_ARRAY_AMD 0x91D8
|
|
||||||
|
|
||||||
#define GL_FLOAT16_SAMPLER_1D_SHADOW_AMD 0x91D9
|
|
||||||
#define GL_FLOAT16_SAMPLER_2D_SHADOW_AMD 0x91DA
|
|
||||||
#define GL_FLOAT16_SAMPLER_2D_RECT_SHADOW_AMD 0x91DB
|
|
||||||
#define GL_FLOAT16_SAMPLER_1D_ARRAY_SHADOW_AMD 0x91DC
|
|
||||||
#define GL_FLOAT16_SAMPLER_2D_ARRAY_SHADOW_AMD 0x91DD
|
|
||||||
#define GL_FLOAT16_SAMPLER_CUBE_SHADOW_AMD 0x91DE
|
|
||||||
#define GL_FLOAT16_SAMPLER_CUBE_MAP_ARRAY_SHADOW_AMD 0x91DF
|
|
||||||
|
|
||||||
#define GL_FLOAT16_IMAGE_1D_AMD 0x91E0
|
|
||||||
#define GL_FLOAT16_IMAGE_2D_AMD 0x91E1
|
|
||||||
#define GL_FLOAT16_IMAGE_3D_AMD 0x91E2
|
|
||||||
#define GL_FLOAT16_IMAGE_2D_RECT_AMD 0x91E3
|
|
||||||
#define GL_FLOAT16_IMAGE_CUBE_AMD 0x91E4
|
|
||||||
#define GL_FLOAT16_IMAGE_1D_ARRAY_AMD 0x91E5
|
|
||||||
#define GL_FLOAT16_IMAGE_2D_ARRAY_AMD 0x91E6
|
|
||||||
#define GL_FLOAT16_IMAGE_CUBE_MAP_ARRAY_AMD 0x91E7
|
|
||||||
#define GL_FLOAT16_IMAGE_BUFFER_AMD 0x91E8
|
|
||||||
#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_AMD 0x91E9
|
|
||||||
#define GL_FLOAT16_IMAGE_2D_MULTISAMPLE_ARRAY_AMD 0x91EA
|
|
||||||
|
|
||||||
#define GL_INT_SAMPLER_1D 0x8DC9
|
|
||||||
#define GL_INT_SAMPLER_2D 0x8DCA
|
|
||||||
#define GL_INT_SAMPLER_3D 0x8DCB
|
|
||||||
#define GL_INT_SAMPLER_CUBE 0x8DCC
|
|
||||||
#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
|
|
||||||
#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
|
|
||||||
#define GL_INT_SAMPLER_2D_RECT 0x8DCD
|
|
||||||
#define GL_INT_SAMPLER_BUFFER 0x8DD0
|
|
||||||
#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
|
|
||||||
#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
|
|
||||||
#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
|
|
||||||
#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900E
|
|
||||||
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB 0x900F
|
|
||||||
#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
|
|
||||||
|
|
||||||
#define GL_IMAGE_1D 0x904C
|
|
||||||
#define GL_IMAGE_2D 0x904D
|
|
||||||
#define GL_IMAGE_3D 0x904E
|
|
||||||
#define GL_IMAGE_2D_RECT 0x904F
|
|
||||||
#define GL_IMAGE_CUBE 0x9050
|
|
||||||
#define GL_IMAGE_BUFFER 0x9051
|
|
||||||
#define GL_IMAGE_1D_ARRAY 0x9052
|
|
||||||
#define GL_IMAGE_2D_ARRAY 0x9053
|
|
||||||
#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
|
|
||||||
#define GL_IMAGE_2D_MULTISAMPLE 0x9055
|
|
||||||
#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
|
|
||||||
#define GL_INT_IMAGE_1D 0x9057
|
|
||||||
#define GL_INT_IMAGE_2D 0x9058
|
|
||||||
#define GL_INT_IMAGE_3D 0x9059
|
|
||||||
#define GL_INT_IMAGE_2D_RECT 0x905A
|
|
||||||
#define GL_INT_IMAGE_CUBE 0x905B
|
|
||||||
#define GL_INT_IMAGE_BUFFER 0x905C
|
|
||||||
#define GL_INT_IMAGE_1D_ARRAY 0x905D
|
|
||||||
#define GL_INT_IMAGE_2D_ARRAY 0x905E
|
|
||||||
#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
|
|
||||||
#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
|
|
||||||
#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
|
|
||||||
#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
|
|
||||||
#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
|
|
||||||
#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
|
|
||||||
#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
|
|
||||||
#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
|
|
||||||
#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
|
|
||||||
#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
|
|
||||||
#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
|
|
||||||
#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
|
|
||||||
#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
|
|
||||||
#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
|
|
||||||
|
|
||||||
#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,521 +0,0 @@
|
||||||
/* A Bison parser, made by GNU Bison 3.0.4. */
|
|
||||||
|
|
||||||
/* Bison interface for Yacc-like parsers in C
|
|
||||||
|
|
||||||
Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
|
|
||||||
#ifndef YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
|
|
||||||
# define YY_YY_GLSLANG_TAB_CPP_H_INCLUDED
|
|
||||||
/* Debug traces. */
|
|
||||||
#ifndef YYDEBUG
|
|
||||||
# define YYDEBUG 1
|
|
||||||
#endif
|
|
||||||
#if YYDEBUG
|
|
||||||
extern int yydebug;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Token type. */
|
|
||||||
#ifndef YYTOKENTYPE
|
|
||||||
# define YYTOKENTYPE
|
|
||||||
enum yytokentype
|
|
||||||
{
|
|
||||||
CONST = 258,
|
|
||||||
BOOL = 259,
|
|
||||||
INT = 260,
|
|
||||||
UINT = 261,
|
|
||||||
FLOAT = 262,
|
|
||||||
BVEC2 = 263,
|
|
||||||
BVEC3 = 264,
|
|
||||||
BVEC4 = 265,
|
|
||||||
IVEC2 = 266,
|
|
||||||
IVEC3 = 267,
|
|
||||||
IVEC4 = 268,
|
|
||||||
UVEC2 = 269,
|
|
||||||
UVEC3 = 270,
|
|
||||||
UVEC4 = 271,
|
|
||||||
VEC2 = 272,
|
|
||||||
VEC3 = 273,
|
|
||||||
VEC4 = 274,
|
|
||||||
MAT2 = 275,
|
|
||||||
MAT3 = 276,
|
|
||||||
MAT4 = 277,
|
|
||||||
MAT2X2 = 278,
|
|
||||||
MAT2X3 = 279,
|
|
||||||
MAT2X4 = 280,
|
|
||||||
MAT3X2 = 281,
|
|
||||||
MAT3X3 = 282,
|
|
||||||
MAT3X4 = 283,
|
|
||||||
MAT4X2 = 284,
|
|
||||||
MAT4X3 = 285,
|
|
||||||
MAT4X4 = 286,
|
|
||||||
SAMPLER2D = 287,
|
|
||||||
SAMPLER3D = 288,
|
|
||||||
SAMPLERCUBE = 289,
|
|
||||||
SAMPLER2DSHADOW = 290,
|
|
||||||
SAMPLERCUBESHADOW = 291,
|
|
||||||
SAMPLER2DARRAY = 292,
|
|
||||||
SAMPLER2DARRAYSHADOW = 293,
|
|
||||||
ISAMPLER2D = 294,
|
|
||||||
ISAMPLER3D = 295,
|
|
||||||
ISAMPLERCUBE = 296,
|
|
||||||
ISAMPLER2DARRAY = 297,
|
|
||||||
USAMPLER2D = 298,
|
|
||||||
USAMPLER3D = 299,
|
|
||||||
USAMPLERCUBE = 300,
|
|
||||||
USAMPLER2DARRAY = 301,
|
|
||||||
SAMPLER = 302,
|
|
||||||
SAMPLERSHADOW = 303,
|
|
||||||
TEXTURE2D = 304,
|
|
||||||
TEXTURE3D = 305,
|
|
||||||
TEXTURECUBE = 306,
|
|
||||||
TEXTURE2DARRAY = 307,
|
|
||||||
ITEXTURE2D = 308,
|
|
||||||
ITEXTURE3D = 309,
|
|
||||||
ITEXTURECUBE = 310,
|
|
||||||
ITEXTURE2DARRAY = 311,
|
|
||||||
UTEXTURE2D = 312,
|
|
||||||
UTEXTURE3D = 313,
|
|
||||||
UTEXTURECUBE = 314,
|
|
||||||
UTEXTURE2DARRAY = 315,
|
|
||||||
ATTRIBUTE = 316,
|
|
||||||
VARYING = 317,
|
|
||||||
FLOAT16_T = 318,
|
|
||||||
FLOAT32_T = 319,
|
|
||||||
DOUBLE = 320,
|
|
||||||
FLOAT64_T = 321,
|
|
||||||
INT64_T = 322,
|
|
||||||
UINT64_T = 323,
|
|
||||||
INT32_T = 324,
|
|
||||||
UINT32_T = 325,
|
|
||||||
INT16_T = 326,
|
|
||||||
UINT16_T = 327,
|
|
||||||
INT8_T = 328,
|
|
||||||
UINT8_T = 329,
|
|
||||||
I64VEC2 = 330,
|
|
||||||
I64VEC3 = 331,
|
|
||||||
I64VEC4 = 332,
|
|
||||||
U64VEC2 = 333,
|
|
||||||
U64VEC3 = 334,
|
|
||||||
U64VEC4 = 335,
|
|
||||||
I32VEC2 = 336,
|
|
||||||
I32VEC3 = 337,
|
|
||||||
I32VEC4 = 338,
|
|
||||||
U32VEC2 = 339,
|
|
||||||
U32VEC3 = 340,
|
|
||||||
U32VEC4 = 341,
|
|
||||||
I16VEC2 = 342,
|
|
||||||
I16VEC3 = 343,
|
|
||||||
I16VEC4 = 344,
|
|
||||||
U16VEC2 = 345,
|
|
||||||
U16VEC3 = 346,
|
|
||||||
U16VEC4 = 347,
|
|
||||||
I8VEC2 = 348,
|
|
||||||
I8VEC3 = 349,
|
|
||||||
I8VEC4 = 350,
|
|
||||||
U8VEC2 = 351,
|
|
||||||
U8VEC3 = 352,
|
|
||||||
U8VEC4 = 353,
|
|
||||||
DVEC2 = 354,
|
|
||||||
DVEC3 = 355,
|
|
||||||
DVEC4 = 356,
|
|
||||||
DMAT2 = 357,
|
|
||||||
DMAT3 = 358,
|
|
||||||
DMAT4 = 359,
|
|
||||||
F16VEC2 = 360,
|
|
||||||
F16VEC3 = 361,
|
|
||||||
F16VEC4 = 362,
|
|
||||||
F16MAT2 = 363,
|
|
||||||
F16MAT3 = 364,
|
|
||||||
F16MAT4 = 365,
|
|
||||||
F32VEC2 = 366,
|
|
||||||
F32VEC3 = 367,
|
|
||||||
F32VEC4 = 368,
|
|
||||||
F32MAT2 = 369,
|
|
||||||
F32MAT3 = 370,
|
|
||||||
F32MAT4 = 371,
|
|
||||||
F64VEC2 = 372,
|
|
||||||
F64VEC3 = 373,
|
|
||||||
F64VEC4 = 374,
|
|
||||||
F64MAT2 = 375,
|
|
||||||
F64MAT3 = 376,
|
|
||||||
F64MAT4 = 377,
|
|
||||||
DMAT2X2 = 378,
|
|
||||||
DMAT2X3 = 379,
|
|
||||||
DMAT2X4 = 380,
|
|
||||||
DMAT3X2 = 381,
|
|
||||||
DMAT3X3 = 382,
|
|
||||||
DMAT3X4 = 383,
|
|
||||||
DMAT4X2 = 384,
|
|
||||||
DMAT4X3 = 385,
|
|
||||||
DMAT4X4 = 386,
|
|
||||||
F16MAT2X2 = 387,
|
|
||||||
F16MAT2X3 = 388,
|
|
||||||
F16MAT2X4 = 389,
|
|
||||||
F16MAT3X2 = 390,
|
|
||||||
F16MAT3X3 = 391,
|
|
||||||
F16MAT3X4 = 392,
|
|
||||||
F16MAT4X2 = 393,
|
|
||||||
F16MAT4X3 = 394,
|
|
||||||
F16MAT4X4 = 395,
|
|
||||||
F32MAT2X2 = 396,
|
|
||||||
F32MAT2X3 = 397,
|
|
||||||
F32MAT2X4 = 398,
|
|
||||||
F32MAT3X2 = 399,
|
|
||||||
F32MAT3X3 = 400,
|
|
||||||
F32MAT3X4 = 401,
|
|
||||||
F32MAT4X2 = 402,
|
|
||||||
F32MAT4X3 = 403,
|
|
||||||
F32MAT4X4 = 404,
|
|
||||||
F64MAT2X2 = 405,
|
|
||||||
F64MAT2X3 = 406,
|
|
||||||
F64MAT2X4 = 407,
|
|
||||||
F64MAT3X2 = 408,
|
|
||||||
F64MAT3X3 = 409,
|
|
||||||
F64MAT3X4 = 410,
|
|
||||||
F64MAT4X2 = 411,
|
|
||||||
F64MAT4X3 = 412,
|
|
||||||
F64MAT4X4 = 413,
|
|
||||||
ATOMIC_UINT = 414,
|
|
||||||
ACCSTRUCTNV = 415,
|
|
||||||
ACCSTRUCTEXT = 416,
|
|
||||||
RAYQUERYEXT = 417,
|
|
||||||
FCOOPMATNV = 418,
|
|
||||||
ICOOPMATNV = 419,
|
|
||||||
UCOOPMATNV = 420,
|
|
||||||
SAMPLERCUBEARRAY = 421,
|
|
||||||
SAMPLERCUBEARRAYSHADOW = 422,
|
|
||||||
ISAMPLERCUBEARRAY = 423,
|
|
||||||
USAMPLERCUBEARRAY = 424,
|
|
||||||
SAMPLER1D = 425,
|
|
||||||
SAMPLER1DARRAY = 426,
|
|
||||||
SAMPLER1DARRAYSHADOW = 427,
|
|
||||||
ISAMPLER1D = 428,
|
|
||||||
SAMPLER1DSHADOW = 429,
|
|
||||||
SAMPLER2DRECT = 430,
|
|
||||||
SAMPLER2DRECTSHADOW = 431,
|
|
||||||
ISAMPLER2DRECT = 432,
|
|
||||||
USAMPLER2DRECT = 433,
|
|
||||||
SAMPLERBUFFER = 434,
|
|
||||||
ISAMPLERBUFFER = 435,
|
|
||||||
USAMPLERBUFFER = 436,
|
|
||||||
SAMPLER2DMS = 437,
|
|
||||||
ISAMPLER2DMS = 438,
|
|
||||||
USAMPLER2DMS = 439,
|
|
||||||
SAMPLER2DMSARRAY = 440,
|
|
||||||
ISAMPLER2DMSARRAY = 441,
|
|
||||||
USAMPLER2DMSARRAY = 442,
|
|
||||||
SAMPLEREXTERNALOES = 443,
|
|
||||||
SAMPLEREXTERNAL2DY2YEXT = 444,
|
|
||||||
ISAMPLER1DARRAY = 445,
|
|
||||||
USAMPLER1D = 446,
|
|
||||||
USAMPLER1DARRAY = 447,
|
|
||||||
F16SAMPLER1D = 448,
|
|
||||||
F16SAMPLER2D = 449,
|
|
||||||
F16SAMPLER3D = 450,
|
|
||||||
F16SAMPLER2DRECT = 451,
|
|
||||||
F16SAMPLERCUBE = 452,
|
|
||||||
F16SAMPLER1DARRAY = 453,
|
|
||||||
F16SAMPLER2DARRAY = 454,
|
|
||||||
F16SAMPLERCUBEARRAY = 455,
|
|
||||||
F16SAMPLERBUFFER = 456,
|
|
||||||
F16SAMPLER2DMS = 457,
|
|
||||||
F16SAMPLER2DMSARRAY = 458,
|
|
||||||
F16SAMPLER1DSHADOW = 459,
|
|
||||||
F16SAMPLER2DSHADOW = 460,
|
|
||||||
F16SAMPLER1DARRAYSHADOW = 461,
|
|
||||||
F16SAMPLER2DARRAYSHADOW = 462,
|
|
||||||
F16SAMPLER2DRECTSHADOW = 463,
|
|
||||||
F16SAMPLERCUBESHADOW = 464,
|
|
||||||
F16SAMPLERCUBEARRAYSHADOW = 465,
|
|
||||||
IMAGE1D = 466,
|
|
||||||
IIMAGE1D = 467,
|
|
||||||
UIMAGE1D = 468,
|
|
||||||
IMAGE2D = 469,
|
|
||||||
IIMAGE2D = 470,
|
|
||||||
UIMAGE2D = 471,
|
|
||||||
IMAGE3D = 472,
|
|
||||||
IIMAGE3D = 473,
|
|
||||||
UIMAGE3D = 474,
|
|
||||||
IMAGE2DRECT = 475,
|
|
||||||
IIMAGE2DRECT = 476,
|
|
||||||
UIMAGE2DRECT = 477,
|
|
||||||
IMAGECUBE = 478,
|
|
||||||
IIMAGECUBE = 479,
|
|
||||||
UIMAGECUBE = 480,
|
|
||||||
IMAGEBUFFER = 481,
|
|
||||||
IIMAGEBUFFER = 482,
|
|
||||||
UIMAGEBUFFER = 483,
|
|
||||||
IMAGE1DARRAY = 484,
|
|
||||||
IIMAGE1DARRAY = 485,
|
|
||||||
UIMAGE1DARRAY = 486,
|
|
||||||
IMAGE2DARRAY = 487,
|
|
||||||
IIMAGE2DARRAY = 488,
|
|
||||||
UIMAGE2DARRAY = 489,
|
|
||||||
IMAGECUBEARRAY = 490,
|
|
||||||
IIMAGECUBEARRAY = 491,
|
|
||||||
UIMAGECUBEARRAY = 492,
|
|
||||||
IMAGE2DMS = 493,
|
|
||||||
IIMAGE2DMS = 494,
|
|
||||||
UIMAGE2DMS = 495,
|
|
||||||
IMAGE2DMSARRAY = 496,
|
|
||||||
IIMAGE2DMSARRAY = 497,
|
|
||||||
UIMAGE2DMSARRAY = 498,
|
|
||||||
F16IMAGE1D = 499,
|
|
||||||
F16IMAGE2D = 500,
|
|
||||||
F16IMAGE3D = 501,
|
|
||||||
F16IMAGE2DRECT = 502,
|
|
||||||
F16IMAGECUBE = 503,
|
|
||||||
F16IMAGE1DARRAY = 504,
|
|
||||||
F16IMAGE2DARRAY = 505,
|
|
||||||
F16IMAGECUBEARRAY = 506,
|
|
||||||
F16IMAGEBUFFER = 507,
|
|
||||||
F16IMAGE2DMS = 508,
|
|
||||||
F16IMAGE2DMSARRAY = 509,
|
|
||||||
TEXTURECUBEARRAY = 510,
|
|
||||||
ITEXTURECUBEARRAY = 511,
|
|
||||||
UTEXTURECUBEARRAY = 512,
|
|
||||||
TEXTURE1D = 513,
|
|
||||||
ITEXTURE1D = 514,
|
|
||||||
UTEXTURE1D = 515,
|
|
||||||
TEXTURE1DARRAY = 516,
|
|
||||||
ITEXTURE1DARRAY = 517,
|
|
||||||
UTEXTURE1DARRAY = 518,
|
|
||||||
TEXTURE2DRECT = 519,
|
|
||||||
ITEXTURE2DRECT = 520,
|
|
||||||
UTEXTURE2DRECT = 521,
|
|
||||||
TEXTUREBUFFER = 522,
|
|
||||||
ITEXTUREBUFFER = 523,
|
|
||||||
UTEXTUREBUFFER = 524,
|
|
||||||
TEXTURE2DMS = 525,
|
|
||||||
ITEXTURE2DMS = 526,
|
|
||||||
UTEXTURE2DMS = 527,
|
|
||||||
TEXTURE2DMSARRAY = 528,
|
|
||||||
ITEXTURE2DMSARRAY = 529,
|
|
||||||
UTEXTURE2DMSARRAY = 530,
|
|
||||||
F16TEXTURE1D = 531,
|
|
||||||
F16TEXTURE2D = 532,
|
|
||||||
F16TEXTURE3D = 533,
|
|
||||||
F16TEXTURE2DRECT = 534,
|
|
||||||
F16TEXTURECUBE = 535,
|
|
||||||
F16TEXTURE1DARRAY = 536,
|
|
||||||
F16TEXTURE2DARRAY = 537,
|
|
||||||
F16TEXTURECUBEARRAY = 538,
|
|
||||||
F16TEXTUREBUFFER = 539,
|
|
||||||
F16TEXTURE2DMS = 540,
|
|
||||||
F16TEXTURE2DMSARRAY = 541,
|
|
||||||
SUBPASSINPUT = 542,
|
|
||||||
SUBPASSINPUTMS = 543,
|
|
||||||
ISUBPASSINPUT = 544,
|
|
||||||
ISUBPASSINPUTMS = 545,
|
|
||||||
USUBPASSINPUT = 546,
|
|
||||||
USUBPASSINPUTMS = 547,
|
|
||||||
F16SUBPASSINPUT = 548,
|
|
||||||
F16SUBPASSINPUTMS = 549,
|
|
||||||
LEFT_OP = 550,
|
|
||||||
RIGHT_OP = 551,
|
|
||||||
INC_OP = 552,
|
|
||||||
DEC_OP = 553,
|
|
||||||
LE_OP = 554,
|
|
||||||
GE_OP = 555,
|
|
||||||
EQ_OP = 556,
|
|
||||||
NE_OP = 557,
|
|
||||||
AND_OP = 558,
|
|
||||||
OR_OP = 559,
|
|
||||||
XOR_OP = 560,
|
|
||||||
MUL_ASSIGN = 561,
|
|
||||||
DIV_ASSIGN = 562,
|
|
||||||
ADD_ASSIGN = 563,
|
|
||||||
MOD_ASSIGN = 564,
|
|
||||||
LEFT_ASSIGN = 565,
|
|
||||||
RIGHT_ASSIGN = 566,
|
|
||||||
AND_ASSIGN = 567,
|
|
||||||
XOR_ASSIGN = 568,
|
|
||||||
OR_ASSIGN = 569,
|
|
||||||
SUB_ASSIGN = 570,
|
|
||||||
STRING_LITERAL = 571,
|
|
||||||
LEFT_PAREN = 572,
|
|
||||||
RIGHT_PAREN = 573,
|
|
||||||
LEFT_BRACKET = 574,
|
|
||||||
RIGHT_BRACKET = 575,
|
|
||||||
LEFT_BRACE = 576,
|
|
||||||
RIGHT_BRACE = 577,
|
|
||||||
DOT = 578,
|
|
||||||
COMMA = 579,
|
|
||||||
COLON = 580,
|
|
||||||
EQUAL = 581,
|
|
||||||
SEMICOLON = 582,
|
|
||||||
BANG = 583,
|
|
||||||
DASH = 584,
|
|
||||||
TILDE = 585,
|
|
||||||
PLUS = 586,
|
|
||||||
STAR = 587,
|
|
||||||
SLASH = 588,
|
|
||||||
PERCENT = 589,
|
|
||||||
LEFT_ANGLE = 590,
|
|
||||||
RIGHT_ANGLE = 591,
|
|
||||||
VERTICAL_BAR = 592,
|
|
||||||
CARET = 593,
|
|
||||||
AMPERSAND = 594,
|
|
||||||
QUESTION = 595,
|
|
||||||
INVARIANT = 596,
|
|
||||||
HIGH_PRECISION = 597,
|
|
||||||
MEDIUM_PRECISION = 598,
|
|
||||||
LOW_PRECISION = 599,
|
|
||||||
PRECISION = 600,
|
|
||||||
PACKED = 601,
|
|
||||||
RESOURCE = 602,
|
|
||||||
SUPERP = 603,
|
|
||||||
FLOATCONSTANT = 604,
|
|
||||||
INTCONSTANT = 605,
|
|
||||||
UINTCONSTANT = 606,
|
|
||||||
BOOLCONSTANT = 607,
|
|
||||||
IDENTIFIER = 608,
|
|
||||||
TYPE_NAME = 609,
|
|
||||||
CENTROID = 610,
|
|
||||||
IN = 611,
|
|
||||||
OUT = 612,
|
|
||||||
INOUT = 613,
|
|
||||||
STRUCT = 614,
|
|
||||||
VOID = 615,
|
|
||||||
WHILE = 616,
|
|
||||||
BREAK = 617,
|
|
||||||
CONTINUE = 618,
|
|
||||||
DO = 619,
|
|
||||||
ELSE = 620,
|
|
||||||
FOR = 621,
|
|
||||||
IF = 622,
|
|
||||||
DISCARD = 623,
|
|
||||||
RETURN = 624,
|
|
||||||
SWITCH = 625,
|
|
||||||
CASE = 626,
|
|
||||||
DEFAULT = 627,
|
|
||||||
UNIFORM = 628,
|
|
||||||
SHARED = 629,
|
|
||||||
BUFFER = 630,
|
|
||||||
FLAT = 631,
|
|
||||||
SMOOTH = 632,
|
|
||||||
LAYOUT = 633,
|
|
||||||
DOUBLECONSTANT = 634,
|
|
||||||
INT16CONSTANT = 635,
|
|
||||||
UINT16CONSTANT = 636,
|
|
||||||
FLOAT16CONSTANT = 637,
|
|
||||||
INT32CONSTANT = 638,
|
|
||||||
UINT32CONSTANT = 639,
|
|
||||||
INT64CONSTANT = 640,
|
|
||||||
UINT64CONSTANT = 641,
|
|
||||||
SUBROUTINE = 642,
|
|
||||||
DEMOTE = 643,
|
|
||||||
PAYLOADNV = 644,
|
|
||||||
PAYLOADINNV = 645,
|
|
||||||
HITATTRNV = 646,
|
|
||||||
CALLDATANV = 647,
|
|
||||||
CALLDATAINNV = 648,
|
|
||||||
PAYLOADEXT = 649,
|
|
||||||
PAYLOADINEXT = 650,
|
|
||||||
HITATTREXT = 651,
|
|
||||||
CALLDATAEXT = 652,
|
|
||||||
CALLDATAINEXT = 653,
|
|
||||||
PATCH = 654,
|
|
||||||
SAMPLE = 655,
|
|
||||||
NONUNIFORM = 656,
|
|
||||||
COHERENT = 657,
|
|
||||||
VOLATILE = 658,
|
|
||||||
RESTRICT = 659,
|
|
||||||
READONLY = 660,
|
|
||||||
WRITEONLY = 661,
|
|
||||||
DEVICECOHERENT = 662,
|
|
||||||
QUEUEFAMILYCOHERENT = 663,
|
|
||||||
WORKGROUPCOHERENT = 664,
|
|
||||||
SUBGROUPCOHERENT = 665,
|
|
||||||
NONPRIVATE = 666,
|
|
||||||
SHADERCALLCOHERENT = 667,
|
|
||||||
NOPERSPECTIVE = 668,
|
|
||||||
EXPLICITINTERPAMD = 669,
|
|
||||||
PERVERTEXNV = 670,
|
|
||||||
PERPRIMITIVENV = 671,
|
|
||||||
PERVIEWNV = 672,
|
|
||||||
PERTASKNV = 673,
|
|
||||||
PRECISE = 674
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Value type. */
|
|
||||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
|
||||||
|
|
||||||
union YYSTYPE
|
|
||||||
{
|
|
||||||
#line 97 "glslang.y" /* yacc.c:1909 */
|
|
||||||
|
|
||||||
struct {
|
|
||||||
glslang::TSourceLoc loc;
|
|
||||||
union {
|
|
||||||
glslang::TString *string;
|
|
||||||
int i;
|
|
||||||
unsigned int u;
|
|
||||||
long long i64;
|
|
||||||
unsigned long long u64;
|
|
||||||
bool b;
|
|
||||||
double d;
|
|
||||||
};
|
|
||||||
glslang::TSymbol* symbol;
|
|
||||||
} lex;
|
|
||||||
struct {
|
|
||||||
glslang::TSourceLoc loc;
|
|
||||||
glslang::TOperator op;
|
|
||||||
union {
|
|
||||||
TIntermNode* intermNode;
|
|
||||||
glslang::TIntermNodePair nodePair;
|
|
||||||
glslang::TIntermTyped* intermTypedNode;
|
|
||||||
glslang::TAttributes* attributes;
|
|
||||||
};
|
|
||||||
union {
|
|
||||||
glslang::TPublicType type;
|
|
||||||
glslang::TFunction* function;
|
|
||||||
glslang::TParameter param;
|
|
||||||
glslang::TTypeLoc typeLine;
|
|
||||||
glslang::TTypeList* typeList;
|
|
||||||
glslang::TArraySizes* arraySizes;
|
|
||||||
glslang::TIdentifierList* identifierList;
|
|
||||||
};
|
|
||||||
glslang::TArraySizes* typeParameters;
|
|
||||||
} interm;
|
|
||||||
|
|
||||||
#line 510 "glslang_tab.cpp.h" /* yacc.c:1909 */
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef union YYSTYPE YYSTYPE;
|
|
||||||
# define YYSTYPE_IS_TRIVIAL 1
|
|
||||||
# define YYSTYPE_IS_DECLARED 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int yyparse (glslang::TParseContext* pParseContext);
|
|
||||||
|
|
||||||
#endif /* !YY_YY_GLSLANG_TAB_CPP_H_INCLUDED */
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,302 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2016 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
|
|
||||||
#ifndef _IOMAPPER_INCLUDED
|
|
||||||
#define _IOMAPPER_INCLUDED
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include "LiveTraverser.h"
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
//
|
|
||||||
// A reflection database and its interface, consistent with the OpenGL API reflection queries.
|
|
||||||
//
|
|
||||||
|
|
||||||
class TInfoSink;
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
class TIntermediate;
|
|
||||||
struct TVarEntryInfo {
|
|
||||||
int id;
|
|
||||||
TIntermSymbol* symbol;
|
|
||||||
bool live;
|
|
||||||
int newBinding;
|
|
||||||
int newSet;
|
|
||||||
int newLocation;
|
|
||||||
int newComponent;
|
|
||||||
int newIndex;
|
|
||||||
EShLanguage stage;
|
|
||||||
struct TOrderById {
|
|
||||||
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) { return l.id < r.id; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TOrderByPriority {
|
|
||||||
// ordering:
|
|
||||||
// 1) has both binding and set
|
|
||||||
// 2) has binding but no set
|
|
||||||
// 3) has no binding but set
|
|
||||||
// 4) has no binding and no set
|
|
||||||
inline bool operator()(const TVarEntryInfo& l, const TVarEntryInfo& r) {
|
|
||||||
const TQualifier& lq = l.symbol->getQualifier();
|
|
||||||
const TQualifier& rq = r.symbol->getQualifier();
|
|
||||||
|
|
||||||
// simple rules:
|
|
||||||
// has binding gives 2 points
|
|
||||||
// has set gives 1 point
|
|
||||||
// who has the most points is more important.
|
|
||||||
int lPoints = (lq.hasBinding() ? 2 : 0) + (lq.hasSet() ? 1 : 0);
|
|
||||||
int rPoints = (rq.hasBinding() ? 2 : 0) + (rq.hasSet() ? 1 : 0);
|
|
||||||
|
|
||||||
if (lPoints == rPoints)
|
|
||||||
return l.id < r.id;
|
|
||||||
return lPoints > rPoints;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base class for shared TIoMapResolver services, used by several derivations.
|
|
||||||
struct TDefaultIoResolverBase : public glslang::TIoMapResolver {
|
|
||||||
public:
|
|
||||||
TDefaultIoResolverBase(const TIntermediate& intermediate);
|
|
||||||
typedef std::vector<int> TSlotSet;
|
|
||||||
typedef std::unordered_map<int, TSlotSet> TSlotSetMap;
|
|
||||||
|
|
||||||
// grow the reflection stage by stage
|
|
||||||
void notifyBinding(EShLanguage, TVarEntryInfo& /*ent*/) override {}
|
|
||||||
void notifyInOut(EShLanguage, TVarEntryInfo& /*ent*/) override {}
|
|
||||||
void beginNotifications(EShLanguage) override {}
|
|
||||||
void endNotifications(EShLanguage) override {}
|
|
||||||
void beginResolve(EShLanguage) override {}
|
|
||||||
void endResolve(EShLanguage) override {}
|
|
||||||
void beginCollect(EShLanguage) override {}
|
|
||||||
void endCollect(EShLanguage) override {}
|
|
||||||
void reserverResourceSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
|
|
||||||
void reserverStorageSlot(TVarEntryInfo& /*ent*/, TInfoSink& /*infoSink*/) override {}
|
|
||||||
int getBaseBinding(TResourceType res, unsigned int set) const;
|
|
||||||
const std::vector<std::string>& getResourceSetBinding() const;
|
|
||||||
virtual TResourceType getResourceType(const glslang::TType& type) = 0;
|
|
||||||
bool doAutoBindingMapping() const;
|
|
||||||
bool doAutoLocationMapping() const;
|
|
||||||
TSlotSet::iterator findSlot(int set, int slot);
|
|
||||||
bool checkEmpty(int set, int slot);
|
|
||||||
bool validateInOut(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
|
|
||||||
int reserveSlot(int set, int slot, int size = 1);
|
|
||||||
int getFreeSlot(int set, int base, int size = 1);
|
|
||||||
int resolveSet(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
|
||||||
int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
|
||||||
int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
|
|
||||||
int resolveInOutComponent(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
|
||||||
int resolveInOutIndex(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
|
||||||
void addStage(EShLanguage stage) override {
|
|
||||||
if (stage < EShLangCount)
|
|
||||||
stageMask[stage] = true;
|
|
||||||
}
|
|
||||||
uint32_t computeTypeLocationSize(const TType& type, EShLanguage stage);
|
|
||||||
|
|
||||||
TSlotSetMap slots;
|
|
||||||
bool hasError = false;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TDefaultIoResolverBase(TDefaultIoResolverBase&);
|
|
||||||
TDefaultIoResolverBase& operator=(TDefaultIoResolverBase&);
|
|
||||||
const TIntermediate& intermediate;
|
|
||||||
int nextUniformLocation;
|
|
||||||
int nextInputLocation;
|
|
||||||
int nextOutputLocation;
|
|
||||||
bool stageMask[EShLangCount + 1];
|
|
||||||
// Return descriptor set specific base if there is one, and the generic base otherwise.
|
|
||||||
int selectBaseBinding(int base, int descriptorSetBase) const {
|
|
||||||
return descriptorSetBase != -1 ? descriptorSetBase : base;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getLayoutSet(const glslang::TType& type) {
|
|
||||||
if (type.getQualifier().hasSet())
|
|
||||||
return type.getQualifier().layoutSet;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isSamplerType(const glslang::TType& type) {
|
|
||||||
return type.getBasicType() == glslang::EbtSampler && type.getSampler().isPureSampler();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isTextureType(const glslang::TType& type) {
|
|
||||||
return (type.getBasicType() == glslang::EbtSampler &&
|
|
||||||
(type.getSampler().isTexture() || type.getSampler().isSubpass()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isUboType(const glslang::TType& type) {
|
|
||||||
return type.getQualifier().storage == EvqUniform;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isImageType(const glslang::TType& type) {
|
|
||||||
return type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isSsboType(const glslang::TType& type) {
|
|
||||||
return type.getQualifier().storage == EvqBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return true if this is a SRV (shader resource view) type:
|
|
||||||
static bool isSrvType(const glslang::TType& type) {
|
|
||||||
return isTextureType(type) || type.getQualifier().storage == EvqBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return true if this is a UAV (unordered access view) type:
|
|
||||||
static bool isUavType(const glslang::TType& type) {
|
|
||||||
if (type.getQualifier().isReadOnly())
|
|
||||||
return false;
|
|
||||||
return (type.getBasicType() == glslang::EbtSampler && type.getSampler().isImage()) ||
|
|
||||||
(type.getQualifier().storage == EvqBuffer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Defaulf I/O resolver for OpenGL
|
|
||||||
struct TDefaultGlslIoResolver : public TDefaultIoResolverBase {
|
|
||||||
public:
|
|
||||||
typedef std::map<TString, int> TVarSlotMap; // <resourceName, location/binding>
|
|
||||||
typedef std::map<int, TVarSlotMap> TSlotMap; // <resourceKey, TVarSlotMap>
|
|
||||||
TDefaultGlslIoResolver(const TIntermediate& intermediate);
|
|
||||||
bool validateBinding(EShLanguage /*stage*/, TVarEntryInfo& /*ent*/) override { return true; }
|
|
||||||
TResourceType getResourceType(const glslang::TType& type) override;
|
|
||||||
int resolveInOutLocation(EShLanguage stage, TVarEntryInfo& ent) override;
|
|
||||||
int resolveUniformLocation(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
|
||||||
int resolveBinding(EShLanguage /*stage*/, TVarEntryInfo& ent) override;
|
|
||||||
void beginResolve(EShLanguage /*stage*/) override;
|
|
||||||
void endResolve(EShLanguage stage) override;
|
|
||||||
void beginCollect(EShLanguage) override;
|
|
||||||
void endCollect(EShLanguage) override;
|
|
||||||
void reserverStorageSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
|
||||||
void reserverResourceSlot(TVarEntryInfo& ent, TInfoSink& infoSink) override;
|
|
||||||
const TString& getAccessName(const TIntermSymbol*);
|
|
||||||
// in/out symbol and uniform symbol are stored in the same resourceSlotMap, the storage key is used to identify each type of symbol.
|
|
||||||
// We use stage and storage qualifier to construct a storage key. it can help us identify the same storage resource used in different stage.
|
|
||||||
// if a resource is a program resource and we don't need know it usage stage, we can use same stage to build storage key.
|
|
||||||
// Note: both stage and type must less then 0xffff.
|
|
||||||
int buildStorageKey(EShLanguage stage, TStorageQualifier type) {
|
|
||||||
assert(static_cast<uint32_t>(stage) <= 0x0000ffff && static_cast<uint32_t>(type) <= 0x0000ffff);
|
|
||||||
return (stage << 16) | type;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Use for mark pre stage, to get more interface symbol information.
|
|
||||||
EShLanguage preStage;
|
|
||||||
// Use for mark current shader stage for resolver
|
|
||||||
EShLanguage currentStage;
|
|
||||||
// Slot map for storage resource(location of uniform and interface symbol) It's a program share slot
|
|
||||||
TSlotMap resourceSlotMap;
|
|
||||||
// Slot map for other resource(image, ubo, ssbo), It's a program share slot.
|
|
||||||
TSlotMap storageSlotMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::map<TString, TVarEntryInfo> TVarLiveMap;
|
|
||||||
|
|
||||||
// override function "operator=", if a vector<const _Kty, _Ty> being sort,
|
|
||||||
// when use vc++, the sort function will call :
|
|
||||||
// pair& operator=(const pair<_Other1, _Other2>& _Right)
|
|
||||||
// {
|
|
||||||
// first = _Right.first;
|
|
||||||
// second = _Right.second;
|
|
||||||
// return (*this);
|
|
||||||
// }
|
|
||||||
// that will make a const type handing on left.
|
|
||||||
// override this function can avoid a compiler error.
|
|
||||||
// In the future, if the vc++ compiler can handle such a situation,
|
|
||||||
// this part of the code will be removed.
|
|
||||||
struct TVarLivePair : std::pair<const TString, TVarEntryInfo> {
|
|
||||||
TVarLivePair(const std::pair<const TString, TVarEntryInfo>& _Right) : pair(_Right.first, _Right.second) {}
|
|
||||||
TVarLivePair& operator=(const TVarLivePair& _Right) {
|
|
||||||
const_cast<TString&>(first) = _Right.first;
|
|
||||||
second = _Right.second;
|
|
||||||
return (*this);
|
|
||||||
}
|
|
||||||
TVarLivePair(const TVarLivePair& src) : pair(src) { }
|
|
||||||
};
|
|
||||||
typedef std::vector<TVarLivePair> TVarLiveVector;
|
|
||||||
|
|
||||||
// I/O mapper
|
|
||||||
class TIoMapper {
|
|
||||||
public:
|
|
||||||
TIoMapper() {}
|
|
||||||
virtual ~TIoMapper() {}
|
|
||||||
// grow the reflection stage by stage
|
|
||||||
bool virtual addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*);
|
|
||||||
bool virtual doMap(TIoMapResolver*, TInfoSink&) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// I/O mapper for OpenGL
|
|
||||||
class TGlslIoMapper : public TIoMapper {
|
|
||||||
public:
|
|
||||||
TGlslIoMapper() {
|
|
||||||
memset(inVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount);
|
|
||||||
memset(outVarMaps, 0, sizeof(TVarLiveMap*) * EShLangCount);
|
|
||||||
memset(uniformVarMap, 0, sizeof(TVarLiveMap*) * EShLangCount);
|
|
||||||
memset(intermediates, 0, sizeof(TIntermediate*) * EShLangCount);
|
|
||||||
}
|
|
||||||
virtual ~TGlslIoMapper() {
|
|
||||||
for (size_t stage = 0; stage < EShLangCount; stage++) {
|
|
||||||
if (inVarMaps[stage] != nullptr) {
|
|
||||||
delete inVarMaps[stage];
|
|
||||||
inVarMaps[stage] = nullptr;
|
|
||||||
}
|
|
||||||
if (outVarMaps[stage] != nullptr) {
|
|
||||||
delete outVarMaps[stage];
|
|
||||||
outVarMaps[stage] = nullptr;
|
|
||||||
}
|
|
||||||
if (uniformVarMap[stage] != nullptr) {
|
|
||||||
delete uniformVarMap[stage];
|
|
||||||
uniformVarMap[stage] = nullptr;
|
|
||||||
}
|
|
||||||
if (intermediates[stage] != nullptr)
|
|
||||||
intermediates[stage] = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// grow the reflection stage by stage
|
|
||||||
bool addStage(EShLanguage, TIntermediate&, TInfoSink&, TIoMapResolver*) override;
|
|
||||||
bool doMap(TIoMapResolver*, TInfoSink&) override;
|
|
||||||
TVarLiveMap *inVarMaps[EShLangCount], *outVarMaps[EShLangCount],
|
|
||||||
*uniformVarMap[EShLangCount];
|
|
||||||
TIntermediate* intermediates[EShLangCount];
|
|
||||||
bool hadError = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _IOMAPPER_INCLUDED
|
|
||||||
|
|
||||||
#endif // GLSLANG_WEB
|
|
|
@ -1,200 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do sub tree walks for
|
|
||||||
// 1) inductive loop bodies to see if the inductive variable is modified
|
|
||||||
// 2) array-index expressions to see if they are "constant-index-expression"
|
|
||||||
//
|
|
||||||
// These are per Appendix A of ES 2.0:
|
|
||||||
//
|
|
||||||
// "Within the body of the loop, the loop index is not statically assigned to nor is it used as the
|
|
||||||
// argument to a function out or inout parameter."
|
|
||||||
//
|
|
||||||
// "The following are constant-index-expressions:
|
|
||||||
// - Constant expressions
|
|
||||||
// - Loop indices as defined in section 4
|
|
||||||
// - Expressions composed of both of the above"
|
|
||||||
//
|
|
||||||
// N.B.: assuming the last rule excludes function calls
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "ParseHelper.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// The inductive loop-body traverser.
|
|
||||||
//
|
|
||||||
// Just look at things that might modify the loop index.
|
|
||||||
//
|
|
||||||
|
|
||||||
class TInductiveTraverser : public TIntermTraverser {
|
|
||||||
public:
|
|
||||||
TInductiveTraverser(int id, TSymbolTable& st)
|
|
||||||
: loopId(id), symbolTable(st), bad(false) { }
|
|
||||||
|
|
||||||
virtual bool visitBinary(TVisit, TIntermBinary* node);
|
|
||||||
virtual bool visitUnary(TVisit, TIntermUnary* node);
|
|
||||||
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
|
||||||
|
|
||||||
int loopId; // unique ID of the symbol that's the loop inductive variable
|
|
||||||
TSymbolTable& symbolTable;
|
|
||||||
bool bad;
|
|
||||||
TSourceLoc badLoc;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TInductiveTraverser(TInductiveTraverser&);
|
|
||||||
TInductiveTraverser& operator=(TInductiveTraverser&);
|
|
||||||
};
|
|
||||||
|
|
||||||
// check binary operations for those modifying the loop index
|
|
||||||
bool TInductiveTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
|
|
||||||
{
|
|
||||||
if (node->modifiesState() && node->getLeft()->getAsSymbolNode() &&
|
|
||||||
node->getLeft()->getAsSymbolNode()->getId() == loopId) {
|
|
||||||
bad = true;
|
|
||||||
badLoc = node->getLoc();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check unary operations for those modifying the loop index
|
|
||||||
bool TInductiveTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
|
|
||||||
{
|
|
||||||
if (node->modifiesState() && node->getOperand()->getAsSymbolNode() &&
|
|
||||||
node->getOperand()->getAsSymbolNode()->getId() == loopId) {
|
|
||||||
bad = true;
|
|
||||||
badLoc = node->getLoc();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check function calls for arguments modifying the loop index
|
|
||||||
bool TInductiveTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
|
|
||||||
{
|
|
||||||
if (node->getOp() == EOpFunctionCall) {
|
|
||||||
// see if an out or inout argument is the loop index
|
|
||||||
const TIntermSequence& args = node->getSequence();
|
|
||||||
for (int i = 0; i < (int)args.size(); ++i) {
|
|
||||||
if (args[i]->getAsSymbolNode() && args[i]->getAsSymbolNode()->getId() == loopId) {
|
|
||||||
TSymbol* function = symbolTable.find(node->getName());
|
|
||||||
const TType* type = (*function->getAsFunction())[i].type;
|
|
||||||
if (type->getQualifier().storage == EvqOut ||
|
|
||||||
type->getQualifier().storage == EvqInOut) {
|
|
||||||
bad = true;
|
|
||||||
badLoc = node->getLoc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// External function to call for loop check.
|
|
||||||
//
|
|
||||||
void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable)
|
|
||||||
{
|
|
||||||
TInductiveTraverser it(loopId, symbolTable);
|
|
||||||
|
|
||||||
if (body == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
body->traverse(&it);
|
|
||||||
|
|
||||||
if (it.bad)
|
|
||||||
error(it.badLoc, "inductive loop index modified", "limitations", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// The "constant-index-expression" tranverser.
|
|
||||||
//
|
|
||||||
// Just look at things that can form an index.
|
|
||||||
//
|
|
||||||
|
|
||||||
class TIndexTraverser : public TIntermTraverser {
|
|
||||||
public:
|
|
||||||
TIndexTraverser(const TIdSetType& ids) : inductiveLoopIds(ids), bad(false) { }
|
|
||||||
virtual void visitSymbol(TIntermSymbol* symbol);
|
|
||||||
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
|
||||||
const TIdSetType& inductiveLoopIds;
|
|
||||||
bool bad;
|
|
||||||
TSourceLoc badLoc;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TIndexTraverser(TIndexTraverser&);
|
|
||||||
TIndexTraverser& operator=(TIndexTraverser&);
|
|
||||||
};
|
|
||||||
|
|
||||||
// make sure symbols are inductive-loop indexes
|
|
||||||
void TIndexTraverser::visitSymbol(TIntermSymbol* symbol)
|
|
||||||
{
|
|
||||||
if (inductiveLoopIds.find(symbol->getId()) == inductiveLoopIds.end()) {
|
|
||||||
bad = true;
|
|
||||||
badLoc = symbol->getLoc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for function calls, assuming they are bad; spec. doesn't really say
|
|
||||||
bool TIndexTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
|
|
||||||
{
|
|
||||||
if (node->getOp() == EOpFunctionCall) {
|
|
||||||
bad = true;
|
|
||||||
badLoc = node->getLoc();
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// External function to call for loop check.
|
|
||||||
//
|
|
||||||
void TParseContext::constantIndexExpressionCheck(TIntermNode* index)
|
|
||||||
{
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
TIndexTraverser it(inductiveLoopIds);
|
|
||||||
|
|
||||||
index->traverse(&it);
|
|
||||||
|
|
||||||
if (it.bad)
|
|
||||||
error(it.badLoc, "Non-constant-index-expression", "limitations", "");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,214 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Traverse a tree of constants to create a single folded constant.
|
|
||||||
// It should only be used when the whole tree is known to be constant.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "ParseHelper.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
class TConstTraverser : public TIntermTraverser {
|
|
||||||
public:
|
|
||||||
TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t)
|
|
||||||
: unionArray(cUnion), type(t),
|
|
||||||
constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false),
|
|
||||||
matrixCols(0), matrixRows(0) { index = 0; tOp = EOpNull; }
|
|
||||||
|
|
||||||
virtual void visitConstantUnion(TIntermConstantUnion* node);
|
|
||||||
virtual bool visitAggregate(TVisit, TIntermAggregate* node);
|
|
||||||
|
|
||||||
int index;
|
|
||||||
TConstUnionArray unionArray;
|
|
||||||
TOperator tOp;
|
|
||||||
const TType& type;
|
|
||||||
TOperator constructorType;
|
|
||||||
bool singleConstantParam;
|
|
||||||
bool error;
|
|
||||||
int size; // size of the constructor ( 4 for vec4)
|
|
||||||
bool isMatrix;
|
|
||||||
int matrixCols;
|
|
||||||
int matrixRows;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TConstTraverser(TConstTraverser&);
|
|
||||||
TConstTraverser& operator=(TConstTraverser&);
|
|
||||||
};
|
|
||||||
|
|
||||||
bool TConstTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
|
|
||||||
{
|
|
||||||
if (! node->isConstructor() && node->getOp() != EOpComma) {
|
|
||||||
error = true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion();
|
|
||||||
if (flag) {
|
|
||||||
singleConstantParam = true;
|
|
||||||
constructorType = node->getOp();
|
|
||||||
size = node->getType().computeNumComponents();
|
|
||||||
|
|
||||||
if (node->getType().isMatrix()) {
|
|
||||||
isMatrix = true;
|
|
||||||
matrixCols = node->getType().getMatrixCols();
|
|
||||||
matrixRows = node->getType().getMatrixRows();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (TIntermSequence::iterator p = node->getSequence().begin();
|
|
||||||
p != node->getSequence().end(); p++) {
|
|
||||||
|
|
||||||
if (node->getOp() == EOpComma)
|
|
||||||
index = 0;
|
|
||||||
|
|
||||||
(*p)->traverse(this);
|
|
||||||
}
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
singleConstantParam = false;
|
|
||||||
constructorType = EOpNull;
|
|
||||||
size = 0;
|
|
||||||
isMatrix = false;
|
|
||||||
matrixCols = 0;
|
|
||||||
matrixRows = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node)
|
|
||||||
{
|
|
||||||
TConstUnionArray leftUnionArray(unionArray);
|
|
||||||
int instanceSize = type.computeNumComponents();
|
|
||||||
|
|
||||||
if (index >= instanceSize)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (! singleConstantParam) {
|
|
||||||
int rightUnionSize = node->getType().computeNumComponents();
|
|
||||||
|
|
||||||
const TConstUnionArray& rightUnionArray = node->getConstArray();
|
|
||||||
for (int i = 0; i < rightUnionSize; i++) {
|
|
||||||
if (index >= instanceSize)
|
|
||||||
return;
|
|
||||||
leftUnionArray[index] = rightUnionArray[i];
|
|
||||||
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int endIndex = index + size;
|
|
||||||
const TConstUnionArray& rightUnionArray = node->getConstArray();
|
|
||||||
if (! isMatrix) {
|
|
||||||
int count = 0;
|
|
||||||
int nodeComps = node->getType().computeNumComponents();
|
|
||||||
for (int i = index; i < endIndex; i++) {
|
|
||||||
if (i >= instanceSize)
|
|
||||||
return;
|
|
||||||
|
|
||||||
leftUnionArray[i] = rightUnionArray[count];
|
|
||||||
|
|
||||||
(index)++;
|
|
||||||
|
|
||||||
if (nodeComps > 1)
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// constructing a matrix, but from what?
|
|
||||||
if (node->isMatrix()) {
|
|
||||||
// Matrix from a matrix; this has the outer matrix, node is the argument matrix.
|
|
||||||
// Traverse the outer, potentially bigger matrix, fill in missing pieces with the
|
|
||||||
// identity matrix.
|
|
||||||
for (int c = 0; c < matrixCols; ++c) {
|
|
||||||
for (int r = 0; r < matrixRows; ++r) {
|
|
||||||
int targetOffset = index + c * matrixRows + r;
|
|
||||||
if (r < node->getType().getMatrixRows() && c < node->getType().getMatrixCols()) {
|
|
||||||
int srcOffset = c * node->getType().getMatrixRows() + r;
|
|
||||||
leftUnionArray[targetOffset] = rightUnionArray[srcOffset];
|
|
||||||
} else if (r == c)
|
|
||||||
leftUnionArray[targetOffset].setDConst(1.0);
|
|
||||||
else
|
|
||||||
leftUnionArray[targetOffset].setDConst(0.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// matrix from vector or scalar
|
|
||||||
int count = 0;
|
|
||||||
const int startIndex = index;
|
|
||||||
int nodeComps = node->getType().computeNumComponents();
|
|
||||||
for (int i = startIndex; i < endIndex; i++) {
|
|
||||||
if (i >= instanceSize)
|
|
||||||
return;
|
|
||||||
if (nodeComps == 1) {
|
|
||||||
// If there is a single scalar parameter to a matrix
|
|
||||||
// constructor, it is used to initialize all the
|
|
||||||
// components on the matrix's diagonal, with the
|
|
||||||
// remaining components initialized to 0.0.
|
|
||||||
if (i == startIndex || (i - startIndex) % (matrixRows + 1) == 0 )
|
|
||||||
leftUnionArray[i] = rightUnionArray[count];
|
|
||||||
else
|
|
||||||
leftUnionArray[i].setDConst(0.0);
|
|
||||||
} else {
|
|
||||||
// construct the matrix in column-major order, from
|
|
||||||
// the components provided, in order
|
|
||||||
leftUnionArray[i] = rightUnionArray[count];
|
|
||||||
}
|
|
||||||
|
|
||||||
index++;
|
|
||||||
|
|
||||||
if (nodeComps > 1)
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
|
|
||||||
{
|
|
||||||
if (root == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
TConstTraverser it(unionArray, singleConstantParam, constructorType, t);
|
|
||||||
|
|
||||||
root->traverse(&it);
|
|
||||||
if (it.error)
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
|
@ -1,236 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2015-2018 Google, Inc.
|
|
||||||
// Copyright (C) 2017 ARM Limited.
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
// This is implemented in Versions.cpp
|
|
||||||
|
|
||||||
#ifndef _PARSE_VERSIONS_INCLUDED_
|
|
||||||
#define _PARSE_VERSIONS_INCLUDED_
|
|
||||||
|
|
||||||
#include "../Public/ShaderLang.h"
|
|
||||||
#include "../Include/InfoSink.h"
|
|
||||||
#include "Scan.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Base class for parse helpers.
|
|
||||||
// This just has version-related information and checking.
|
|
||||||
// This class should be sufficient for preprocessing.
|
|
||||||
//
|
|
||||||
class TParseVersions {
|
|
||||||
public:
|
|
||||||
TParseVersions(TIntermediate& interm, int version, EProfile profile,
|
|
||||||
const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink,
|
|
||||||
bool forwardCompatible, EShMessages messages)
|
|
||||||
:
|
|
||||||
#ifndef GLSLANG_WEB
|
|
||||||
forwardCompatible(forwardCompatible),
|
|
||||||
profile(profile),
|
|
||||||
#endif
|
|
||||||
infoSink(infoSink), version(version),
|
|
||||||
language(language),
|
|
||||||
spvVersion(spvVersion),
|
|
||||||
intermediate(interm), messages(messages), numErrors(0), currentScanner(0) { }
|
|
||||||
virtual ~TParseVersions() { }
|
|
||||||
void requireStage(const TSourceLoc&, EShLanguageMask, const char* featureDesc);
|
|
||||||
void requireStage(const TSourceLoc&, EShLanguage, const char* featureDesc);
|
|
||||||
#ifdef GLSLANG_WEB
|
|
||||||
const EProfile profile = EEsProfile;
|
|
||||||
bool isEsProfile() const { return true; }
|
|
||||||
void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc)
|
|
||||||
{
|
|
||||||
if (! (EEsProfile & profileMask))
|
|
||||||
error(loc, "not supported with this profile:", featureDesc, ProfileName(profile));
|
|
||||||
}
|
|
||||||
void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions,
|
|
||||||
const char* const extensions[], const char* featureDesc)
|
|
||||||
{
|
|
||||||
if ((EEsProfile & profileMask) && (minVersion == 0 || version < minVersion))
|
|
||||||
error(loc, "not supported for this version or the enabled extensions", featureDesc, "");
|
|
||||||
}
|
|
||||||
void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension,
|
|
||||||
const char* featureDesc)
|
|
||||||
{
|
|
||||||
profileRequires(loc, profileMask, minVersion, extension ? 1 : 0, &extension, featureDesc);
|
|
||||||
}
|
|
||||||
void initializeExtensionBehavior() { }
|
|
||||||
void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc) { }
|
|
||||||
void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc) { }
|
|
||||||
void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
|
||||||
const char* featureDesc) { }
|
|
||||||
void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
|
||||||
const char* featureDesc) { }
|
|
||||||
TExtensionBehavior getExtensionBehavior(const char*) { return EBhMissing; }
|
|
||||||
bool extensionTurnedOn(const char* const extension) { return false; }
|
|
||||||
bool extensionsTurnedOn(int numExtensions, const char* const extensions[]) { return false; }
|
|
||||||
void updateExtensionBehavior(int line, const char* const extension, const char* behavior) { }
|
|
||||||
void updateExtensionBehavior(const char* const extension, TExtensionBehavior) { }
|
|
||||||
void checkExtensionStage(const TSourceLoc&, const char* const extension) { }
|
|
||||||
void fullIntegerCheck(const TSourceLoc&, const char* op) { }
|
|
||||||
void doubleCheck(const TSourceLoc&, const char* op) { }
|
|
||||||
bool float16Arithmetic() { return false; }
|
|
||||||
void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { }
|
|
||||||
bool int16Arithmetic() { return false; }
|
|
||||||
void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { }
|
|
||||||
bool int8Arithmetic() { return false; }
|
|
||||||
void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc) { }
|
|
||||||
void int64Check(const TSourceLoc&, const char* op, bool builtIn = false) { }
|
|
||||||
void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false) { }
|
|
||||||
void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false) { }
|
|
||||||
bool relaxedErrors() const { return false; }
|
|
||||||
bool suppressWarnings() const { return true; }
|
|
||||||
bool isForwardCompatible() const { return false; }
|
|
||||||
#else
|
|
||||||
bool forwardCompatible; // true if errors are to be given for use of deprecated features
|
|
||||||
EProfile profile; // the declared profile in the shader (core by default)
|
|
||||||
bool isEsProfile() const { return profile == EEsProfile; }
|
|
||||||
void requireProfile(const TSourceLoc& loc, int profileMask, const char* featureDesc);
|
|
||||||
void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, int numExtensions,
|
|
||||||
const char* const extensions[], const char* featureDesc);
|
|
||||||
void profileRequires(const TSourceLoc& loc, int profileMask, int minVersion, const char* extension,
|
|
||||||
const char* featureDesc);
|
|
||||||
virtual void initializeExtensionBehavior();
|
|
||||||
virtual void checkDeprecated(const TSourceLoc&, int queryProfiles, int depVersion, const char* featureDesc);
|
|
||||||
virtual void requireNotRemoved(const TSourceLoc&, int queryProfiles, int removedVersion, const char* featureDesc);
|
|
||||||
virtual void requireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
|
||||||
const char* featureDesc);
|
|
||||||
virtual void ppRequireExtensions(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
|
||||||
const char* featureDesc);
|
|
||||||
virtual TExtensionBehavior getExtensionBehavior(const char*);
|
|
||||||
virtual bool extensionTurnedOn(const char* const extension);
|
|
||||||
virtual bool extensionsTurnedOn(int numExtensions, const char* const extensions[]);
|
|
||||||
virtual void updateExtensionBehavior(int line, const char* const extension, const char* behavior);
|
|
||||||
virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior);
|
|
||||||
virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[],
|
|
||||||
const char* featureDesc);
|
|
||||||
virtual void checkExtensionStage(const TSourceLoc&, const char* const extension);
|
|
||||||
virtual void fullIntegerCheck(const TSourceLoc&, const char* op);
|
|
||||||
|
|
||||||
virtual void unimplemented(const TSourceLoc&, const char* featureDesc);
|
|
||||||
virtual void doubleCheck(const TSourceLoc&, const char* op);
|
|
||||||
virtual void float16Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual void float16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual bool float16Arithmetic();
|
|
||||||
virtual void requireFloat16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
|
|
||||||
virtual void int16ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual bool int16Arithmetic();
|
|
||||||
virtual void requireInt16Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
|
|
||||||
virtual void int8ScalarVectorCheck(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual bool int8Arithmetic();
|
|
||||||
virtual void requireInt8Arithmetic(const TSourceLoc& loc, const char* op, const char* featureDesc);
|
|
||||||
virtual void float16OpaqueCheck(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual void int64Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual void explicitInt8Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual void explicitInt16Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual void explicitInt32Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual void explicitFloat32Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual void explicitFloat64Check(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual void fcoopmatCheck(const TSourceLoc&, const char* op, bool builtIn = false);
|
|
||||||
virtual void intcoopmatCheck(const TSourceLoc&, const char *op, bool builtIn = false);
|
|
||||||
bool relaxedErrors() const { return (messages & EShMsgRelaxedErrors) != 0; }
|
|
||||||
bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; }
|
|
||||||
bool isForwardCompatible() const { return forwardCompatible; }
|
|
||||||
#endif // GLSLANG_WEB
|
|
||||||
virtual void spvRemoved(const TSourceLoc&, const char* op);
|
|
||||||
virtual void vulkanRemoved(const TSourceLoc&, const char* op);
|
|
||||||
virtual void requireVulkan(const TSourceLoc&, const char* op);
|
|
||||||
virtual void requireSpv(const TSourceLoc&, const char* op);
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(GLSLANG_WEB) && !defined(GLSLANG_WEB_DEVEL)
|
|
||||||
void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...) { addError(); }
|
|
||||||
void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...) { }
|
|
||||||
void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...) { addError(); }
|
|
||||||
void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...) { }
|
|
||||||
#else
|
|
||||||
virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...) = 0;
|
|
||||||
virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...) = 0;
|
|
||||||
virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...) = 0;
|
|
||||||
virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
|
|
||||||
const char* szExtraInfoFormat, ...) = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void addError() { ++numErrors; }
|
|
||||||
int getNumErrors() const { return numErrors; }
|
|
||||||
|
|
||||||
void setScanner(TInputScanner* scanner) { currentScanner = scanner; }
|
|
||||||
TInputScanner* getScanner() const { return currentScanner; }
|
|
||||||
const TSourceLoc& getCurrentLoc() const { return currentScanner->getSourceLoc(); }
|
|
||||||
void setCurrentLine(int line) { currentScanner->setLine(line); }
|
|
||||||
void setCurrentColumn(int col) { currentScanner->setColumn(col); }
|
|
||||||
void setCurrentSourceName(const char* name) { currentScanner->setFile(name); }
|
|
||||||
void setCurrentString(int string) { currentScanner->setString(string); }
|
|
||||||
|
|
||||||
void getPreamble(std::string&);
|
|
||||||
#ifdef ENABLE_HLSL
|
|
||||||
bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; }
|
|
||||||
bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; }
|
|
||||||
bool hlslDX9Compatible() const { return (messages & EShMsgHlslDX9Compatible) != 0; }
|
|
||||||
#else
|
|
||||||
bool isReadingHLSL() const { return false; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TInfoSink& infoSink;
|
|
||||||
|
|
||||||
// compilation mode
|
|
||||||
int version; // version, updated by #version in the shader
|
|
||||||
EShLanguage language; // really the stage
|
|
||||||
SpvVersion spvVersion;
|
|
||||||
TIntermediate& intermediate; // helper for making and hooking up pieces of the parse tree
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TMap<TString, TExtensionBehavior> extensionBehavior; // for each extension string, what its current behavior is set to
|
|
||||||
EShMessages messages; // errors/warnings/rule-sets
|
|
||||||
int numErrors; // number of compile-time errors encountered
|
|
||||||
TInputScanner* currentScanner;
|
|
||||||
|
|
||||||
private:
|
|
||||||
explicit TParseVersions(const TParseVersions&);
|
|
||||||
TParseVersions& operator=(const TParseVersions&);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // _PARSE_VERSIONS_INCLUDED_
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,181 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
/****************************************************************************\
|
|
||||||
Copyright (c) 2002, NVIDIA Corporation.
|
|
||||||
|
|
||||||
NVIDIA Corporation("NVIDIA") supplies this software to you in
|
|
||||||
consideration of your agreement to the following terms, and your use,
|
|
||||||
installation, modification or redistribution of this NVIDIA software
|
|
||||||
constitutes acceptance of these terms. If you do not agree with these
|
|
||||||
terms, please do not use, install, modify or redistribute this NVIDIA
|
|
||||||
software.
|
|
||||||
|
|
||||||
In consideration of your agreement to abide by the following terms, and
|
|
||||||
subject to these terms, NVIDIA grants you a personal, non-exclusive
|
|
||||||
license, under NVIDIA's copyrights in this original NVIDIA software (the
|
|
||||||
"NVIDIA Software"), to use, reproduce, modify and redistribute the
|
|
||||||
NVIDIA Software, with or without modifications, in source and/or binary
|
|
||||||
forms; provided that if you redistribute the NVIDIA Software, you must
|
|
||||||
retain the copyright notice of NVIDIA, this notice and the following
|
|
||||||
text and disclaimers in all such redistributions of the NVIDIA Software.
|
|
||||||
Neither the name, trademarks, service marks nor logos of NVIDIA
|
|
||||||
Corporation may be used to endorse or promote products derived from the
|
|
||||||
NVIDIA Software without specific prior written permission from NVIDIA.
|
|
||||||
Except as expressly stated in this notice, no other rights or licenses
|
|
||||||
express or implied, are granted by NVIDIA herein, including but not
|
|
||||||
limited to any patent rights that may be infringed by your derivative
|
|
||||||
works or by other works in which the NVIDIA Software may be
|
|
||||||
incorporated. No hardware is licensed hereunder.
|
|
||||||
|
|
||||||
THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
|
|
||||||
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
|
||||||
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
|
|
||||||
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
|
||||||
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
|
|
||||||
PRODUCTS.
|
|
||||||
|
|
||||||
IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
|
|
||||||
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
||||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
|
|
||||||
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
|
|
||||||
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
|
|
||||||
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
|
||||||
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
\****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
|
||||||
#define _CRT_SECURE_NO_WARNINGS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "PpContext.h"
|
|
||||||
#include "PpTokens.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
using namespace glslang;
|
|
||||||
|
|
||||||
const struct {
|
|
||||||
int val;
|
|
||||||
const char* str;
|
|
||||||
} tokens[] = {
|
|
||||||
|
|
||||||
{ PPAtomAddAssign, "+=" },
|
|
||||||
{ PPAtomSubAssign, "-=" },
|
|
||||||
{ PPAtomMulAssign, "*=" },
|
|
||||||
{ PPAtomDivAssign, "/=" },
|
|
||||||
{ PPAtomModAssign, "%=" },
|
|
||||||
|
|
||||||
{ PpAtomRight, ">>" },
|
|
||||||
{ PpAtomLeft, "<<" },
|
|
||||||
{ PpAtomAnd, "&&" },
|
|
||||||
{ PpAtomOr, "||" },
|
|
||||||
{ PpAtomXor, "^^" },
|
|
||||||
|
|
||||||
{ PpAtomRightAssign, ">>=" },
|
|
||||||
{ PpAtomLeftAssign, "<<=" },
|
|
||||||
{ PpAtomAndAssign, "&=" },
|
|
||||||
{ PpAtomOrAssign, "|=" },
|
|
||||||
{ PpAtomXorAssign, "^=" },
|
|
||||||
|
|
||||||
{ PpAtomEQ, "==" },
|
|
||||||
{ PpAtomNE, "!=" },
|
|
||||||
{ PpAtomGE, ">=" },
|
|
||||||
{ PpAtomLE, "<=" },
|
|
||||||
|
|
||||||
{ PpAtomDecrement, "--" },
|
|
||||||
{ PpAtomIncrement, "++" },
|
|
||||||
|
|
||||||
{ PpAtomColonColon, "::" },
|
|
||||||
|
|
||||||
{ PpAtomDefine, "define" },
|
|
||||||
{ PpAtomUndef, "undef" },
|
|
||||||
{ PpAtomIf, "if" },
|
|
||||||
{ PpAtomElif, "elif" },
|
|
||||||
{ PpAtomElse, "else" },
|
|
||||||
{ PpAtomEndif, "endif" },
|
|
||||||
{ PpAtomIfdef, "ifdef" },
|
|
||||||
{ PpAtomIfndef, "ifndef" },
|
|
||||||
{ PpAtomLine, "line" },
|
|
||||||
{ PpAtomPragma, "pragma" },
|
|
||||||
{ PpAtomError, "error" },
|
|
||||||
|
|
||||||
{ PpAtomVersion, "version" },
|
|
||||||
{ PpAtomCore, "core" },
|
|
||||||
{ PpAtomCompatibility, "compatibility" },
|
|
||||||
{ PpAtomEs, "es" },
|
|
||||||
{ PpAtomExtension, "extension" },
|
|
||||||
|
|
||||||
{ PpAtomLineMacro, "__LINE__" },
|
|
||||||
{ PpAtomFileMacro, "__FILE__" },
|
|
||||||
{ PpAtomVersionMacro, "__VERSION__" },
|
|
||||||
|
|
||||||
{ PpAtomInclude, "include" },
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end anonymous namespace
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize the atom table.
|
|
||||||
//
|
|
||||||
TStringAtomMap::TStringAtomMap()
|
|
||||||
{
|
|
||||||
badToken.assign("<bad token>");
|
|
||||||
|
|
||||||
// Add single character tokens to the atom table:
|
|
||||||
const char* s = "~!%^&*()-+=|,.<>/?;:[]{}#\\";
|
|
||||||
char t[2];
|
|
||||||
|
|
||||||
t[1] = '\0';
|
|
||||||
while (*s) {
|
|
||||||
t[0] = *s;
|
|
||||||
addAtomFixed(t, s[0]);
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add multiple character scanner tokens :
|
|
||||||
for (size_t ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
|
|
||||||
addAtomFixed(tokens[ii].str, tokens[ii].val);
|
|
||||||
|
|
||||||
nextAtom = PpAtomLast;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
|
@ -1,120 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
// Copyright (C) 2015-2018 Google, Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
/****************************************************************************\
|
|
||||||
Copyright (c) 2002, NVIDIA Corporation.
|
|
||||||
|
|
||||||
NVIDIA Corporation("NVIDIA") supplies this software to you in
|
|
||||||
consideration of your agreement to the following terms, and your use,
|
|
||||||
installation, modification or redistribution of this NVIDIA software
|
|
||||||
constitutes acceptance of these terms. If you do not agree with these
|
|
||||||
terms, please do not use, install, modify or redistribute this NVIDIA
|
|
||||||
software.
|
|
||||||
|
|
||||||
In consideration of your agreement to abide by the following terms, and
|
|
||||||
subject to these terms, NVIDIA grants you a personal, non-exclusive
|
|
||||||
license, under NVIDIA's copyrights in this original NVIDIA software (the
|
|
||||||
"NVIDIA Software"), to use, reproduce, modify and redistribute the
|
|
||||||
NVIDIA Software, with or without modifications, in source and/or binary
|
|
||||||
forms; provided that if you redistribute the NVIDIA Software, you must
|
|
||||||
retain the copyright notice of NVIDIA, this notice and the following
|
|
||||||
text and disclaimers in all such redistributions of the NVIDIA Software.
|
|
||||||
Neither the name, trademarks, service marks nor logos of NVIDIA
|
|
||||||
Corporation may be used to endorse or promote products derived from the
|
|
||||||
NVIDIA Software without specific prior written permission from NVIDIA.
|
|
||||||
Except as expressly stated in this notice, no other rights or licenses
|
|
||||||
express or implied, are granted by NVIDIA herein, including but not
|
|
||||||
limited to any patent rights that may be infringed by your derivative
|
|
||||||
works or by other works in which the NVIDIA Software may be
|
|
||||||
incorporated. No hardware is licensed hereunder.
|
|
||||||
|
|
||||||
THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
|
|
||||||
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
|
||||||
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
|
|
||||||
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
|
||||||
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
|
|
||||||
PRODUCTS.
|
|
||||||
|
|
||||||
IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
|
|
||||||
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
||||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
|
|
||||||
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
|
|
||||||
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
|
|
||||||
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
|
||||||
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
\****************************************************************************/
|
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <locale>
|
|
||||||
|
|
||||||
#include "PpContext.h"
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
TPpContext::TPpContext(TParseContextBase& pc, const std::string& rootFileName, TShader::Includer& inclr) :
|
|
||||||
preamble(0), strings(0), previous_token('\n'), parseContext(pc), includer(inclr), inComment(false),
|
|
||||||
rootFileName(rootFileName),
|
|
||||||
currentSourceFile(rootFileName),
|
|
||||||
disableEscapeSequences(false)
|
|
||||||
{
|
|
||||||
ifdepth = 0;
|
|
||||||
for (elsetracker = 0; elsetracker < maxIfNesting; elsetracker++)
|
|
||||||
elseSeen[elsetracker] = false;
|
|
||||||
elsetracker = 0;
|
|
||||||
|
|
||||||
strtodStream.imbue(std::locale::classic());
|
|
||||||
}
|
|
||||||
|
|
||||||
TPpContext::~TPpContext()
|
|
||||||
{
|
|
||||||
delete [] preamble;
|
|
||||||
|
|
||||||
// free up the inputStack
|
|
||||||
while (! inputStack.empty())
|
|
||||||
popInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TPpContext::setInput(TInputScanner& input, bool versionWillBeError)
|
|
||||||
{
|
|
||||||
assert(inputStack.size() == 0);
|
|
||||||
|
|
||||||
pushInput(new tStringInput(this, input));
|
|
||||||
|
|
||||||
errorOnVersion = versionWillBeError;
|
|
||||||
versionSeen = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
|
@ -1,703 +0,0 @@
|
||||||
//
|
|
||||||
// Copyright (C) 2013 LunarG, Inc.
|
|
||||||
// Copyright (C) 2015-2018 Google, Inc.
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without
|
|
||||||
// modification, are permitted provided that the following conditions
|
|
||||||
// are met:
|
|
||||||
//
|
|
||||||
// Redistributions of source code must retain the above copyright
|
|
||||||
// notice, this list of conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// Redistributions in binary form must reproduce the above
|
|
||||||
// copyright notice, this list of conditions and the following
|
|
||||||
// disclaimer in the documentation and/or other materials provided
|
|
||||||
// with the distribution.
|
|
||||||
//
|
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
|
||||||
// contributors may be used to endorse or promote products derived
|
|
||||||
// from this software without specific prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
||||||
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
||||||
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
||||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
||||||
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
||||||
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
// POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
/****************************************************************************\
|
|
||||||
Copyright (c) 2002, NVIDIA Corporation.
|
|
||||||
|
|
||||||
NVIDIA Corporation("NVIDIA") supplies this software to you in
|
|
||||||
consideration of your agreement to the following terms, and your use,
|
|
||||||
installation, modification or redistribution of this NVIDIA software
|
|
||||||
constitutes acceptance of these terms. If you do not agree with these
|
|
||||||
terms, please do not use, install, modify or redistribute this NVIDIA
|
|
||||||
software.
|
|
||||||
|
|
||||||
In consideration of your agreement to abide by the following terms, and
|
|
||||||
subject to these terms, NVIDIA grants you a personal, non-exclusive
|
|
||||||
license, under NVIDIA's copyrights in this original NVIDIA software (the
|
|
||||||
"NVIDIA Software"), to use, reproduce, modify and redistribute the
|
|
||||||
NVIDIA Software, with or without modifications, in source and/or binary
|
|
||||||
forms; provided that if you redistribute the NVIDIA Software, you must
|
|
||||||
retain the copyright notice of NVIDIA, this notice and the following
|
|
||||||
text and disclaimers in all such redistributions of the NVIDIA Software.
|
|
||||||
Neither the name, trademarks, service marks nor logos of NVIDIA
|
|
||||||
Corporation may be used to endorse or promote products derived from the
|
|
||||||
NVIDIA Software without specific prior written permission from NVIDIA.
|
|
||||||
Except as expressly stated in this notice, no other rights or licenses
|
|
||||||
express or implied, are granted by NVIDIA herein, including but not
|
|
||||||
limited to any patent rights that may be infringed by your derivative
|
|
||||||
works or by other works in which the NVIDIA Software may be
|
|
||||||
incorporated. No hardware is licensed hereunder.
|
|
||||||
|
|
||||||
THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
|
|
||||||
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
|
||||||
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
|
|
||||||
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
|
||||||
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
|
|
||||||
PRODUCTS.
|
|
||||||
|
|
||||||
IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
|
|
||||||
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
||||||
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
||||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
|
|
||||||
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
|
|
||||||
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
|
|
||||||
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
|
|
||||||
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
\****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef PPCONTEXT_H
|
|
||||||
#define PPCONTEXT_H
|
|
||||||
|
|
||||||
#include <stack>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "../ParseHelper.h"
|
|
||||||
#include "PpTokens.h"
|
|
||||||
|
|
||||||
/* windows only pragma */
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable : 4127)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace glslang {
|
|
||||||
|
|
||||||
class TPpToken {
|
|
||||||
public:
|
|
||||||
TPpToken() { clear(); }
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
space = false;
|
|
||||||
i64val = 0;
|
|
||||||
loc.init();
|
|
||||||
name[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used for comparing macro definitions, so checks what is relevant for that.
|
|
||||||
bool operator==(const TPpToken& right) const
|
|
||||||
{
|
|
||||||
return space == right.space &&
|
|
||||||
ival == right.ival && dval == right.dval && i64val == right.i64val &&
|
|
||||||
strncmp(name, right.name, MaxTokenLength) == 0;
|
|
||||||
}
|
|
||||||
bool operator!=(const TPpToken& right) const { return ! operator==(right); }
|
|
||||||
|
|
||||||
TSourceLoc loc;
|
|
||||||
// True if a space (for white space or a removed comment) should also be
|
|
||||||
// recognized, in front of the token returned:
|
|
||||||
bool space;
|
|
||||||
// Numeric value of the token:
|
|
||||||
union {
|
|
||||||
int ival;
|
|
||||||
double dval;
|
|
||||||
long long i64val;
|
|
||||||
};
|
|
||||||
// Text string of the token:
|
|
||||||
char name[MaxTokenLength + 1];
|
|
||||||
};
|
|
||||||
|
|
||||||
class TStringAtomMap {
|
|
||||||
//
|
|
||||||
// Implementation is in PpAtom.cpp
|
|
||||||
//
|
|
||||||
// Maintain a bi-directional mapping between relevant preprocessor strings and
|
|
||||||
// "atoms" which a unique integers (small, contiguous, not hash-like) per string.
|
|
||||||
//
|
|
||||||
public:
|
|
||||||
TStringAtomMap();
|
|
||||||
|
|
||||||
// Map string -> atom.
|
|
||||||
// Return 0 if no existing string.
|
|
||||||
int getAtom(const char* s) const
|
|
||||||
{
|
|
||||||
auto it = atomMap.find(s);
|
|
||||||
return it == atomMap.end() ? 0 : it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map a new or existing string -> atom, inventing a new atom if necessary.
|
|
||||||
int getAddAtom(const char* s)
|
|
||||||
{
|
|
||||||
int atom = getAtom(s);
|
|
||||||
if (atom == 0) {
|
|
||||||
atom = nextAtom++;
|
|
||||||
addAtomFixed(s, atom);
|
|
||||||
}
|
|
||||||
return atom;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map atom -> string.
|
|
||||||
const char* getString(int atom) const { return stringMap[atom]->c_str(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TStringAtomMap(TStringAtomMap&);
|
|
||||||
TStringAtomMap& operator=(TStringAtomMap&);
|
|
||||||
|
|
||||||
TUnorderedMap<TString, int> atomMap;
|
|
||||||
TVector<const TString*> stringMap; // these point into the TString in atomMap
|
|
||||||
int nextAtom;
|
|
||||||
|
|
||||||
// Bad source characters can lead to bad atoms, so gracefully handle those by
|
|
||||||
// pre-filling the table with them (to avoid if tests later).
|
|
||||||
TString badToken;
|
|
||||||
|
|
||||||
// Add bi-directional mappings:
|
|
||||||
// - string -> atom
|
|
||||||
// - atom -> string
|
|
||||||
void addAtomFixed(const char* s, int atom)
|
|
||||||
{
|
|
||||||
auto it = atomMap.insert(std::pair<TString, int>(s, atom)).first;
|
|
||||||
if (stringMap.size() < (size_t)atom + 1)
|
|
||||||
stringMap.resize(atom + 100, &badToken);
|
|
||||||
stringMap[atom] = &it->first;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class TInputScanner;
|
|
||||||
|
|
||||||
enum MacroExpandResult {
|
|
||||||
MacroExpandNotStarted, // macro not expanded, which might not be an error
|
|
||||||
MacroExpandError, // a clear error occurred while expanding, no expansion
|
|
||||||
MacroExpandStarted, // macro expansion process has started
|
|
||||||
MacroExpandUndef // macro is undefined and will be expanded
|
|
||||||
};
|
|
||||||
|
|
||||||
// This class is the result of turning a huge pile of C code communicating through globals
|
|
||||||
// into a class. This was done to allowing instancing to attain thread safety.
|
|
||||||
// Don't expect too much in terms of OO design.
|
|
||||||
class TPpContext {
|
|
||||||
public:
|
|
||||||
TPpContext(TParseContextBase&, const std::string& rootFileName, TShader::Includer&);
|
|
||||||
virtual ~TPpContext();
|
|
||||||
|
|
||||||
void setPreamble(const char* preamble, size_t length);
|
|
||||||
|
|
||||||
int tokenize(TPpToken& ppToken);
|
|
||||||
int tokenPaste(int token, TPpToken&);
|
|
||||||
|
|
||||||
class tInput {
|
|
||||||
public:
|
|
||||||
tInput(TPpContext* p) : done(false), pp(p) { }
|
|
||||||
virtual ~tInput() { }
|
|
||||||
|
|
||||||
virtual int scan(TPpToken*) = 0;
|
|
||||||
virtual int getch() = 0;
|
|
||||||
virtual void ungetch() = 0;
|
|
||||||
virtual bool peekPasting() { return false; } // true when about to see ##
|
|
||||||
virtual bool peekContinuedPasting(int) { return false; } // true when non-spaced tokens can paste
|
|
||||||
virtual bool endOfReplacementList() { return false; } // true when at the end of a macro replacement list (RHS of #define)
|
|
||||||
virtual bool isMacroInput() { return false; }
|
|
||||||
|
|
||||||
// Will be called when we start reading tokens from this instance
|
|
||||||
virtual void notifyActivated() {}
|
|
||||||
// Will be called when we do not read tokens from this instance anymore
|
|
||||||
virtual void notifyDeleted() {}
|
|
||||||
protected:
|
|
||||||
bool done;
|
|
||||||
TPpContext* pp;
|
|
||||||
};
|
|
||||||
|
|
||||||
void setInput(TInputScanner& input, bool versionWillBeError);
|
|
||||||
|
|
||||||
void pushInput(tInput* in)
|
|
||||||
{
|
|
||||||
inputStack.push_back(in);
|
|
||||||
in->notifyActivated();
|
|
||||||
}
|
|
||||||
void popInput()
|
|
||||||
{
|
|
||||||
inputStack.back()->notifyDeleted();
|
|
||||||
delete inputStack.back();
|
|
||||||
inputStack.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// From PpTokens.cpp
|
|
||||||
//
|
|
||||||
|
|
||||||
// Capture the needed parts of a token stream for macro recording/playback.
|
|
||||||
class TokenStream {
|
|
||||||
public:
|
|
||||||
// Manage a stream of these 'Token', which capture the relevant parts
|
|
||||||
// of a TPpToken, plus its atom.
|
|
||||||
class Token {
|
|
||||||
public:
|
|
||||||
Token(int atom, const TPpToken& ppToken) :
|
|
||||||
atom(atom),
|
|
||||||
space(ppToken.space),
|
|
||||||
i64val(ppToken.i64val),
|
|
||||||
name(ppToken.name) { }
|
|
||||||
int get(TPpToken& ppToken)
|
|
||||||
{
|
|
||||||
ppToken.clear();
|
|
||||||
ppToken.space = space;
|
|
||||||
ppToken.i64val = i64val;
|
|
||||||
snprintf(ppToken.name, sizeof(ppToken.name), "%s", name.c_str());
|
|
||||||
return atom;
|
|
||||||
}
|
|
||||||
bool isAtom(int a) const { return atom == a; }
|
|
||||||
int getAtom() const { return atom; }
|
|
||||||
bool nonSpaced() const { return !space; }
|
|
||||||
protected:
|
|
||||||
Token() {}
|
|
||||||
int atom;
|
|
||||||
bool space; // did a space precede the token?
|
|
||||||
long long i64val;
|
|
||||||
TString name;
|
|
||||||
};
|
|
||||||
|
|
||||||
TokenStream() : currentPos(0) { }
|
|
||||||
|
|
||||||
void putToken(int token, TPpToken* ppToken);
|
|
||||||
bool peekToken(int atom) { return !atEnd() && stream[currentPos].isAtom(atom); }
|
|
||||||
bool peekContinuedPasting(int atom)
|
|
||||||
{
|
|
||||||
// This is basically necessary because, for example, the PP
|
|
||||||
// tokenizer only accepts valid numeric-literals plus suffixes, so
|
|
||||||
// separates numeric-literals plus bad suffix into two tokens, which
|
|
||||||
// should get both pasted together as one token when token pasting.
|
|
||||||
//
|
|
||||||
// The following code is a bit more generalized than the above example.
|
|
||||||
if (!atEnd() && atom == PpAtomIdentifier && stream[currentPos].nonSpaced()) {
|
|
||||||
switch(stream[currentPos].getAtom()) {
|
|
||||||
case PpAtomConstInt:
|
|
||||||
case PpAtomConstUint:
|
|
||||||
case PpAtomConstInt64:
|
|
||||||
case PpAtomConstUint64:
|
|
||||||
case PpAtomConstInt16:
|
|
||||||
case PpAtomConstUint16:
|
|
||||||
case PpAtomConstFloat:
|
|
||||||
case PpAtomConstDouble:
|
|
||||||
case PpAtomConstFloat16:
|
|
||||||
case PpAtomConstString:
|
|
||||||
case PpAtomIdentifier:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int getToken(TParseContextBase&, TPpToken*);
|
|
||||||
bool atEnd() { return currentPos >= stream.size(); }
|
|
||||||
bool peekTokenizedPasting(bool lastTokenPastes);
|
|
||||||
bool peekUntokenizedPasting();
|
|
||||||
void reset() { currentPos = 0; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TVector<Token> stream;
|
|
||||||
size_t currentPos;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// From Pp.cpp
|
|
||||||
//
|
|
||||||
|
|
||||||
struct MacroSymbol {
|
|
||||||
MacroSymbol() : functionLike(0), busy(0), undef(0) { }
|
|
||||||
TVector<int> args;
|
|
||||||
TokenStream body;
|
|
||||||
unsigned functionLike : 1; // 0 means object-like, 1 means function-like
|
|
||||||
unsigned busy : 1;
|
|
||||||
unsigned undef : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef TMap<int, MacroSymbol> TSymbolMap;
|
|
||||||
TSymbolMap macroDefs; // map atoms to macro definitions
|
|
||||||
MacroSymbol* lookupMacroDef(int atom)
|
|
||||||
{
|
|
||||||
auto existingMacroIt = macroDefs.find(atom);
|
|
||||||
return (existingMacroIt == macroDefs.end()) ? nullptr : &(existingMacroIt->second);
|
|
||||||
}
|
|
||||||
void addMacroDef(int atom, MacroSymbol& macroDef) { macroDefs[atom] = macroDef; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TPpContext(TPpContext&);
|
|
||||||
TPpContext& operator=(TPpContext&);
|
|
||||||
|
|
||||||
TStringAtomMap atomStrings;
|
|
||||||
char* preamble; // string to parse, all before line 1 of string 0, it is 0 if no preamble
|
|
||||||
int preambleLength;
|
|
||||||
char** strings; // official strings of shader, starting a string 0 line 1
|
|
||||||
size_t* lengths;
|
|
||||||
int numStrings; // how many official strings there are
|
|
||||||
int currentString; // which string we're currently parsing (-1 for preamble)
|
|
||||||
|
|
||||||
// Scanner data:
|
|
||||||
int previous_token;
|
|
||||||
TParseContextBase& parseContext;
|
|
||||||
|
|
||||||
// Get the next token from *stack* of input sources, popping input sources
|
|
||||||
// that are out of tokens, down until an input source is found that has a token.
|
|
||||||
// Return EndOfInput when there are no more tokens to be found by doing this.
|
|
||||||
int scanToken(TPpToken* ppToken)
|
|
||||||
{
|
|
||||||
int token = EndOfInput;
|
|
||||||
|
|
||||||
while (! inputStack.empty()) {
|
|
||||||
token = inputStack.back()->scan(ppToken);
|
|
||||||
if (token != EndOfInput || inputStack.empty())
|
|
||||||
break;
|
|
||||||
popInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
int getChar() { return inputStack.back()->getch(); }
|
|
||||||
void ungetChar() { inputStack.back()->ungetch(); }
|
|
||||||
bool peekPasting() { return !inputStack.empty() && inputStack.back()->peekPasting(); }
|
|
||||||
bool peekContinuedPasting(int a)
|
|
||||||
{
|
|
||||||
return !inputStack.empty() && inputStack.back()->peekContinuedPasting(a);
|
|
||||||
}
|
|
||||||
bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); }
|
|
||||||
bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); }
|
|
||||||
|
|
||||||
static const int maxIfNesting = 65;
|
|
||||||
|
|
||||||
int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor)
|
|
||||||
bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth
|
|
||||||
int elsetracker; // #if-#else and #endif constructs...Counter.
|
|
||||||
|
|
||||||
class tMacroInput : public tInput {
|
|
||||||
public:
|
|
||||||
tMacroInput(TPpContext* pp) : tInput(pp), prepaste(false), postpaste(false) { }
|
|
||||||
virtual ~tMacroInput()
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < args.size(); ++i)
|
|
||||||
delete args[i];
|
|
||||||
for (size_t i = 0; i < expandedArgs.size(); ++i)
|
|
||||||
delete expandedArgs[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual int scan(TPpToken*) override;
|
|
||||||
virtual int getch() override { assert(0); return EndOfInput; }
|
|
||||||
virtual void ungetch() override { assert(0); }
|
|
||||||
bool peekPasting() override { return prepaste; }
|
|
||||||
bool peekContinuedPasting(int a) override { return mac->body.peekContinuedPasting(a); }
|
|
||||||
bool endOfReplacementList() override { return mac->body.atEnd(); }
|
|
||||||
bool isMacroInput() override { return true; }
|
|
||||||
|
|
||||||
MacroSymbol *mac;
|
|
||||||
TVector<TokenStream*> args;
|
|
||||||
TVector<TokenStream*> expandedArgs;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
bool prepaste; // true if we are just before ##
|
|
||||||
bool postpaste; // true if we are right after ##
|
|
||||||
};
|
|
||||||
|
|
||||||
class tMarkerInput : public tInput {
|
|
||||||
public:
|
|
||||||
tMarkerInput(TPpContext* pp) : tInput(pp) { }
|
|
||||||
virtual int scan(TPpToken*) override
|
|
||||||
{
|
|
||||||
if (done)
|
|
||||||
return EndOfInput;
|
|
||||||
done = true;
|
|
||||||
|
|
||||||
return marker;
|
|
||||||
}
|
|
||||||
virtual int getch() override { assert(0); return EndOfInput; }
|
|
||||||
virtual void ungetch() override { assert(0); }
|
|
||||||
static const int marker = -3;
|
|
||||||
};
|
|
||||||
|
|
||||||
class tZeroInput : public tInput {
|
|
||||||
public:
|
|
||||||
tZeroInput(TPpContext* pp) : tInput(pp) { }
|
|
||||||
virtual int scan(TPpToken*) override;
|
|
||||||
virtual int getch() override { assert(0); return EndOfInput; }
|
|
||||||
virtual void ungetch() override { assert(0); }
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<tInput*> inputStack;
|
|
||||||
bool errorOnVersion;
|
|
||||||
bool versionSeen;
|
|
||||||
|
|
||||||
//
|
|
||||||
// from Pp.cpp
|
|
||||||
//
|
|
||||||
|
|
||||||
// Used to obtain #include content.
|
|
||||||
TShader::Includer& includer;
|
|
||||||
|
|
||||||
int CPPdefine(TPpToken * ppToken);
|
|
||||||
int CPPundef(TPpToken * ppToken);
|
|
||||||
int CPPelse(int matchelse, TPpToken * ppToken);
|
|
||||||
int extraTokenCheck(int atom, TPpToken* ppToken, int token);
|
|
||||||
int eval(int token, int precedence, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
|
|
||||||
int evalToToken(int token, bool shortCircuit, int& res, bool& err, TPpToken * ppToken);
|
|
||||||
int CPPif (TPpToken * ppToken);
|
|
||||||
int CPPifdef(int defined, TPpToken * ppToken);
|
|
||||||
int CPPinclude(TPpToken * ppToken);
|
|
||||||
int CPPline(TPpToken * ppToken);
|
|
||||||
int CPPerror(TPpToken * ppToken);
|
|
||||||
int CPPpragma(TPpToken * ppToken);
|
|
||||||
int CPPversion(TPpToken * ppToken);
|
|
||||||
int CPPextension(TPpToken * ppToken);
|
|
||||||
int readCPPline(TPpToken * ppToken);
|
|
||||||
int scanHeaderName(TPpToken* ppToken, char delimit);
|
|
||||||
TokenStream* PrescanMacroArg(TokenStream&, TPpToken*, bool newLineOkay);
|
|
||||||
MacroExpandResult MacroExpand(TPpToken* ppToken, bool expandUndef, bool newLineOkay);
|
|
||||||
|
|
||||||
//
|
|
||||||
// From PpTokens.cpp
|
|
||||||
//
|
|
||||||
void pushTokenStreamInput(TokenStream&, bool pasting = false);
|
|
||||||
void UngetToken(int token, TPpToken*);
|
|
||||||
|
|
||||||
class tTokenInput : public tInput {
|
|
||||||
public:
|
|
||||||
tTokenInput(TPpContext* pp, TokenStream* t, bool prepasting) :
|
|
||||||
tInput(pp),
|
|
||||||
tokens(t),
|
|
||||||
lastTokenPastes(prepasting) { }
|
|
||||||
virtual int scan(TPpToken *ppToken) override { return tokens->getToken(pp->parseContext, ppToken); }
|
|
||||||
virtual int getch() override { assert(0); return EndOfInput; }
|
|
||||||
virtual void ungetch() override { assert(0); }
|
|
||||||
virtual bool peekPasting() override { return tokens->peekTokenizedPasting(lastTokenPastes); }
|
|
||||||
bool peekContinuedPasting(int a) override { return tokens->peekContinuedPasting(a); }
|
|
||||||
protected:
|
|
||||||
TokenStream* tokens;
|
|
||||||
bool lastTokenPastes; // true if the last token in the input is to be pasted, rather than consumed as a token
|
|
||||||
};
|
|
||||||
|
|
||||||
class tUngotTokenInput : public tInput {
|
|
||||||
public:
|
|
||||||
tUngotTokenInput(TPpContext* pp, int t, TPpToken* p) : tInput(pp), token(t), lval(*p) { }
|
|
||||||
virtual int scan(TPpToken *) override;
|
|
||||||
virtual int getch() override { assert(0); return EndOfInput; }
|
|
||||||
virtual void ungetch() override { assert(0); }
|
|
||||||
protected:
|
|
||||||
int token;
|
|
||||||
TPpToken lval;
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// From PpScanner.cpp
|
|
||||||
//
|
|
||||||
class tStringInput : public tInput {
|
|
||||||
public:
|
|
||||||
tStringInput(TPpContext* pp, TInputScanner& i) : tInput(pp), input(&i) { }
|
|
||||||
virtual int scan(TPpToken*) override;
|
|
||||||
|
|
||||||
// Scanner used to get source stream characters.
|
|
||||||
// - Escaped newlines are handled here, invisibly to the caller.
|
|
||||||
// - All forms of newline are handled, and turned into just a '\n'.
|
|
||||||
int getch() override
|
|
||||||
{
|
|
||||||
int ch = input->get();
|
|
||||||
|
|
||||||
if (ch == '\\') {
|
|
||||||
// Move past escaped newlines, as many as sequentially exist
|
|
||||||
do {
|
|
||||||
if (input->peek() == '\r' || input->peek() == '\n') {
|
|
||||||
bool allowed = pp->parseContext.lineContinuationCheck(input->getSourceLoc(), pp->inComment);
|
|
||||||
if (! allowed && pp->inComment)
|
|
||||||
return '\\';
|
|
||||||
|
|
||||||
// escape one newline now
|
|
||||||
ch = input->get();
|
|
||||||
int nextch = input->get();
|
|
||||||
if (ch == '\r' && nextch == '\n')
|
|
||||||
ch = input->get();
|
|
||||||
else
|
|
||||||
ch = nextch;
|
|
||||||
} else
|
|
||||||
return '\\';
|
|
||||||
} while (ch == '\\');
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle any non-escaped newline
|
|
||||||
if (ch == '\r' || ch == '\n') {
|
|
||||||
if (ch == '\r' && input->peek() == '\n')
|
|
||||||
input->get();
|
|
||||||
return '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scanner used to backup the source stream characters. Newlines are
|
|
||||||
// handled here, invisibly to the caller, meaning have to undo exactly
|
|
||||||
// what getch() above does (e.g., don't leave things in the middle of a
|
|
||||||
// sequence of escaped newlines).
|
|
||||||
void ungetch() override
|
|
||||||
{
|
|
||||||
input->unget();
|
|
||||||
|
|
||||||
do {
|
|
||||||
int ch = input->peek();
|
|
||||||
if (ch == '\r' || ch == '\n') {
|
|
||||||
if (ch == '\n') {
|
|
||||||
// correct for two-character newline
|
|
||||||
input->unget();
|
|
||||||
if (input->peek() != '\r')
|
|
||||||
input->get();
|
|
||||||
}
|
|
||||||
// now in front of a complete newline, move past an escape character
|
|
||||||
input->unget();
|
|
||||||
if (input->peek() == '\\')
|
|
||||||
input->unget();
|
|
||||||
else {
|
|
||||||
input->get();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
} while (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
TInputScanner* input;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Holds a reference to included file data, as well as a
|
|
||||||
// prologue and an epilogue string. This can be scanned using the tInput
|
|
||||||
// interface and acts as a single source string.
|
|
||||||
class TokenizableIncludeFile : public tInput {
|
|
||||||
public:
|
|
||||||
// Copies prologue and epilogue. The includedFile must remain valid
|
|
||||||
// until this TokenizableIncludeFile is no longer used.
|
|
||||||
TokenizableIncludeFile(const TSourceLoc& startLoc,
|
|
||||||
const std::string& prologue,
|
|
||||||
TShader::Includer::IncludeResult* includedFile,
|
|
||||||
const std::string& epilogue,
|
|
||||||
TPpContext* pp)
|
|
||||||
: tInput(pp),
|
|
||||||
prologue_(prologue),
|
|
||||||
epilogue_(epilogue),
|
|
||||||
includedFile_(includedFile),
|
|
||||||
scanner(3, strings, lengths, nullptr, 0, 0, true),
|
|
||||||
prevScanner(nullptr),
|
|
||||||
stringInput(pp, scanner)
|
|
||||||
{
|
|
||||||
strings[0] = prologue_.data();
|
|
||||||
strings[1] = includedFile_->headerData;
|
|
||||||
strings[2] = epilogue_.data();
|
|
||||||
|
|
||||||
lengths[0] = prologue_.size();
|
|
||||||
lengths[1] = includedFile_->headerLength;
|
|
||||||
lengths[2] = epilogue_.size();
|
|
||||||
|
|
||||||
scanner.setLine(startLoc.line);
|
|
||||||
scanner.setString(startLoc.string);
|
|
||||||
|
|
||||||
scanner.setFile(startLoc.getFilenameStr(), 0);
|
|
||||||
scanner.setFile(startLoc.getFilenameStr(), 1);
|
|
||||||
scanner.setFile(startLoc.getFilenameStr(), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tInput methods:
|
|
||||||
int scan(TPpToken* t) override { return stringInput.scan(t); }
|
|
||||||
int getch() override { return stringInput.getch(); }
|
|
||||||
void ungetch() override { stringInput.ungetch(); }
|
|
||||||
|
|
||||||
void notifyActivated() override
|
|
||||||
{
|
|
||||||
prevScanner = pp->parseContext.getScanner();
|
|
||||||
pp->parseContext.setScanner(&scanner);
|
|
||||||
pp->push_include(includedFile_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void notifyDeleted() override
|
|
||||||
{
|
|
||||||
pp->parseContext.setScanner(prevScanner);
|
|
||||||
pp->pop_include();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
TokenizableIncludeFile& operator=(const TokenizableIncludeFile&);
|
|
||||||
|
|
||||||
// Stores the prologue for this string.
|
|
||||||
const std::string prologue_;
|
|
||||||
|
|
||||||
// Stores the epilogue for this string.
|
|
||||||
const std::string epilogue_;
|
|
||||||
|
|
||||||
// Points to the IncludeResult that this TokenizableIncludeFile represents.
|
|
||||||
TShader::Includer::IncludeResult* includedFile_;
|
|
||||||
|
|
||||||
// Will point to prologue_, includedFile_->headerData and epilogue_
|
|
||||||
// This is passed to scanner constructor.
|
|
||||||
// These do not own the storage and it must remain valid until this
|
|
||||||
// object has been destroyed.
|
|
||||||
const char* strings[3];
|
|
||||||
// Length of str_, passed to scanner constructor.
|
|
||||||
size_t lengths[3];
|
|
||||||
// Scans over str_.
|
|
||||||
TInputScanner scanner;
|
|
||||||
// The previous effective scanner before the scanner in this instance
|
|
||||||
// has been activated.
|
|
||||||
TInputScanner* prevScanner;
|
|
||||||
// Delegate object implementing the tInput interface.
|
|
||||||
tStringInput stringInput;
|
|
||||||
};
|
|
||||||
|
|
||||||
int ScanFromString(char* s);
|
|
||||||
void missingEndifCheck();
|
|
||||||
int lFloatConst(int len, int ch, TPpToken* ppToken);
|
|
||||||
int characterLiteral(TPpToken* ppToken);
|
|
||||||
|
|
||||||
void push_include(TShader::Includer::IncludeResult* result)
|
|
||||||
{
|
|
||||||
currentSourceFile = result->headerName;
|
|
||||||
includeStack.push(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pop_include()
|
|
||||||
{
|
|
||||||
TShader::Includer::IncludeResult* include = includeStack.top();
|
|
||||||
includeStack.pop();
|
|
||||||
includer.releaseInclude(include);
|
|
||||||
if (includeStack.empty()) {
|
|
||||||
currentSourceFile = rootFileName;
|
|
||||||
} else {
|
|
||||||
currentSourceFile = includeStack.top()->headerName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool inComment;
|
|
||||||
std::string rootFileName;
|
|
||||||
std::stack<TShader::Includer::IncludeResult*> includeStack;
|
|
||||||
std::string currentSourceFile;
|
|
||||||
|
|
||||||
std::istringstream strtodStream;
|
|
||||||
bool disableEscapeSequences;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace glslang
|
|
||||||
|
|
||||||
#endif // PPCONTEXT_H
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue