mirror of
https://github.com/RPCS3/glslang.git
synced 2024-11-23 19:29:44 +00:00
glslangValidator: Add straightforward SPIR-V support (non-optimizing, ~3.x functionality).
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@30032 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
1899e83369
commit
0df0cdeeeb
@ -1,59 +0,0 @@
|
||||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "BilBuilder.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <cstdio>
|
||||
#endif
|
||||
|
||||
namespace glbil {
|
||||
|
||||
Builder::Builder()
|
||||
{
|
||||
}
|
||||
|
||||
Builder::~Builder()
|
||||
{
|
||||
}
|
||||
|
||||
void MissingFunctionality(const char* fun)
|
||||
{
|
||||
printf("Missing functionality: %s\n", fun);
|
||||
}
|
||||
|
||||
}; // end glbil namespace
|
@ -1,56 +0,0 @@
|
||||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
#ifndef BilBuilder_H
|
||||
#define BilBuilder_H
|
||||
|
||||
#include "Bil.h"
|
||||
#include "Bir.h"
|
||||
|
||||
#include <stack>
|
||||
|
||||
namespace glbil {
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
Builder();
|
||||
virtual ~Builder();
|
||||
};
|
||||
|
||||
void MissingFunctionality(const char*);
|
||||
|
||||
}; // end glbil namespace
|
||||
|
||||
#endif // BilBuilder_H
|
49
BIL/Bir.h
49
BIL/Bir.h
@ -1,49 +0,0 @@
|
||||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
#ifndef Bir_H
|
||||
#define Bir_H
|
||||
|
||||
#include "Bil.h"
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace glbil {
|
||||
|
||||
|
||||
}; // end glbil namespace
|
||||
|
||||
#endif // Bir_H
|
@ -1,14 +0,0 @@
|
||||
namespace GLSL_STD_450 {
|
||||
|
||||
enum Entrypoints {
|
||||
Round,
|
||||
Count
|
||||
};
|
||||
|
||||
extern const char* Names[Count];
|
||||
|
||||
inline void Initialize()
|
||||
{
|
||||
}
|
||||
|
||||
}; // end namespace GLSL_STD_450
|
@ -1,53 +0,0 @@
|
||||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "Bil.h"
|
||||
#include "GlslangToBil.h"
|
||||
#include "BilBuilder.h"
|
||||
|
||||
// Glslang includes
|
||||
#include "glslang/MachineIndependent/localintermediate.h"
|
||||
#include "glslang/MachineIndependent/SymbolTable.h"
|
||||
|
||||
namespace glslang {
|
||||
|
||||
void GlslangToBil(const glslang::TIntermediate& intermediate, std::vector<unsigned int> bil)
|
||||
{
|
||||
}
|
||||
|
||||
void OutputBil(const std::vector<unsigned int>& bil, const char* baseName)
|
||||
{
|
||||
}
|
||||
|
||||
}; // end namespace glslang
|
@ -16,4 +16,4 @@ endif(WIN32)
|
||||
add_subdirectory(glslang)
|
||||
add_subdirectory(OGLCompilersDLL)
|
||||
add_subdirectory(StandAlone)
|
||||
add_subdirectory(BIL)
|
||||
add_subdirectory(SPIRV)
|
||||
|
@ -3,20 +3,20 @@ cmake_minimum_required(VERSION 2.8)
|
||||
include_directories(.. ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(SOURCES
|
||||
GlslangToBil.cpp
|
||||
BilBuilder.cpp)
|
||||
GlslangToSpv.cpp
|
||||
SpvBuilder.cpp)
|
||||
|
||||
set(HEADERS
|
||||
Bil.h
|
||||
GlslangToBil.h
|
||||
BilBuilder.h
|
||||
Bir.h)
|
||||
spirv.h
|
||||
GlslangToSpv.h
|
||||
SpvBuilder.h
|
||||
SpvIR.h)
|
||||
|
||||
add_library(BIL STATIC ${SOURCES} ${HEADERS})
|
||||
add_library(SPIRV STATIC ${SOURCES} ${HEADERS})
|
||||
|
||||
if(WIN32)
|
||||
source_group("Source" FILES ${SOURCES} ${HEADERS})
|
||||
endif(WIN32)
|
||||
|
||||
install(TARGETS BIL
|
||||
install(TARGETS SPIRV
|
||||
ARCHIVE DESTINATION lib)
|
212
SPIRV/GLSL450Lib.h
Normal file
212
SPIRV/GLSL450Lib.h
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
** Copyright (c) 2014-2015 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
//
|
||||
// Author: John Kessenich, LunarG
|
||||
//
|
||||
|
||||
namespace GLSL_STD_450 {
|
||||
|
||||
enum Entrypoints {
|
||||
Round,
|
||||
RoundEven,
|
||||
Trunc,
|
||||
Abs,
|
||||
Sign,
|
||||
Floor,
|
||||
Ceil,
|
||||
Fract,
|
||||
|
||||
Radians,
|
||||
Degrees,
|
||||
Sin,
|
||||
Cos,
|
||||
Tan,
|
||||
Asin,
|
||||
Acos,
|
||||
Atan,
|
||||
Sinh,
|
||||
Cosh,
|
||||
Tanh,
|
||||
Asinh,
|
||||
Acosh,
|
||||
Atanh,
|
||||
Atan2,
|
||||
|
||||
Pow,
|
||||
Exp,
|
||||
Log,
|
||||
Exp2,
|
||||
Log2,
|
||||
Sqrt,
|
||||
InverseSqrt,
|
||||
|
||||
Determinant,
|
||||
MatrixInverse,
|
||||
|
||||
Modf, // second argument needs the OpVariable, not an OpLoad
|
||||
Min,
|
||||
Max,
|
||||
Clamp,
|
||||
Mix,
|
||||
Step,
|
||||
SmoothStep,
|
||||
|
||||
FloatBitsToInt,
|
||||
FloatBitsToUint,
|
||||
IntBitsToFloat,
|
||||
UintBitsToFloat,
|
||||
|
||||
Fma,
|
||||
Frexp,
|
||||
Ldexp,
|
||||
|
||||
PackSnorm4x8,
|
||||
PackUnorm4x8,
|
||||
PackSnorm2x16,
|
||||
PackUnorm2x16,
|
||||
PackHalf2x16,
|
||||
PackDouble2x32,
|
||||
UnpackSnorm2x16,
|
||||
UnpackUnorm2x16,
|
||||
UnpackHalf2x16,
|
||||
UnpackSnorm4x8,
|
||||
UnpackUnorm4x8,
|
||||
UnpackDouble2x32,
|
||||
|
||||
Length,
|
||||
Distance,
|
||||
Cross,
|
||||
Normalize,
|
||||
Ftransform,
|
||||
FaceForward,
|
||||
Reflect,
|
||||
Refract,
|
||||
|
||||
UaddCarry,
|
||||
UsubBorrow,
|
||||
UmulExtended,
|
||||
ImulExtended,
|
||||
BitfieldExtract,
|
||||
BitfieldInsert,
|
||||
BitfieldReverse,
|
||||
BitCount,
|
||||
FindLSB,
|
||||
FindMSB,
|
||||
|
||||
InterpolateAtCentroid,
|
||||
InterpolateAtSample,
|
||||
InterpolateAtOffset,
|
||||
|
||||
Count
|
||||
};
|
||||
|
||||
inline void GetDebugNames(const char** names)
|
||||
{
|
||||
for (int i = 0; i < Count; ++i)
|
||||
names[i] = "unknown";
|
||||
|
||||
names[Round] = "round";
|
||||
names[RoundEven] = "roundEven";
|
||||
names[Trunc] = "trunc";
|
||||
names[Abs] = "abs";
|
||||
names[Sign] = "sign";
|
||||
names[Floor] = "floor";
|
||||
names[Ceil] = "ceil";
|
||||
names[Fract] = "fract";
|
||||
names[Radians] = "radians";
|
||||
names[Degrees] = "degrees";
|
||||
names[Sin] = "sin";
|
||||
names[Cos] = "cos";
|
||||
names[Tan] = "tan";
|
||||
names[Asin] = "asin";
|
||||
names[Acos] = "acos";
|
||||
names[Atan] = "atan";
|
||||
names[Sinh] = "sinh";
|
||||
names[Cosh] = "cosh";
|
||||
names[Tanh] = "tanh";
|
||||
names[Asinh] = "asinh";
|
||||
names[Acosh] = "acosh";
|
||||
names[Atanh] = "atanh";
|
||||
names[Atan2] = "atan2";
|
||||
names[Pow] = "pow";
|
||||
names[Exp] = "exp";
|
||||
names[Log] = "log";
|
||||
names[Exp2] = "exp2";
|
||||
names[Log2] = "log2";
|
||||
names[Sqrt] = "sqrt";
|
||||
names[InverseSqrt] = "inverseSqrt";
|
||||
names[Determinant] = "determinant";
|
||||
names[MatrixInverse] = "matrixInverse";
|
||||
names[Modf] = "modf";
|
||||
names[Min] = "min";
|
||||
names[Max] = "max";
|
||||
names[Clamp] = "clamp";
|
||||
names[Mix] = "mix";
|
||||
names[Step] = "step";
|
||||
names[SmoothStep] = "smoothStep";
|
||||
names[FloatBitsToInt] = "floatBitsToInt";
|
||||
names[FloatBitsToUint] = "floatBitsToUint";
|
||||
names[IntBitsToFloat] = "intBitsToFloat";
|
||||
names[UintBitsToFloat] = "uintBitsToFloat";
|
||||
names[Fma] = "fma";
|
||||
names[Frexp] = "frexp";
|
||||
names[Ldexp] = "ldexp";
|
||||
names[PackSnorm4x8] = "packSnorm4x8";
|
||||
names[PackUnorm4x8] = "packUnorm4x8";
|
||||
names[PackSnorm2x16] = "packSnorm2x16";
|
||||
names[PackUnorm2x16] = "packUnorm2x16";
|
||||
names[PackHalf2x16] = "packHalf2x16";
|
||||
names[PackDouble2x32] = "packDouble2x32";
|
||||
names[PackHalf2x16] = "packHalf2x16";
|
||||
names[UnpackSnorm2x16] = "unpackSnorm2x16";
|
||||
names[UnpackUnorm2x16] = "unpackUnorm2x16";
|
||||
names[UnpackHalf2x16] = "unpackHalf2x16";
|
||||
names[UnpackSnorm4x8] = "unpackSnorm4x8";
|
||||
names[UnpackUnorm4x8] = "unpackUnorm4x8";
|
||||
names[UnpackDouble2x32] = "unpackDouble2x32";
|
||||
names[UnpackHalf2x16] = "unpackHalf2x16";
|
||||
names[Length] = "length";
|
||||
names[Distance] = "distance";
|
||||
names[Cross] = "cross";
|
||||
names[Normalize] = "normalize";
|
||||
names[Ftransform] = "ftransform";
|
||||
names[FaceForward] = "faceForward";
|
||||
names[Reflect] = "reflect";
|
||||
names[Refract] = "refract";
|
||||
names[UaddCarry] = "uaddCarry";
|
||||
names[UsubBorrow] = "usubBorrow";
|
||||
names[UmulExtended] = "umulExtended";
|
||||
names[ImulExtended] = "imulExtended";
|
||||
names[BitfieldExtract] = "bitfieldExtract";
|
||||
names[BitfieldInsert] = "bitfieldInsert";
|
||||
names[BitfieldReverse] = "bitfieldReverse";
|
||||
names[BitCount] = "bitCount";
|
||||
names[FindLSB] = "findLSB";
|
||||
names[FindMSB] = "findMSB";
|
||||
names[InterpolateAtCentroid] = "interpolateAtCentroid";
|
||||
names[InterpolateAtSample] = "interpolateAtSample";
|
||||
names[InterpolateAtOffset] = "interpolateAtOffset";
|
||||
}
|
||||
|
||||
}; // end namespace GLSL_STD_450
|
2589
SPIRV/GlslangToSpv.cpp
Normal file
2589
SPIRV/GlslangToSpv.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -36,8 +36,7 @@
|
||||
|
||||
namespace glslang {
|
||||
|
||||
void GlslangToBil(const glslang::TIntermediate& intermediate, std::vector<unsigned int> bil);
|
||||
|
||||
void OutputBil(const std::vector<unsigned int>& bil, const char* baseName);
|
||||
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv);
|
||||
void OutputSpv(const std::vector<unsigned int>& spirv, const char* baseName);
|
||||
|
||||
};
|
2011
SPIRV/SpvBuilder.cpp
Normal file
2011
SPIRV/SpvBuilder.cpp
Normal file
File diff suppressed because it is too large
Load Diff
519
SPIRV/SpvBuilder.h
Normal file
519
SPIRV/SpvBuilder.h
Normal file
@ -0,0 +1,519 @@
|
||||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Author: John Kessenich, LunarG
|
||||
//
|
||||
|
||||
//
|
||||
// "Builder" is an interface to fully build SPIR-V IR. Allocate one of
|
||||
// these to build (a thread safe) internal SPIR-V representation (IR),
|
||||
// and then dump it as a binary stream according to the SPIR-V specification.
|
||||
//
|
||||
// A Builder has a 1:1 relationship with a SPIR-V module.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef SpvBuilder_H
|
||||
#define SpvBuilder_H
|
||||
|
||||
#include "spirv.h"
|
||||
#include "spvIR.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stack>
|
||||
#include <map>
|
||||
|
||||
namespace spv {
|
||||
|
||||
class Builder {
|
||||
public:
|
||||
Builder(unsigned int userNumber);
|
||||
virtual ~Builder();
|
||||
|
||||
static const int maxMatrixSize = 4;
|
||||
|
||||
void setSource(spv::SourceLanguage lang, int version)
|
||||
{
|
||||
source = lang;
|
||||
sourceVersion = version;
|
||||
}
|
||||
void addSourceExtension(const char* ext) { extensions.push_back(ext); }
|
||||
Id import(const char*);
|
||||
void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
|
||||
{
|
||||
addressModel = addr;
|
||||
memoryModel = mem;
|
||||
}
|
||||
|
||||
// To get a new <id> for anything needing a new one.
|
||||
Id getUniqueId() { return ++uniqueId; }
|
||||
|
||||
// To get a set of new <id>s, e.g., for a set of function parameters
|
||||
Id getUniqueIds(int numIds)
|
||||
{
|
||||
Id id = uniqueId + 1;
|
||||
uniqueId += numIds;
|
||||
return id;
|
||||
}
|
||||
|
||||
// For creating new types (will return old type if the requested one was already made).
|
||||
Id makeVoidType();
|
||||
Id makeBoolType();
|
||||
Id makePointer(StorageClass, Id type);
|
||||
Id makeIntegerType(int width, bool hasSign); // generic
|
||||
Id makeIntType(int width) { return makeIntegerType(width, true); }
|
||||
Id makeUintType(int width) { return makeIntegerType(width, false); }
|
||||
Id makeFloatType(int width);
|
||||
Id makeStructType(std::vector<Id>& members, const char*);
|
||||
Id makeVectorType(Id component, int size);
|
||||
Id makeMatrixType(Id component, int cols, int rows);
|
||||
Id makeArrayType(Id element, unsigned size);
|
||||
Id makeFunctionType(Id returnType, std::vector<Id>& paramTypes);
|
||||
enum samplerContent {
|
||||
samplerContentTexture,
|
||||
samplerContentImage,
|
||||
samplerContentTextureFilter
|
||||
};
|
||||
Id makeSampler(Id sampledType, Dimensionality, samplerContent, bool arrayed, bool shadow, bool ms);
|
||||
|
||||
// For querying about types.
|
||||
Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
|
||||
Id getDerefTypeId(Id resultId) const;
|
||||
OpCode getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); }
|
||||
OpCode getTypeClass(Id typeId) const { return getOpCode(typeId); }
|
||||
OpCode getMostBasicTypeClass(Id typeId) const;
|
||||
int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
|
||||
int getNumTypeComponents(Id typeId) const;
|
||||
Id getScalarTypeId(Id typeId) const;
|
||||
Id getContainedTypeId(Id typeId) const;
|
||||
Id getContainedTypeId(Id typeId, int) const;
|
||||
|
||||
bool isPointer(Id resultId) const { return isPointerType(getTypeId(resultId)); }
|
||||
bool isScalar(Id resultId) const { return isScalarType(getTypeId(resultId)); }
|
||||
bool isVector(Id resultId) const { return isVectorType(getTypeId(resultId)); }
|
||||
bool isMatrix(Id resultId) const { return isMatrixType(getTypeId(resultId)); }
|
||||
bool isAggregate(Id resultId) const { return isAggregateType(getTypeId(resultId)); }
|
||||
|
||||
bool isPointerType(Id typeId) const { return getTypeClass(typeId) == OpTypePointer; }
|
||||
bool isScalarType(Id typeId) const { return getTypeClass(typeId) == OpTypeFloat || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
|
||||
bool isVectorType(Id typeId) const { return getTypeClass(typeId) == OpTypeVector; }
|
||||
bool isMatrixType(Id typeId) const { return getTypeClass(typeId) == OpTypeMatrix; }
|
||||
bool isStructType(Id typeId) const { return getTypeClass(typeId) == OpTypeStruct; }
|
||||
bool isArrayType(Id typeId) const { return getTypeClass(typeId) == OpTypeArray; }
|
||||
bool isAggregateType(Id typeId) const { return isArrayType(typeId) || isStructType(typeId); }
|
||||
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
|
||||
|
||||
bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
|
||||
unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
|
||||
|
||||
int getTypeNumColumns(Id typeId) const
|
||||
{
|
||||
assert(isMatrixType(typeId));
|
||||
return getNumTypeComponents(typeId);
|
||||
}
|
||||
int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); }
|
||||
int getTypeNumRows(Id typeId) const
|
||||
{
|
||||
assert(isMatrixType(typeId));
|
||||
return getNumTypeComponents(getContainedTypeId(typeId));
|
||||
}
|
||||
int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
|
||||
|
||||
Dimensionality getDimensionality(Id resultId) const
|
||||
{
|
||||
assert(isSamplerType(getTypeId(resultId)));
|
||||
return (Dimensionality)module.getInstruction(getTypeId(resultId))->getImmediateOperand(1);
|
||||
}
|
||||
bool isArrayedSampler(Id resultId) const
|
||||
{
|
||||
assert(isSamplerType(getTypeId(resultId)));
|
||||
return module.getInstruction(getTypeId(resultId))->getImmediateOperand(3) != 0;
|
||||
}
|
||||
|
||||
// For making new constants (will return old constant if the requested one was already made).
|
||||
Id makeBoolConstant(bool b);
|
||||
Id makeIntConstant(Id typeId, unsigned value);
|
||||
Id makeIntConstant(int i) { return makeIntConstant(makeIntType(32), (unsigned)i); }
|
||||
Id makeUintConstant(unsigned u) { return makeIntConstant(makeUintType(32), u); }
|
||||
Id makeFloatConstant(float f);
|
||||
Id makeDoubleConstant(double d);
|
||||
|
||||
// Turn the array of constants into a proper spv constant of the requested type.
|
||||
Id makeCompositeConstant(Id type, std::vector<Id>& comps);
|
||||
|
||||
// Methods for adding information outside the CFG.
|
||||
void addEntryPoint(ExecutionModel, Function*);
|
||||
void addExecutionMode(Function*, ExecutionMode mode, int value = -1);
|
||||
void addName(Id, const char* name);
|
||||
void addMemberName(Id, int member, const char* name);
|
||||
void addLine(Id target, Id fileName, int line, int column);
|
||||
void addDecoration(Id, Decoration, int num = -1);
|
||||
void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
|
||||
|
||||
// At the end of what block do the next create*() instructions go?
|
||||
void setBuildPoint(Block* bp) { buildPoint = bp; }
|
||||
Block* getBuildPoint() const { return buildPoint; }
|
||||
|
||||
// Make the main function.
|
||||
Function* makeMain();
|
||||
|
||||
// Return from main. Implicit denotes a return at the very end of main.
|
||||
void makeMainReturn(bool implicit = false) { makeReturn(implicit, 0, true); }
|
||||
|
||||
// Close the main function.
|
||||
void closeMain();
|
||||
|
||||
// Make a shader-style function, and create its entry block if entry is non-zero.
|
||||
// Return the function, pass back the entry.
|
||||
Function* makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes, Block **entry = 0);
|
||||
|
||||
// Create a return. Pass whether it is a return form main, and the return
|
||||
// value (if applicable). In the case of an implicit return, no post-return
|
||||
// block is inserted.
|
||||
void makeReturn(bool implicit = false, Id retVal = 0, bool isMain = false);
|
||||
|
||||
// Generate all the code needed to finish up a function.
|
||||
void leaveFunction(bool main);
|
||||
|
||||
// Create a discard.
|
||||
void makeDiscard();
|
||||
|
||||
// Create a global or function local or IO variable.
|
||||
Id createVariable(StorageClass, Id type, const char* name = 0);
|
||||
|
||||
// Store into an Id and return the l-value
|
||||
void createStore(Id rValue, Id lValue);
|
||||
|
||||
// Load from an Id and return it
|
||||
Id createLoad(Id lValue);
|
||||
|
||||
// Create an OpAccessChain instruction
|
||||
Id createAccessChain(StorageClass, Id base, std::vector<Id>& offsets);
|
||||
|
||||
// Create an OpCompositeExtract instruction
|
||||
Id createCompositeExtract(Id composite, Id typeId, unsigned index);
|
||||
Id createCompositeExtract(Id composite, Id typeId, std::vector<unsigned>& indexes);
|
||||
Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index);
|
||||
Id createCompositeInsert(Id object, Id composite, Id typeId, std::vector<unsigned>& indexes);
|
||||
|
||||
Id createEmptyOp(OpCode);
|
||||
void createControlBarrier(unsigned executionScope);
|
||||
void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics);
|
||||
Id createUnaryOp(OpCode, Id typeId, Id operand);
|
||||
Id createBinOp(OpCode, Id typeId, Id operand1, Id operand2);
|
||||
Id createTriOp(OpCode, Id typeId, Id operand1, Id operand2, Id operand3);
|
||||
Id createTernaryOp(OpCode, Id typeId, Id operand1, Id operand2, Id operand3);
|
||||
Id createFunctionCall(spv::Function*, std::vector<spv::Id>&);
|
||||
|
||||
// Take an rvalue (source) and a set of channels to extract from it to
|
||||
// make a new rvalue, which is returned.
|
||||
Id createRvalueSwizzle(Id typeId, Id source, std::vector<unsigned>& channels);
|
||||
|
||||
// Take a copy of an lvalue (target) and a source of components, and set the
|
||||
// source components into the lvalue where the 'channels' say to put them.
|
||||
// An update version of the target is returned.
|
||||
// (No true lvalue or stores are used.)
|
||||
Id createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<unsigned>& channels);
|
||||
|
||||
// If the value passed in is an instruction and the precision is not EMpNone,
|
||||
// it gets tagged with the requested precision.
|
||||
void setPrecision(Id value, Decoration precision)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Can smear a scalar to a vector for the following forms:
|
||||
// - promoteScalar(scalar, vector) // smear scalar to width of vector
|
||||
// - promoteScalar(vector, scalar) // smear scalar to width of vector
|
||||
// - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to
|
||||
// - promoteScalar(scalar, scalar) // do nothing
|
||||
// Other forms are not allowed.
|
||||
//
|
||||
// Note: One of the arguments will change, with the result coming back that way rather than
|
||||
// through the return value.
|
||||
void promoteScalar(Decoration precision, Id& left, Id& right);
|
||||
|
||||
// make a value by smearing the scalar to fill the type
|
||||
Id smearScalar(Decoration precision, Id scalarVal, Id);
|
||||
|
||||
// Create a call to a built-in function.
|
||||
Id createBuiltinCall(Decoration precision, Id resultType, Id builtins, int entryPoint, std::vector<Id>& args);
|
||||
|
||||
// List of parameters used to create a texture operation
|
||||
struct TextureParameters {
|
||||
Id sampler;
|
||||
Id coords;
|
||||
Id bias;
|
||||
Id lod;
|
||||
Id Dref;
|
||||
Id offset;
|
||||
Id gradX;
|
||||
Id gradY;
|
||||
};
|
||||
|
||||
// Select the correct texture operation based on all inputs, and emit the correct instruction
|
||||
Id createTextureCall(Decoration precision, Id resultType, bool proj, const TextureParameters&);
|
||||
|
||||
// Emit the OpTextureQuery* instruction that was passed in.
|
||||
// Figure out the right return value and type, and return it.
|
||||
Id createTextureQueryCall(OpCode, const TextureParameters&);
|
||||
|
||||
Id createSamplePositionCall(Decoration precision, Id, Id);
|
||||
|
||||
Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned);
|
||||
Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id);
|
||||
|
||||
// Reduction comparision for composites: For equal and not-equal resulting in a scalar.
|
||||
Id createCompare(Decoration precision, Id, Id, bool /* true if for equal, fales if for not-equal */);
|
||||
|
||||
// OpCompositeConstruct
|
||||
Id createCompositeConstruct(Id typeId, std::vector<Id>& constituents);
|
||||
|
||||
// vector or scalar constructor
|
||||
Id createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId);
|
||||
|
||||
// matrix constructor
|
||||
Id createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id constructee);
|
||||
|
||||
// Helper to use for building nested control flow with if-then-else.
|
||||
class If {
|
||||
public:
|
||||
If(Id condition, Builder& builder);
|
||||
~If() {}
|
||||
|
||||
void makeBeginElse();
|
||||
void makeEndIf();
|
||||
|
||||
private:
|
||||
Builder& builder;
|
||||
Id condition;
|
||||
Function* function;
|
||||
Block* headerBlock;
|
||||
Block* thenBlock;
|
||||
Block* elseBlock;
|
||||
Block* mergeBlock;
|
||||
};
|
||||
|
||||
// Make a switch statement. A switch has 'numSegments' of pieces of code, not containing
|
||||
// any case/default labels, all separated by one or more case/default labels. Each possible
|
||||
// case value v is a jump to the caseValues[v] segment. The defaultSegment is also in this
|
||||
// number space. How to compute the value is given by 'condition', as in switch(condition).
|
||||
//
|
||||
// The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches.
|
||||
//
|
||||
// Use a defaultSegment < 0 if there is no default segment (to branch to post switch).
|
||||
//
|
||||
// Returns the right set of basic blocks to start each code segment with, so that the caller's
|
||||
// recursion stack can hold the memory for it.
|
||||
//
|
||||
void makeSwitch(Id condition, int numSegments, std::vector<int>& caseValues, std::vector<int>& valueToSegment, int defaultSegment,
|
||||
std::vector<Block*>& segmentBB); // return argument
|
||||
|
||||
// Add a branch to the innermost switch's merge block.
|
||||
void addSwitchBreak();
|
||||
|
||||
// Move to the next code segment, passing in the return argument in makeSwitch()
|
||||
void nextSwitchSegment(std::vector<Block*>& segmentBB, int segment);
|
||||
|
||||
// Finish off the innermost switch.
|
||||
void endSwitch(std::vector<Block*>& segmentBB);
|
||||
|
||||
// Start the beginning of a new loop.
|
||||
void makeNewLoop();
|
||||
|
||||
// Add the branch at the end of the loop header, and leave the build position
|
||||
// in the first block of the body.
|
||||
// 'condition' is true if should exit the loop
|
||||
void createLoopHeaderBranch(Id condition);
|
||||
|
||||
// Add a back-edge (e.g "continue") for the innermost loop that you're in
|
||||
void createLoopBackEdge(bool implicit=false);
|
||||
|
||||
// Add an exit (e.g. "break") for the innermost loop that you're in
|
||||
void createLoopExit();
|
||||
|
||||
// Close the innermost loop that you're in
|
||||
void closeLoop();
|
||||
|
||||
//
|
||||
// Access chain design for an R-Value vs. L-Value:
|
||||
//
|
||||
// There is a single access chain the builder is building at
|
||||
// any particular time. Such a chain can be used to either to a load or
|
||||
// a store, when desired.
|
||||
//
|
||||
// Expressions can be r-values, l-values, or both, or only r-values:
|
||||
// a[b.c].d = .... // l-value
|
||||
// ... = a[b.c].d; // r-value, that also looks like an l-value
|
||||
// ++a[b.c].d; // r-value and l-value
|
||||
// (x + y)[2]; // r-value only, can't possibly be l-value
|
||||
//
|
||||
// Computing an r-value means generating code. Hence,
|
||||
// r-values should only be computed when they are needed, not speculatively.
|
||||
//
|
||||
// Computing an l-value means saving away information for later use in the compiler,
|
||||
// no code is generated until the l-value is later dereferenced. It is okay
|
||||
// to speculatively generate an l-value, just not okay to speculatively dereference it.
|
||||
//
|
||||
// The base of the access chain (the left-most variable or expression
|
||||
// from which everything is based) can be set either as an l-value
|
||||
// or as an r-value. Most efficient would be to set an l-value if one
|
||||
// is available. If an expression was evaluated, the resulting r-value
|
||||
// can be set as the chain base.
|
||||
//
|
||||
// The users of this single access chain can save and restore if they
|
||||
// want to nest or manage multiple chains.
|
||||
//
|
||||
|
||||
struct AccessChain {
|
||||
Id base; // for l-values, pointer to the base object, for r-values, the base object
|
||||
std::vector<Id> indexChain;
|
||||
Id instr; // the instruction that generates this access chain
|
||||
std::vector<unsigned> swizzle;
|
||||
Id component; // a dynamic component index
|
||||
int swizzleTargetWidth;
|
||||
Id resultType; // dereferenced type, to be inclusive of swizzles, which can't have a pointer
|
||||
bool isRValue;
|
||||
};
|
||||
|
||||
//
|
||||
// the SPIR-V builder maintains a single active chain that
|
||||
// the following methods operated on
|
||||
//
|
||||
|
||||
// for external save and restore
|
||||
AccessChain getAccessChain() { return accessChain; }
|
||||
void setAccessChain(AccessChain newChain) { accessChain = newChain; }
|
||||
|
||||
// clear accessChain
|
||||
void clearAccessChain();
|
||||
|
||||
// set new base as an l-value base
|
||||
void setAccessChainLValue(Id lValue)
|
||||
{
|
||||
assert(isPointer(lValue));
|
||||
accessChain.base = lValue;
|
||||
}
|
||||
|
||||
// set new base value as an r-value
|
||||
void setAccessChainRValue(Id rValue)
|
||||
{
|
||||
accessChain.isRValue = true;
|
||||
accessChain.base = rValue;
|
||||
accessChain.resultType = getTypeId(rValue);
|
||||
}
|
||||
|
||||
// push offset onto the end of the chain
|
||||
void accessChainPush(Id offset, Id newType)
|
||||
{
|
||||
accessChain.indexChain.push_back(offset);
|
||||
accessChain.resultType = newType;
|
||||
}
|
||||
|
||||
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle
|
||||
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, int width, Id type);
|
||||
|
||||
// push a variable component selection onto the access chain; supporting only one, so unsided
|
||||
void accessChainPushComponent(Id component) { accessChain.component = component; }
|
||||
|
||||
// use accessChain and swizzle to store value
|
||||
void accessChainStore(Id rvalue);
|
||||
|
||||
// use accessChain and swizzle to load an r-value
|
||||
Id accessChainLoad(Decoration precision);
|
||||
|
||||
// get the direct pointer for an l-value
|
||||
Id accessChainGetLValue();
|
||||
|
||||
void dump(std::vector<unsigned int>&) const;
|
||||
|
||||
protected:
|
||||
Id findScalarConstant(OpCode typeClass, Id typeId, unsigned value) const;
|
||||
Id findCompositeConstant(OpCode typeClass, std::vector<Id>& comps) const;
|
||||
Id collapseAccessChain();
|
||||
void simplifyAccessChainSwizzle();
|
||||
void createAndSetNoPredecessorBlock(const char*);
|
||||
void createBranch(Block* block);
|
||||
void createMerge(OpCode, Block*, unsigned int control);
|
||||
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
|
||||
void dumpInstructions(std::vector<unsigned int>&, const std::vector<Instruction*>&) const;
|
||||
|
||||
SourceLanguage source;
|
||||
int sourceVersion;
|
||||
std::vector<const char*> extensions;
|
||||
AddressingModel addressModel;
|
||||
MemoryModel memoryModel;
|
||||
int builderNumber;
|
||||
Module module;
|
||||
Block* buildPoint;
|
||||
Id uniqueId;
|
||||
Function* mainFunction;
|
||||
Block* stageExit;
|
||||
AccessChain accessChain;
|
||||
|
||||
// special blocks of instructions for output
|
||||
std::vector<Instruction*> imports;
|
||||
std::vector<Instruction*> entryPoints;
|
||||
std::vector<Instruction*> executionModes;
|
||||
std::vector<Instruction*> names;
|
||||
std::vector<Instruction*> lines;
|
||||
std::vector<Instruction*> decorations;
|
||||
std::vector<Instruction*> constantsTypesGlobals;
|
||||
std::vector<Instruction*> externals;
|
||||
|
||||
// not output, internally used for quick & dirty canonical (unique) creation
|
||||
std::vector<Instruction*> groupedConstants[OpConstant]; // all types appear before OpConstant
|
||||
std::vector<Instruction*> groupedTypes[OpConstant];
|
||||
|
||||
// stack of switches
|
||||
std::stack<Block*> switchMerges;
|
||||
|
||||
// Data that needs to be kept in order to properly handle loops.
|
||||
struct Loop {
|
||||
Block* header;
|
||||
Block* merge;
|
||||
Function* function;
|
||||
};
|
||||
|
||||
// Our loop stack.
|
||||
std::stack<Loop> loops;
|
||||
}; // end Builder class
|
||||
|
||||
void MissingFunctionality(const char*);
|
||||
void ValidationError(const char* error);
|
||||
|
||||
}; // end spv namespace
|
||||
|
||||
#endif // SpvBuilder_H
|
762
SPIRV/spirv.h
Normal file
762
SPIRV/spirv.h
Normal file
@ -0,0 +1,762 @@
|
||||
/*
|
||||
** Copyright (c) 2014-2015 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
||||
** copy of this software and/or associated documentation files (the
|
||||
** "Materials"), to deal in the Materials without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
||||
** permit persons to whom the Materials are furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included
|
||||
** in all copies or substantial portions of the Materials.
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
//
|
||||
// Enumeration tokens for SPIR V.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef spirv_H
|
||||
#define spirv_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace spv{
|
||||
#endif
|
||||
|
||||
const int MagicNumber = 0x07230203;
|
||||
const int Version = 99;
|
||||
|
||||
typedef unsigned int Id;
|
||||
|
||||
const Id NoResult = 0;
|
||||
const Id NoType = 0;
|
||||
|
||||
const unsigned int OpCodeMask = 0xFFFF;
|
||||
const unsigned int WordCountShift = 16;
|
||||
|
||||
// Set of capabilities. Generally, something is assumed to be in core,
|
||||
// if nothing else is said. So, these are used to identify when something
|
||||
// requires a specific capability to be declared.
|
||||
enum Capability {
|
||||
CapMatrix,
|
||||
CapShader,
|
||||
CapGeom,
|
||||
CapTess,
|
||||
CapAddr,
|
||||
CapLink,
|
||||
CapKernel
|
||||
};
|
||||
|
||||
// What language is the source code in? Note the OpSource instruction has a separate
|
||||
// operand for the version number, this is just the language name. The GLSL
|
||||
// compatibility profile will be indicated by using an OpSourceExtension string.
|
||||
enum SourceLanguage {
|
||||
LangUnknown,
|
||||
LangESSL,
|
||||
LangGLSL,
|
||||
LangOpenCL,
|
||||
|
||||
LangCount // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
// Used per entry point to communicate the "stage" or other model of
|
||||
// execution used by that entry point.
|
||||
// See OpEntryPoint.
|
||||
enum ExecutionModel {
|
||||
ModelVertex,
|
||||
ModelTessellationControl,
|
||||
ModelTessellationEvaluation,
|
||||
ModelGeometry,
|
||||
ModelFragment,
|
||||
ModelGLCompute,
|
||||
ModelKernel,
|
||||
|
||||
ModelCount // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
// Used as an argument to OpMemoryModel
|
||||
enum AddressingModel {
|
||||
AddressingLogical,
|
||||
AddressingPhysical32,
|
||||
AddressingPhysical64,
|
||||
|
||||
AddressingCount // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
// Used as an argment to OpMemoryModel
|
||||
enum MemoryModel {
|
||||
MemorySimple,
|
||||
MemoryGLSL450,
|
||||
MemoryOCL12,
|
||||
MemoryOCL20,
|
||||
MemoryOCL21,
|
||||
|
||||
MemoryCount // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
// Used per entry point to communicate modes related to input, output, and execution.
|
||||
// See OpExecutionMode.
|
||||
enum ExecutionMode {
|
||||
ExecutionInvocations,
|
||||
ExecutionSpacingEqual,
|
||||
ExecutionSpacingFractionalEven,
|
||||
ExecutionSpacingFractionalOdd,
|
||||
ExecutionVertexOrderCw,
|
||||
ExecutionVertexOrderCcw,
|
||||
ExecutionPixelCenterInteger,
|
||||
ExecutionOriginUpperLeft,
|
||||
ExecutionEarlyFragmentTests,
|
||||
ExecutionPointMode,
|
||||
ExecutionXfb,
|
||||
ExecutionDepthReplacing,
|
||||
ExecutionDepthAny,
|
||||
ExecutionDepthGreater,
|
||||
ExecutionDepthLess,
|
||||
ExecutionDepthUnchanged,
|
||||
ExecutionLocalSize,
|
||||
ExecutionLocalSizeHint,
|
||||
|
||||
ExecutionInputPoints,
|
||||
ExecutionInputLines,
|
||||
ExecutionInputLinesAdjacency,
|
||||
ExecutionInputTriangles,
|
||||
ExecutionInputTrianglesAdjacency,
|
||||
ExecutionInputQuads,
|
||||
ExecutionInputIsolines,
|
||||
|
||||
ExecutionOutputVertices,
|
||||
ExecutionOutputPoints,
|
||||
ExecutionOutputLineStrip,
|
||||
ExecutionOutputTriangleStrip,
|
||||
|
||||
ExecutionVecTypeHint,
|
||||
ExecutionContractionOff,
|
||||
ExecutionModeCount // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
enum StorageClass {
|
||||
StorageConstantUniform,
|
||||
StorageInput,
|
||||
StorageUniform,
|
||||
StorageOutput,
|
||||
StorageWorkgroupLocal,
|
||||
StorageWorkgroupGlobal,
|
||||
StoragePrivateGlobal,
|
||||
StorageFunction,
|
||||
StorageGeneric,
|
||||
StoragePrivate,
|
||||
StorageAtomicCounter,
|
||||
StorageCount // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
// Dimensionalities currently used for sampling.
|
||||
// See TypeSampler in TypeClass.
|
||||
enum Dimensionality {
|
||||
Dim1D,
|
||||
Dim2D,
|
||||
Dim3D,
|
||||
DimCube,
|
||||
DimRect,
|
||||
DimBuffer,
|
||||
|
||||
DimCount // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
// Sampler addressing mode.
|
||||
enum SamplerAddressingMode {
|
||||
SamplerAddressingNone = 0,
|
||||
SamplerAddressingClampToEdge = 2,
|
||||
SamplerAddressingClamp = 4,
|
||||
SamplerAddressingRepeat = 6,
|
||||
SamplerAddressingRepeatMirrored = 8,
|
||||
SamplerAddressingModeLast,
|
||||
};
|
||||
|
||||
// Sampler filter mode.
|
||||
enum SamplerFilterMode {
|
||||
SamplerFilterNearest = 0x10,
|
||||
SamplerFilterLinear = 0x20,
|
||||
SamplerFilterModeLast,
|
||||
};
|
||||
|
||||
// FP Fast Math Mode.
|
||||
enum FPFastMath {
|
||||
FPFastMathNNan = 0, // assume parameters and result are not NaN.
|
||||
FPFastMathNInf = 0x02, // assume parameters and result are not +/- Inf.
|
||||
FPFastMathNSZ = 0x04, // treat the sign of a zero parameter or result as insignificant.
|
||||
FPFastMathARcp = 0x08, // allow the usage of reciprocal rather than perform a division.
|
||||
FPFastMathFast = 0x10, // allow Algebraic transformations according to real number associative and distibutive algebra. This flag implies all the others.
|
||||
FPFastMathLast,
|
||||
};
|
||||
|
||||
// FP Fast Math Mode.
|
||||
enum FPRoundingMode {
|
||||
FPRoundRTE, // round to nearest even.
|
||||
FPRoundRTZ, // round towards zero.
|
||||
FPRoundRTP, // round towards positive infinity.
|
||||
FPRoundRTN, // round towards negative infinity.
|
||||
FPRoundLast,
|
||||
};
|
||||
|
||||
// Global identifier linkage types (by default the linkage type of global identifiers is private. This means that they are only accessible to objects inside the module.)
|
||||
enum LinkageType {
|
||||
LinkageExport, // accessible by objects in other modules as well.
|
||||
LinkageImport, // a forward declaration to a global identifier that exists in another module.
|
||||
LinkageLast,
|
||||
};
|
||||
|
||||
// Access Qualifiers for OpenCL pipes and images
|
||||
enum AccessQualifier {
|
||||
AccessQualReadOnly,
|
||||
AccessQualWriteOnly,
|
||||
AccessQualReadWrite,
|
||||
AccessQualLast,
|
||||
};
|
||||
|
||||
// Function argument attributes
|
||||
enum FunctionParameterAttribute {
|
||||
FuncParamAttrZext, // value should be zero extended if needed
|
||||
FuncParamAttrSext, // value should be sign extended if needed
|
||||
FuncParamAttrByval, // only valid for pointer parameters (not for ret value), this indicates that the pointer parameter should really be passed by value to the function.
|
||||
FuncParamAttrSret, // indicates that the pointer parameter specifies the address of a structure that is the return value of the function in the source program. only applicable to the first parameter
|
||||
FuncParamAttrNoAlias,
|
||||
FuncParamAttrNoCapture,
|
||||
FuncParamAttrSVM,
|
||||
FuncParamAttrNoWrite,
|
||||
FuncParamAttrNoReadWrite,
|
||||
FuncParamAttrLast, // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
|
||||
// Extra forms of "qualification" to add as needed. See OpDecorate.
|
||||
enum Decoration {
|
||||
// For legacy ES precision qualifiers; newer language
|
||||
// designs can use the "num-bits" feature in TypeClass.
|
||||
// The precision qualifiers may be decorated on type <id>s or instruction <id>s.
|
||||
DecPrecisionLow,
|
||||
DecPrecisionMedium,
|
||||
DecPrecisionHigh,
|
||||
|
||||
DecBlock, // basic in/out/uniform block, applied only to types of TypeStruct
|
||||
DecBufferBlock, // shader storage buffer block
|
||||
DecRowMajor,
|
||||
DecColMajor,
|
||||
DecGLSLShared,
|
||||
DecGLSLStd140,
|
||||
DecGLSLStd430,
|
||||
DecGLSLPacked,
|
||||
DecSmooth,
|
||||
DecNoperspective,
|
||||
DecFlat,
|
||||
DecPatch,
|
||||
DecCentroid,
|
||||
DecSample,
|
||||
DecInvariant,
|
||||
DecRestrict,
|
||||
DecAliased,
|
||||
DecVolatile,
|
||||
DecConstant,
|
||||
DecCoherent,
|
||||
DecNonwritable,
|
||||
DecNonreadable,
|
||||
DecUniform,
|
||||
DecNoStaticUse,
|
||||
|
||||
DecCPacked,
|
||||
DecFPSaturatedConv,
|
||||
|
||||
// these all take one additional operand
|
||||
DecStream,
|
||||
DecLocation,
|
||||
DecComponent,
|
||||
DecIndex,
|
||||
DecBinding,
|
||||
DecDescriptorSet,
|
||||
DecOffset,
|
||||
DecAlignment,
|
||||
DecXfbBuffer,
|
||||
DecStride,
|
||||
DecBuiltIn,
|
||||
DecFuncParamAttr,
|
||||
DecFPRoundingMode,
|
||||
DecFPFastMathMode,
|
||||
DecLinkageType,
|
||||
DecSpecId,
|
||||
|
||||
DecCount // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
enum BuiltIn {
|
||||
BuiltInPosition,
|
||||
BuiltInPointSize,
|
||||
BuiltInClipVertex,
|
||||
BuiltInClipDistance,
|
||||
BuiltInCullDistance,
|
||||
BuiltInVertexId,
|
||||
BuiltInInstanceId,
|
||||
BuiltInPrimitiveId,
|
||||
BuiltInInvocationId,
|
||||
BuiltInLayer,
|
||||
BuiltInViewportIndex,
|
||||
BuiltInTessLevelOuter,
|
||||
BuiltInTessLevelInner,
|
||||
BuiltInTessCoord,
|
||||
BuiltInPatchVertices,
|
||||
BuiltInFragCoord,
|
||||
BuiltInPointCoord,
|
||||
BuiltInFrontFacing,
|
||||
BuiltInSampleId,
|
||||
BuiltInSamplePosition,
|
||||
BuiltInSampleMask,
|
||||
BuiltInFragColor,
|
||||
BuiltInFragDepth,
|
||||
BuiltInHelperInvocation,
|
||||
|
||||
// OpenGL compute stage, OpenCL work item built-ins
|
||||
BuiltInNumWorkgroups, // number of work-groups that will execute a kernel
|
||||
BuiltInWorkgroupSize, // OpenCL number of local work-items
|
||||
BuiltInWorkgroupId, // OpenCL work group id
|
||||
BuiltInLocalInvocationId, // OpenCL local work item id (decorates a vector3 i32/i64)
|
||||
BuiltInGlobalInvocationId, // OpenCL global work item id (decorates a vector3 i32/i64)
|
||||
BuiltInLocalInvocationIndex, // not in use in OpenCL
|
||||
BuiltInWorkDim, // OpenCL number of dimensions in use (decorates a scalar i32/i64)
|
||||
BuiltInGlobalSize, // OpenCL number of global work items, per dimension (decorates a vector3 i32/i64)
|
||||
BuiltInEnqueuedWorkgroupSize, // OpenCL 2.0 only, get local size
|
||||
BuiltInGlobalOffset, // OpenCL offset values specified global_work_offset
|
||||
BuiltInGlobalLinearId, // OpenCL 2.0 only, work items 1-dimensional global ID.
|
||||
BuiltInWorkgroupLinearId, // OpenCL 2.0 only work items 1-dimensional local ID.
|
||||
|
||||
// OpenCL 2.0 subgroups
|
||||
BuiltInSubgroupSize, // Returns the number of work-items in the subgroup
|
||||
BuiltInSubgroupMaxSize, // Returns the maximum size of a subgroup within the dispatch
|
||||
BuiltInNumSubgroups, // Returns the maximum size of a subgroup within the dispatch
|
||||
BuiltInNumEnqueuedSubgroups, // Returns the maximum size of a subgroup within the dispatch
|
||||
BuiltInSubgroupId, //
|
||||
BuiltInSubgroupLocalInvocationId, // Returns the unique work-item ID within the current subgroup
|
||||
|
||||
BuiltInCount // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
enum SelectControl {
|
||||
SelectControlNone,
|
||||
SelectControlFlatten,
|
||||
SelectControlDontFlatten,
|
||||
|
||||
SelectControlCount, // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
enum LoopControl {
|
||||
LoopControlNone,
|
||||
LoopControlUnroll,
|
||||
LoopControlDontUnroll,
|
||||
|
||||
LoopControlCount,
|
||||
};
|
||||
|
||||
enum FunctionControlMask {
|
||||
FunctionControlNone = 0x0,
|
||||
FunctionControlInline = 0x1,
|
||||
FunctionControlDontInline = 0x2,
|
||||
FunctionControlPure = 0x4,
|
||||
FunctionControlConst = 0x8,
|
||||
|
||||
FunctionControlCount = 4,
|
||||
};
|
||||
|
||||
enum MemorySemanticsMask {
|
||||
MemorySemanticsRelaxed = 0x0001,
|
||||
MemorySemanticsSequentiallyConsistent = 0x0002,
|
||||
MemorySemanticsAcquire = 0x0004,
|
||||
MemorySemanticsRelease = 0x0008,
|
||||
|
||||
MemorySemanticsUniform = 0x0010,
|
||||
MemorySemanticsSubgroup = 0x0020,
|
||||
MemorySemanticsWorkgroupLocal = 0x0040,
|
||||
MemorySemanticsWorkgroupGlobal = 0x0080,
|
||||
MemorySemanticsAtomicCounter = 0x0100,
|
||||
MemorySemanticsImage = 0x0200,
|
||||
MemorySemanticsAllMemory = 0x03FF,
|
||||
|
||||
MemorySemanticsCount = 10
|
||||
};
|
||||
|
||||
enum MemoryAccessMask {
|
||||
MemoryAccessVolatile = 0x0001,
|
||||
MemoryAccessAligned = 0x0002,
|
||||
|
||||
MemoryAccessCount = 2
|
||||
};
|
||||
|
||||
enum ExecutionScope {
|
||||
ExecutionScopeCrossDevice,
|
||||
ExecutionScopeDevice,
|
||||
ExecutionScopeWorkgroup,
|
||||
ExecutionScopeSubgroup,
|
||||
|
||||
ExecutionScopeCount // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
enum GroupOperation {
|
||||
GroupOpReduce,
|
||||
GroupOpInclusiveScan,
|
||||
GroupOpExclusiveScan,
|
||||
|
||||
GroupOpCount
|
||||
};
|
||||
|
||||
enum KernelEnqueueFlags {
|
||||
EnqFlagNoWait,
|
||||
EnqFlagWaitKernel,
|
||||
EnqFlagWaitWaitWorgGroup,
|
||||
|
||||
EnqFlagCount
|
||||
};
|
||||
|
||||
enum KernelProfilingInfo {
|
||||
ProfInfoCmdExecTime = 0x01,
|
||||
ProfilingInfoCount = 1
|
||||
};
|
||||
|
||||
enum OpCode {
|
||||
OpNop = 0, // Not used.
|
||||
|
||||
OpSource,
|
||||
OpSourceExtension,
|
||||
OpExtension,
|
||||
OpExtInstImport,
|
||||
|
||||
OpMemoryModel,
|
||||
OpEntryPoint,
|
||||
OpExecutionMode,
|
||||
|
||||
OpTypeVoid,
|
||||
OpTypeBool,
|
||||
OpTypeInt,
|
||||
OpTypeFloat,
|
||||
OpTypeVector,
|
||||
OpTypeMatrix,
|
||||
OpTypeSampler,
|
||||
OpTypeFilter,
|
||||
OpTypeArray,
|
||||
OpTypeRuntimeArray,
|
||||
OpTypeStruct,
|
||||
OpTypeOpaque,
|
||||
OpTypePointer,
|
||||
OpTypeFunction,
|
||||
OpTypeEvent,
|
||||
OpTypeDeviceEvent,
|
||||
OpTypeReserveId,
|
||||
OpTypeQueue,
|
||||
OpTypePipe,
|
||||
|
||||
OpConstantTrue,
|
||||
OpConstantFalse,
|
||||
OpConstant,
|
||||
OpConstantComposite,
|
||||
OpConstantSampler,
|
||||
OpConstantNullPointer,
|
||||
OpConstantNullObject,
|
||||
|
||||
OpSpecConstantTrue,
|
||||
OpSpecConstantFalse,
|
||||
OpSpecConstant,
|
||||
OpSpecConstantComposite,
|
||||
|
||||
OpVariable,
|
||||
OpVariableArray,
|
||||
|
||||
OpFunction,
|
||||
OpFunctionParameter,
|
||||
OpFunctionEnd,
|
||||
OpFunctionCall,
|
||||
|
||||
OpExtInst,
|
||||
|
||||
OpUndef,
|
||||
|
||||
OpLoad,
|
||||
OpStore,
|
||||
|
||||
OpPhi,
|
||||
|
||||
OpDecorationGroup,
|
||||
OpDecorate,
|
||||
OpMemberDecorate,
|
||||
OpGroupDecorate,
|
||||
OpGroupMemberDecorate,
|
||||
|
||||
OpName,
|
||||
OpMemberName,
|
||||
OpString,
|
||||
OpLine,
|
||||
|
||||
OpVectorExtractDynamic,
|
||||
OpVectorInsertDynamic,
|
||||
OpVectorShuffle,
|
||||
|
||||
OpCompositeConstruct,
|
||||
OpCompositeExtract,
|
||||
OpCompositeInsert,
|
||||
|
||||
OpCopyObject,
|
||||
OpCopyMemory,
|
||||
OpCopyMemorySized,
|
||||
|
||||
OpSampler,
|
||||
|
||||
OpTextureSample,
|
||||
OpTextureSampleDref,
|
||||
OpTextureSampleLod,
|
||||
OpTextureSampleProj,
|
||||
OpTextureSampleGrad,
|
||||
OpTextureSampleOffset,
|
||||
OpTextureSampleProjLod,
|
||||
OpTextureSampleProjGrad,
|
||||
OpTextureSampleLodOffset,
|
||||
OpTextureSampleProjOffset,
|
||||
OpTextureSampleGradOffset,
|
||||
OpTextureSampleProjLodOffset,
|
||||
OpTextureSampleProjGradOffset,
|
||||
|
||||
OpTextureFetchTexel,
|
||||
OpTextureFetchTexelOffset,
|
||||
OpTextureFetchSample,
|
||||
OpTextureFetchBuffer,
|
||||
OpTextureGather,
|
||||
OpTextureGatherOffset,
|
||||
OpTextureGatherOffsets,
|
||||
|
||||
OpTextureQuerySizeLod,
|
||||
OpTextureQuerySize,
|
||||
OpTextureQueryLod,
|
||||
OpTextureQueryLevels,
|
||||
OpTextureQuerySamples,
|
||||
|
||||
OpAccessChain,
|
||||
OpInBoundsAccessChain,
|
||||
|
||||
OpSNegate,
|
||||
OpFNegate,
|
||||
|
||||
OpNot,
|
||||
|
||||
OpAny,
|
||||
OpAll,
|
||||
|
||||
OpConvertFToU,
|
||||
OpConvertFToS,
|
||||
OpConvertSToF,
|
||||
OpConvertUToF,
|
||||
OpUConvert,
|
||||
OpSConvert,
|
||||
OpFConvert,
|
||||
OpConvertPtrToU,
|
||||
OpConvertUToPtr,
|
||||
OpPtrCastToGeneric, // cast a pointer storage class to be in storage generic
|
||||
OpGenericCastToPtr, // cast a pointer in the generic storage class generic to another storage class
|
||||
OpBitcast,
|
||||
|
||||
OpTranspose,
|
||||
|
||||
OpIsNan,
|
||||
OpIsInf,
|
||||
OpIsFinite,
|
||||
OpIsNormal,
|
||||
OpSignBitSet,
|
||||
OpLessOrGreater,
|
||||
OpOrdered,
|
||||
OpUnordered,
|
||||
|
||||
OpArrayLength,
|
||||
|
||||
OpIAdd,
|
||||
OpFAdd,
|
||||
OpISub,
|
||||
OpFSub,
|
||||
OpIMul,
|
||||
OpFMul,
|
||||
OpUDiv,
|
||||
OpSDiv,
|
||||
OpFDiv,
|
||||
|
||||
OpUMod,
|
||||
OpSRem,
|
||||
OpSMod,
|
||||
OpFRem,
|
||||
OpFMod,
|
||||
|
||||
OpVectorTimesScalar,
|
||||
OpMatrixTimesScalar,
|
||||
OpVectorTimesMatrix,
|
||||
OpMatrixTimesVector,
|
||||
OpMatrixTimesMatrix,
|
||||
OpOuterProduct,
|
||||
|
||||
OpDot,
|
||||
|
||||
OpShiftRightLogical,
|
||||
OpShiftRightArithmetic,
|
||||
OpShiftLeftLogical,
|
||||
OpLogicalOr,
|
||||
OpLogicalXor,
|
||||
OpLogicalAnd,
|
||||
|
||||
OpBitwiseOr,
|
||||
OpBitwiseXor,
|
||||
OpBitwiseAnd,
|
||||
|
||||
OpSelect,
|
||||
|
||||
OpIEqual,
|
||||
OpFOrdEqual,
|
||||
OpFUnordEqual,
|
||||
|
||||
OpINotEqual,
|
||||
OpFOrdNotEqual,
|
||||
OpFUnordNotEqual,
|
||||
|
||||
OpULessThan,
|
||||
OpSLessThan,
|
||||
OpFOrdLessThan,
|
||||
OpFUnordLessThan,
|
||||
|
||||
OpUGreaterThan,
|
||||
OpSGreaterThan,
|
||||
OpFOrdGreaterThan,
|
||||
OpFUnordGreaterThan,
|
||||
|
||||
OpULessThanEqual,
|
||||
OpSLessThanEqual,
|
||||
OpFOrdLessThanEqual,
|
||||
OpFUnordLessThanEqual,
|
||||
|
||||
OpUGreaterThanEqual,
|
||||
OpSGreaterThanEqual,
|
||||
OpFOrdGreaterThanEqual,
|
||||
OpFUnordGreaterThanEqual,
|
||||
|
||||
OpDPdx,
|
||||
OpDPdy,
|
||||
OpFwidth,
|
||||
OpDPdxFine,
|
||||
OpDPdyFine,
|
||||
OpFwidthFine,
|
||||
OpDPdxCoarse,
|
||||
OpDPdyCoarse,
|
||||
OpFwidthCoarse,
|
||||
|
||||
OpEmitVertex,
|
||||
OpEndPrimitive,
|
||||
OpEmitStreamVertex,
|
||||
OpEndStreamPrimitive,
|
||||
|
||||
OpControlBarrier,
|
||||
OpMemoryBarrier,
|
||||
|
||||
OpImagePointer,
|
||||
|
||||
OpAtomicInit,
|
||||
OpAtomicLoad,
|
||||
OpAtomicStore,
|
||||
OpAtomicExchange,
|
||||
OpAtomicCompareExchange,
|
||||
OpAtomicCompareExchangeWeak,
|
||||
OpAtomicIIncrement,
|
||||
OpAtomicIDecrement,
|
||||
OpAtomicIAdd,
|
||||
OpAtomicISub,
|
||||
OpAtomicUMin,
|
||||
OpAtomicUMax,
|
||||
OpAtomicAnd,
|
||||
OpAtomicOr,
|
||||
OpAtomicXor,
|
||||
|
||||
OpLoopMerge,
|
||||
OpSelectionMerge,
|
||||
OpLabel,
|
||||
OpBranch,
|
||||
OpBranchConditional,
|
||||
OpSwitch,
|
||||
OpKill,
|
||||
OpReturn,
|
||||
OpReturnValue,
|
||||
|
||||
OpUnreachable,
|
||||
|
||||
OpLifetimeStart,
|
||||
OpLifetimeStop,
|
||||
|
||||
OpCompileFlag,
|
||||
|
||||
OpAsyncGroupCopy,
|
||||
OpWaitGroupEvents,
|
||||
|
||||
OpGroupAll,
|
||||
OpGroupAny,
|
||||
OpGroupBroadcast,
|
||||
|
||||
OpGroupIAdd,
|
||||
OpGroupFAdd,
|
||||
OpGroupFMin,
|
||||
OpGroupUMin,
|
||||
OpGroupSMin,
|
||||
OpGroupFMax,
|
||||
OpGroupUMax,
|
||||
OpGroupSMax,
|
||||
|
||||
OpGenericCastToPtrExplicit,
|
||||
OpGenericPtrMemSemantics,
|
||||
|
||||
OpReadPipe,
|
||||
OpWritePipe,
|
||||
OpReservedReadPipe,
|
||||
OpReservedWritePipe,
|
||||
OpReserveReadPipePackets,
|
||||
OpReserveWritePipePackets,
|
||||
OpCommitReadPipe,
|
||||
OpCommitWritePipe,
|
||||
OpIsValidReserveId,
|
||||
OpGetNumPipePackets,
|
||||
OpGetMaxPipePackets,
|
||||
OpGroupReserveReadPipePackets,
|
||||
OpGroupReserveWritePipePackets,
|
||||
OpGroupCommitReadPipe,
|
||||
OpGroupCommitWritePipe,
|
||||
|
||||
OpEnqueueMarker,
|
||||
OpEnqueueKernel,
|
||||
OpGetKernelNDrangeSubGroupCount,
|
||||
OpGetKernelNDrangeMaxSubGroupSize,
|
||||
|
||||
OpGetKernelWorkGroupSize,
|
||||
OpGetKernelPreferredWorkGroupSizeMultiple,
|
||||
|
||||
OpRetainEvent,
|
||||
OpReleaseEvent,
|
||||
|
||||
OpCreateUserEvent,
|
||||
OpIsValidEvent,
|
||||
OpSetUserEventStatus,
|
||||
OpCaptureEventProfilingInfo,
|
||||
OpGetDefaultQueue,
|
||||
|
||||
OpBuildNDRange,
|
||||
|
||||
OpCount // guard for validation, "default:" statements, etc.
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}; // end namespace spv
|
||||
#endif
|
||||
|
||||
#endif // spirv_H
|
348
SPIRV/spvIR.h
Normal file
348
SPIRV/spvIR.h
Normal file
@ -0,0 +1,348 @@
|
||||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
//Redistribution and use in source and binary forms, with or without
|
||||
//modification, are permitted provided that the following conditions
|
||||
//are met:
|
||||
//
|
||||
// Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
//
|
||||
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Author: John Kessenich, LunarG
|
||||
//
|
||||
|
||||
// SPIRV-IR
|
||||
//
|
||||
// Simple in-memory representation (IR) of SPIRV. Just for holding
|
||||
// Each function's CFG of blocks. Has this hierarchy:
|
||||
// - Module, which is a list of
|
||||
// - Function, which is a list of
|
||||
// - Block, which is a list of
|
||||
// - Instruction
|
||||
//
|
||||
|
||||
#pragma once
|
||||
#ifndef spvIR_H
|
||||
#define spvIR_H
|
||||
|
||||
#include "spirv.h"
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace spv {
|
||||
|
||||
class Function;
|
||||
class Module;
|
||||
|
||||
//
|
||||
// SPIR-V IR instruction.
|
||||
//
|
||||
|
||||
class Instruction {
|
||||
public:
|
||||
Instruction(Id resultId, Id typeId, OpCode opCode) : resultId(resultId), typeId(typeId), opCode(opCode), string(0) { }
|
||||
explicit Instruction(OpCode opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), string(0) { }
|
||||
virtual ~Instruction()
|
||||
{
|
||||
delete string;
|
||||
}
|
||||
void addIdOperand(Id id) { operands.push_back(id); }
|
||||
void addImmediateOperand(unsigned int immediate) { operands.push_back(immediate); }
|
||||
void addStringOperand(const char* str)
|
||||
{
|
||||
string = new std::vector<unsigned int>;
|
||||
unsigned int word;
|
||||
char* wordString = (char*)&word;
|
||||
char* wordPtr = wordString;
|
||||
int charCount = 0;
|
||||
char c;
|
||||
do {
|
||||
c = *(str++);
|
||||
*(wordPtr++) = c;
|
||||
++charCount;
|
||||
if (charCount == 4) {
|
||||
string->push_back(word);
|
||||
wordPtr = wordString;
|
||||
charCount = 0;
|
||||
}
|
||||
} while (c != 0);
|
||||
|
||||
// deal with partial last word
|
||||
if (charCount > 0) {
|
||||
// pad with 0s
|
||||
for (; charCount < 4; ++charCount)
|
||||
*(wordPtr++) = 0;
|
||||
string->push_back(word);
|
||||
}
|
||||
|
||||
originalString = str;
|
||||
}
|
||||
OpCode getOpCode() const { return opCode; }
|
||||
int getNumOperands() const { return operands.size(); }
|
||||
Id getResultId() const { return resultId; }
|
||||
Id getTypeId() const { return typeId; }
|
||||
Id getIdOperand(int op) const { return operands[op]; }
|
||||
unsigned int getImmediateOperand(int op) const { return operands[op]; }
|
||||
const char* getStringOperand() const { return originalString.c_str(); }
|
||||
|
||||
// Write out the binary form.
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
// Compute the wordCount
|
||||
unsigned int wordCount = 1;
|
||||
if (typeId)
|
||||
++wordCount;
|
||||
if (resultId)
|
||||
++wordCount;
|
||||
wordCount += operands.size();
|
||||
if (string)
|
||||
wordCount += string->size();
|
||||
|
||||
// Write out the beginning of the instruction
|
||||
out.push_back(((wordCount) << WordCountShift) | opCode);
|
||||
if (typeId)
|
||||
out.push_back(typeId);
|
||||
if (resultId)
|
||||
out.push_back(resultId);
|
||||
|
||||
// Write out the operands
|
||||
for (int op = 0; op < (int)operands.size(); ++op)
|
||||
out.push_back(operands[op]);
|
||||
if (string)
|
||||
for (int op = 0; op < (int)string->size(); ++op)
|
||||
out.push_back((*string)[op]);
|
||||
}
|
||||
|
||||
protected:
|
||||
Instruction(const Instruction&);
|
||||
Id resultId;
|
||||
Id typeId;
|
||||
OpCode opCode;
|
||||
std::vector<Id> operands;
|
||||
std::vector<unsigned int>* string; // usually non-existent
|
||||
std::string originalString; // could be optimized away; convenience for getting string operand
|
||||
};
|
||||
|
||||
//
|
||||
// SPIR-V IR block.
|
||||
//
|
||||
|
||||
class Block {
|
||||
public:
|
||||
// Setting insert to true indicates to add this new block
|
||||
// to the end of the parent function.
|
||||
Block(Id id, Function& parent);
|
||||
virtual ~Block()
|
||||
{
|
||||
// TODO: free instructions
|
||||
}
|
||||
|
||||
Id getId() { return instructions.front()->getResultId(); }
|
||||
|
||||
Function& getParent() const { return parent; }
|
||||
void addInstruction(Instruction* inst);
|
||||
void addPredecessor(Block* pred) { predecessors.push_back(pred); }
|
||||
void addLocalVariable(Instruction* inst) { localVariables.push_back(inst); }
|
||||
int getNumPredecessors() const { return (int)predecessors.size(); }
|
||||
|
||||
bool isTerminated() const
|
||||
{
|
||||
switch (instructions.back()->getOpCode()) {
|
||||
case OpBranch:
|
||||
case OpBranchConditional:
|
||||
case OpSwitch:
|
||||
case OpKill:
|
||||
case OpReturn:
|
||||
case OpReturnValue:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
instructions[0]->dump(out);
|
||||
for (int i = 0; i < (int)localVariables.size(); ++i)
|
||||
localVariables[i]->dump(out);
|
||||
for (int i = 1; i < (int)instructions.size(); ++i)
|
||||
instructions[i]->dump(out);
|
||||
}
|
||||
|
||||
protected:
|
||||
Block(const Block&);
|
||||
|
||||
// To enforce keeping parent and ownership in sync:
|
||||
friend Function;
|
||||
|
||||
std::vector<Instruction*> instructions;
|
||||
std::vector<Block*> predecessors;
|
||||
std::vector<Instruction*> localVariables;
|
||||
Function& parent;
|
||||
};
|
||||
|
||||
//
|
||||
// SPIR-V IR Function.
|
||||
//
|
||||
|
||||
class Function {
|
||||
public:
|
||||
Function(Id id, Id resultType, Id functionType, Id firstParam, Module& parent);
|
||||
virtual ~Function()
|
||||
{
|
||||
for (int i = 0; i < (int)parameterInstructions.size(); ++i)
|
||||
delete parameterInstructions[i];
|
||||
|
||||
for (int i = 0; i < (int)blocks.size(); ++i)
|
||||
delete blocks[i];
|
||||
}
|
||||
Id getId() const { return functionInstruction.getResultId(); }
|
||||
Id getParamId(int p) { return parameterInstructions[p]->getResultId(); }
|
||||
|
||||
void addBlock(Block* block) { blocks.push_back(block); }
|
||||
void popBlock(Block* block) { assert(blocks.back() == block); blocks.pop_back(); }
|
||||
|
||||
Module& getParent() const { return parent; }
|
||||
Block* getEntryBlock() const { return blocks.front(); }
|
||||
Block* getLastBlock() const { return blocks.back(); }
|
||||
void addLocalVariable(Instruction* inst);
|
||||
Id getReturnType() const { return functionInstruction.getTypeId(); }
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
// OpFunction
|
||||
functionInstruction.dump(out);
|
||||
|
||||
// OpFunctionParameter
|
||||
for (int p = 0; p < (int)parameterInstructions.size(); ++p)
|
||||
parameterInstructions[p]->dump(out);
|
||||
|
||||
// Blocks
|
||||
for (int b = 0; b < (int)blocks.size(); ++b)
|
||||
blocks[b]->dump(out);
|
||||
Instruction end(0, 0, OpFunctionEnd);
|
||||
end.dump(out);
|
||||
}
|
||||
|
||||
protected:
|
||||
Function(const Function&);
|
||||
Module& parent;
|
||||
Instruction functionInstruction;
|
||||
std::vector<Instruction*> parameterInstructions;
|
||||
std::vector<Block*> blocks;
|
||||
};
|
||||
|
||||
//
|
||||
// SPIR-V IR Module.
|
||||
//
|
||||
|
||||
class Module {
|
||||
public:
|
||||
Module() {}
|
||||
virtual ~Module()
|
||||
{
|
||||
// TODO delete things
|
||||
}
|
||||
|
||||
void addFunction(Function *fun) { functions.push_back(fun); }
|
||||
|
||||
void mapInstruction(Instruction *instruction)
|
||||
{
|
||||
spv::Id resultId = instruction->getResultId();
|
||||
// map the instruction's result id
|
||||
if (resultId >= idToInstruction.size())
|
||||
idToInstruction.resize(resultId + 16);
|
||||
idToInstruction[resultId] = instruction;
|
||||
}
|
||||
|
||||
Instruction* getInstruction(Id id) const { return idToInstruction[id]; }
|
||||
spv::Id getTypeId(Id resultId) const { return idToInstruction[resultId]->getTypeId(); }
|
||||
StorageClass getStorageClass(Id typeId) const { return (StorageClass)idToInstruction[typeId]->getImmediateOperand(0); }
|
||||
void dump(std::vector<unsigned int>& out) const
|
||||
{
|
||||
for (int f = 0; f < (int)functions.size(); ++f)
|
||||
functions[f]->dump(out);
|
||||
}
|
||||
|
||||
protected:
|
||||
Module(const Module&);
|
||||
std::vector<Function*> functions;
|
||||
|
||||
// map from result id to instruction having that result id
|
||||
std::vector<Instruction*> idToInstruction;
|
||||
|
||||
// map from a result id to its type id
|
||||
};
|
||||
|
||||
//
|
||||
// Implementation (it's here due to circular type definitions).
|
||||
//
|
||||
|
||||
// Add both
|
||||
// - the OpFunction instruction
|
||||
// - all the OpFunctionParameter instructions
|
||||
__inline Function::Function(Id id, Id resultType, Id functionType, Id firstParamId, Module& parent)
|
||||
: parent(parent), functionInstruction(id, resultType, OpFunction)
|
||||
{
|
||||
// OpFunction
|
||||
functionInstruction.addImmediateOperand(FunctionControlNone);
|
||||
functionInstruction.addIdOperand(functionType);
|
||||
parent.mapInstruction(&functionInstruction);
|
||||
parent.addFunction(this);
|
||||
|
||||
// OpFunctionParameter
|
||||
Instruction* typeInst = parent.getInstruction(functionType);
|
||||
int numParams = typeInst->getNumOperands() - 1;
|
||||
for (int p = 0; p < numParams; ++p) {
|
||||
Instruction* param = new Instruction(firstParamId + p, typeInst->getIdOperand(p + 1), OpFunctionParameter);
|
||||
parent.mapInstruction(param);
|
||||
parameterInstructions.push_back(param);
|
||||
}
|
||||
}
|
||||
|
||||
__inline void Function::addLocalVariable(Instruction* inst)
|
||||
{
|
||||
blocks[0]->addLocalVariable(inst);
|
||||
parent.mapInstruction(inst);
|
||||
}
|
||||
|
||||
__inline Block::Block(Id id, Function& parent) : parent(parent)
|
||||
{
|
||||
instructions.push_back(new Instruction(id, NoType, OpLabel));
|
||||
}
|
||||
|
||||
__inline void Block::addInstruction(Instruction* inst)
|
||||
{
|
||||
instructions.push_back(inst);
|
||||
if (inst->getResultId())
|
||||
parent.getParent().mapInstruction(inst);
|
||||
}
|
||||
|
||||
}; // end spv namespace
|
||||
|
||||
#endif // spvIR_H
|
@ -17,7 +17,7 @@ set(LIBRARIES
|
||||
glslang
|
||||
OGLCompiler
|
||||
OSDependent
|
||||
BIL)
|
||||
SPIRV)
|
||||
|
||||
if(WIN32)
|
||||
set(LIBRARIES ${LIBRARIES} psapi)
|
||||
|
@ -40,8 +40,8 @@
|
||||
#include "Worklist.h"
|
||||
#include "./../glslang/Include/ShHandle.h"
|
||||
#include "./../glslang/Public/ShaderLang.h"
|
||||
#include "../BIL/GlslangToBil.h"
|
||||
#include "../BIL/GLSL450Lib.h"
|
||||
#include "../SPIRV/GlslangToSpv.h"
|
||||
#include "../SPIRV/GLSL450Lib.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
@ -66,7 +66,7 @@ enum TOptions {
|
||||
EOptionDumpReflection = 0x100,
|
||||
EOptionSuppressWarnings = 0x200,
|
||||
EOptionDumpVersions = 0x400,
|
||||
EOptionBil = 0x800,
|
||||
EOptionSpv = 0x800,
|
||||
EOptionDefaultDesktop = 0x1000,
|
||||
};
|
||||
|
||||
@ -479,8 +479,8 @@ bool ProcessArguments(int argc, char* argv[])
|
||||
Work[argc] = 0;
|
||||
if (argv[0][0] == '-') {
|
||||
switch (argv[0][1]) {
|
||||
case 'b':
|
||||
Options |= EOptionBil;
|
||||
case 'V':
|
||||
Options |= EOptionSpv;
|
||||
Options |= EOptionLinkProgram;
|
||||
break;
|
||||
case 'c':
|
||||
@ -634,14 +634,14 @@ void CompileAndLinkShaders()
|
||||
program.dumpReflection();
|
||||
}
|
||||
|
||||
if (Options & EOptionBil) {
|
||||
if (Options & EOptionSpv) {
|
||||
if (CompileFailed || LinkFailed)
|
||||
printf("Bil is not generated for failed compile or link\n");
|
||||
printf("SPIRV is not generated for failed compile or link\n");
|
||||
else {
|
||||
for (int stage = 0; stage < EShLangCount; ++stage) {
|
||||
if (program.getIntermediate((EShLanguage)stage)) {
|
||||
std::vector<unsigned int> bil;
|
||||
glslang::GlslangToBil(*program.getIntermediate((EShLanguage)stage), bil);
|
||||
std::vector<unsigned int> spirv;
|
||||
glslang::GlslangToSpv(*program.getIntermediate((EShLanguage)stage), spirv);
|
||||
const char* name;
|
||||
switch (stage) {
|
||||
case EShLangVertex: name = "vert"; break;
|
||||
@ -652,7 +652,7 @@ void CompileAndLinkShaders()
|
||||
case EShLangCompute: name = "comp"; break;
|
||||
default: name = "unknown"; break;
|
||||
}
|
||||
glslang::OutputBil(bil, name);
|
||||
glslang::OutputSpv(spirv, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -839,7 +839,7 @@ void usage()
|
||||
{
|
||||
printf("Usage: glslangValidator [option]... [file]...\n"
|
||||
"\n"
|
||||
"Where: each 'file' ends in\n"
|
||||
"Where: each 'file' ends in .<stage>, where <stage> is one of\n"
|
||||
" .conf to provide an optional config file that replaces the default configuration\n"
|
||||
" (see -c option below for generating a template)\n"
|
||||
" .vert for a vertex shader\n"
|
||||
@ -853,7 +853,7 @@ void usage()
|
||||
"\n"
|
||||
"To get other information, use one of the following options:\n"
|
||||
"(Each option must be specified separately, but can go anywhere in the command line.)\n"
|
||||
" -b create BIL in file <stage>.bil\n"
|
||||
" -V create SPIR-V in file <stage>.spv\n"
|
||||
" -c configuration dump; use to create default configuration file (redirect to a .conf file)\n"
|
||||
" -d default to desktop (#version 110) when there is no version in the shader (default is ES version 100)\n"
|
||||
" -i intermediate tree (glslang AST) is printed out\n"
|
||||
|
@ -482,6 +482,7 @@ public:
|
||||
|
||||
layoutLocation = layoutLocationEnd;
|
||||
layoutComponent = layoutComponentEnd;
|
||||
layoutSet = layoutSetEnd;
|
||||
layoutBinding = layoutBindingEnd;
|
||||
layoutIndex = layoutIndexEnd;
|
||||
|
||||
@ -513,6 +514,9 @@ public:
|
||||
unsigned int layoutComponent : 3;
|
||||
static const unsigned int layoutComponentEnd = 4;
|
||||
|
||||
unsigned int layoutSet : 7;
|
||||
static const unsigned int layoutSetEnd = 0x3F;
|
||||
|
||||
unsigned int layoutBinding : 8;
|
||||
static const unsigned int layoutBindingEnd = 0xFF;
|
||||
|
||||
@ -575,6 +579,10 @@ public:
|
||||
{
|
||||
return layoutIndex != layoutIndexEnd;
|
||||
}
|
||||
bool hasSet() const
|
||||
{
|
||||
return layoutSet != layoutSetEnd;
|
||||
}
|
||||
bool hasBinding() const
|
||||
{
|
||||
return layoutBinding != layoutBindingEnd;
|
||||
@ -1201,6 +1209,8 @@ public:
|
||||
if (qualifier.hasIndex())
|
||||
p += snprintf(p, end - p, "index=%d ", qualifier.layoutIndex);
|
||||
}
|
||||
if (qualifier.hasSet())
|
||||
p += snprintf(p, end - p, "set=%d ", qualifier.layoutSet);
|
||||
if (qualifier.hasBinding())
|
||||
p += snprintf(p, end - p, "binding=%d ", qualifier.layoutBinding);
|
||||
if (qualifier.hasStream())
|
||||
|
@ -3312,6 +3312,12 @@ void TParseContext::setLayoutQualifier(TSourceLoc loc, TPublicType& publicType,
|
||||
else
|
||||
publicType.qualifier.layoutLocation = value;
|
||||
return;
|
||||
} else if (id == "set") {
|
||||
if ((unsigned int)value >= TQualifier::layoutSetEnd)
|
||||
error(loc, "set is too large", id.c_str(), "");
|
||||
else
|
||||
publicType.qualifier.layoutSet = value;
|
||||
return;
|
||||
} else if (id == "binding") {
|
||||
profileRequires(loc, ~EEsProfile, 420, GL_ARB_shading_language_420pack, "binding");
|
||||
profileRequires(loc, EEsProfile, 310, 0, "binding");
|
||||
@ -3476,6 +3482,8 @@ void TParseContext::mergeObjectLayoutQualifiers(TSourceLoc loc, TQualifier& dst,
|
||||
if (src.hasOffset())
|
||||
dst.layoutOffset = src.layoutOffset;
|
||||
|
||||
if (src.hasSet())
|
||||
dst.layoutSet = src.layoutSet;
|
||||
if (src.layoutBinding != TQualifier::layoutBindingEnd)
|
||||
dst.layoutBinding = src.layoutBinding;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user