Final round for line endings.
This commit is contained in:
parent
b63263267d
commit
140f3df134
@ -1,6 +1,6 @@
|
|||||||
This directory contains a Linux binary for the glslang validator.
|
This directory contains a Linux binary for the glslang validator.
|
||||||
|
|
||||||
Installation: The executable in this directory is self sufficient, and can be
|
Installation: The executable in this directory is self sufficient, and can be
|
||||||
placed where desired; in a test directory, or in a system path, etc.
|
placed where desired; in a test directory, or in a system path, etc.
|
||||||
|
|
||||||
Usage: Execute glslangValidator with no arguments to get a usage statement.
|
Usage: Execute glslangValidator with no arguments to get a usage statement.
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
This directory contains a Windows binary for the glslang validator.
|
This directory contains a Windows binary for the glslang validator.
|
||||||
|
|
||||||
Installation: The executable in this directory is self sufficient, and can be
|
Installation: The executable in this directory is self sufficient, and can be
|
||||||
placed where desired; in a test directory, or in a system path, etc.
|
placed where desired; in a test directory, or in a system path, etc.
|
||||||
|
|
||||||
Usage: Execute glslangValidator with no arguments to get a usage statement.
|
Usage: Execute glslangValidator with no arguments to get a usage statement.
|
||||||
|
|||||||
@ -1,21 +1,21 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
include_directories(. ../glslang)
|
include_directories(. ../glslang)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
include_directories(${include_directories} ../glslang/OSDependent/Windows)
|
include_directories(${include_directories} ../glslang/OSDependent/Windows)
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
include_directories(${include_directories} ../glslang/OSDependent/Linux)
|
include_directories(${include_directories} ../glslang/OSDependent/Linux)
|
||||||
else(WIN32)
|
else(WIN32)
|
||||||
message("unknown platform")
|
message("unknown platform")
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
set(SOURCES InitializeDll.cpp InitializeDll.h)
|
set(SOURCES InitializeDll.cpp InitializeDll.h)
|
||||||
|
|
||||||
add_library(OGLCompiler STATIC ${SOURCES})
|
add_library(OGLCompiler STATIC ${SOURCES})
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
source_group("Source" FILES ${SOURCES})
|
source_group("Source" FILES ${SOURCES})
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
install(TARGETS OGLCompiler
|
install(TARGETS OGLCompiler
|
||||||
ARCHIVE DESTINATION lib)
|
ARCHIVE DESTINATION lib)
|
||||||
|
|||||||
@ -1,28 +1,28 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
include_directories(.. ${CMAKE_CURRENT_BINARY_DIR})
|
include_directories(.. ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
GlslangToSpv.cpp
|
GlslangToSpv.cpp
|
||||||
SpvBuilder.cpp
|
SpvBuilder.cpp
|
||||||
SPVRemapper.cpp
|
SPVRemapper.cpp
|
||||||
doc.cpp
|
doc.cpp
|
||||||
disassemble.cpp)
|
disassemble.cpp)
|
||||||
|
|
||||||
set(HEADERS
|
set(HEADERS
|
||||||
spirv.h
|
spirv.h
|
||||||
GlslangToSpv.h
|
GlslangToSpv.h
|
||||||
SpvBuilder.h
|
SpvBuilder.h
|
||||||
SPVRemapper.h
|
SPVRemapper.h
|
||||||
spvIR.h
|
spvIR.h
|
||||||
doc.h
|
doc.h
|
||||||
disassemble.h)
|
disassemble.h)
|
||||||
|
|
||||||
add_library(SPIRV STATIC ${SOURCES} ${HEADERS})
|
add_library(SPIRV STATIC ${SOURCES} ${HEADERS})
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
source_group("Source" FILES ${SOURCES} ${HEADERS})
|
source_group("Source" FILES ${SOURCES} ${HEADERS})
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
install(TARGETS SPIRV
|
install(TARGETS SPIRV
|
||||||
ARCHIVE DESTINATION lib)
|
ARCHIVE DESTINATION lib)
|
||||||
|
|||||||
@ -1,210 +1,210 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright (c) 2014-2015 The Khronos Group Inc.
|
** Copyright (c) 2014-2015 The Khronos Group Inc.
|
||||||
**
|
**
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
** copy of this software and/or associated documentation files (the
|
** copy of this software and/or associated documentation files (the
|
||||||
** "Materials"), to deal in the Materials without restriction, including
|
** "Materials"), to deal in the Materials without restriction, including
|
||||||
** without limitation the rights to use, copy, modify, merge, publish,
|
** without limitation the rights to use, copy, modify, merge, publish,
|
||||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||||
** permit persons to whom the Materials are furnished to do so, subject to
|
** permit persons to whom the Materials are furnished to do so, subject to
|
||||||
** the following conditions:
|
** the following conditions:
|
||||||
**
|
**
|
||||||
** The above copyright notice and this permission notice shall be included
|
** The above copyright notice and this permission notice shall be included
|
||||||
** in all copies or substantial portions of the Materials.
|
** in all copies or substantial portions of the Materials.
|
||||||
**
|
**
|
||||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//
|
//
|
||||||
// Author: John Kessenich, LunarG
|
// Author: John Kessenich, LunarG
|
||||||
//
|
//
|
||||||
|
|
||||||
namespace GLSL_STD_450 {
|
namespace GLSL_STD_450 {
|
||||||
|
|
||||||
enum Entrypoints {
|
enum Entrypoints {
|
||||||
Round = 0,
|
Round = 0,
|
||||||
RoundEven = 1,
|
RoundEven = 1,
|
||||||
Trunc = 2,
|
Trunc = 2,
|
||||||
Abs = 3,
|
Abs = 3,
|
||||||
Sign = 4,
|
Sign = 4,
|
||||||
Floor = 5,
|
Floor = 5,
|
||||||
Ceil = 6,
|
Ceil = 6,
|
||||||
Fract = 7,
|
Fract = 7,
|
||||||
|
|
||||||
Radians = 8,
|
Radians = 8,
|
||||||
Degrees = 9,
|
Degrees = 9,
|
||||||
Sin = 10,
|
Sin = 10,
|
||||||
Cos = 11,
|
Cos = 11,
|
||||||
Tan = 12,
|
Tan = 12,
|
||||||
Asin = 13,
|
Asin = 13,
|
||||||
Acos = 14,
|
Acos = 14,
|
||||||
Atan = 15,
|
Atan = 15,
|
||||||
Sinh = 16,
|
Sinh = 16,
|
||||||
Cosh = 17,
|
Cosh = 17,
|
||||||
Tanh = 18,
|
Tanh = 18,
|
||||||
Asinh = 19,
|
Asinh = 19,
|
||||||
Acosh = 20,
|
Acosh = 20,
|
||||||
Atanh = 21,
|
Atanh = 21,
|
||||||
Atan2 = 22,
|
Atan2 = 22,
|
||||||
|
|
||||||
Pow = 23,
|
Pow = 23,
|
||||||
Exp = 24,
|
Exp = 24,
|
||||||
Log = 25,
|
Log = 25,
|
||||||
Exp2 = 26,
|
Exp2 = 26,
|
||||||
Log2 = 27,
|
Log2 = 27,
|
||||||
Sqrt = 28,
|
Sqrt = 28,
|
||||||
InverseSqrt = 29,
|
InverseSqrt = 29,
|
||||||
|
|
||||||
Determinant = 30,
|
Determinant = 30,
|
||||||
MatrixInverse = 31,
|
MatrixInverse = 31,
|
||||||
|
|
||||||
Modf = 32, // second argument needs the OpVariable = , not an OpLoad
|
Modf = 32, // second argument needs the OpVariable = , not an OpLoad
|
||||||
Min = 33,
|
Min = 33,
|
||||||
Max = 34,
|
Max = 34,
|
||||||
Clamp = 35,
|
Clamp = 35,
|
||||||
Mix = 36,
|
Mix = 36,
|
||||||
Step = 37,
|
Step = 37,
|
||||||
SmoothStep = 38,
|
SmoothStep = 38,
|
||||||
|
|
||||||
FloatBitsToInt = 39,
|
FloatBitsToInt = 39,
|
||||||
FloatBitsToUint = 40,
|
FloatBitsToUint = 40,
|
||||||
IntBitsToFloat = 41,
|
IntBitsToFloat = 41,
|
||||||
UintBitsToFloat = 42,
|
UintBitsToFloat = 42,
|
||||||
|
|
||||||
Fma = 43,
|
Fma = 43,
|
||||||
Frexp = 44,
|
Frexp = 44,
|
||||||
Ldexp = 45,
|
Ldexp = 45,
|
||||||
|
|
||||||
PackSnorm4x8 = 46,
|
PackSnorm4x8 = 46,
|
||||||
PackUnorm4x8 = 47,
|
PackUnorm4x8 = 47,
|
||||||
PackSnorm2x16 = 48,
|
PackSnorm2x16 = 48,
|
||||||
PackUnorm2x16 = 49,
|
PackUnorm2x16 = 49,
|
||||||
PackHalf2x16 = 50,
|
PackHalf2x16 = 50,
|
||||||
PackDouble2x32 = 51,
|
PackDouble2x32 = 51,
|
||||||
UnpackSnorm2x16 = 52,
|
UnpackSnorm2x16 = 52,
|
||||||
UnpackUnorm2x16 = 53,
|
UnpackUnorm2x16 = 53,
|
||||||
UnpackHalf2x16 = 54,
|
UnpackHalf2x16 = 54,
|
||||||
UnpackSnorm4x8 = 55,
|
UnpackSnorm4x8 = 55,
|
||||||
UnpackUnorm4x8 = 56,
|
UnpackUnorm4x8 = 56,
|
||||||
UnpackDouble2x32 = 57,
|
UnpackDouble2x32 = 57,
|
||||||
|
|
||||||
Length = 58,
|
Length = 58,
|
||||||
Distance = 59,
|
Distance = 59,
|
||||||
Cross = 60,
|
Cross = 60,
|
||||||
Normalize = 61,
|
Normalize = 61,
|
||||||
Ftransform = 62,
|
Ftransform = 62,
|
||||||
FaceForward = 63,
|
FaceForward = 63,
|
||||||
Reflect = 64,
|
Reflect = 64,
|
||||||
Refract = 65,
|
Refract = 65,
|
||||||
|
|
||||||
UaddCarry = 66,
|
UaddCarry = 66,
|
||||||
UsubBorrow = 67,
|
UsubBorrow = 67,
|
||||||
UmulExtended = 68,
|
UmulExtended = 68,
|
||||||
ImulExtended = 69,
|
ImulExtended = 69,
|
||||||
BitfieldExtract = 70,
|
BitfieldExtract = 70,
|
||||||
BitfieldInsert = 71,
|
BitfieldInsert = 71,
|
||||||
BitfieldReverse = 72,
|
BitfieldReverse = 72,
|
||||||
BitCount = 73,
|
BitCount = 73,
|
||||||
FindLSB = 74,
|
FindLSB = 74,
|
||||||
FindMSB = 75,
|
FindMSB = 75,
|
||||||
|
|
||||||
InterpolateAtCentroid = 76,
|
InterpolateAtCentroid = 76,
|
||||||
InterpolateAtSample = 77,
|
InterpolateAtSample = 77,
|
||||||
InterpolateAtOffset = 78,
|
InterpolateAtOffset = 78,
|
||||||
|
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void GetDebugNames(const char** names)
|
inline void GetDebugNames(const char** names)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Count; ++i)
|
for (int i = 0; i < Count; ++i)
|
||||||
names[i] = "Unknown";
|
names[i] = "Unknown";
|
||||||
|
|
||||||
names[Round] = "round";
|
names[Round] = "round";
|
||||||
names[RoundEven] = "roundEven";
|
names[RoundEven] = "roundEven";
|
||||||
names[Trunc] = "trunc";
|
names[Trunc] = "trunc";
|
||||||
names[Abs] = "abs";
|
names[Abs] = "abs";
|
||||||
names[Sign] = "sign";
|
names[Sign] = "sign";
|
||||||
names[Floor] = "floor";
|
names[Floor] = "floor";
|
||||||
names[Ceil] = "ceil";
|
names[Ceil] = "ceil";
|
||||||
names[Fract] = "fract";
|
names[Fract] = "fract";
|
||||||
names[Radians] = "radians";
|
names[Radians] = "radians";
|
||||||
names[Degrees] = "degrees";
|
names[Degrees] = "degrees";
|
||||||
names[Sin] = "sin";
|
names[Sin] = "sin";
|
||||||
names[Cos] = "cos";
|
names[Cos] = "cos";
|
||||||
names[Tan] = "tan";
|
names[Tan] = "tan";
|
||||||
names[Asin] = "asin";
|
names[Asin] = "asin";
|
||||||
names[Acos] = "acos";
|
names[Acos] = "acos";
|
||||||
names[Atan] = "atan";
|
names[Atan] = "atan";
|
||||||
names[Sinh] = "sinh";
|
names[Sinh] = "sinh";
|
||||||
names[Cosh] = "cosh";
|
names[Cosh] = "cosh";
|
||||||
names[Tanh] = "tanh";
|
names[Tanh] = "tanh";
|
||||||
names[Asinh] = "asinh";
|
names[Asinh] = "asinh";
|
||||||
names[Acosh] = "acosh";
|
names[Acosh] = "acosh";
|
||||||
names[Atanh] = "atanh";
|
names[Atanh] = "atanh";
|
||||||
names[Atan2] = "atan2";
|
names[Atan2] = "atan2";
|
||||||
names[Pow] = "pow";
|
names[Pow] = "pow";
|
||||||
names[Exp] = "exp";
|
names[Exp] = "exp";
|
||||||
names[Log] = "log";
|
names[Log] = "log";
|
||||||
names[Exp2] = "exp2";
|
names[Exp2] = "exp2";
|
||||||
names[Log2] = "log2";
|
names[Log2] = "log2";
|
||||||
names[Sqrt] = "sqrt";
|
names[Sqrt] = "sqrt";
|
||||||
names[InverseSqrt] = "inverseSqrt";
|
names[InverseSqrt] = "inverseSqrt";
|
||||||
names[Determinant] = "determinant";
|
names[Determinant] = "determinant";
|
||||||
names[MatrixInverse] = "matrixInverse";
|
names[MatrixInverse] = "matrixInverse";
|
||||||
names[Modf] = "modf";
|
names[Modf] = "modf";
|
||||||
names[Min] = "min";
|
names[Min] = "min";
|
||||||
names[Max] = "max";
|
names[Max] = "max";
|
||||||
names[Clamp] = "clamp";
|
names[Clamp] = "clamp";
|
||||||
names[Mix] = "mix";
|
names[Mix] = "mix";
|
||||||
names[Step] = "step";
|
names[Step] = "step";
|
||||||
names[SmoothStep] = "smoothStep";
|
names[SmoothStep] = "smoothStep";
|
||||||
names[FloatBitsToInt] = "floatBitsToInt";
|
names[FloatBitsToInt] = "floatBitsToInt";
|
||||||
names[FloatBitsToUint] = "floatBitsToUint";
|
names[FloatBitsToUint] = "floatBitsToUint";
|
||||||
names[IntBitsToFloat] = "intBitsToFloat";
|
names[IntBitsToFloat] = "intBitsToFloat";
|
||||||
names[UintBitsToFloat] = "uintBitsToFloat";
|
names[UintBitsToFloat] = "uintBitsToFloat";
|
||||||
names[Fma] = "fma";
|
names[Fma] = "fma";
|
||||||
names[Frexp] = "frexp";
|
names[Frexp] = "frexp";
|
||||||
names[Ldexp] = "ldexp";
|
names[Ldexp] = "ldexp";
|
||||||
names[PackSnorm4x8] = "packSnorm4x8";
|
names[PackSnorm4x8] = "packSnorm4x8";
|
||||||
names[PackUnorm4x8] = "packUnorm4x8";
|
names[PackUnorm4x8] = "packUnorm4x8";
|
||||||
names[PackSnorm2x16] = "packSnorm2x16";
|
names[PackSnorm2x16] = "packSnorm2x16";
|
||||||
names[PackUnorm2x16] = "packUnorm2x16";
|
names[PackUnorm2x16] = "packUnorm2x16";
|
||||||
names[PackHalf2x16] = "packHalf2x16";
|
names[PackHalf2x16] = "packHalf2x16";
|
||||||
names[PackDouble2x32] = "packDouble2x32";
|
names[PackDouble2x32] = "packDouble2x32";
|
||||||
names[UnpackSnorm2x16] = "unpackSnorm2x16";
|
names[UnpackSnorm2x16] = "unpackSnorm2x16";
|
||||||
names[UnpackUnorm2x16] = "unpackUnorm2x16";
|
names[UnpackUnorm2x16] = "unpackUnorm2x16";
|
||||||
names[UnpackHalf2x16] = "unpackHalf2x16";
|
names[UnpackHalf2x16] = "unpackHalf2x16";
|
||||||
names[UnpackSnorm4x8] = "unpackSnorm4x8";
|
names[UnpackSnorm4x8] = "unpackSnorm4x8";
|
||||||
names[UnpackUnorm4x8] = "unpackUnorm4x8";
|
names[UnpackUnorm4x8] = "unpackUnorm4x8";
|
||||||
names[UnpackDouble2x32] = "unpackDouble2x32";
|
names[UnpackDouble2x32] = "unpackDouble2x32";
|
||||||
names[Length] = "length";
|
names[Length] = "length";
|
||||||
names[Distance] = "distance";
|
names[Distance] = "distance";
|
||||||
names[Cross] = "cross";
|
names[Cross] = "cross";
|
||||||
names[Normalize] = "normalize";
|
names[Normalize] = "normalize";
|
||||||
names[Ftransform] = "ftransform";
|
names[Ftransform] = "ftransform";
|
||||||
names[FaceForward] = "faceForward";
|
names[FaceForward] = "faceForward";
|
||||||
names[Reflect] = "reflect";
|
names[Reflect] = "reflect";
|
||||||
names[Refract] = "refract";
|
names[Refract] = "refract";
|
||||||
names[UaddCarry] = "uaddCarry";
|
names[UaddCarry] = "uaddCarry";
|
||||||
names[UsubBorrow] = "usubBorrow";
|
names[UsubBorrow] = "usubBorrow";
|
||||||
names[UmulExtended] = "umulExtended";
|
names[UmulExtended] = "umulExtended";
|
||||||
names[ImulExtended] = "imulExtended";
|
names[ImulExtended] = "imulExtended";
|
||||||
names[BitfieldExtract] = "bitfieldExtract";
|
names[BitfieldExtract] = "bitfieldExtract";
|
||||||
names[BitfieldInsert] = "bitfieldInsert";
|
names[BitfieldInsert] = "bitfieldInsert";
|
||||||
names[BitfieldReverse] = "bitfieldReverse";
|
names[BitfieldReverse] = "bitfieldReverse";
|
||||||
names[BitCount] = "bitCount";
|
names[BitCount] = "bitCount";
|
||||||
names[FindLSB] = "findLSB";
|
names[FindLSB] = "findLSB";
|
||||||
names[FindMSB] = "findMSB";
|
names[FindMSB] = "findMSB";
|
||||||
names[InterpolateAtCentroid] = "interpolateAtCentroid";
|
names[InterpolateAtCentroid] = "interpolateAtCentroid";
|
||||||
names[InterpolateAtSample] = "interpolateAtSample";
|
names[InterpolateAtSample] = "interpolateAtSample";
|
||||||
names[InterpolateAtOffset] = "interpolateAtOffset";
|
names[InterpolateAtOffset] = "interpolateAtOffset";
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // end namespace GLSL_STD_450
|
}; // end namespace GLSL_STD_450
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,42 +1,42 @@
|
|||||||
//
|
//
|
||||||
//Copyright (C) 2014 LunarG, Inc.
|
//Copyright (C) 2014 LunarG, Inc.
|
||||||
//
|
//
|
||||||
//All rights reserved.
|
//All rights reserved.
|
||||||
//
|
//
|
||||||
//Redistribution and use in source and binary forms, with or without
|
//Redistribution and use in source and binary forms, with or without
|
||||||
//modification, are permitted provided that the following conditions
|
//modification, are permitted provided that the following conditions
|
||||||
//are met:
|
//are met:
|
||||||
//
|
//
|
||||||
// Redistributions of source code must retain the above copyright
|
// Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// Redistributions in binary form must reproduce the above
|
// Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following
|
// copyright notice, this list of conditions and the following
|
||||||
// disclaimer in the documentation and/or other materials provided
|
// disclaimer in the documentation and/or other materials provided
|
||||||
// with the distribution.
|
// with the distribution.
|
||||||
//
|
//
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived
|
// contributors may be used to endorse or promote products derived
|
||||||
// from this software without specific prior written permission.
|
// from this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
//POSSIBILITY OF SUCH DAMAGE.
|
//POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "../glslang/Include/intermediate.h"
|
#include "../glslang/Include/intermediate.h"
|
||||||
|
|
||||||
namespace glslang {
|
namespace glslang {
|
||||||
|
|
||||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv);
|
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv);
|
||||||
void OutputSpv(const std::vector<unsigned int>& spirv, const char* baseName);
|
void OutputSpv(const std::vector<unsigned int>& spirv, const char* baseName);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,288 +1,288 @@
|
|||||||
//
|
//
|
||||||
//Copyright (C) 2015 LunarG, Inc.
|
//Copyright (C) 2015 LunarG, Inc.
|
||||||
//
|
//
|
||||||
//All rights reserved.
|
//All rights reserved.
|
||||||
//
|
//
|
||||||
//Redistribution and use in source and binary forms, with or without
|
//Redistribution and use in source and binary forms, with or without
|
||||||
//modification, are permitted provided that the following conditions
|
//modification, are permitted provided that the following conditions
|
||||||
//are met:
|
//are met:
|
||||||
//
|
//
|
||||||
// Redistributions of source code must retain the above copyright
|
// Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// Redistributions in binary form must reproduce the above
|
// Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following
|
// copyright notice, this list of conditions and the following
|
||||||
// disclaimer in the documentation and/or other materials provided
|
// disclaimer in the documentation and/or other materials provided
|
||||||
// with the distribution.
|
// with the distribution.
|
||||||
//
|
//
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived
|
// contributors may be used to endorse or promote products derived
|
||||||
// from this software without specific prior written permission.
|
// from this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
//POSSIBILITY OF SUCH DAMAGE.
|
//POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef SPIRVREMAPPER_H
|
#ifndef SPIRVREMAPPER_H
|
||||||
#define SPIRVREMAPPER_H
|
#define SPIRVREMAPPER_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
namespace spv {
|
namespace spv {
|
||||||
|
|
||||||
// MSVC defines __cplusplus as an older value, even when it supports almost all of 11.
|
// MSVC defines __cplusplus as an older value, even when it supports almost all of 11.
|
||||||
// We handle that here by making our own symbol.
|
// We handle that here by making our own symbol.
|
||||||
#if __cplusplus >= 201103L || _MSC_VER >= 1700
|
#if __cplusplus >= 201103L || _MSC_VER >= 1700
|
||||||
# define use_cpp11 1
|
# define use_cpp11 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class spirvbin_base_t
|
class spirvbin_base_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Options {
|
enum Options {
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
STRIP = (1<<0),
|
STRIP = (1<<0),
|
||||||
MAP_TYPES = (1<<1),
|
MAP_TYPES = (1<<1),
|
||||||
MAP_NAMES = (1<<2),
|
MAP_NAMES = (1<<2),
|
||||||
MAP_FUNCS = (1<<3),
|
MAP_FUNCS = (1<<3),
|
||||||
DCE_FUNCS = (1<<4),
|
DCE_FUNCS = (1<<4),
|
||||||
DCE_VARS = (1<<5),
|
DCE_VARS = (1<<5),
|
||||||
DCE_TYPES = (1<<6),
|
DCE_TYPES = (1<<6),
|
||||||
OPT_LOADSTORE = (1<<7),
|
OPT_LOADSTORE = (1<<7),
|
||||||
OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV
|
OPT_FWD_LS = (1<<8), // EXPERIMENTAL: PRODUCES INVALID SCHEMA-0 SPIRV
|
||||||
MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS),
|
MAP_ALL = (MAP_TYPES | MAP_NAMES | MAP_FUNCS),
|
||||||
DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES),
|
DCE_ALL = (DCE_FUNCS | DCE_VARS | DCE_TYPES),
|
||||||
OPT_ALL = (OPT_LOADSTORE),
|
OPT_ALL = (OPT_LOADSTORE),
|
||||||
|
|
||||||
ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL),
|
ALL_BUT_STRIP = (MAP_ALL | DCE_ALL | OPT_ALL),
|
||||||
DO_EVERYTHING = (STRIP | ALL_BUT_STRIP)
|
DO_EVERYTHING = (STRIP | ALL_BUT_STRIP)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SPV
|
} // namespace SPV
|
||||||
|
|
||||||
#if !defined (use_cpp11)
|
#if !defined (use_cpp11)
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
namespace spv {
|
namespace spv {
|
||||||
class spirvbin_t : public spirvbin_base_t
|
class spirvbin_t : public spirvbin_base_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
spirvbin_t(int /*verbose = 0*/) { }
|
spirvbin_t(int /*verbose = 0*/) { }
|
||||||
|
|
||||||
void remap(std::vector<unsigned int>& /*spv*/, unsigned int /*opts = 0*/)
|
void remap(std::vector<unsigned int>& /*spv*/, unsigned int /*opts = 0*/)
|
||||||
{
|
{
|
||||||
printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n");
|
printf("Tool not compiled for C++11, which is required for SPIR-V remapping.\n");
|
||||||
exit(5);
|
exit(5);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SPV
|
} // namespace SPV
|
||||||
|
|
||||||
#else // defined (use_cpp11)
|
#else // defined (use_cpp11)
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "../../glslang/SPIRV/spirv.h"
|
#include "../../glslang/SPIRV/spirv.h"
|
||||||
#include "../../glslang/SPIRV/spvIR.h"
|
#include "../../glslang/SPIRV/spvIR.h"
|
||||||
|
|
||||||
namespace spv {
|
namespace spv {
|
||||||
|
|
||||||
// class to hold SPIR-V binary data for remapping, DCE, and debug stripping
|
// class to hold SPIR-V binary data for remapping, DCE, and debug stripping
|
||||||
class spirvbin_t : public spirvbin_base_t
|
class spirvbin_t : public spirvbin_base_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose) { }
|
spirvbin_t(int verbose = 0) : entryPoint(spv::NoResult), largestNewId(0), verbose(verbose) { }
|
||||||
|
|
||||||
// remap on an existing binary in memory
|
// remap on an existing binary in memory
|
||||||
void remap(std::vector<std::uint32_t>& spv, std::uint32_t opts = DO_EVERYTHING);
|
void remap(std::vector<std::uint32_t>& spv, std::uint32_t opts = DO_EVERYTHING);
|
||||||
|
|
||||||
// Type for error/log handler functions
|
// Type for error/log handler functions
|
||||||
typedef std::function<void(const std::string&)> errorfn_t;
|
typedef std::function<void(const std::string&)> errorfn_t;
|
||||||
typedef std::function<void(const std::string&)> logfn_t;
|
typedef std::function<void(const std::string&)> logfn_t;
|
||||||
|
|
||||||
// Register error/log handling functions (can be lambda fn / functor / etc)
|
// Register error/log handling functions (can be lambda fn / functor / etc)
|
||||||
static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; }
|
static void registerErrorHandler(errorfn_t handler) { errorHandler = handler; }
|
||||||
static void registerLogHandler(logfn_t handler) { logHandler = handler; }
|
static void registerLogHandler(logfn_t handler) { logHandler = handler; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// This can be overridden to provide other message behavior if needed
|
// This can be overridden to provide other message behavior if needed
|
||||||
virtual void msg(int minVerbosity, int indent, const std::string& txt) const;
|
virtual void msg(int minVerbosity, int indent, const std::string& txt) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Local to global, or global to local ID map
|
// Local to global, or global to local ID map
|
||||||
typedef std::unordered_map<spv::Id, spv::Id> idmap_t;
|
typedef std::unordered_map<spv::Id, spv::Id> idmap_t;
|
||||||
typedef std::unordered_set<spv::Id> idset_t;
|
typedef std::unordered_set<spv::Id> idset_t;
|
||||||
|
|
||||||
void remap(std::uint32_t opts = DO_EVERYTHING);
|
void remap(std::uint32_t opts = DO_EVERYTHING);
|
||||||
|
|
||||||
// Map of names to IDs
|
// Map of names to IDs
|
||||||
typedef std::unordered_map<std::string, spv::Id> namemap_t;
|
typedef std::unordered_map<std::string, spv::Id> namemap_t;
|
||||||
|
|
||||||
typedef std::uint32_t spirword_t;
|
typedef std::uint32_t spirword_t;
|
||||||
|
|
||||||
typedef std::pair<unsigned, unsigned> range_t;
|
typedef std::pair<unsigned, unsigned> range_t;
|
||||||
typedef std::function<void(spv::Id&)> idfn_t;
|
typedef std::function<void(spv::Id&)> idfn_t;
|
||||||
typedef std::function<bool(spv::Op, unsigned start)> instfn_t;
|
typedef std::function<bool(spv::Op, unsigned start)> instfn_t;
|
||||||
|
|
||||||
// Special Values for ID map:
|
// Special Values for ID map:
|
||||||
static const spv::Id unmapped; // unchanged from default value
|
static const spv::Id unmapped; // unchanged from default value
|
||||||
static const spv::Id unused; // unused ID
|
static const spv::Id unused; // unused ID
|
||||||
static const int header_size; // SPIR header = 5 words
|
static const int header_size; // SPIR header = 5 words
|
||||||
|
|
||||||
class id_iterator_t;
|
class id_iterator_t;
|
||||||
|
|
||||||
// For mapping type entries between different shaders
|
// For mapping type entries between different shaders
|
||||||
typedef std::vector<spirword_t> typeentry_t;
|
typedef std::vector<spirword_t> typeentry_t;
|
||||||
typedef std::map<spv::Id, typeentry_t> globaltypes_t;
|
typedef std::map<spv::Id, typeentry_t> globaltypes_t;
|
||||||
|
|
||||||
// A set that preserves position order, and a reverse map
|
// A set that preserves position order, and a reverse map
|
||||||
typedef std::set<int> posmap_t;
|
typedef std::set<int> posmap_t;
|
||||||
typedef std::unordered_map<spv::Id, int> posmap_rev_t;
|
typedef std::unordered_map<spv::Id, int> posmap_rev_t;
|
||||||
|
|
||||||
// handle error
|
// handle error
|
||||||
void error(const std::string& txt) const { errorHandler(txt); }
|
void error(const std::string& txt) const { errorHandler(txt); }
|
||||||
|
|
||||||
bool isConstOp(spv::Op opCode) const;
|
bool isConstOp(spv::Op opCode) const;
|
||||||
bool isTypeOp(spv::Op opCode) const;
|
bool isTypeOp(spv::Op opCode) const;
|
||||||
bool isStripOp(spv::Op opCode) const;
|
bool isStripOp(spv::Op opCode) const;
|
||||||
bool isFlowCtrlOpen(spv::Op opCode) const;
|
bool isFlowCtrlOpen(spv::Op opCode) const;
|
||||||
bool isFlowCtrlClose(spv::Op opCode) const;
|
bool isFlowCtrlClose(spv::Op opCode) const;
|
||||||
range_t literalRange(spv::Op opCode) const;
|
range_t literalRange(spv::Op opCode) const;
|
||||||
range_t typeRange(spv::Op opCode) const;
|
range_t typeRange(spv::Op opCode) const;
|
||||||
range_t constRange(spv::Op opCode) const;
|
range_t constRange(spv::Op opCode) const;
|
||||||
|
|
||||||
spv::Id& asId(unsigned word) { return spv[word]; }
|
spv::Id& asId(unsigned word) { return spv[word]; }
|
||||||
const spv::Id& asId(unsigned word) const { return spv[word]; }
|
const spv::Id& asId(unsigned word) const { return spv[word]; }
|
||||||
spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); }
|
spv::Op asOpCode(unsigned word) const { return opOpCode(spv[word]); }
|
||||||
std::uint32_t asOpCodeHash(unsigned word);
|
std::uint32_t asOpCodeHash(unsigned word);
|
||||||
spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); }
|
spv::Decoration asDecoration(unsigned word) const { return spv::Decoration(spv[word]); }
|
||||||
unsigned asWordCount(unsigned word) const { return opWordCount(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)); }
|
spv::Id asTypeConstId(unsigned word) const { return asId(word + (isTypeOp(asOpCode(word)) ? 1 : 2)); }
|
||||||
unsigned typePos(spv::Id id) const;
|
unsigned typePos(spv::Id id) const;
|
||||||
|
|
||||||
static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; }
|
static unsigned opWordCount(spirword_t data) { return data >> spv::WordCountShift; }
|
||||||
static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); }
|
static spv::Op opOpCode(spirword_t data) { return spv::Op(data & spv::OpCodeMask); }
|
||||||
|
|
||||||
// Header access & set methods
|
// Header access & set methods
|
||||||
spirword_t magic() const { return spv[0]; } // return magic number
|
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() const { return spv[3]; } // return Id bound from header
|
||||||
spirword_t bound(spirword_t b) { return spv[3] = b; };
|
spirword_t bound(spirword_t b) { return spv[3] = b; };
|
||||||
spirword_t genmagic() const { return spv[2]; } // generator magic
|
spirword_t genmagic() const { return spv[2]; } // generator magic
|
||||||
spirword_t genmagic(spirword_t m) { return spv[2] = m; }
|
spirword_t genmagic(spirword_t m) { return spv[2] = m; }
|
||||||
spirword_t schemaNum() const { return spv[4]; } // schema number from header
|
spirword_t schemaNum() const { return spv[4]; } // schema number from header
|
||||||
|
|
||||||
// Mapping fns: get
|
// Mapping fns: get
|
||||||
spv::Id localId(spv::Id id) const { return idMapL[id]; }
|
spv::Id localId(spv::Id id) const { return idMapL[id]; }
|
||||||
|
|
||||||
// Mapping fns: set
|
// Mapping fns: set
|
||||||
inline spv::Id localId(spv::Id id, spv::Id newId);
|
inline spv::Id localId(spv::Id id, spv::Id newId);
|
||||||
void countIds(spv::Id id);
|
void countIds(spv::Id id);
|
||||||
|
|
||||||
// Return next unused new local ID.
|
// Return next unused new local ID.
|
||||||
// NOTE: boost::dynamic_bitset would be more efficient due to find_next(),
|
// NOTE: boost::dynamic_bitset would be more efficient due to find_next(),
|
||||||
// which std::vector<bool> doens't have.
|
// which std::vector<bool> doens't have.
|
||||||
inline spv::Id nextUnusedId(spv::Id id);
|
inline spv::Id nextUnusedId(spv::Id id);
|
||||||
|
|
||||||
void buildLocalMaps();
|
void buildLocalMaps();
|
||||||
std::string literalString(unsigned word) const; // Return literal as a std::string
|
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; }
|
int literalStringWords(const std::string& str) const { return (int(str.size())+4)/4; }
|
||||||
|
|
||||||
bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); }
|
bool isNewIdMapped(spv::Id newId) const { return isMapped(newId); }
|
||||||
bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; }
|
bool isOldIdUnmapped(spv::Id oldId) const { return localId(oldId) == unmapped; }
|
||||||
bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; }
|
bool isOldIdUnused(spv::Id oldId) const { return localId(oldId) == unused; }
|
||||||
bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); }
|
bool isOldIdMapped(spv::Id oldId) const { return !isOldIdUnused(oldId) && !isOldIdUnmapped(oldId); }
|
||||||
bool isFunction(spv::Id oldId) const { return fnPos.find(oldId) != fnPos.end(); }
|
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;
|
// bool matchType(const globaltypes_t& globalTypes, spv::Id lt, spv::Id gt) const;
|
||||||
// spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const;
|
// spv::Id findType(const globaltypes_t& globalTypes, spv::Id lt) const;
|
||||||
std::uint32_t hashType(unsigned typeStart) const;
|
std::uint32_t hashType(unsigned typeStart) const;
|
||||||
|
|
||||||
spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0);
|
spirvbin_t& process(instfn_t, idfn_t, unsigned begin = 0, unsigned end = 0);
|
||||||
int processInstruction(unsigned word, instfn_t, idfn_t);
|
int processInstruction(unsigned word, instfn_t, idfn_t);
|
||||||
|
|
||||||
void validate() const;
|
void validate() const;
|
||||||
void mapTypeConst();
|
void mapTypeConst();
|
||||||
void mapFnBodies();
|
void mapFnBodies();
|
||||||
void optLoadStore();
|
void optLoadStore();
|
||||||
void dceFuncs();
|
void dceFuncs();
|
||||||
void dceVars();
|
void dceVars();
|
||||||
void dceTypes();
|
void dceTypes();
|
||||||
void mapNames();
|
void mapNames();
|
||||||
void foldIds(); // fold IDs to smallest space
|
void foldIds(); // fold IDs to smallest space
|
||||||
void forwardLoadStores(); // load store forwarding (EXPERIMENTAL)
|
void forwardLoadStores(); // load store forwarding (EXPERIMENTAL)
|
||||||
void offsetIds(); // create relative offset IDs
|
void offsetIds(); // create relative offset IDs
|
||||||
|
|
||||||
void applyMap(); // remap per local name map
|
void applyMap(); // remap per local name map
|
||||||
void mapRemainder(); // map any IDs we haven't touched yet
|
void mapRemainder(); // map any IDs we haven't touched yet
|
||||||
void stripDebug(); // strip debug info
|
void stripDebug(); // strip debug info
|
||||||
void strip(); // remove debug symbols
|
void strip(); // remove debug symbols
|
||||||
|
|
||||||
std::vector<spirword_t> spv; // SPIR words
|
std::vector<spirword_t> spv; // SPIR words
|
||||||
|
|
||||||
namemap_t nameMap; // ID names from OpName
|
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
|
// 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.
|
// boost::dynamic_bitset, but we're trying to avoid a boost dependency.
|
||||||
typedef std::uint64_t bits_t;
|
typedef std::uint64_t bits_t;
|
||||||
std::vector<bits_t> mapped; // which new IDs have been mapped
|
std::vector<bits_t> mapped; // which new IDs have been mapped
|
||||||
static const int mBits = sizeof(bits_t) * 4;
|
static const int mBits = sizeof(bits_t) * 4;
|
||||||
|
|
||||||
bool isMapped(spv::Id id) const { return id < maxMappedId() && ((mapped[id/mBits] & (1LL<<(id%mBits))) != 0); }
|
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 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); }
|
void resizeMapped(spv::Id id) { if (id >= maxMappedId()) mapped.resize(id/mBits+1, 0); }
|
||||||
size_t maxMappedId() const { return mapped.size() * mBits; }
|
size_t maxMappedId() const { return mapped.size() * mBits; }
|
||||||
|
|
||||||
// Add a strip range for a given instruction starting at 'start'
|
// Add a strip range for a given instruction starting at 'start'
|
||||||
// Note: avoiding brace initializers to please older versions os MSVC.
|
// Note: avoiding brace initializers to please older versions os MSVC.
|
||||||
void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); }
|
void stripInst(unsigned start) { stripRange.push_back(range_t(start, start + asWordCount(start))); }
|
||||||
|
|
||||||
// Function start and end. use unordered_map because we'll have
|
// Function start and end. use unordered_map because we'll have
|
||||||
// many fewer functions than IDs.
|
// many fewer functions than IDs.
|
||||||
std::unordered_map<spv::Id, range_t> fnPos;
|
std::unordered_map<spv::Id, range_t> fnPos;
|
||||||
std::unordered_map<spv::Id, range_t> fnPosDCE; // deleted functions
|
std::unordered_map<spv::Id, range_t> fnPosDCE; // deleted functions
|
||||||
|
|
||||||
// Which functions are called, anywhere in the module, with a call count
|
// Which functions are called, anywhere in the module, with a call count
|
||||||
std::unordered_map<spv::Id, int> fnCalls;
|
std::unordered_map<spv::Id, int> fnCalls;
|
||||||
|
|
||||||
posmap_t typeConstPos; // word positions that define types & consts (ordered)
|
posmap_t typeConstPos; // word positions that define types & consts (ordered)
|
||||||
posmap_rev_t typeConstPosR; // reverse map from IDs to positions
|
posmap_rev_t typeConstPosR; // reverse map from IDs to positions
|
||||||
|
|
||||||
std::vector<spv::Id> idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs
|
std::vector<spv::Id> idMapL; // ID {M}ap from {L}ocal to {G}lobal IDs
|
||||||
|
|
||||||
spv::Id entryPoint; // module entry point
|
spv::Id entryPoint; // module entry point
|
||||||
spv::Id largestNewId; // biggest new ID we have mapped anything to
|
spv::Id largestNewId; // biggest new ID we have mapped anything to
|
||||||
|
|
||||||
// Sections of the binary to strip, given as [begin,end)
|
// Sections of the binary to strip, given as [begin,end)
|
||||||
std::vector<range_t> stripRange;
|
std::vector<range_t> stripRange;
|
||||||
|
|
||||||
// processing options:
|
// processing options:
|
||||||
std::uint32_t options;
|
std::uint32_t options;
|
||||||
int verbose; // verbosity level
|
int verbose; // verbosity level
|
||||||
|
|
||||||
static errorfn_t errorHandler;
|
static errorfn_t errorHandler;
|
||||||
static logfn_t logHandler;
|
static logfn_t logHandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SPV
|
} // namespace SPV
|
||||||
|
|
||||||
#endif // defined (use_cpp11)
|
#endif // defined (use_cpp11)
|
||||||
#endif // SPIRVREMAPPER_H
|
#endif // SPIRVREMAPPER_H
|
||||||
|
|||||||
4274
SPIRV/SpvBuilder.cpp
4274
SPIRV/SpvBuilder.cpp
File diff suppressed because it is too large
Load Diff
1126
SPIRV/SpvBuilder.h
1126
SPIRV/SpvBuilder.h
File diff suppressed because it is too large
Load Diff
@ -1,435 +1,435 @@
|
|||||||
//
|
//
|
||||||
//Copyright (C) 2014 LunarG, Inc.
|
//Copyright (C) 2014 LunarG, Inc.
|
||||||
//
|
//
|
||||||
//All rights reserved.
|
//All rights reserved.
|
||||||
//
|
//
|
||||||
//Redistribution and use in source and binary forms, with or without
|
//Redistribution and use in source and binary forms, with or without
|
||||||
//modification, are permitted provided that the following conditions
|
//modification, are permitted provided that the following conditions
|
||||||
//are met:
|
//are met:
|
||||||
//
|
//
|
||||||
// Redistributions of source code must retain the above copyright
|
// Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// Redistributions in binary form must reproduce the above
|
// Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following
|
// copyright notice, this list of conditions and the following
|
||||||
// disclaimer in the documentation and/or other materials provided
|
// disclaimer in the documentation and/or other materials provided
|
||||||
// with the distribution.
|
// with the distribution.
|
||||||
//
|
//
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived
|
// contributors may be used to endorse or promote products derived
|
||||||
// from this software without specific prior written permission.
|
// from this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTAstreamITY AND FITNESS
|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTAstreamITY AND FITNESS
|
||||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
//CAUSED AND ON ANY THEORY OF LIAstreamITY, WHETHER IN CONTRACT, STRICT
|
//CAUSED AND ON ANY THEORY OF LIAstreamITY, WHETHER IN CONTRACT, STRICT
|
||||||
//LIAstreamITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
//LIAstreamITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
//POSSIstreamITY OF SUCH DAMAGE.
|
//POSSIstreamITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
//
|
//
|
||||||
// Author: John Kessenich, LunarG
|
// Author: John Kessenich, LunarG
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// Disassembler for SPIR-V.
|
// Disassembler for SPIR-V.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "GLSL450Lib.h"
|
#include "GLSL450Lib.h"
|
||||||
extern const char* GlslStd450DebugNames[GLSL_STD_450::Count];
|
extern const char* GlslStd450DebugNames[GLSL_STD_450::Count];
|
||||||
|
|
||||||
#include "disassemble.h"
|
#include "disassemble.h"
|
||||||
#include "doc.h"
|
#include "doc.h"
|
||||||
|
|
||||||
namespace spv {
|
namespace spv {
|
||||||
|
|
||||||
void Kill(std::ostream& out, const char* message)
|
void Kill(std::ostream& out, const char* message)
|
||||||
{
|
{
|
||||||
out << std::endl << "Disassembly failed: " << message << std::endl;
|
out << std::endl << "Disassembly failed: " << message << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container class for a single instance of a SPIR-V stream, with methods for disassembly.
|
// Container class for a single instance of a SPIR-V stream, with methods for disassembly.
|
||||||
class SpirvStream {
|
class SpirvStream {
|
||||||
public:
|
public:
|
||||||
SpirvStream(std::ostream& out, const std::vector<unsigned int>& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { }
|
SpirvStream(std::ostream& out, const std::vector<unsigned int>& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { }
|
||||||
virtual ~SpirvStream() { }
|
virtual ~SpirvStream() { }
|
||||||
|
|
||||||
void validate();
|
void validate();
|
||||||
void processInstructions();
|
void processInstructions();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SpirvStream(SpirvStream&);
|
SpirvStream(SpirvStream&);
|
||||||
SpirvStream& operator=(SpirvStream&);
|
SpirvStream& operator=(SpirvStream&);
|
||||||
|
|
||||||
Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; }
|
Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; }
|
||||||
|
|
||||||
// Output methods
|
// Output methods
|
||||||
void outputIndent();
|
void outputIndent();
|
||||||
void formatId(Id id, std::stringstream&);
|
void formatId(Id id, std::stringstream&);
|
||||||
void outputResultId(Id id);
|
void outputResultId(Id id);
|
||||||
void outputTypeId(Id id);
|
void outputTypeId(Id id);
|
||||||
void outputId(Id id);
|
void outputId(Id id);
|
||||||
void disassembleImmediates(int numOperands);
|
void disassembleImmediates(int numOperands);
|
||||||
void disassembleIds(int numOperands);
|
void disassembleIds(int numOperands);
|
||||||
void disassembleString();
|
void disassembleString();
|
||||||
void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
|
void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
std::ostream& out; // where to write the disassembly
|
std::ostream& out; // where to write the disassembly
|
||||||
const std::vector<unsigned int>& stream; // the actual word stream
|
const std::vector<unsigned int>& stream; // the actual word stream
|
||||||
int size; // the size of the word stream
|
int size; // the size of the word stream
|
||||||
int word; // the next word of the stream to read
|
int word; // the next word of the stream to read
|
||||||
|
|
||||||
// map each <id> to the instruction that created it
|
// map each <id> to the instruction that created it
|
||||||
Id bound;
|
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<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>
|
std::vector<std::string> idDescriptor; // the best text string known for explaining the <id>
|
||||||
|
|
||||||
// schema
|
// schema
|
||||||
unsigned int schema;
|
unsigned int schema;
|
||||||
|
|
||||||
// stack of structured-merge points
|
// stack of structured-merge points
|
||||||
std::stack<Id> nestedControl;
|
std::stack<Id> nestedControl;
|
||||||
Id nextNestedControl; // need a slight delay for when we are nested
|
Id nextNestedControl; // need a slight delay for when we are nested
|
||||||
};
|
};
|
||||||
|
|
||||||
void SpirvStream::validate()
|
void SpirvStream::validate()
|
||||||
{
|
{
|
||||||
size = (int)stream.size();
|
size = (int)stream.size();
|
||||||
if (size < 4)
|
if (size < 4)
|
||||||
Kill(out, "stream is too short");
|
Kill(out, "stream is too short");
|
||||||
|
|
||||||
// Magic number
|
// Magic number
|
||||||
if (stream[word++] != MagicNumber) {
|
if (stream[word++] != MagicNumber) {
|
||||||
out << "Bad magic number";
|
out << "Bad magic number";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
out << "// Module Version " << stream[word++] << std::endl;
|
out << "// Module Version " << stream[word++] << std::endl;
|
||||||
|
|
||||||
// Generator's magic number
|
// Generator's magic number
|
||||||
out << "// Generated by (magic number): " << std::setbase(16) << stream[word++] << std::setbase(10) << std::endl;
|
out << "// Generated by (magic number): " << std::setbase(16) << stream[word++] << std::setbase(10) << std::endl;
|
||||||
|
|
||||||
// Result <id> bound
|
// Result <id> bound
|
||||||
bound = stream[word++];
|
bound = stream[word++];
|
||||||
idInstruction.resize(bound);
|
idInstruction.resize(bound);
|
||||||
idDescriptor.resize(bound);
|
idDescriptor.resize(bound);
|
||||||
out << "// Id's are bound by " << bound << std::endl;
|
out << "// Id's are bound by " << bound << std::endl;
|
||||||
out << std::endl;
|
out << std::endl;
|
||||||
|
|
||||||
// Reserved schema, must be 0 for now
|
// Reserved schema, must be 0 for now
|
||||||
schema = stream[word++];
|
schema = stream[word++];
|
||||||
if (schema != 0)
|
if (schema != 0)
|
||||||
Kill(out, "bad schema, must be 0");
|
Kill(out, "bad schema, must be 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop over all the instructions, in order, processing each.
|
// Loop over all the instructions, in order, processing each.
|
||||||
// Boiler plate for each is handled here directly, the rest is dispatched.
|
// Boiler plate for each is handled here directly, the rest is dispatched.
|
||||||
void SpirvStream::processInstructions()
|
void SpirvStream::processInstructions()
|
||||||
{
|
{
|
||||||
// Instructions
|
// Instructions
|
||||||
while (word < size) {
|
while (word < size) {
|
||||||
int instructionStart = word;
|
int instructionStart = word;
|
||||||
|
|
||||||
// Instruction wordCount and opcode
|
// Instruction wordCount and opcode
|
||||||
unsigned int firstWord = stream[word];
|
unsigned int firstWord = stream[word];
|
||||||
unsigned wordCount = firstWord >> WordCountShift;
|
unsigned wordCount = firstWord >> WordCountShift;
|
||||||
Op opCode = (Op)(firstWord & OpCodeMask);
|
Op opCode = (Op)(firstWord & OpCodeMask);
|
||||||
int nextInst = word + wordCount;
|
int nextInst = word + wordCount;
|
||||||
++word;
|
++word;
|
||||||
|
|
||||||
// Presence of full instruction
|
// Presence of full instruction
|
||||||
if (nextInst > size)
|
if (nextInst > size)
|
||||||
Kill(out, "stream instruction terminated too early");
|
Kill(out, "stream instruction terminated too early");
|
||||||
|
|
||||||
// Base for computing number of operands; will be updated as more is learned
|
// Base for computing number of operands; will be updated as more is learned
|
||||||
unsigned numOperands = wordCount - 1;
|
unsigned numOperands = wordCount - 1;
|
||||||
|
|
||||||
// Type <id>
|
// Type <id>
|
||||||
Id typeId = 0;
|
Id typeId = 0;
|
||||||
if (InstructionDesc[opCode].hasType()) {
|
if (InstructionDesc[opCode].hasType()) {
|
||||||
typeId = stream[word++];
|
typeId = stream[word++];
|
||||||
--numOperands;
|
--numOperands;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result <id>
|
// Result <id>
|
||||||
Id resultId = 0;
|
Id resultId = 0;
|
||||||
if (InstructionDesc[opCode].hasResult()) {
|
if (InstructionDesc[opCode].hasResult()) {
|
||||||
resultId = stream[word++];
|
resultId = stream[word++];
|
||||||
--numOperands;
|
--numOperands;
|
||||||
|
|
||||||
// save instruction for future reference
|
// save instruction for future reference
|
||||||
idInstruction[resultId] = instructionStart;
|
idInstruction[resultId] = instructionStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
outputResultId(resultId);
|
outputResultId(resultId);
|
||||||
outputTypeId(typeId);
|
outputTypeId(typeId);
|
||||||
outputIndent();
|
outputIndent();
|
||||||
|
|
||||||
// Hand off the Op and all its operands
|
// Hand off the Op and all its operands
|
||||||
disassembleInstruction(resultId, typeId, opCode, numOperands);
|
disassembleInstruction(resultId, typeId, opCode, numOperands);
|
||||||
if (word != nextInst) {
|
if (word != nextInst) {
|
||||||
out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;
|
out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;
|
||||||
word = nextInst;
|
word = nextInst;
|
||||||
}
|
}
|
||||||
out << std::endl;
|
out << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvStream::outputIndent()
|
void SpirvStream::outputIndent()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (int)nestedControl.size(); ++i)
|
for (int i = 0; i < (int)nestedControl.size(); ++i)
|
||||||
out << " ";
|
out << " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvStream::formatId(Id id, std::stringstream& idStream)
|
void SpirvStream::formatId(Id id, std::stringstream& idStream)
|
||||||
{
|
{
|
||||||
if (id >= bound)
|
if (id >= bound)
|
||||||
Kill(out, "Bad <id>");
|
Kill(out, "Bad <id>");
|
||||||
|
|
||||||
if (id != 0) {
|
if (id != 0) {
|
||||||
idStream << id;
|
idStream << id;
|
||||||
if (idDescriptor[id].size() > 0)
|
if (idDescriptor[id].size() > 0)
|
||||||
idStream << "(" << idDescriptor[id] << ")";
|
idStream << "(" << idDescriptor[id] << ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvStream::outputResultId(Id id)
|
void SpirvStream::outputResultId(Id id)
|
||||||
{
|
{
|
||||||
const int width = 16;
|
const int width = 16;
|
||||||
std::stringstream idStream;
|
std::stringstream idStream;
|
||||||
formatId(id, idStream);
|
formatId(id, idStream);
|
||||||
out << std::setw(width) << std::right << idStream.str();
|
out << std::setw(width) << std::right << idStream.str();
|
||||||
if (id != 0)
|
if (id != 0)
|
||||||
out << ":";
|
out << ":";
|
||||||
else
|
else
|
||||||
out << " ";
|
out << " ";
|
||||||
|
|
||||||
if (nestedControl.size() && id == nestedControl.top())
|
if (nestedControl.size() && id == nestedControl.top())
|
||||||
nestedControl.pop();
|
nestedControl.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvStream::outputTypeId(Id id)
|
void SpirvStream::outputTypeId(Id id)
|
||||||
{
|
{
|
||||||
const int width = 12;
|
const int width = 12;
|
||||||
std::stringstream idStream;
|
std::stringstream idStream;
|
||||||
formatId(id, idStream);
|
formatId(id, idStream);
|
||||||
out << std::setw(width) << std::right << idStream.str() << " ";
|
out << std::setw(width) << std::right << idStream.str() << " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvStream::outputId(Id id)
|
void SpirvStream::outputId(Id id)
|
||||||
{
|
{
|
||||||
if (id >= bound)
|
if (id >= bound)
|
||||||
Kill(out, "Bad <id>");
|
Kill(out, "Bad <id>");
|
||||||
|
|
||||||
out << id;
|
out << id;
|
||||||
if (idDescriptor[id].size() > 0)
|
if (idDescriptor[id].size() > 0)
|
||||||
out << "(" << idDescriptor[id] << ")";
|
out << "(" << idDescriptor[id] << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvStream::disassembleImmediates(int numOperands)
|
void SpirvStream::disassembleImmediates(int numOperands)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < numOperands; ++i) {
|
for (int i = 0; i < numOperands; ++i) {
|
||||||
out << stream[word++];
|
out << stream[word++];
|
||||||
if (i < numOperands - 1)
|
if (i < numOperands - 1)
|
||||||
out << " ";
|
out << " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvStream::disassembleIds(int numOperands)
|
void SpirvStream::disassembleIds(int numOperands)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < numOperands; ++i) {
|
for (int i = 0; i < numOperands; ++i) {
|
||||||
outputId(stream[word++]);
|
outputId(stream[word++]);
|
||||||
if (i < numOperands - 1)
|
if (i < numOperands - 1)
|
||||||
out << " ";
|
out << " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvStream::disassembleString()
|
void SpirvStream::disassembleString()
|
||||||
{
|
{
|
||||||
out << " \"";
|
out << " \"";
|
||||||
|
|
||||||
char* wordString;
|
char* wordString;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
do {
|
do {
|
||||||
unsigned int content = stream[word];
|
unsigned int content = stream[word];
|
||||||
wordString = (char*)&content;
|
wordString = (char*)&content;
|
||||||
for (int charCount = 0; charCount < 4; ++charCount) {
|
for (int charCount = 0; charCount < 4; ++charCount) {
|
||||||
if (*wordString == 0) {
|
if (*wordString == 0) {
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
out << *(wordString++);
|
out << *(wordString++);
|
||||||
}
|
}
|
||||||
++word;
|
++word;
|
||||||
} while (! done);
|
} while (! done);
|
||||||
|
|
||||||
out << "\"";
|
out << "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
|
void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
|
||||||
{
|
{
|
||||||
// Process the opcode
|
// Process the opcode
|
||||||
|
|
||||||
out << (OpcodeString(opCode) + 2); // leave out the "Op"
|
out << (OpcodeString(opCode) + 2); // leave out the "Op"
|
||||||
|
|
||||||
if (opCode == OpLoopMerge || opCode == OpSelectionMerge)
|
if (opCode == OpLoopMerge || opCode == OpSelectionMerge)
|
||||||
nextNestedControl = stream[word];
|
nextNestedControl = stream[word];
|
||||||
else if (opCode == OpBranchConditional || opCode == OpSwitch) {
|
else if (opCode == OpBranchConditional || opCode == OpSwitch) {
|
||||||
if (nextNestedControl) {
|
if (nextNestedControl) {
|
||||||
nestedControl.push(nextNestedControl);
|
nestedControl.push(nextNestedControl);
|
||||||
nextNestedControl = 0;
|
nextNestedControl = 0;
|
||||||
}
|
}
|
||||||
} else if (opCode == OpExtInstImport)
|
} else if (opCode == OpExtInstImport)
|
||||||
idDescriptor[resultId] = (char*)(&stream[word]);
|
idDescriptor[resultId] = (char*)(&stream[word]);
|
||||||
else {
|
else {
|
||||||
if (idDescriptor[resultId].size() == 0) {
|
if (idDescriptor[resultId].size() == 0) {
|
||||||
switch (opCode) {
|
switch (opCode) {
|
||||||
case OpTypeInt:
|
case OpTypeInt:
|
||||||
idDescriptor[resultId] = "int";
|
idDescriptor[resultId] = "int";
|
||||||
break;
|
break;
|
||||||
case OpTypeFloat:
|
case OpTypeFloat:
|
||||||
idDescriptor[resultId] = "float";
|
idDescriptor[resultId] = "float";
|
||||||
break;
|
break;
|
||||||
case OpTypeBool:
|
case OpTypeBool:
|
||||||
idDescriptor[resultId] = "bool";
|
idDescriptor[resultId] = "bool";
|
||||||
break;
|
break;
|
||||||
case OpTypeStruct:
|
case OpTypeStruct:
|
||||||
idDescriptor[resultId] = "struct";
|
idDescriptor[resultId] = "struct";
|
||||||
break;
|
break;
|
||||||
case OpTypePointer:
|
case OpTypePointer:
|
||||||
idDescriptor[resultId] = "ptr";
|
idDescriptor[resultId] = "ptr";
|
||||||
break;
|
break;
|
||||||
case OpTypeVector:
|
case OpTypeVector:
|
||||||
if (idDescriptor[stream[word]].size() > 0)
|
if (idDescriptor[stream[word]].size() > 0)
|
||||||
idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1);
|
idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1);
|
||||||
idDescriptor[resultId].append("vec");
|
idDescriptor[resultId].append("vec");
|
||||||
switch (stream[word + 1]) {
|
switch (stream[word + 1]) {
|
||||||
case 2: idDescriptor[resultId].append("2"); break;
|
case 2: idDescriptor[resultId].append("2"); break;
|
||||||
case 3: idDescriptor[resultId].append("3"); break;
|
case 3: idDescriptor[resultId].append("3"); break;
|
||||||
case 4: idDescriptor[resultId].append("4"); break;
|
case 4: idDescriptor[resultId].append("4"); break;
|
||||||
case 8: idDescriptor[resultId].append("8"); break;
|
case 8: idDescriptor[resultId].append("8"); break;
|
||||||
case 16: idDescriptor[resultId].append("16"); break;
|
case 16: idDescriptor[resultId].append("16"); break;
|
||||||
case 32: idDescriptor[resultId].append("32"); break;
|
case 32: idDescriptor[resultId].append("32"); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the operands. Note, a new context-dependent set could be
|
// Process the operands. Note, a new context-dependent set could be
|
||||||
// swapped in mid-traversal.
|
// swapped in mid-traversal.
|
||||||
|
|
||||||
// Handle textures specially, so can put out helpful strings.
|
// Handle textures specially, so can put out helpful strings.
|
||||||
if (opCode == OpTypeSampler) {
|
if (opCode == OpTypeSampler) {
|
||||||
disassembleIds(1);
|
disassembleIds(1);
|
||||||
out << " " << DimensionString((Dim)stream[word++]);
|
out << " " << DimensionString((Dim)stream[word++]);
|
||||||
switch (stream[word++]) {
|
switch (stream[word++]) {
|
||||||
case 0: out << " texture"; break;
|
case 0: out << " texture"; break;
|
||||||
case 1: out << " image"; break;
|
case 1: out << " image"; break;
|
||||||
case 2: out << " filter+texture"; break;
|
case 2: out << " filter+texture"; break;
|
||||||
}
|
}
|
||||||
out << (stream[word++] != 0 ? " array" : "");
|
out << (stream[word++] != 0 ? " array" : "");
|
||||||
out << (stream[word++] != 0 ? " depth" : "");
|
out << (stream[word++] != 0 ? " depth" : "");
|
||||||
out << (stream[word++] != 0 ? " multi-sampled" : "");
|
out << (stream[word++] != 0 ? " multi-sampled" : "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle all the parameterized operands
|
// Handle all the parameterized operands
|
||||||
for (int op = 0; op < InstructionDesc[opCode].operands.getNum(); ++op) {
|
for (int op = 0; op < InstructionDesc[opCode].operands.getNum(); ++op) {
|
||||||
out << " ";
|
out << " ";
|
||||||
OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op);
|
OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op);
|
||||||
switch (operandClass) {
|
switch (operandClass) {
|
||||||
case OperandId:
|
case OperandId:
|
||||||
disassembleIds(1);
|
disassembleIds(1);
|
||||||
// Get names for printing "(XXX)" for readability, *after* this id
|
// Get names for printing "(XXX)" for readability, *after* this id
|
||||||
if (opCode == OpName)
|
if (opCode == OpName)
|
||||||
idDescriptor[stream[word - 1]] = (char*)(&stream[word]);
|
idDescriptor[stream[word - 1]] = (char*)(&stream[word]);
|
||||||
break;
|
break;
|
||||||
case OperandOptionalId:
|
case OperandOptionalId:
|
||||||
case OperandVariableIds:
|
case OperandVariableIds:
|
||||||
disassembleIds(numOperands);
|
disassembleIds(numOperands);
|
||||||
return;
|
return;
|
||||||
case OperandVariableLiterals:
|
case OperandVariableLiterals:
|
||||||
if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) ||
|
if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) ||
|
||||||
(opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) {
|
(opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) {
|
||||||
out << BuiltInString(stream[word++]);
|
out << BuiltInString(stream[word++]);
|
||||||
--numOperands;
|
--numOperands;
|
||||||
++op;
|
++op;
|
||||||
}
|
}
|
||||||
disassembleImmediates(numOperands);
|
disassembleImmediates(numOperands);
|
||||||
return;
|
return;
|
||||||
case OperandVariableLiteralId:
|
case OperandVariableLiteralId:
|
||||||
while (numOperands > 0) {
|
while (numOperands > 0) {
|
||||||
out << std::endl;
|
out << std::endl;
|
||||||
outputResultId(0);
|
outputResultId(0);
|
||||||
outputTypeId(0);
|
outputTypeId(0);
|
||||||
outputIndent();
|
outputIndent();
|
||||||
out << " case ";
|
out << " case ";
|
||||||
disassembleImmediates(1);
|
disassembleImmediates(1);
|
||||||
out << ": ";
|
out << ": ";
|
||||||
disassembleIds(1);
|
disassembleIds(1);
|
||||||
numOperands -= 2;
|
numOperands -= 2;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case OperandLiteralNumber:
|
case OperandLiteralNumber:
|
||||||
disassembleImmediates(1);
|
disassembleImmediates(1);
|
||||||
if (opCode == OpExtInst) {
|
if (opCode == OpExtInst) {
|
||||||
unsigned entrypoint = stream[word - 1];
|
unsigned entrypoint = stream[word - 1];
|
||||||
if (entrypoint < GLSL_STD_450::Count)
|
if (entrypoint < GLSL_STD_450::Count)
|
||||||
out << "(" << GlslStd450DebugNames[entrypoint] << ")";
|
out << "(" << GlslStd450DebugNames[entrypoint] << ")";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OperandLiteralString:
|
case OperandLiteralString:
|
||||||
disassembleString();
|
disassembleString();
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
assert(operandClass >= OperandSource && operandClass < OperandOpcode);
|
assert(operandClass >= OperandSource && operandClass < OperandOpcode);
|
||||||
|
|
||||||
if (OperandClassParams[operandClass].bitmask) {
|
if (OperandClassParams[operandClass].bitmask) {
|
||||||
unsigned int mask = stream[word++];
|
unsigned int mask = stream[word++];
|
||||||
if (mask == 0)
|
if (mask == 0)
|
||||||
out << "None";
|
out << "None";
|
||||||
else {
|
else {
|
||||||
for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {
|
for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {
|
||||||
if (mask & (1 << m))
|
if (mask & (1 << m))
|
||||||
out << OperandClassParams[operandClass].getName(m) << " ";
|
out << OperandClassParams[operandClass].getName(m) << " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
out << OperandClassParams[operandClass].getName(stream[word++]);
|
out << OperandClassParams[operandClass].getName(stream[word++]);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
--numOperands;
|
--numOperands;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
|
void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
|
||||||
{
|
{
|
||||||
SpirvStream SpirvStream(out, stream);
|
SpirvStream SpirvStream(out, stream);
|
||||||
SpirvStream.validate();
|
SpirvStream.validate();
|
||||||
SpirvStream.processInstructions();
|
SpirvStream.processInstructions();
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // end namespace spv
|
}; // end namespace spv
|
||||||
|
|||||||
@ -1,56 +1,56 @@
|
|||||||
//
|
//
|
||||||
//Copyright (C) 2014 LunarG, Inc.
|
//Copyright (C) 2014 LunarG, Inc.
|
||||||
//
|
//
|
||||||
//All rights reserved.
|
//All rights reserved.
|
||||||
//
|
//
|
||||||
//Redistribution and use in source and binary forms, with or without
|
//Redistribution and use in source and binary forms, with or without
|
||||||
//modification, are permitted provided that the following conditions
|
//modification, are permitted provided that the following conditions
|
||||||
//are met:
|
//are met:
|
||||||
//
|
//
|
||||||
// Redistributions of source code must retain the above copyright
|
// Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// Redistributions in binary form must reproduce the above
|
// Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following
|
// copyright notice, this list of conditions and the following
|
||||||
// disclaimer in the documentation and/or other materials provided
|
// disclaimer in the documentation and/or other materials provided
|
||||||
// with the distribution.
|
// with the distribution.
|
||||||
//
|
//
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived
|
// contributors may be used to endorse or promote products derived
|
||||||
// from this software without specific prior written permission.
|
// from this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
//POSSIBILITY OF SUCH DAMAGE.
|
//POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
//
|
//
|
||||||
// Author: John Kessenich, LunarG
|
// Author: John Kessenich, LunarG
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// Disassembler for SPIR-V.
|
// Disassembler for SPIR-V.
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#ifndef disassembler_H
|
#ifndef disassembler_H
|
||||||
#define disassembler_H
|
#define disassembler_H
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace spv {
|
namespace spv {
|
||||||
|
|
||||||
void Disassemble(std::ostream& out, const std::vector<unsigned int>&);
|
void Disassemble(std::ostream& out, const std::vector<unsigned int>&);
|
||||||
|
|
||||||
}; // end namespace spv
|
}; // end namespace spv
|
||||||
|
|
||||||
#endif // disassembler_H
|
#endif // disassembler_H
|
||||||
|
|||||||
4254
SPIRV/doc.cpp
4254
SPIRV/doc.cpp
File diff suppressed because it is too large
Load Diff
512
SPIRV/doc.h
512
SPIRV/doc.h
@ -1,256 +1,256 @@
|
|||||||
//
|
//
|
||||||
//Copyright (C) 2014 LunarG, Inc.
|
//Copyright (C) 2014 LunarG, Inc.
|
||||||
//
|
//
|
||||||
//All rights reserved.
|
//All rights reserved.
|
||||||
//
|
//
|
||||||
//Redistribution and use in source and binary forms, with or without
|
//Redistribution and use in source and binary forms, with or without
|
||||||
//modification, are permitted provided that the following conditions
|
//modification, are permitted provided that the following conditions
|
||||||
//are met:
|
//are met:
|
||||||
//
|
//
|
||||||
// Redistributions of source code must retain the above copyright
|
// Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// Redistributions in binary form must reproduce the above
|
// Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following
|
// copyright notice, this list of conditions and the following
|
||||||
// disclaimer in the documentation and/or other materials provided
|
// disclaimer in the documentation and/or other materials provided
|
||||||
// with the distribution.
|
// with the distribution.
|
||||||
//
|
//
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived
|
// contributors may be used to endorse or promote products derived
|
||||||
// from this software without specific prior written permission.
|
// from this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
//POSSIBILITY OF SUCH DAMAGE.
|
//POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
//
|
//
|
||||||
// Author: John Kessenich, LunarG
|
// Author: John Kessenich, LunarG
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// Parameterize the SPIR-V enumerants.
|
// Parameterize the SPIR-V enumerants.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "spirv.h"
|
#include "spirv.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace spv {
|
namespace spv {
|
||||||
|
|
||||||
// Fill in all the parameters
|
// Fill in all the parameters
|
||||||
void Parameterize();
|
void Parameterize();
|
||||||
|
|
||||||
// Return the English names of all the enums.
|
// Return the English names of all the enums.
|
||||||
const char* SourceString(int);
|
const char* SourceString(int);
|
||||||
const char* AddressingString(int);
|
const char* AddressingString(int);
|
||||||
const char* MemoryString(int);
|
const char* MemoryString(int);
|
||||||
const char* ExecutionModelString(int);
|
const char* ExecutionModelString(int);
|
||||||
const char* ExecutionModeString(int);
|
const char* ExecutionModeString(int);
|
||||||
const char* StorageClassString(int);
|
const char* StorageClassString(int);
|
||||||
const char* DecorationString(int);
|
const char* DecorationString(int);
|
||||||
const char* BuiltInString(int);
|
const char* BuiltInString(int);
|
||||||
const char* DimensionString(int);
|
const char* DimensionString(int);
|
||||||
const char* SelectControlString(int);
|
const char* SelectControlString(int);
|
||||||
const char* LoopControlString(int);
|
const char* LoopControlString(int);
|
||||||
const char* FunctionControlString(int);
|
const char* FunctionControlString(int);
|
||||||
const char* SamplerAddressingModeString(int);
|
const char* SamplerAddressingModeString(int);
|
||||||
const char* SamplerFilterModeString(int);
|
const char* SamplerFilterModeString(int);
|
||||||
const char* FPFastMathString(int);
|
const char* FPFastMathString(int);
|
||||||
const char* FPRoundingModeString(int);
|
const char* FPRoundingModeString(int);
|
||||||
const char* LinkageTypeString(int);
|
const char* LinkageTypeString(int);
|
||||||
const char* FuncParamAttrString(int);
|
const char* FuncParamAttrString(int);
|
||||||
const char* AccessQualifierString(int);
|
const char* AccessQualifierString(int);
|
||||||
const char* MemorySemanticsString(int);
|
const char* MemorySemanticsString(int);
|
||||||
const char* MemoryAccessString(int);
|
const char* MemoryAccessString(int);
|
||||||
const char* ExecutionScopeString(int);
|
const char* ExecutionScopeString(int);
|
||||||
const char* GroupOperationString(int);
|
const char* GroupOperationString(int);
|
||||||
const char* KernelEnqueueFlagsString(int);
|
const char* KernelEnqueueFlagsString(int);
|
||||||
const char* KernelProfilingInfoString(int);
|
const char* KernelProfilingInfoString(int);
|
||||||
const char* OpcodeString(int);
|
const char* OpcodeString(int);
|
||||||
|
|
||||||
// For grouping opcodes into subsections
|
// For grouping opcodes into subsections
|
||||||
enum OpcodeClass {
|
enum OpcodeClass {
|
||||||
OpClassMisc, // default, until opcode is classified
|
OpClassMisc, // default, until opcode is classified
|
||||||
OpClassDebug,
|
OpClassDebug,
|
||||||
OpClassAnnotate,
|
OpClassAnnotate,
|
||||||
OpClassExtension,
|
OpClassExtension,
|
||||||
OpClassMode,
|
OpClassMode,
|
||||||
OpClassType,
|
OpClassType,
|
||||||
OpClassConstant,
|
OpClassConstant,
|
||||||
OpClassMemory,
|
OpClassMemory,
|
||||||
OpClassFunction,
|
OpClassFunction,
|
||||||
OpClassTexture,
|
OpClassTexture,
|
||||||
OpClassConvert,
|
OpClassConvert,
|
||||||
OpClassComposite,
|
OpClassComposite,
|
||||||
OpClassArithmetic,
|
OpClassArithmetic,
|
||||||
OpClassRelationalLogical,
|
OpClassRelationalLogical,
|
||||||
OpClassDerivative,
|
OpClassDerivative,
|
||||||
OpClassFlowControl,
|
OpClassFlowControl,
|
||||||
OpClassAtomic,
|
OpClassAtomic,
|
||||||
OpClassPrimitive,
|
OpClassPrimitive,
|
||||||
OpClassBarrier,
|
OpClassBarrier,
|
||||||
OpClassGroup,
|
OpClassGroup,
|
||||||
OpClassDeviceSideEnqueue,
|
OpClassDeviceSideEnqueue,
|
||||||
OpClassPipe,
|
OpClassPipe,
|
||||||
|
|
||||||
OpClassCount
|
OpClassCount
|
||||||
};
|
};
|
||||||
|
|
||||||
// For parameterizing operands.
|
// For parameterizing operands.
|
||||||
enum OperandClass {
|
enum OperandClass {
|
||||||
OperandNone,
|
OperandNone,
|
||||||
OperandId,
|
OperandId,
|
||||||
OperandOptionalId,
|
OperandOptionalId,
|
||||||
OperandVariableIds,
|
OperandVariableIds,
|
||||||
OperandVariableLiterals,
|
OperandVariableLiterals,
|
||||||
OperandVariableLiteralId,
|
OperandVariableLiteralId,
|
||||||
OperandLiteralNumber,
|
OperandLiteralNumber,
|
||||||
OperandLiteralString,
|
OperandLiteralString,
|
||||||
OperandSource,
|
OperandSource,
|
||||||
OperandExecutionModel,
|
OperandExecutionModel,
|
||||||
OperandAddressing,
|
OperandAddressing,
|
||||||
OperandMemory,
|
OperandMemory,
|
||||||
OperandExecutionMode,
|
OperandExecutionMode,
|
||||||
OperandStorage,
|
OperandStorage,
|
||||||
OperandDimensionality,
|
OperandDimensionality,
|
||||||
OperandSamplerAddressingMode,
|
OperandSamplerAddressingMode,
|
||||||
OperandSamplerFilterMode,
|
OperandSamplerFilterMode,
|
||||||
OperandFPFastMath,
|
OperandFPFastMath,
|
||||||
OperandFPRoundingMode,
|
OperandFPRoundingMode,
|
||||||
OperandLinkageType,
|
OperandLinkageType,
|
||||||
OperandAccessQualifier,
|
OperandAccessQualifier,
|
||||||
OperandFuncParamAttr,
|
OperandFuncParamAttr,
|
||||||
OperandDecoration,
|
OperandDecoration,
|
||||||
OperandBuiltIn,
|
OperandBuiltIn,
|
||||||
OperandSelect,
|
OperandSelect,
|
||||||
OperandLoop,
|
OperandLoop,
|
||||||
OperandFunction,
|
OperandFunction,
|
||||||
OperandMemorySemantics,
|
OperandMemorySemantics,
|
||||||
OperandMemoryAccess,
|
OperandMemoryAccess,
|
||||||
OperandExecutionScope,
|
OperandExecutionScope,
|
||||||
OperandGroupOperation,
|
OperandGroupOperation,
|
||||||
OperandKernelEnqueueFlags,
|
OperandKernelEnqueueFlags,
|
||||||
OperandKernelProfilingInfo,
|
OperandKernelProfilingInfo,
|
||||||
|
|
||||||
OperandOpcode,
|
OperandOpcode,
|
||||||
|
|
||||||
OperandCount
|
OperandCount
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set of capabilities. Generally, something is assumed to be in core,
|
// Set of capabilities. Generally, something is assumed to be in core,
|
||||||
// if nothing else is said. So, these are used to identify when something
|
// if nothing else is said. So, these are used to identify when something
|
||||||
// requires a specific capability to be declared.
|
// requires a specific capability to be declared.
|
||||||
enum Capability {
|
enum Capability {
|
||||||
CapMatrix,
|
CapMatrix,
|
||||||
CapShader,
|
CapShader,
|
||||||
CapGeom,
|
CapGeom,
|
||||||
CapTess,
|
CapTess,
|
||||||
CapAddr,
|
CapAddr,
|
||||||
CapLink,
|
CapLink,
|
||||||
CapKernel
|
CapKernel
|
||||||
};
|
};
|
||||||
|
|
||||||
// Any specific enum can have a set of capabilities that allow it:
|
// Any specific enum can have a set of capabilities that allow it:
|
||||||
typedef std::vector<Capability> EnumCaps;
|
typedef std::vector<Capability> EnumCaps;
|
||||||
|
|
||||||
// Parameterize a set of operands with their OperandClass(es) and descriptions.
|
// Parameterize a set of operands with their OperandClass(es) and descriptions.
|
||||||
class OperandParameters {
|
class OperandParameters {
|
||||||
public:
|
public:
|
||||||
OperandParameters() { }
|
OperandParameters() { }
|
||||||
void push(OperandClass oc, const char* d)
|
void push(OperandClass oc, const char* d)
|
||||||
{
|
{
|
||||||
opClass.push_back(oc);
|
opClass.push_back(oc);
|
||||||
desc.push_back(d);
|
desc.push_back(d);
|
||||||
}
|
}
|
||||||
OperandClass getClass(int op) const { return opClass[op]; }
|
OperandClass getClass(int op) const { return opClass[op]; }
|
||||||
const char* getDesc(int op) const { return desc[op]; }
|
const char* getDesc(int op) const { return desc[op]; }
|
||||||
int getNum() const { return (int)opClass.size(); }
|
int getNum() const { return (int)opClass.size(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<OperandClass> opClass;
|
std::vector<OperandClass> opClass;
|
||||||
std::vector<const char*> desc;
|
std::vector<const char*> desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parameterize an enumerant
|
// Parameterize an enumerant
|
||||||
class EnumParameters {
|
class EnumParameters {
|
||||||
public:
|
public:
|
||||||
EnumParameters() : desc(0) { }
|
EnumParameters() : desc(0) { }
|
||||||
EnumCaps caps;
|
EnumCaps caps;
|
||||||
const char* desc;
|
const char* desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parameterize a set of enumerants that form an enum
|
// Parameterize a set of enumerants that form an enum
|
||||||
class EnumDefinition : public EnumParameters {
|
class EnumDefinition : public EnumParameters {
|
||||||
public:
|
public:
|
||||||
EnumDefinition() :
|
EnumDefinition() :
|
||||||
ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { }
|
ceiling(0), bitmask(false), getName(0), enumParams(0), operandParams(0) { }
|
||||||
void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false)
|
void set(int ceil, const char* (*name)(int), EnumParameters* ep, bool mask = false)
|
||||||
{
|
{
|
||||||
ceiling = ceil;
|
ceiling = ceil;
|
||||||
getName = name;
|
getName = name;
|
||||||
bitmask = mask;
|
bitmask = mask;
|
||||||
enumParams = ep;
|
enumParams = ep;
|
||||||
}
|
}
|
||||||
void setOperands(OperandParameters* op) { operandParams = op; }
|
void setOperands(OperandParameters* op) { operandParams = op; }
|
||||||
int ceiling; // ceiling of enumerants
|
int ceiling; // ceiling of enumerants
|
||||||
bool bitmask; // true if these enumerants combine into a bitmask
|
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)
|
const char* (*getName)(int); // a function that returns the name for each enumerant value (or shift)
|
||||||
EnumParameters* enumParams; // parameters for each individual enumerant
|
EnumParameters* enumParams; // parameters for each individual enumerant
|
||||||
OperandParameters* operandParams; // sets of operands
|
OperandParameters* operandParams; // sets of operands
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parameterize an instruction's logical format, including its known set of operands,
|
// Parameterize an instruction's logical format, including its known set of operands,
|
||||||
// per OperandParameters above.
|
// per OperandParameters above.
|
||||||
class InstructionParameters {
|
class InstructionParameters {
|
||||||
public:
|
public:
|
||||||
InstructionParameters() :
|
InstructionParameters() :
|
||||||
typePresent(true), // most normal, only exceptions have to be spelled out
|
typePresent(true), // most normal, only exceptions have to be spelled out
|
||||||
resultPresent(true), // most normal, only exceptions have to be spelled out
|
resultPresent(true), // most normal, only exceptions have to be spelled out
|
||||||
opDesc(0),
|
opDesc(0),
|
||||||
opClass(OpClassMisc)
|
opClass(OpClassMisc)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void setResultAndType(bool r, bool t)
|
void setResultAndType(bool r, bool t)
|
||||||
{
|
{
|
||||||
resultPresent = r;
|
resultPresent = r;
|
||||||
typePresent = t;
|
typePresent = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasResult() const { return resultPresent != 0; }
|
bool hasResult() const { return resultPresent != 0; }
|
||||||
bool hasType() const { return typePresent != 0; }
|
bool hasType() const { return typePresent != 0; }
|
||||||
|
|
||||||
const char* opDesc;
|
const char* opDesc;
|
||||||
EnumCaps capabilities;
|
EnumCaps capabilities;
|
||||||
OpcodeClass opClass;
|
OpcodeClass opClass;
|
||||||
OperandParameters operands;
|
OperandParameters operands;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int typePresent : 1;
|
int typePresent : 1;
|
||||||
int resultPresent : 1;
|
int resultPresent : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const int OpcodeCeiling = 267;
|
const int OpcodeCeiling = 267;
|
||||||
|
|
||||||
// The set of objects that hold all the instruction/operand
|
// The set of objects that hold all the instruction/operand
|
||||||
// parameterization information.
|
// parameterization information.
|
||||||
extern InstructionParameters InstructionDesc[];
|
extern InstructionParameters InstructionDesc[];
|
||||||
|
|
||||||
// These hold definitions of the enumerants used for operands
|
// These hold definitions of the enumerants used for operands
|
||||||
extern EnumDefinition OperandClassParams[];
|
extern EnumDefinition OperandClassParams[];
|
||||||
|
|
||||||
const char* GetOperandDesc(OperandClass operand);
|
const char* GetOperandDesc(OperandClass operand);
|
||||||
void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false);
|
void PrintImmediateRow(int imm, const char* name, const EnumParameters* enumParams, bool caps, bool hex = false);
|
||||||
const char* AccessQualifierString(int attr);
|
const char* AccessQualifierString(int attr);
|
||||||
|
|
||||||
void PrintOperands(const OperandParameters& operands, int reservedOperands);
|
void PrintOperands(const OperandParameters& operands, int reservedOperands);
|
||||||
|
|
||||||
}; // end namespace spv
|
}; // end namespace spv
|
||||||
|
|||||||
2608
SPIRV/spirv.h
2608
SPIRV/spirv.h
File diff suppressed because it is too large
Load Diff
738
SPIRV/spvIR.h
738
SPIRV/spvIR.h
@ -1,369 +1,369 @@
|
|||||||
//
|
//
|
||||||
//Copyright (C) 2014 LunarG, Inc.
|
//Copyright (C) 2014 LunarG, Inc.
|
||||||
//
|
//
|
||||||
//All rights reserved.
|
//All rights reserved.
|
||||||
//
|
//
|
||||||
//Redistribution and use in source and binary forms, with or without
|
//Redistribution and use in source and binary forms, with or without
|
||||||
//modification, are permitted provided that the following conditions
|
//modification, are permitted provided that the following conditions
|
||||||
//are met:
|
//are met:
|
||||||
//
|
//
|
||||||
// Redistributions of source code must retain the above copyright
|
// Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// Redistributions in binary form must reproduce the above
|
// Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following
|
// copyright notice, this list of conditions and the following
|
||||||
// disclaimer in the documentation and/or other materials provided
|
// disclaimer in the documentation and/or other materials provided
|
||||||
// with the distribution.
|
// with the distribution.
|
||||||
//
|
//
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived
|
// contributors may be used to endorse or promote products derived
|
||||||
// from this software without specific prior written permission.
|
// from this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
//POSSIBILITY OF SUCH DAMAGE.
|
//POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
//
|
//
|
||||||
// Author: John Kessenich, LunarG
|
// Author: John Kessenich, LunarG
|
||||||
//
|
//
|
||||||
|
|
||||||
// SPIRV-IR
|
// SPIRV-IR
|
||||||
//
|
//
|
||||||
// Simple in-memory representation (IR) of SPIRV. Just for holding
|
// Simple in-memory representation (IR) of SPIRV. Just for holding
|
||||||
// Each function's CFG of blocks. Has this hierarchy:
|
// Each function's CFG of blocks. Has this hierarchy:
|
||||||
// - Module, which is a list of
|
// - Module, which is a list of
|
||||||
// - Function, which is a list of
|
// - Function, which is a list of
|
||||||
// - Block, which is a list of
|
// - Block, which is a list of
|
||||||
// - Instruction
|
// - Instruction
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#ifndef spvIR_H
|
#ifndef spvIR_H
|
||||||
#define spvIR_H
|
#define spvIR_H
|
||||||
|
|
||||||
#include "spirv.h"
|
#include "spirv.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
namespace spv {
|
namespace spv {
|
||||||
|
|
||||||
class Function;
|
class Function;
|
||||||
class Module;
|
class Module;
|
||||||
|
|
||||||
const Id NoResult = 0;
|
const Id NoResult = 0;
|
||||||
const Id NoType = 0;
|
const Id NoType = 0;
|
||||||
|
|
||||||
const unsigned int BadValue = 0xFFFFFFFF;
|
const unsigned int BadValue = 0xFFFFFFFF;
|
||||||
const Decoration NoPrecision = (Decoration)BadValue;
|
const Decoration NoPrecision = (Decoration)BadValue;
|
||||||
const MemorySemanticsMask MemorySemanticsAllMemory = (MemorySemanticsMask)0x3FF;
|
const MemorySemanticsMask MemorySemanticsAllMemory = (MemorySemanticsMask)0x3FF;
|
||||||
|
|
||||||
//
|
//
|
||||||
// SPIR-V IR instruction.
|
// SPIR-V IR instruction.
|
||||||
//
|
//
|
||||||
|
|
||||||
class Instruction {
|
class Instruction {
|
||||||
public:
|
public:
|
||||||
Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), string(0) { }
|
Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), string(0) { }
|
||||||
explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), string(0) { }
|
explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), string(0) { }
|
||||||
virtual ~Instruction()
|
virtual ~Instruction()
|
||||||
{
|
{
|
||||||
delete string;
|
delete string;
|
||||||
}
|
}
|
||||||
void addIdOperand(Id id) { operands.push_back(id); }
|
void addIdOperand(Id id) { operands.push_back(id); }
|
||||||
void addImmediateOperand(unsigned int immediate) { operands.push_back(immediate); }
|
void addImmediateOperand(unsigned int immediate) { operands.push_back(immediate); }
|
||||||
void addStringOperand(const char* str)
|
void addStringOperand(const char* str)
|
||||||
{
|
{
|
||||||
originalString = str;
|
originalString = str;
|
||||||
string = new std::vector<unsigned int>;
|
string = new std::vector<unsigned int>;
|
||||||
unsigned int word;
|
unsigned int word;
|
||||||
char* wordString = (char*)&word;
|
char* wordString = (char*)&word;
|
||||||
char* wordPtr = wordString;
|
char* wordPtr = wordString;
|
||||||
int charCount = 0;
|
int charCount = 0;
|
||||||
char c;
|
char c;
|
||||||
do {
|
do {
|
||||||
c = *(str++);
|
c = *(str++);
|
||||||
*(wordPtr++) = c;
|
*(wordPtr++) = c;
|
||||||
++charCount;
|
++charCount;
|
||||||
if (charCount == 4) {
|
if (charCount == 4) {
|
||||||
string->push_back(word);
|
string->push_back(word);
|
||||||
wordPtr = wordString;
|
wordPtr = wordString;
|
||||||
charCount = 0;
|
charCount = 0;
|
||||||
}
|
}
|
||||||
} while (c != 0);
|
} while (c != 0);
|
||||||
|
|
||||||
// deal with partial last word
|
// deal with partial last word
|
||||||
if (charCount > 0) {
|
if (charCount > 0) {
|
||||||
// pad with 0s
|
// pad with 0s
|
||||||
for (; charCount < 4; ++charCount)
|
for (; charCount < 4; ++charCount)
|
||||||
*(wordPtr++) = 0;
|
*(wordPtr++) = 0;
|
||||||
string->push_back(word);
|
string->push_back(word);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Op getOpCode() const { return opCode; }
|
Op getOpCode() const { return opCode; }
|
||||||
int getNumOperands() const { return (int)operands.size(); }
|
int getNumOperands() const { return (int)operands.size(); }
|
||||||
Id getResultId() const { return resultId; }
|
Id getResultId() const { return resultId; }
|
||||||
Id getTypeId() const { return typeId; }
|
Id getTypeId() const { return typeId; }
|
||||||
Id getIdOperand(int op) const { return operands[op]; }
|
Id getIdOperand(int op) const { return operands[op]; }
|
||||||
unsigned int getImmediateOperand(int op) const { return operands[op]; }
|
unsigned int getImmediateOperand(int op) const { return operands[op]; }
|
||||||
const char* getStringOperand() const { return originalString.c_str(); }
|
const char* getStringOperand() const { return originalString.c_str(); }
|
||||||
|
|
||||||
// Write out the binary form.
|
// Write out the binary form.
|
||||||
void dump(std::vector<unsigned int>& out) const
|
void dump(std::vector<unsigned int>& out) const
|
||||||
{
|
{
|
||||||
// Compute the wordCount
|
// Compute the wordCount
|
||||||
unsigned int wordCount = 1;
|
unsigned int wordCount = 1;
|
||||||
if (typeId)
|
if (typeId)
|
||||||
++wordCount;
|
++wordCount;
|
||||||
if (resultId)
|
if (resultId)
|
||||||
++wordCount;
|
++wordCount;
|
||||||
wordCount += (unsigned int)operands.size();
|
wordCount += (unsigned int)operands.size();
|
||||||
if (string)
|
if (string)
|
||||||
wordCount += (unsigned int)string->size();
|
wordCount += (unsigned int)string->size();
|
||||||
|
|
||||||
// Write out the beginning of the instruction
|
// Write out the beginning of the instruction
|
||||||
out.push_back(((wordCount) << WordCountShift) | opCode);
|
out.push_back(((wordCount) << WordCountShift) | opCode);
|
||||||
if (typeId)
|
if (typeId)
|
||||||
out.push_back(typeId);
|
out.push_back(typeId);
|
||||||
if (resultId)
|
if (resultId)
|
||||||
out.push_back(resultId);
|
out.push_back(resultId);
|
||||||
|
|
||||||
// Write out the operands
|
// Write out the operands
|
||||||
for (int op = 0; op < (int)operands.size(); ++op)
|
for (int op = 0; op < (int)operands.size(); ++op)
|
||||||
out.push_back(operands[op]);
|
out.push_back(operands[op]);
|
||||||
if (string)
|
if (string)
|
||||||
for (int op = 0; op < (int)string->size(); ++op)
|
for (int op = 0; op < (int)string->size(); ++op)
|
||||||
out.push_back((*string)[op]);
|
out.push_back((*string)[op]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Instruction(const Instruction&);
|
Instruction(const Instruction&);
|
||||||
Id resultId;
|
Id resultId;
|
||||||
Id typeId;
|
Id typeId;
|
||||||
Op opCode;
|
Op opCode;
|
||||||
std::vector<Id> operands;
|
std::vector<Id> operands;
|
||||||
std::vector<unsigned int>* string; // usually non-existent
|
std::vector<unsigned int>* string; // usually non-existent
|
||||||
std::string originalString; // could be optimized away; convenience for getting string operand
|
std::string originalString; // could be optimized away; convenience for getting string operand
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// SPIR-V IR block.
|
// SPIR-V IR block.
|
||||||
//
|
//
|
||||||
|
|
||||||
class Block {
|
class Block {
|
||||||
public:
|
public:
|
||||||
Block(Id id, Function& parent);
|
Block(Id id, Function& parent);
|
||||||
virtual ~Block()
|
virtual ~Block()
|
||||||
{
|
{
|
||||||
// TODO: free instructions
|
// TODO: free instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
Id getId() { return instructions.front()->getResultId(); }
|
Id getId() { return instructions.front()->getResultId(); }
|
||||||
|
|
||||||
Function& getParent() const { return parent; }
|
Function& getParent() const { return parent; }
|
||||||
void addInstruction(Instruction* inst);
|
void addInstruction(Instruction* inst);
|
||||||
void addPredecessor(Block* pred) { predecessors.push_back(pred); }
|
void addPredecessor(Block* pred) { predecessors.push_back(pred); }
|
||||||
void addLocalVariable(Instruction* inst) { localVariables.push_back(inst); }
|
void addLocalVariable(Instruction* inst) { localVariables.push_back(inst); }
|
||||||
int getNumPredecessors() const { return (int)predecessors.size(); }
|
int getNumPredecessors() const { return (int)predecessors.size(); }
|
||||||
void setUnreachable() { unreachable = true; }
|
void setUnreachable() { unreachable = true; }
|
||||||
bool isUnreachable() const { return unreachable; }
|
bool isUnreachable() const { return unreachable; }
|
||||||
|
|
||||||
bool isTerminated() const
|
bool isTerminated() const
|
||||||
{
|
{
|
||||||
switch (instructions.back()->getOpCode()) {
|
switch (instructions.back()->getOpCode()) {
|
||||||
case OpBranch:
|
case OpBranch:
|
||||||
case OpBranchConditional:
|
case OpBranchConditional:
|
||||||
case OpSwitch:
|
case OpSwitch:
|
||||||
case OpKill:
|
case OpKill:
|
||||||
case OpReturn:
|
case OpReturn:
|
||||||
case OpReturnValue:
|
case OpReturnValue:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump(std::vector<unsigned int>& out) const
|
void dump(std::vector<unsigned int>& out) const
|
||||||
{
|
{
|
||||||
// skip the degenerate unreachable blocks
|
// skip the degenerate unreachable blocks
|
||||||
// TODO: code gen: skip all unreachable blocks (transitive closure)
|
// TODO: code gen: skip all unreachable blocks (transitive closure)
|
||||||
// (but, until that's done safer to keep non-degenerate unreachable blocks, in case others depend on something)
|
// (but, until that's done safer to keep non-degenerate unreachable blocks, in case others depend on something)
|
||||||
if (unreachable && instructions.size() <= 2)
|
if (unreachable && instructions.size() <= 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
instructions[0]->dump(out);
|
instructions[0]->dump(out);
|
||||||
for (int i = 0; i < (int)localVariables.size(); ++i)
|
for (int i = 0; i < (int)localVariables.size(); ++i)
|
||||||
localVariables[i]->dump(out);
|
localVariables[i]->dump(out);
|
||||||
for (int i = 1; i < (int)instructions.size(); ++i)
|
for (int i = 1; i < (int)instructions.size(); ++i)
|
||||||
instructions[i]->dump(out);
|
instructions[i]->dump(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Block(const Block&);
|
Block(const Block&);
|
||||||
Block& operator=(Block&);
|
Block& operator=(Block&);
|
||||||
|
|
||||||
// To enforce keeping parent and ownership in sync:
|
// To enforce keeping parent and ownership in sync:
|
||||||
friend Function;
|
friend Function;
|
||||||
|
|
||||||
std::vector<Instruction*> instructions;
|
std::vector<Instruction*> instructions;
|
||||||
std::vector<Block*> predecessors;
|
std::vector<Block*> predecessors;
|
||||||
std::vector<Instruction*> localVariables;
|
std::vector<Instruction*> localVariables;
|
||||||
Function& parent;
|
Function& parent;
|
||||||
|
|
||||||
// track whether this block is known to be uncreachable (not necessarily
|
// track whether this block is known to be uncreachable (not necessarily
|
||||||
// true for all unreachable blocks, but should be set at least
|
// true for all unreachable blocks, but should be set at least
|
||||||
// for the extraneous ones introduced by the builder).
|
// for the extraneous ones introduced by the builder).
|
||||||
bool unreachable;
|
bool unreachable;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// SPIR-V IR Function.
|
// SPIR-V IR Function.
|
||||||
//
|
//
|
||||||
|
|
||||||
class Function {
|
class Function {
|
||||||
public:
|
public:
|
||||||
Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent);
|
Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent);
|
||||||
virtual ~Function()
|
virtual ~Function()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < (int)parameterInstructions.size(); ++i)
|
for (int i = 0; i < (int)parameterInstructions.size(); ++i)
|
||||||
delete parameterInstructions[i];
|
delete parameterInstructions[i];
|
||||||
|
|
||||||
for (int i = 0; i < (int)blocks.size(); ++i)
|
for (int i = 0; i < (int)blocks.size(); ++i)
|
||||||
delete blocks[i];
|
delete blocks[i];
|
||||||
}
|
}
|
||||||
Id getId() const { return functionInstruction.getResultId(); }
|
Id getId() const { return functionInstruction.getResultId(); }
|
||||||
Id getParamId(int p) { return parameterInstructions[p]->getResultId(); }
|
Id getParamId(int p) { return parameterInstructions[p]->getResultId(); }
|
||||||
|
|
||||||
void addBlock(Block* block) { blocks.push_back(block); }
|
void addBlock(Block* block) { blocks.push_back(block); }
|
||||||
void popBlock(Block*) { blocks.pop_back(); }
|
void popBlock(Block*) { blocks.pop_back(); }
|
||||||
|
|
||||||
Module& getParent() const { return parent; }
|
Module& getParent() const { return parent; }
|
||||||
Block* getEntryBlock() const { return blocks.front(); }
|
Block* getEntryBlock() const { return blocks.front(); }
|
||||||
Block* getLastBlock() const { return blocks.back(); }
|
Block* getLastBlock() const { return blocks.back(); }
|
||||||
void addLocalVariable(Instruction* inst);
|
void addLocalVariable(Instruction* inst);
|
||||||
Id getReturnType() const { return functionInstruction.getTypeId(); }
|
Id getReturnType() const { return functionInstruction.getTypeId(); }
|
||||||
void dump(std::vector<unsigned int>& out) const
|
void dump(std::vector<unsigned int>& out) const
|
||||||
{
|
{
|
||||||
// OpFunction
|
// OpFunction
|
||||||
functionInstruction.dump(out);
|
functionInstruction.dump(out);
|
||||||
|
|
||||||
// OpFunctionParameter
|
// OpFunctionParameter
|
||||||
for (int p = 0; p < (int)parameterInstructions.size(); ++p)
|
for (int p = 0; p < (int)parameterInstructions.size(); ++p)
|
||||||
parameterInstructions[p]->dump(out);
|
parameterInstructions[p]->dump(out);
|
||||||
|
|
||||||
// Blocks
|
// Blocks
|
||||||
for (int b = 0; b < (int)blocks.size(); ++b)
|
for (int b = 0; b < (int)blocks.size(); ++b)
|
||||||
blocks[b]->dump(out);
|
blocks[b]->dump(out);
|
||||||
Instruction end(0, 0, OpFunctionEnd);
|
Instruction end(0, 0, OpFunctionEnd);
|
||||||
end.dump(out);
|
end.dump(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Function(const Function&);
|
Function(const Function&);
|
||||||
Function& operator=(Function&);
|
Function& operator=(Function&);
|
||||||
|
|
||||||
Module& parent;
|
Module& parent;
|
||||||
Instruction functionInstruction;
|
Instruction functionInstruction;
|
||||||
std::vector<Instruction*> parameterInstructions;
|
std::vector<Instruction*> parameterInstructions;
|
||||||
std::vector<Block*> blocks;
|
std::vector<Block*> blocks;
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// SPIR-V IR Module.
|
// SPIR-V IR Module.
|
||||||
//
|
//
|
||||||
|
|
||||||
class Module {
|
class Module {
|
||||||
public:
|
public:
|
||||||
Module() {}
|
Module() {}
|
||||||
virtual ~Module()
|
virtual ~Module()
|
||||||
{
|
{
|
||||||
// TODO delete things
|
// TODO delete things
|
||||||
}
|
}
|
||||||
|
|
||||||
void addFunction(Function *fun) { functions.push_back(fun); }
|
void addFunction(Function *fun) { functions.push_back(fun); }
|
||||||
|
|
||||||
void mapInstruction(Instruction *instruction)
|
void mapInstruction(Instruction *instruction)
|
||||||
{
|
{
|
||||||
spv::Id resultId = instruction->getResultId();
|
spv::Id resultId = instruction->getResultId();
|
||||||
// map the instruction's result id
|
// map the instruction's result id
|
||||||
if (resultId >= idToInstruction.size())
|
if (resultId >= idToInstruction.size())
|
||||||
idToInstruction.resize(resultId + 16);
|
idToInstruction.resize(resultId + 16);
|
||||||
idToInstruction[resultId] = instruction;
|
idToInstruction[resultId] = instruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction* getInstruction(Id id) const { return idToInstruction[id]; }
|
Instruction* getInstruction(Id id) const { return idToInstruction[id]; }
|
||||||
spv::Id getTypeId(Id resultId) const { return idToInstruction[resultId]->getTypeId(); }
|
spv::Id getTypeId(Id resultId) const { return idToInstruction[resultId]->getTypeId(); }
|
||||||
StorageClass getStorageClass(Id typeId) const { return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); }
|
StorageClass getStorageClass(Id typeId) const { return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); }
|
||||||
void dump(std::vector<unsigned int>& out) const
|
void dump(std::vector<unsigned int>& out) const
|
||||||
{
|
{
|
||||||
for (int f = 0; f < (int)functions.size(); ++f)
|
for (int f = 0; f < (int)functions.size(); ++f)
|
||||||
functions[f]->dump(out);
|
functions[f]->dump(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Module(const Module&);
|
Module(const Module&);
|
||||||
std::vector<Function*> functions;
|
std::vector<Function*> functions;
|
||||||
|
|
||||||
// map from result id to instruction having that result id
|
// map from result id to instruction having that result id
|
||||||
std::vector<Instruction*> idToInstruction;
|
std::vector<Instruction*> idToInstruction;
|
||||||
|
|
||||||
// map from a result id to its type id
|
// map from a result id to its type id
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Implementation (it's here due to circular type definitions).
|
// Implementation (it's here due to circular type definitions).
|
||||||
//
|
//
|
||||||
|
|
||||||
// Add both
|
// Add both
|
||||||
// - the OpFunction instruction
|
// - the OpFunction instruction
|
||||||
// - all the OpFunctionParameter instructions
|
// - all the OpFunctionParameter instructions
|
||||||
__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
|
__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
|
||||||
: parent(parent), functionInstruction(id, resultType, OpFunction)
|
: parent(parent), functionInstruction(id, resultType, OpFunction)
|
||||||
{
|
{
|
||||||
// OpFunction
|
// OpFunction
|
||||||
functionInstruction.addImmediateOperand(FunctionControlMaskNone);
|
functionInstruction.addImmediateOperand(FunctionControlMaskNone);
|
||||||
functionInstruction.addIdOperand(functionType);
|
functionInstruction.addIdOperand(functionType);
|
||||||
parent.mapInstruction(&functionInstruction);
|
parent.mapInstruction(&functionInstruction);
|
||||||
parent.addFunction(this);
|
parent.addFunction(this);
|
||||||
|
|
||||||
// OpFunctionParameter
|
// OpFunctionParameter
|
||||||
Instruction* typeInst = parent.getInstruction(functionType);
|
Instruction* typeInst = parent.getInstruction(functionType);
|
||||||
int numParams = typeInst->getNumOperands() - 1;
|
int numParams = typeInst->getNumOperands() - 1;
|
||||||
for (int p = 0; p < numParams; ++p) {
|
for (int p = 0; p < numParams; ++p) {
|
||||||
Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter);
|
Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter);
|
||||||
parent.mapInstruction(param);
|
parent.mapInstruction(param);
|
||||||
parameterInstructions.push_back(param);
|
parameterInstructions.push_back(param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__inline void Function::addLocalVariable(Instruction* inst)
|
__inline void Function::addLocalVariable(Instruction* inst)
|
||||||
{
|
{
|
||||||
blocks[0]->addLocalVariable(inst);
|
blocks[0]->addLocalVariable(inst);
|
||||||
parent.mapInstruction(inst);
|
parent.mapInstruction(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false)
|
__inline Block::Block(Id id, Function& parent) : parent(parent), unreachable(false)
|
||||||
{
|
{
|
||||||
instructions.push_back(new Instruction(id, NoType, OpLabel));
|
instructions.push_back(new Instruction(id, NoType, OpLabel));
|
||||||
}
|
}
|
||||||
|
|
||||||
__inline void Block::addInstruction(Instruction* inst)
|
__inline void Block::addInstruction(Instruction* inst)
|
||||||
{
|
{
|
||||||
instructions.push_back(inst);
|
instructions.push_back(inst);
|
||||||
if (inst->getResultId())
|
if (inst->getResultId())
|
||||||
parent.getParent().mapInstruction(inst);
|
parent.getParent().mapInstruction(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // end spv namespace
|
}; // end spv namespace
|
||||||
|
|
||||||
#endif // spvIR_H
|
#endif // spvIR_H
|
||||||
|
|||||||
@ -1,41 +1,41 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
include_directories(.)
|
include_directories(.)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
include_directories(../glslang/OSDependent/Windows)
|
include_directories(../glslang/OSDependent/Windows)
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
include_directories(../glslang/OSDependent/Linux)
|
include_directories(../glslang/OSDependent/Linux)
|
||||||
else(WIN32)
|
else(WIN32)
|
||||||
message("unkown platform")
|
message("unkown platform")
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
set(SOURCES StandAlone.cpp)
|
set(SOURCES StandAlone.cpp)
|
||||||
set(REMAPPER_SOURCES spirv-remap.cpp)
|
set(REMAPPER_SOURCES spirv-remap.cpp)
|
||||||
|
|
||||||
add_executable(glslangValidator ${SOURCES})
|
add_executable(glslangValidator ${SOURCES})
|
||||||
add_executable(spirv-remap ${REMAPPER_SOURCES})
|
add_executable(spirv-remap ${REMAPPER_SOURCES})
|
||||||
|
|
||||||
set(LIBRARIES
|
set(LIBRARIES
|
||||||
glslang
|
glslang
|
||||||
OGLCompiler
|
OGLCompiler
|
||||||
OSDependent
|
OSDependent
|
||||||
SPIRV)
|
SPIRV)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(LIBRARIES ${LIBRARIES} psapi)
|
set(LIBRARIES ${LIBRARIES} psapi)
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
set(LIBRARIES ${LIBRARIES} pthread)
|
set(LIBRARIES ${LIBRARIES} pthread)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
target_link_libraries(glslangValidator ${LIBRARIES})
|
target_link_libraries(glslangValidator ${LIBRARIES})
|
||||||
target_link_libraries(spirv-remap ${LIBRARIES})
|
target_link_libraries(spirv-remap ${LIBRARIES})
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
source_group("Source" FILES ${SOURCES})
|
source_group("Source" FILES ${SOURCES})
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
install(TARGETS glslangValidator
|
install(TARGETS glslangValidator
|
||||||
RUNTIME DESTINATION bin)
|
RUNTIME DESTINATION bin)
|
||||||
|
|
||||||
install(TARGETS spirv-remap
|
install(TARGETS spirv-remap
|
||||||
RUNTIME DESTINATION bin)
|
RUNTIME DESTINATION bin)
|
||||||
|
|||||||
@ -1,337 +1,337 @@
|
|||||||
//
|
//
|
||||||
//Copyright (C) 2015 LunarG, Inc.
|
//Copyright (C) 2015 LunarG, Inc.
|
||||||
//
|
//
|
||||||
//All rights reserved.
|
//All rights reserved.
|
||||||
//
|
//
|
||||||
//Redistribution and use in source and binary forms, with or without
|
//Redistribution and use in source and binary forms, with or without
|
||||||
//modification, are permitted provided that the following conditions
|
//modification, are permitted provided that the following conditions
|
||||||
//are met:
|
//are met:
|
||||||
//
|
//
|
||||||
// Redistributions of source code must retain the above copyright
|
// Redistributions of source code must retain the above copyright
|
||||||
// notice, this list of conditions and the following disclaimer.
|
// notice, this list of conditions and the following disclaimer.
|
||||||
//
|
//
|
||||||
// Redistributions in binary form must reproduce the above
|
// Redistributions in binary form must reproduce the above
|
||||||
// copyright notice, this list of conditions and the following
|
// copyright notice, this list of conditions and the following
|
||||||
// disclaimer in the documentation and/or other materials provided
|
// disclaimer in the documentation and/or other materials provided
|
||||||
// with the distribution.
|
// with the distribution.
|
||||||
//
|
//
|
||||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||||
// contributors may be used to endorse or promote products derived
|
// contributors may be used to endorse or promote products derived
|
||||||
// from this software without specific prior written permission.
|
// from this software without specific prior written permission.
|
||||||
//
|
//
|
||||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
//POSSIBILITY OF SUCH DAMAGE.
|
//POSSIBILITY OF SUCH DAMAGE.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "../SPIRV/SPVRemapper.h"
|
#include "../SPIRV/SPVRemapper.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
typedef unsigned int SpvWord;
|
typedef unsigned int SpvWord;
|
||||||
|
|
||||||
// Poor man's basename: given a complete path, return file portion.
|
// Poor man's basename: given a complete path, return file portion.
|
||||||
// E.g:
|
// E.g:
|
||||||
// Linux: /foo/bar/test -> test
|
// Linux: /foo/bar/test -> test
|
||||||
// Win: c:\foo\bar\test -> test
|
// Win: c:\foo\bar\test -> test
|
||||||
// It's not very efficient, but that doesn't matter for our minimal-duty use.
|
// It's not very efficient, but that doesn't matter for our minimal-duty use.
|
||||||
// Using boost::filesystem would be better in many ways, but want to avoid that dependency.
|
// Using boost::filesystem would be better in many ways, but want to avoid that dependency.
|
||||||
|
|
||||||
// OS dependent path separator (avoiding boost::filesystem dependency)
|
// OS dependent path separator (avoiding boost::filesystem dependency)
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
char path_sep_char() { return '\\'; }
|
char path_sep_char() { return '\\'; }
|
||||||
#else
|
#else
|
||||||
char path_sep_char() { return '/'; }
|
char path_sep_char() { return '/'; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string basename(const std::string filename)
|
std::string basename(const std::string filename)
|
||||||
{
|
{
|
||||||
const size_t sepLoc = filename.find_last_of(path_sep_char());
|
const size_t sepLoc = filename.find_last_of(path_sep_char());
|
||||||
|
|
||||||
return (sepLoc == filename.npos) ? filename : filename.substr(sepLoc+1);
|
return (sepLoc == filename.npos) ? filename : filename.substr(sepLoc+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void errHandler(const std::string& str) {
|
void errHandler(const std::string& str) {
|
||||||
std::cout << str << std::endl;
|
std::cout << str << std::endl;
|
||||||
exit(5);
|
exit(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logHandler(const std::string& str) {
|
void logHandler(const std::string& str) {
|
||||||
std::cout << str << std::endl;
|
std::cout << str << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read word stream from disk
|
// Read word stream from disk
|
||||||
void read(std::vector<SpvWord>& spv, const std::string& inFilename, int verbosity)
|
void read(std::vector<SpvWord>& spv, const std::string& inFilename, int verbosity)
|
||||||
{
|
{
|
||||||
std::ifstream fp;
|
std::ifstream fp;
|
||||||
|
|
||||||
if (verbosity > 0)
|
if (verbosity > 0)
|
||||||
logHandler(std::string(" reading: ") + inFilename);
|
logHandler(std::string(" reading: ") + inFilename);
|
||||||
|
|
||||||
spv.clear();
|
spv.clear();
|
||||||
fp.open(inFilename, std::fstream::in | std::fstream::binary);
|
fp.open(inFilename, std::fstream::in | std::fstream::binary);
|
||||||
|
|
||||||
if (fp.fail())
|
if (fp.fail())
|
||||||
errHandler("error opening file for read: ");
|
errHandler("error opening file for read: ");
|
||||||
|
|
||||||
// Reserve space (for efficiency, not for correctness)
|
// Reserve space (for efficiency, not for correctness)
|
||||||
fp.seekg(0, fp.end);
|
fp.seekg(0, fp.end);
|
||||||
spv.reserve(size_t(fp.tellg()) / sizeof(SpvWord));
|
spv.reserve(size_t(fp.tellg()) / sizeof(SpvWord));
|
||||||
fp.seekg(0, fp.beg);
|
fp.seekg(0, fp.beg);
|
||||||
|
|
||||||
while (!fp.eof()) {
|
while (!fp.eof()) {
|
||||||
SpvWord inWord;
|
SpvWord inWord;
|
||||||
fp.read((char *)&inWord, sizeof(inWord));
|
fp.read((char *)&inWord, sizeof(inWord));
|
||||||
|
|
||||||
if (!fp.eof()) {
|
if (!fp.eof()) {
|
||||||
spv.push_back(inWord);
|
spv.push_back(inWord);
|
||||||
if (fp.fail())
|
if (fp.fail())
|
||||||
errHandler(std::string("error reading file: ") + inFilename);
|
errHandler(std::string("error reading file: ") + inFilename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(std::vector<SpvWord>& spv, const std::string& outFile, int verbosity)
|
void write(std::vector<SpvWord>& spv, const std::string& outFile, int verbosity)
|
||||||
{
|
{
|
||||||
if (outFile.empty())
|
if (outFile.empty())
|
||||||
errHandler("missing output filename.");
|
errHandler("missing output filename.");
|
||||||
|
|
||||||
std::ofstream fp;
|
std::ofstream fp;
|
||||||
|
|
||||||
if (verbosity > 0)
|
if (verbosity > 0)
|
||||||
logHandler(std::string(" writing: ") + outFile);
|
logHandler(std::string(" writing: ") + outFile);
|
||||||
|
|
||||||
fp.open(outFile, std::fstream::out | std::fstream::binary);
|
fp.open(outFile, std::fstream::out | std::fstream::binary);
|
||||||
|
|
||||||
if (fp.fail())
|
if (fp.fail())
|
||||||
errHandler(std::string("error opening file for write: ") + outFile);
|
errHandler(std::string("error opening file for write: ") + outFile);
|
||||||
|
|
||||||
for (auto word : spv) {
|
for (auto word : spv) {
|
||||||
fp.write((char *)&word, sizeof(word));
|
fp.write((char *)&word, sizeof(word));
|
||||||
if (fp.fail())
|
if (fp.fail())
|
||||||
errHandler(std::string("error writing file: ") + outFile);
|
errHandler(std::string("error writing file: ") + outFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// file is closed by destructor
|
// file is closed by destructor
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print helpful usage message to stdout, and exit
|
// Print helpful usage message to stdout, and exit
|
||||||
void usage(const char* const name, const char* const msg = 0)
|
void usage(const char* const name, const char* const msg = 0)
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
std::cout << msg << std::endl << std::endl;
|
std::cout << msg << std::endl << std::endl;
|
||||||
|
|
||||||
std::cout << "Usage: " << std::endl;
|
std::cout << "Usage: " << std::endl;
|
||||||
|
|
||||||
std::cout << " " << basename(name)
|
std::cout << " " << basename(name)
|
||||||
<< " [-v[v[...]] | --verbose [int]]"
|
<< " [-v[v[...]] | --verbose [int]]"
|
||||||
<< " [--map (all|types|names|funcs)]"
|
<< " [--map (all|types|names|funcs)]"
|
||||||
<< " [--dce (all|types|funcs)]"
|
<< " [--dce (all|types|funcs)]"
|
||||||
<< " [--opt (all|loadstore)]"
|
<< " [--opt (all|loadstore)]"
|
||||||
<< " [--strip-all | --strip all | -s]"
|
<< " [--strip-all | --strip all | -s]"
|
||||||
<< " [--do-everything]"
|
<< " [--do-everything]"
|
||||||
<< " --input | -i file1 [file2...] --output|-o DESTDIR"
|
<< " --input | -i file1 [file2...] --output|-o DESTDIR"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
std::cout << " " << basename(name) << " [--version | -V]" << std::endl;
|
std::cout << " " << basename(name) << " [--version | -V]" << std::endl;
|
||||||
std::cout << " " << basename(name) << " [--help | -?]" << std::endl;
|
std::cout << " " << basename(name) << " [--help | -?]" << std::endl;
|
||||||
|
|
||||||
exit(5);
|
exit(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// grind through each SPIR in turn
|
// grind through each SPIR in turn
|
||||||
void execute(const std::vector<std::string>& inputFile, const std::string& outputDir,
|
void execute(const std::vector<std::string>& inputFile, const std::string& outputDir,
|
||||||
int opts, int verbosity)
|
int opts, int verbosity)
|
||||||
{
|
{
|
||||||
for (const auto& filename : inputFile) {
|
for (const auto& filename : inputFile) {
|
||||||
std::vector<SpvWord> spv;
|
std::vector<SpvWord> spv;
|
||||||
read(spv, filename, verbosity);
|
read(spv, filename, verbosity);
|
||||||
spv::spirvbin_t(verbosity).remap(spv, opts);
|
spv::spirvbin_t(verbosity).remap(spv, opts);
|
||||||
|
|
||||||
const std::string outfile = outputDir + path_sep_char() + basename(filename);
|
const std::string outfile = outputDir + path_sep_char() + basename(filename);
|
||||||
|
|
||||||
write(spv, outfile, verbosity);
|
write(spv, outfile, verbosity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbosity > 0)
|
if (verbosity > 0)
|
||||||
std::cout << "Done: " << inputFile.size() << " file(s) processed" << std::endl;
|
std::cout << "Done: " << inputFile.size() << " file(s) processed" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse command line options
|
// Parse command line options
|
||||||
void parseCmdLine(int argc, char** argv, std::vector<std::string>& inputFile,
|
void parseCmdLine(int argc, char** argv, std::vector<std::string>& inputFile,
|
||||||
std::string& outputDir,
|
std::string& outputDir,
|
||||||
int& options,
|
int& options,
|
||||||
int& verbosity)
|
int& verbosity)
|
||||||
{
|
{
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
|
|
||||||
verbosity = 0;
|
verbosity = 0;
|
||||||
options = spv::spirvbin_t::NONE;
|
options = spv::spirvbin_t::NONE;
|
||||||
|
|
||||||
// Parse command line.
|
// Parse command line.
|
||||||
// boost::program_options would be quite a bit nicer, but we don't want to
|
// boost::program_options would be quite a bit nicer, but we don't want to
|
||||||
// introduce a dependency on boost.
|
// introduce a dependency on boost.
|
||||||
for (int a=1; a<argc; ) {
|
for (int a=1; a<argc; ) {
|
||||||
const std::string arg = argv[a];
|
const std::string arg = argv[a];
|
||||||
|
|
||||||
if (arg == "--output" || arg == "-o") {
|
if (arg == "--output" || arg == "-o") {
|
||||||
// Output directory
|
// Output directory
|
||||||
if (++a >= argc)
|
if (++a >= argc)
|
||||||
usage(argv[0], "--output requires an argument");
|
usage(argv[0], "--output requires an argument");
|
||||||
if (!outputDir.empty())
|
if (!outputDir.empty())
|
||||||
usage(argv[0], "--output can be provided only once");
|
usage(argv[0], "--output can be provided only once");
|
||||||
|
|
||||||
outputDir = argv[a++];
|
outputDir = argv[a++];
|
||||||
|
|
||||||
// Remove trailing directory separator characters
|
// Remove trailing directory separator characters
|
||||||
while (!outputDir.empty() && outputDir.back() == path_sep_char())
|
while (!outputDir.empty() && outputDir.back() == path_sep_char())
|
||||||
outputDir.pop_back();
|
outputDir.pop_back();
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (arg == "-vv") { verbosity = 2; ++a; } // verbosity shortcuts
|
else if (arg == "-vv") { verbosity = 2; ++a; } // verbosity shortcuts
|
||||||
else if (arg == "-vvv") { verbosity = 3; ++a; } // ...
|
else if (arg == "-vvv") { verbosity = 3; ++a; } // ...
|
||||||
else if (arg == "-vvvv") { verbosity = 4; ++a; } // ...
|
else if (arg == "-vvvv") { verbosity = 4; ++a; } // ...
|
||||||
else if (arg == "-vvvvv") { verbosity = 5; ++a; } // ...
|
else if (arg == "-vvvvv") { verbosity = 5; ++a; } // ...
|
||||||
|
|
||||||
else if (arg == "--verbose" || arg == "-v") {
|
else if (arg == "--verbose" || arg == "-v") {
|
||||||
++a;
|
++a;
|
||||||
verbosity = 1;
|
verbosity = 1;
|
||||||
|
|
||||||
if (a < argc) {
|
if (a < argc) {
|
||||||
try {
|
try {
|
||||||
verbosity = std::stoi(argv[a]);
|
verbosity = std::stoi(argv[a]);
|
||||||
++a;
|
++a;
|
||||||
} catch (const std::invalid_argument&) { } // ok to have no numeric value
|
} catch (const std::invalid_argument&) { } // ok to have no numeric value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (arg == "--version" || arg == "-V") {
|
else if (arg == "--version" || arg == "-V") {
|
||||||
std::cout << basename(argv[0]) << " version 0.97 " << __DATE__ << " " << __TIME__ << std::endl;
|
std::cout << basename(argv[0]) << " version 0.97 " << __DATE__ << " " << __TIME__ << std::endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
} else if (arg == "--input" || arg == "-i") {
|
} else if (arg == "--input" || arg == "-i") {
|
||||||
// Collect input files
|
// Collect input files
|
||||||
for (++a; a < argc && argv[a][0] != '-'; ++a)
|
for (++a; a < argc && argv[a][0] != '-'; ++a)
|
||||||
inputFile.push_back(argv[a]);
|
inputFile.push_back(argv[a]);
|
||||||
} else if (arg == "--do-everything") {
|
} else if (arg == "--do-everything") {
|
||||||
++a;
|
++a;
|
||||||
options = options | spv::spirvbin_t::DO_EVERYTHING;
|
options = options | spv::spirvbin_t::DO_EVERYTHING;
|
||||||
} else if (arg == "--strip-all" || arg == "-s") {
|
} else if (arg == "--strip-all" || arg == "-s") {
|
||||||
++a;
|
++a;
|
||||||
options = options | spv::spirvbin_t::STRIP;
|
options = options | spv::spirvbin_t::STRIP;
|
||||||
} else if (arg == "--strip") {
|
} else if (arg == "--strip") {
|
||||||
++a;
|
++a;
|
||||||
if (strncmp(argv[a], "all", 3) == 0) {
|
if (strncmp(argv[a], "all", 3) == 0) {
|
||||||
options = options | spv::spirvbin_t::STRIP;
|
options = options | spv::spirvbin_t::STRIP;
|
||||||
++a;
|
++a;
|
||||||
}
|
}
|
||||||
} else if (arg == "--dce") {
|
} else if (arg == "--dce") {
|
||||||
// Parse comma (or colon, etc) separated list of things to dce
|
// Parse comma (or colon, etc) separated list of things to dce
|
||||||
++a;
|
++a;
|
||||||
for (const char* c = argv[a]; *c; ++c) {
|
for (const char* c = argv[a]; *c; ++c) {
|
||||||
if (strncmp(c, "all", 3) == 0) {
|
if (strncmp(c, "all", 3) == 0) {
|
||||||
options = (options | spv::spirvbin_t::DCE_ALL);
|
options = (options | spv::spirvbin_t::DCE_ALL);
|
||||||
c += 3;
|
c += 3;
|
||||||
} else if (strncmp(c, "*", 1) == 0) {
|
} else if (strncmp(c, "*", 1) == 0) {
|
||||||
options = (options | spv::spirvbin_t::DCE_ALL);
|
options = (options | spv::spirvbin_t::DCE_ALL);
|
||||||
c += 1;
|
c += 1;
|
||||||
} else if (strncmp(c, "funcs", 5) == 0) {
|
} else if (strncmp(c, "funcs", 5) == 0) {
|
||||||
options = (options | spv::spirvbin_t::DCE_FUNCS);
|
options = (options | spv::spirvbin_t::DCE_FUNCS);
|
||||||
c += 5;
|
c += 5;
|
||||||
} else if (strncmp(c, "types", 5) == 0) {
|
} else if (strncmp(c, "types", 5) == 0) {
|
||||||
options = (options | spv::spirvbin_t::DCE_TYPES);
|
options = (options | spv::spirvbin_t::DCE_TYPES);
|
||||||
c += 5;
|
c += 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++a;
|
++a;
|
||||||
} else if (arg == "--map") {
|
} else if (arg == "--map") {
|
||||||
// Parse comma (or colon, etc) separated list of things to map
|
// Parse comma (or colon, etc) separated list of things to map
|
||||||
++a;
|
++a;
|
||||||
for (const char* c = argv[a]; *c; ++c) {
|
for (const char* c = argv[a]; *c; ++c) {
|
||||||
if (strncmp(c, "all", 3) == 0) {
|
if (strncmp(c, "all", 3) == 0) {
|
||||||
options = (options | spv::spirvbin_t::MAP_ALL);
|
options = (options | spv::spirvbin_t::MAP_ALL);
|
||||||
c += 3;
|
c += 3;
|
||||||
} else if (strncmp(c, "*", 1) == 0) {
|
} else if (strncmp(c, "*", 1) == 0) {
|
||||||
options = (options | spv::spirvbin_t::MAP_ALL);
|
options = (options | spv::spirvbin_t::MAP_ALL);
|
||||||
c += 1;
|
c += 1;
|
||||||
} else if (strncmp(c, "types", 5) == 0) {
|
} else if (strncmp(c, "types", 5) == 0) {
|
||||||
options = (options | spv::spirvbin_t::MAP_TYPES);
|
options = (options | spv::spirvbin_t::MAP_TYPES);
|
||||||
c += 5;
|
c += 5;
|
||||||
} else if (strncmp(c, "names", 5) == 0) {
|
} else if (strncmp(c, "names", 5) == 0) {
|
||||||
options = (options | spv::spirvbin_t::MAP_NAMES);
|
options = (options | spv::spirvbin_t::MAP_NAMES);
|
||||||
c += 5;
|
c += 5;
|
||||||
} else if (strncmp(c, "funcs", 5) == 0) {
|
} else if (strncmp(c, "funcs", 5) == 0) {
|
||||||
options = (options | spv::spirvbin_t::MAP_FUNCS);
|
options = (options | spv::spirvbin_t::MAP_FUNCS);
|
||||||
c += 5;
|
c += 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++a;
|
++a;
|
||||||
} else if (arg == "--opt") {
|
} else if (arg == "--opt") {
|
||||||
++a;
|
++a;
|
||||||
for (const char* c = argv[a]; *c; ++c) {
|
for (const char* c = argv[a]; *c; ++c) {
|
||||||
if (strncmp(c, "all", 3) == 0) {
|
if (strncmp(c, "all", 3) == 0) {
|
||||||
options = (options | spv::spirvbin_t::OPT_ALL);
|
options = (options | spv::spirvbin_t::OPT_ALL);
|
||||||
c += 3;
|
c += 3;
|
||||||
} else if (strncmp(c, "*", 1) == 0) {
|
} else if (strncmp(c, "*", 1) == 0) {
|
||||||
options = (options | spv::spirvbin_t::OPT_ALL);
|
options = (options | spv::spirvbin_t::OPT_ALL);
|
||||||
c += 1;
|
c += 1;
|
||||||
} else if (strncmp(c, "loadstore", 9) == 0) {
|
} else if (strncmp(c, "loadstore", 9) == 0) {
|
||||||
options = (options | spv::spirvbin_t::OPT_LOADSTORE);
|
options = (options | spv::spirvbin_t::OPT_LOADSTORE);
|
||||||
c += 9;
|
c += 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++a;
|
++a;
|
||||||
} else if (arg == "--help" || arg == "-?") {
|
} else if (arg == "--help" || arg == "-?") {
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
} else {
|
} else {
|
||||||
usage(argv[0], "Unknown command line option");
|
usage(argv[0], "Unknown command line option");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
std::vector<std::string> inputFile;
|
std::vector<std::string> inputFile;
|
||||||
std::string outputDir;
|
std::string outputDir;
|
||||||
int opts;
|
int opts;
|
||||||
int verbosity;
|
int verbosity;
|
||||||
|
|
||||||
#ifdef use_cpp11
|
#ifdef use_cpp11
|
||||||
// handle errors by exiting
|
// handle errors by exiting
|
||||||
spv::spirvbin_t::registerErrorHandler(errHandler);
|
spv::spirvbin_t::registerErrorHandler(errHandler);
|
||||||
|
|
||||||
// Log messages to std::cout
|
// Log messages to std::cout
|
||||||
spv::spirvbin_t::registerLogHandler(logHandler);
|
spv::spirvbin_t::registerLogHandler(logHandler);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (argc < 2)
|
if (argc < 2)
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
|
|
||||||
parseCmdLine(argc, argv, inputFile, outputDir, opts, verbosity);
|
parseCmdLine(argc, argv, inputFile, outputDir, opts, verbosity);
|
||||||
|
|
||||||
if (outputDir.empty())
|
if (outputDir.empty())
|
||||||
usage(argv[0], "Output directory required");
|
usage(argv[0], "Output directory required");
|
||||||
|
|
||||||
std::string errmsg;
|
std::string errmsg;
|
||||||
|
|
||||||
// Main operations: read, remap, and write.
|
// Main operations: read, remap, and write.
|
||||||
execute(inputFile, outputDir, opts, verbosity);
|
execute(inputFile, outputDir, opts, verbosity);
|
||||||
|
|
||||||
// If we get here, everything went OK! Nothing more to be done.
|
// If we get here, everything went OK! Nothing more to be done.
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user