Skip to content
Commits on Source (128)
File mode changed from 100755 to 100644
......@@ -8,10 +8,10 @@
*.txt text
# source code can be native and normalized, but simpler if lf everywhere; will try that way
*.h text eof=lf
*.c text eof=lf
*.cpp text eof=lf
*.y text eof=lf
*.out text eof=lf
*.conf text eof=lf
*.err text eof=lf
*.h text eol=lf
*.c text eol=lf
*.cpp text eol=lf
*.y text eol=lf
*.out text eol=lf
*.conf text eol=lf
*.err text eol=lf
LOCAL_PATH := $(call my-dir)
GLSLANG_OS_FLAGS := -DGLSLANG_OSINCLUDE_UNIX
# AMD and NV extensions are turned on by default in upstream Glslang.
GLSLANG_DEFINES:= -DAMD_EXTENSIONS -DNV_EXTENSIONS -DENABLE_HLSL $(GLSLANG_OS_FLAGS)
include $(CLEAR_VARS)
LOCAL_MODULE:=OSDependent
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)
LOCAL_SRC_FILES:=glslang/OSDependent/Unix/ossource.cpp
LOCAL_C_INCLUDES:=$(LOCAL_PATH) $(LOCAL_PATH)/glslang/OSDependent/Unix/
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/glslang/OSDependent/Unix/
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:=OGLCompiler
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)
LOCAL_SRC_FILES:=OGLCompilersDLL/InitializeDll.cpp
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/OGLCompiler
LOCAL_STATIC_LIBRARIES:=OSDependent
include $(BUILD_STATIC_LIBRARY)
# Build Glslang's HLSL parser library.
include $(CLEAR_VARS)
LOCAL_MODULE:=HLSL
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
LOCAL_SRC_FILES:= \
hlsl/hlslAttributes.cpp \
hlsl/hlslGrammar.cpp \
hlsl/hlslOpMap.cpp \
hlsl/hlslParseables.cpp \
hlsl/hlslParseHelper.cpp \
hlsl/hlslScanContext.cpp \
hlsl/hlslTokenStream.cpp
LOCAL_C_INCLUDES:=$(LOCAL_PATH) \
$(LOCAL_PATH)/hlsl
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
GLSLANG_OUT_PATH=$(if $(call host-path-is-absolute,$(TARGET_OUT)),$(TARGET_OUT),$(abspath $(TARGET_OUT)))
LOCAL_MODULE:=glslang
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES)
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)
LOCAL_SRC_FILES:= \
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/propagateNoContraction.cpp \
glslang/MachineIndependent/reflection.cpp \
glslang/MachineIndependent/RemoveTree.cpp \
glslang/MachineIndependent/Scan.cpp \
glslang/MachineIndependent/ShaderLang.cpp \
glslang/MachineIndependent/SymbolTable.cpp \
glslang/MachineIndependent/Versions.cpp \
glslang/MachineIndependent/preprocessor/PpAtom.cpp \
glslang/MachineIndependent/preprocessor/PpContext.cpp \
glslang/MachineIndependent/preprocessor/Pp.cpp \
glslang/MachineIndependent/preprocessor/PpScanner.cpp \
glslang/MachineIndependent/preprocessor/PpTokens.cpp
LOCAL_C_INCLUDES:=$(LOCAL_PATH) \
$(LOCAL_PATH)/glslang/MachineIndependent \
$(GLSLANG_OUT_PATH)
LOCAL_STATIC_LIBRARIES:=OSDependent OGLCompiler HLSL
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:=SPIRV
LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -Werror $(GLSLANG_DEFINES)
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)
LOCAL_SRC_FILES:= \
SPIRV/GlslangToSpv.cpp \
SPIRV/InReadableOrder.cpp \
SPIRV/Logger.cpp \
SPIRV/SPVRemapper.cpp \
SPIRV/SpvBuilder.cpp \
SPIRV/SpvPostProcess.cpp \
SPIRV/SpvTools.cpp \
SPIRV/disassemble.cpp \
SPIRV/doc.cpp
LOCAL_C_INCLUDES:=$(LOCAL_PATH) $(LOCAL_PATH)/glslang/SPIRV
LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/glslang/SPIRV
LOCAL_STATIC_LIBRARIES:=glslang
include $(BUILD_STATIC_LIBRARY)
......@@ -141,13 +141,45 @@ source_set("glslang_sources") {
if (is_clang) {
cflags_cc = [
"-Wno-implicit-fallthrough",
"-Wno-extra-semi",
"-Wno-ignored-qualifiers",
"-Wno-implicit-fallthrough",
"-Wno-inconsistent-missing-override",
"-Wno-sign-compare",
"-Wno-unused-variable",
]
}
if (is_win && !is_clang) {
cflags = [
"/wd4018", # signed/unsigned mismatch
]
}
deps = [
"${spirv_tools_dir}:spvtools_opt",
]
}
source_set("glslang_default_resource_limits_sources") {
sources = [
"StandAlone/ResourceLimits.cpp",
"StandAlone/ResourceLimits.h",
]
deps = [ ":glslang_sources" ]
public_configs = [ ":glslang_public" ]
}
source_set("glslang_validator") {
sources = [
"StandAlone/DirStackFileIncluder.h",
"StandAlone/StandAlone.cpp",
]
if (!is_win) {
cflags = [ "-Woverflow" ]
}
defines = [ "ENABLE_OPT=0" ]
deps = [
":glslang_default_resource_limits_sources",
":glslang_sources",
]
}
......@@ -46,12 +46,8 @@ endif()
# Precompiled header macro. Parameters are source file list and filename for pch cpp file.
macro(glslang_pch SRCS PCHCPP)
if(MSVC)
if (CMAKE_GENERATOR MATCHES "^Visual Studio")
if(MSVC AND CMAKE_GENERATOR MATCHES "^Visual Studio")
set(PCH_NAME "$(IntDir)\\pch.pch")
else()
set(PCH_NAME "${CMAKE_CURRENT_BINARY_DIR}/pch.pch")
endif()
# make source files use/depend on PCH_NAME
set_source_files_properties(${${SRCS}} PROPERTIES COMPILE_FLAGS "/Yupch.h /FIpch.h /Fp${PCH_NAME} /Zm300" OBJECT_DEPENDS "${PCH_NAME}")
# make PCHCPP file compile and generate PCH_NAME
......@@ -77,7 +73,7 @@ if(ENABLE_HLSL)
endif(ENABLE_HLSL)
if(WIN32)
set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Adds a postfix for debug-built libraries.")
set(CMAKE_DEBUG_POSTFIX "d")
if(MSVC)
include(ChooseMSVCCRT.cmake)
endif(MSVC)
......
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.
\****************************************************************************/
......@@ -127,6 +127,9 @@ cmake $SOURCE_DIR -DCMAKE_INSTALL_PREFIX="$(pwd)/install"
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
......
......@@ -28,10 +28,11 @@
#define GLSLextEXT_H
static const int GLSLextEXTVersion = 100;
static const int GLSLextEXTRevision = 1;
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";
#endif // #ifndef GLSLextEXT_H
......@@ -40,5 +40,6 @@ static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_
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";
#endif // #ifndef GLSLextKHR_H
This diff is collapsed.
//
// Copyright (C) 2014 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
//
// All rights reserved.
//
......
//
// Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2016 Google, Inc.
// Copyright (C) 2015-2018 Google, Inc.
//
// All rights reserved.
//
......@@ -60,6 +60,7 @@ Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogg
sourceVersion(0),
sourceFileStringId(NoResult),
currentLine(0),
currentFile(nullptr),
emitOpLines(false),
addressModel(AddressingModelLogical),
memoryModel(MemoryModelGLSL450),
......@@ -87,8 +88,9 @@ Id Builder::import(const char* name)
return import->getResultId();
}
// Emit an OpLine if we've been asked to emit OpLines and the line number
// has changed since the last time, and is a valid line number.
// Emit instruction for non-filename-based #line directives (ie. no filename
// seen yet): emit an OpLine if we've been asked to emit OpLines and the line
// number has changed since the last time, and is a valid line number.
void Builder::setLine(int lineNum)
{
if (lineNum != 0 && lineNum != currentLine) {
......@@ -98,6 +100,26 @@ void Builder::setLine(int lineNum)
}
}
// If no filename, do non-filename-based #line emit. Else do filename-based emit.
// Emit OpLine if we've been asked to emit OpLines and the line number or filename
// has changed since the last time, and line number is valid.
void Builder::setLine(int lineNum, const char* filename)
{
if (filename == nullptr) {
setLine(lineNum);
return;
}
if ((lineNum != 0 && lineNum != currentLine) || currentFile == nullptr ||
strncmp(filename, currentFile, strlen(currentFile) + 1) != 0) {
currentLine = lineNum;
currentFile = filename;
if (emitOpLines) {
spv::Id strId = getStringId(filename);
addLine(strId, currentLine, 0);
}
}
}
void Builder::addLine(Id fileName, int lineNum, int column)
{
Instruction* line = new Instruction(OpLine);
......@@ -172,6 +194,40 @@ Id Builder::makePointer(StorageClass storageClass, Id pointee)
return type->getResultId();
}
Id Builder::makeForwardPointer(StorageClass storageClass)
{
// Caching/uniquifying doesn't work here, because we don't know the
// pointee type and there can be multiple forward pointers of the same
// storage type. Somebody higher up in the stack must keep track.
Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeForwardPointer);
type->addImmediateOperand(storageClass);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
return type->getResultId();
}
Id Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardPointerType, Id pointee)
{
// try to find it
Instruction* type;
for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
type = groupedTypes[OpTypePointer][t];
if (type->getImmediateOperand(0) == (unsigned)storageClass &&
type->getIdOperand(1) == pointee)
return type->getResultId();
}
type = new Instruction(forwardPointerType, NoType, OpTypePointer);
type->addImmediateOperand(storageClass);
type->addIdOperand(pointee);
groupedTypes[OpTypePointer].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
return type->getResultId();
}
Id Builder::makeIntegerType(int width, bool hasSign)
{
// try to find it
......@@ -509,6 +565,7 @@ Id Builder::makeAccelerationStructureNVType()
Instruction *type;
if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) {
type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV);
groupedTypes[OpTypeAccelerationStructureNV].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
} else {
......@@ -554,6 +611,7 @@ int Builder::getNumTypeConstituents(Id typeId) const
case OpTypeBool:
case OpTypeInt:
case OpTypeFloat:
case OpTypePointer:
return 1;
case OpTypeVector:
case OpTypeMatrix:
......@@ -647,17 +705,36 @@ bool Builder::containsType(Id typeId, spv::Op typeOp, unsigned int width) const
return true;
}
return false;
case OpTypePointer:
return false;
case OpTypeVector:
case OpTypeMatrix:
case OpTypeArray:
case OpTypeRuntimeArray:
case OpTypePointer:
return containsType(getContainedTypeId(typeId), typeOp, width);
default:
return typeClass == typeOp;
}
}
// return true if the type is a pointer to PhysicalStorageBufferEXT or an
// array of such pointers. These require restrict/aliased decorations.
bool Builder::containsPhysicalStorageBufferOrArray(Id typeId) const
{
const Instruction& instr = *module.getInstruction(typeId);
Op typeClass = instr.getOpCode();
switch (typeClass)
{
case OpTypePointer:
return getTypeStorageClass(typeId) == StorageClassPhysicalStorageBufferEXT;
case OpTypeArray:
return containsPhysicalStorageBufferOrArray(getContainedTypeId(typeId));
default:
return false;
}
}
// See if a scalar constant of this type has already been created, so it
// can be reused rather than duplicated. (Required by the specification).
Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value)
......@@ -1230,15 +1307,39 @@ Id Builder::createUndefined(Id type)
return inst->getResultId();
}
// av/vis/nonprivate are unnecessary and illegal for some storage classes.
spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const
{
switch (sc) {
case spv::StorageClassUniform:
case spv::StorageClassWorkgroup:
case spv::StorageClassStorageBuffer:
case spv::StorageClassPhysicalStorageBufferEXT:
break;
default:
memoryAccess = spv::MemoryAccessMask(memoryAccess &
~(spv::MemoryAccessMakePointerAvailableKHRMask |
spv::MemoryAccessMakePointerVisibleKHRMask |
spv::MemoryAccessNonPrivatePointerKHRMask));
break;
}
return memoryAccess;
}
// Comments in header
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{
Instruction* store = new Instruction(OpStore);
store->addIdOperand(lValue);
store->addIdOperand(rValue);
memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
if (memoryAccess != MemoryAccessMaskNone) {
store->addImmediateOperand(memoryAccess);
if (memoryAccess & spv::MemoryAccessAlignedMask) {
store->addImmediateOperand(alignment);
}
if (memoryAccess & spv::MemoryAccessMakePointerAvailableKHRMask) {
store->addIdOperand(makeUintConstant(scope));
}
......@@ -1248,13 +1349,18 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce
}
// Comments in header
Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{
Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
load->addIdOperand(lValue);
memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
if (memoryAccess != MemoryAccessMaskNone) {
load->addImmediateOperand(memoryAccess);
if (memoryAccess & spv::MemoryAccessAlignedMask) {
load->addImmediateOperand(alignment);
}
if (memoryAccess & spv::MemoryAccessMakePointerVisibleKHRMask) {
load->addIdOperand(makeUintConstant(scope));
}
......@@ -1293,7 +1399,7 @@ Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vec
Id Builder::createArrayLength(Id base, unsigned int member)
{
spv::Id intType = makeIntType(32);
spv::Id intType = makeUintType(32);
Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength);
length->addIdOperand(base);
length->addImmediateOperand(member);
......@@ -2096,7 +2202,8 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
// Go through the source arguments, each one could have either
// a single or multiple components to contribute.
for (unsigned int i = 0; i < sources.size(); ++i) {
if (isScalar(sources[i]))
if (isScalar(sources[i]) || isPointer(sources[i]))
latchResult(sources[i]);
else if (isVector(sources[i]))
accumulateVectorConstituents(sources[i]);
......@@ -2411,11 +2518,15 @@ void Builder::clearAccessChain()
accessChain.preSwizzleBaseType = NoType;
accessChain.isRValue = false;
accessChain.coherentFlags.clear();
accessChain.alignment = 0;
}
// Comments in header
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType)
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
{
accessChain.coherentFlags |= coherentFlags;
accessChain.alignment |= alignment;
// swizzles can be stacked in GLSL, but simplified to a single
// one here; the base type doesn't change
if (accessChain.preSwizzleBaseType == NoType)
......@@ -2437,7 +2548,7 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizz
}
// Comments in header
void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{
assert(accessChain.isRValue == false);
......@@ -2455,11 +2566,17 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
}
createStore(source, base, memoryAccess, scope);
// take LSB of alignment
alignment = alignment & ~(alignment & (alignment-1));
if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
}
createStore(source, base, memoryAccess, scope, alignment);
}
// Comments in header
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{
Id id;
......@@ -2502,8 +2619,15 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
id = accessChain.base; // no precision, it was set when this was defined
} else {
transferAccessChainSwizzle(true);
// take LSB of alignment
alignment = alignment & ~(alignment & (alignment-1));
if (getStorageClass(accessChain.base) == StorageClassPhysicalStorageBufferEXT) {
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
}
// load through the access chain
id = createLoad(collapseAccessChain(), memoryAccess, scope);
id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment);
setPrecision(id, precision);
addDecoration(id, nonUniform);
}
......@@ -2809,7 +2933,8 @@ void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* els
// OpSource
// [OpSourceContinued]
// ...
void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
void Builder::dumpSourceInstructions(const spv::Id fileId, const std::string& text,
std::vector<unsigned int>& out) const
{
const int maxWordCount = 0xFFFF;
const int opSourceWordCount = 4;
......@@ -2821,14 +2946,14 @@ void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
sourceInst.addImmediateOperand(source);
sourceInst.addImmediateOperand(sourceVersion);
// File operand
if (sourceFileStringId != NoResult) {
sourceInst.addIdOperand(sourceFileStringId);
if (fileId != NoResult) {
sourceInst.addIdOperand(fileId);
// Source operand
if (sourceText.size() > 0) {
if (text.size() > 0) {
int nextByte = 0;
std::string subString;
while ((int)sourceText.size() - nextByte > 0) {
subString = sourceText.substr(nextByte, nonNullBytesPerInstruction);
while ((int)text.size() - nextByte > 0) {
subString = text.substr(nextByte, nonNullBytesPerInstruction);
if (nextByte == 0) {
// OpSource
sourceInst.addStringOperand(subString.c_str());
......@@ -2848,6 +2973,14 @@ void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
}
}
// Dump an OpSource[Continued] sequence for the source and every include file
void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
{
dumpSourceInstructions(sourceFileStringId, sourceText, out);
for (auto iItr = includeFiles.begin(); iItr != includeFiles.end(); ++iItr)
dumpSourceInstructions(iItr->first, *iItr->second, out);
}
void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
{
for (int i = 0; i < (int)instructions.size(); ++i) {
......
//
// Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2016 Google, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2017 ARM Limited.
//
// All rights reserved.
......@@ -57,6 +57,7 @@
#include <sstream>
#include <stack>
#include <unordered_map>
#include <map>
namespace spv {
......@@ -74,18 +75,33 @@ public:
source = lang;
sourceVersion = version;
}
void setSourceFile(const std::string& file)
spv::Id getStringId(const std::string& str)
{
Instruction* fileString = new Instruction(getUniqueId(), NoType, OpString);
fileString->addStringOperand(file.c_str());
sourceFileStringId = fileString->getResultId();
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));
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 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)
{
......@@ -106,16 +122,25 @@ public:
return id;
}
// Log the current line, and if different than the last one,
// issue a new OpLine, using the current file name.
// 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 type);
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); }
......@@ -171,6 +196,7 @@ public:
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;
......@@ -277,10 +303,10 @@ public:
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);
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);
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);
......@@ -512,6 +538,7 @@ public:
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 {
......@@ -578,31 +605,34 @@ public:
}
// push offset onto the end of the chain
void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags)
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);
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)
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);
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);
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// get the direct pointer for an l-value
Id accessChainGetLValue();
......@@ -616,7 +646,7 @@ public:
void postProcess();
// Hook to visit each instruction in a block in a function
void postProcess(const Instruction&);
void postProcess(Instruction&);
// Hook to visit each instruction in a reachable block in a function.
void postProcessReachable(const Instruction&);
// Hook to visit each non-32-bit sized float/int operation in a block.
......@@ -649,8 +679,10 @@ public:
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;
......@@ -658,6 +690,7 @@ public:
spv::Id sourceFileStringId;
std::string sourceText;
int currentLine;
const char* currentFile;
bool emitOpLines;
std::set<std::string> extensions;
std::vector<const char*> sourceExtensions;
......@@ -695,6 +728,12 @@ public:
// 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
......
//
// Copyright (C) 2016-2018 Google, Inc.
// Copyright (C) 2018 Google, Inc.
//
// All rights reserved.
//
......@@ -87,6 +87,7 @@ void Builder::postProcessType(const Instruction& inst, Id typeId)
StorageClass storageClass = getStorageClass(inst.getIdOperand(0));
if (width == 8) {
switch (storageClass) {
case StorageClassPhysicalStorageBufferEXT:
case StorageClassUniform:
case StorageClassStorageBuffer:
case StorageClassPushConstant:
......@@ -97,6 +98,7 @@ void Builder::postProcessType(const Instruction& inst, Id typeId)
}
} else if (width == 16) {
switch (storageClass) {
case StorageClassPhysicalStorageBufferEXT:
case StorageClassUniform:
case StorageClassStorageBuffer:
case StorageClassPushConstant:
......@@ -151,7 +153,7 @@ void Builder::postProcessType(const Instruction& inst, Id typeId)
}
// Called for each instruction that resides in a block.
void Builder::postProcess(const Instruction& inst)
void Builder::postProcess(Instruction& inst)
{
// Add capabilities based simply on the opcode.
switch (inst.getOpCode()) {
......@@ -190,6 +192,88 @@ void Builder::postProcess(const Instruction& inst)
break;
#endif
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);
// Compute the index of the alignment operand.
int alignmentIdx = 2;
if (memoryAccess & MemoryAccessVolatileMask)
alignmentIdx++;
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;
}
......@@ -258,6 +342,47 @@ void Builder::postProcess()
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);
}
}
}
}
}
// 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)) {
addExtension(spv::E_SPV_KHR_8bit_storage);
addCapability(spv::CapabilityStorageBuffer8BitAccess);
}
if (containsType(type->getIdOperand(1), OpTypeInt, 16) ||
containsType(type->getIdOperand(1), OpTypeFloat, 16)) {
addExtension(spv::E_SPV_KHR_16bit_storage);
addCapability(spv::CapabilityStorageBuffer16BitAccess);
}
}
}
}
......
......@@ -152,6 +152,13 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>
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::CreateDeadBranchElimPass());
optimizer.RegisterPass(spvtools::CreateMergeReturnPass());
optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass());
......@@ -180,8 +187,11 @@ void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>
}
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
if (options->generateDebugInfo) {
optimizer.RegisterPass(spvtools::CreateRedundantLineInfoElimPass());
}
optimizer.Run(spirv.data(), spirv.size(), &spirv, spvtools::ValidatorOptions(), true);
optimizer.Run(spirv.data(), spirv.size(), &spirv);
}
}; // end namespace glslang
......
File mode changed from 100755 to 100644
......@@ -540,6 +540,14 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
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:
......
......@@ -124,6 +124,8 @@ const char* AddressingString(int addr)
case 1: return "Physical32";
case 2: return "Physical64";
case AddressingModelPhysicalStorageBuffer64EXT: return "PhysicalStorageBuffer64EXT";
default: return "Bad";
}
}
......@@ -220,6 +222,8 @@ const char* StorageClassString(int StorageClass)
case StorageClassIncomingCallableDataNV: return "IncomingCallableDataNV";
#endif
case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT";
default: return "Bad";
}
}
......@@ -295,6 +299,8 @@ const char* DecorationString(int decoration)
case DecorationNonUniformEXT: return "DecorationNonUniformEXT";
case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE";
case DecorationHlslSemanticGOOGLE: return "DecorationHlslSemanticGOOGLE";
case DecorationRestrictPointerEXT: return "DecorationRestrictPointerEXT";
case DecorationAliasedPointerEXT: return "DecorationAliasedPointerEXT";
}
}
......@@ -388,12 +394,15 @@ const char* BuiltInString(int builtIn)
case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
case BuiltInPositionPerViewNV: return "PositionPerViewNV";
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
case BuiltInFragmentSizeNV: return "FragmentSizeNV";
case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV";
// case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT
// case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT
case BuiltInBaryCoordNV: return "BaryCoordNV";
case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
#endif
case BuiltInFragSizeEXT: return "FragSizeEXT";
case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT";
case 5264: return "FullyCoveredEXT";
......@@ -897,8 +906,9 @@ const char* CapabilityString(int info)
case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV";
case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
case CapabilityMeshShadingNV: return "MeshShadingNV";
case CapabilityShadingRateNV: return "ShadingRateNV";
// case CapabilityShadingRateNV: return "ShadingRateNV"; // superseded by CapabilityFragmentDensityEXT
#endif
case CapabilityFragmentDensityEXT: return "FragmentDensityEXT";
case CapabilityFragmentFullyCoveredEXT: return "FragmentFullyCoveredEXT";
......@@ -918,6 +928,8 @@ const char* CapabilityString(int info)
case CapabilityVulkanMemoryModelKHR: return "CapabilityVulkanMemoryModelKHR";
case CapabilityVulkanMemoryModelDeviceScopeKHR: return "CapabilityVulkanMemoryModelDeviceScopeKHR";
case CapabilityPhysicalStorageBufferAddressesEXT: return "CapabilityPhysicalStorageBufferAddressesEXT";
default: return "Bad";
}
}
......
// Copyright (c) 2014-2018 The Khronos Group Inc.
// Copyright (c) 2014-2019 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"),
......@@ -26,13 +26,16 @@
// the Binary Section of the SPIR-V specification.
// Enumeration tokens for SPIR-V, in various styles:
// C, C++, C++11, JSON, Lua, Python
// C, C++, C++11, JSON, Lua, Python, C#, D
//
// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
// - C# will use enum classes in the Specification class located in the "Spv" namespace,
// e.g.: Spv.Specification.SourceLanguage.GLSL
// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL
//
// Some tokens act like mask values, which can be OR'd together,
// while others are mutually exclusive. The mask-like ones have
......@@ -47,11 +50,11 @@ namespace spv {
typedef unsigned int Id;
#define SPV_VERSION 0x10300
#define SPV_REVISION 1
#define SPV_REVISION 6
static const unsigned int MagicNumber = 0x07230203;
static const unsigned int Version = 0x00010300;
static const unsigned int Revision = 1;
static const unsigned int Revision = 6;
static const unsigned int OpCodeMask = 0xffff;
static const unsigned int WordCountShift = 16;
......@@ -88,6 +91,7 @@ enum AddressingModel {
AddressingModelLogical = 0,
AddressingModelPhysical32 = 1,
AddressingModelPhysical64 = 2,
AddressingModelPhysicalStorageBuffer64EXT = 5348,
AddressingModelMax = 0x7fffffff,
};
......@@ -139,6 +143,11 @@ enum ExecutionMode {
ExecutionModeLocalSizeId = 38,
ExecutionModeLocalSizeHintId = 39,
ExecutionModePostDepthCoverage = 4446,
ExecutionModeDenormPreserve = 4459,
ExecutionModeDenormFlushToZero = 4460,
ExecutionModeSignedZeroInfNanPreserve = 4461,
ExecutionModeRoundingModeRTE = 4462,
ExecutionModeRoundingModeRTZ = 4463,
ExecutionModeStencilRefReplacingEXT = 5027,
ExecutionModeOutputLinesNV = 5269,
ExecutionModeOutputPrimitivesNV = 5270,
......@@ -168,6 +177,7 @@ enum StorageClass {
StorageClassHitAttributeNV = 5339,
StorageClassIncomingRayPayloadNV = 5342,
StorageClassShaderRecordBufferNV = 5343,
StorageClassPhysicalStorageBufferEXT = 5349,
StorageClassMax = 0x7fffffff,
};
......@@ -416,6 +426,8 @@ enum Decoration {
DecorationMaxByteOffset = 45,
DecorationAlignmentId = 46,
DecorationMaxByteOffsetId = 47,
DecorationNoSignedWrap = 4469,
DecorationNoUnsignedWrap = 4470,
DecorationExplicitInterpAMD = 4999,
DecorationOverrideCoverageNV = 5248,
DecorationPassthroughNV = 5250,
......@@ -426,6 +438,8 @@ enum Decoration {
DecorationPerTaskNV = 5273,
DecorationPerVertexNV = 5285,
DecorationNonUniformEXT = 5300,
DecorationRestrictPointerEXT = 5355,
DecorationAliasedPointerEXT = 5356,
DecorationHlslCounterBufferGOOGLE = 5634,
DecorationHlslSemanticGOOGLE = 5635,
DecorationMax = 0x7fffffff,
......@@ -512,7 +526,9 @@ enum BuiltIn {
BuiltInMeshViewIndicesNV = 5281,
BuiltInBaryCoordNV = 5286,
BuiltInBaryCoordNoPerspNV = 5287,
BuiltInFragSizeEXT = 5292,
BuiltInFragmentSizeNV = 5292,
BuiltInFragInvocationCountEXT = 5293,
BuiltInInvocationsPerPixelNV = 5293,
BuiltInLaunchIdNV = 5319,
BuiltInLaunchSizeNV = 5320,
......@@ -753,6 +769,11 @@ enum Capability {
CapabilityStorageBuffer8BitAccess = 4448,
CapabilityUniformAndStorageBuffer8BitAccess = 4449,
CapabilityStoragePushConstant8 = 4450,
CapabilityDenormPreserve = 4464,
CapabilityDenormFlushToZero = 4465,
CapabilitySignedZeroInfNanPreserve = 4466,
CapabilityRoundingModeRTE = 4467,
CapabilityRoundingModeRTZ = 4468,
CapabilityFloat16ImageAMD = 5008,
CapabilityImageGatherBiasLodAMD = 5009,
CapabilityFragmentMaskAMD = 5010,
......@@ -770,6 +791,7 @@ enum Capability {
CapabilityImageFootprintNV = 5282,
CapabilityFragmentBarycentricNV = 5284,
CapabilityComputeDerivativeGroupQuadsNV = 5288,
CapabilityFragmentDensityEXT = 5291,
CapabilityShadingRateNV = 5291,
CapabilityGroupNonUniformPartitionedNV = 5297,
CapabilityShaderNonUniformEXT = 5301,
......@@ -787,6 +809,7 @@ enum Capability {
CapabilityRayTracingNV = 5340,
CapabilityVulkanMemoryModelKHR = 5345,
CapabilityVulkanMemoryModelDeviceScopeKHR = 5346,
CapabilityPhysicalStorageBufferAddressesEXT = 5347,
CapabilityComputeDerivativeGroupLinearNV = 5350,
CapabilitySubgroupShuffleINTEL = 5568,
CapabilitySubgroupBufferBlockIOINTEL = 5569,
......
//
// Copyright (C) 2014 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
//
// All rights reserved.
//
......@@ -101,6 +102,11 @@ public:
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;
......@@ -202,6 +208,7 @@ public:
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).
......