Merge branch 'master' of github.com:KhronosGroup/glslang into clang-format

This commit is contained in:
Dejan Mircevski 2016-06-05 20:42:20 -04:00
commit f377f5287b
241 changed files with 33708 additions and 7992 deletions

View file

@ -1,8 +1,7 @@
cmake_minimum_required(VERSION 2.8)
set(SOURCES
GlslangToSpv.cpp
InReadableOrder.cpp
Logger.cpp
SpvBuilder.cpp
SPVRemapper.cpp
doc.cpp
@ -12,6 +11,7 @@ set(HEADERS
spirv.hpp
GLSL.std.450.h
GlslangToSpv.h
Logger.h
SpvBuilder.h
SPVRemapper.h
spvIR.h
@ -19,6 +19,7 @@ set(HEADERS
disassemble.h)
add_library(SPIRV STATIC ${SOURCES} ${HEADERS})
set_property(TARGET SPIRV PROPERTY FOLDER glslang)
if(WIN32)
source_group("Source" FILES ${SOURCES} ${HEADERS})

File diff suppressed because it is too large Load diff

View file

@ -34,10 +34,16 @@
#include "../glslang/Include/intermediate.h"
#include <string>
#include <vector>
#include "Logger.h"
namespace glslang {
void GetSpirvVersion(std::string&);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger);
void OutputSpv(const std::vector<unsigned int>& spirv, const char* baseName);
};
}

View file

@ -32,10 +32,6 @@
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
// Author: Dejan Mircevski, Google
//
// The SPIR-V spec requires code blocks to appear in an order satisfying the
// dominator-tree direction (ie, dominator before the dominated). This is,
// actually, easy to achieve: any pre-order CFG traversal algorithm will do it.

68
SPIRV/Logger.cpp Normal file
View file

@ -0,0 +1,68 @@
//
// Copyright (C) 2016 Google, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include "Logger.h"
#include <algorithm>
#include <iterator>
#include <sstream>
namespace spv {
void SpvBuildLogger::tbdFunctionality(const std::string& f)
{
if (std::find(std::begin(tbdFeatures), std::end(tbdFeatures), f) == std::end(tbdFeatures))
tbdFeatures.push_back(f);
}
void SpvBuildLogger::missingFunctionality(const std::string& f)
{
if (std::find(std::begin(missingFeatures), std::end(missingFeatures), f) == std::end(missingFeatures))
missingFeatures.push_back(f);
}
std::string SpvBuildLogger::getAllMessages() const {
std::ostringstream messages;
for (auto it = tbdFeatures.cbegin(); it != tbdFeatures.cend(); ++it)
messages << "TBD functionality: " << *it << "\n";
for (auto it = missingFeatures.cbegin(); it != missingFeatures.cend(); ++it)
messages << "Missing functionality: " << *it << "\n";
for (auto it = warnings.cbegin(); it != warnings.cend(); ++it)
messages << "warning: " << *it << "\n";
for (auto it = errors.cbegin(); it != errors.cend(); ++it)
messages << "error: " << *it << "\n";
return messages.str();
}
} // end spv namespace

74
SPIRV/Logger.h Normal file
View file

@ -0,0 +1,74 @@
//
// Copyright (C) 2016 Google, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#ifndef GLSLANG_SPIRV_LOGGER_H
#define GLSLANG_SPIRV_LOGGER_H
#include <string>
#include <vector>
namespace spv {
// A class for holding all SPIR-V build status messages, including
// missing/TBD functionalities, warnings, and errors.
class SpvBuildLogger {
public:
SpvBuildLogger() {}
// Registers a TBD functionality.
void tbdFunctionality(const std::string& f);
// Registers a missing functionality.
void missingFunctionality(const std::string& f);
// Logs a warning.
void warning(const std::string& w) { warnings.push_back(w); }
// Logs an error.
void error(const std::string& e) { errors.push_back(e); }
// Returns all messages accumulated in the order of:
// TBD functionalities, missing functionalities, warnings, errors.
std::string getAllMessages() const;
private:
SpvBuildLogger(const SpvBuildLogger&);
std::vector<std::string> tbdFeatures;
std::vector<std::string> missingFeatures;
std::vector<std::string> warnings;
std::vector<std::string> errors;
};
} // end spv namespace
#endif // GLSLANG_SPIRV_LOGGER_H

View file

@ -573,7 +573,7 @@ namespace spv {
op_fn_nop);
// Window size for context-sensitive canonicalization values
// Emperical best size from a single data set. TODO: Would be a good tunable.
// Empirical best size from a single data set. TODO: Would be a good tunable.
// We essentially perform a little convolution around each instruction,
// to capture the flavor of nearby code, to hopefully match to similar
// code in other modules.
@ -926,8 +926,17 @@ namespace spv {
// Count function variable use
process(
[&](spv::Op opCode, unsigned start) {
if (opCode == spv::OpVariable) { ++varUseCount[asId(start+2)]; return true; }
return false;
if (opCode == spv::OpVariable) {
++varUseCount[asId(start+2)];
return true;
} else if (opCode == spv::OpEntryPoint) {
const int wordCount = asWordCount(start);
for (int i = 4; i < wordCount; i++) {
++varUseCount[asId(start+i)];
}
return true;
} else
return false;
},
[&](spv::Id& id) { if (varUseCount[id]) ++varUseCount[id]; }

View file

@ -33,20 +33,16 @@
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
// Author: John Kessenich, LunarG
//
//
// Helper for making SPIR-V IR. Generally, this is documented in the header
// SpvBuilder.h.
//
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unordered_set>
#include <algorithm>
#include "SpvBuilder.h"
@ -56,15 +52,17 @@
namespace spv {
Builder::Builder(unsigned int magicNumber)
: source(SourceLanguageUnknown),
sourceVersion(0),
addressModel(AddressingModelLogical),
memoryModel(MemoryModelGLSL450),
builderNumber(magicNumber),
buildPoint(0),
uniqueId(0),
mainFunction(0)
Builder::Builder(unsigned int magicNumber, SpvBuildLogger* buildLogger) :
source(SourceLanguageUnknown),
sourceVersion(0),
addressModel(AddressingModelLogical),
memoryModel(MemoryModelGLSL450),
builderNumber(magicNumber),
buildPoint(0),
uniqueId(0),
mainFunction(0),
generatingOpCodeForSpecConst(false),
logger(buildLogger)
{
clearAccessChain();
}
@ -616,7 +614,7 @@ Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned valu
return 0;
}
// Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double').
// Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double' or 'int64').
Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) const
{
Instruction* constant;
@ -656,6 +654,21 @@ bool Builder::isConstantOpCode(Op opcode) const
}
}
// Return true if consuming 'opcode' means consuming a specialization constant.
bool Builder::isSpecConstantOpCode(Op opcode) const
{
switch (opcode) {
case OpSpecConstantTrue:
case OpSpecConstantFalse:
case OpSpecConstant:
case OpSpecConstantComposite:
case OpSpecConstantOp:
return true;
default:
return false;
}
}
Id Builder::makeBoolConstant(bool b, bool specConstant)
{
Id typeId = makeBoolType();
@ -710,6 +723,31 @@ Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant)
return c->getResultId();
}
Id Builder::makeInt64Constant(Id typeId, unsigned long long value, bool specConstant)
{
Op opcode = specConstant ? OpSpecConstant : OpConstant;
unsigned op1 = value & 0xFFFFFFFF;
unsigned op2 = value >> 32;
// See if we already made it. Applies only to regular constants, because specialization constants
// must remain distinct for the purpose of applying a SpecId decoration.
if (! specConstant) {
Id existing = findScalarConstant(OpTypeInt, opcode, typeId, op1, op2);
if (existing)
return existing;
}
Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
c->addImmediateOperand(op1);
c->addImmediateOperand(op2);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
groupedConstants[OpTypeInt].push_back(c);
module.mapInstruction(c);
return c->getResultId();
}
Id Builder::makeFloatConstant(float f, bool specConstant)
{
Op opcode = specConstant ? OpSpecConstant : OpConstant;
@ -924,7 +962,7 @@ void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decorat
}
// Comments in header
Function* Builder::makeMain()
Function* Builder::makeEntrypoint(const char* entryPoint)
{
assert(!mainFunction);
@ -932,8 +970,7 @@ Function* Builder::makeMain()
std::vector<Id> params;
std::vector<Decoration> precisions;
mainFunction =
makeFunctionEntry(NoPrecision, makeVoidType(), "main", params, precisions, &entry);
mainFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, precisions, &entry);
return mainFunction;
}
@ -1104,6 +1141,11 @@ Id Builder::createArrayLength(Id base, unsigned int member)
Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
{
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), std::vector<Id>(1, index));
}
Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
extract->addIdOperand(composite);
extract->addImmediateOperand(index);
@ -1114,6 +1156,11 @@ Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
Id Builder::createCompositeExtract(Id composite, Id typeId, std::vector<unsigned>& indexes)
{
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), indexes);
}
Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
extract->addIdOperand(composite);
for (int i = 0; i < (int)indexes.size(); ++i)
@ -1212,6 +1259,11 @@ void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemant
// An opcode that has one operands, a result id, and a type
Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
{
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
return createSpecConstantOp(opCode, typeId, std::vector<Id>(1, operand), std::vector<Id>());
}
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
op->addIdOperand(operand);
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
@ -1221,6 +1273,13 @@ Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
{
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
std::vector<Id> operands(2);
operands[0] = left; operands[1] = right;
return createSpecConstantOp(opCode, typeId, operands, std::vector<Id>());
}
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
op->addIdOperand(left);
op->addIdOperand(right);
@ -1231,6 +1290,16 @@ Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
{
// Generate code for spec constants if in spec constant operation
// generation mode.
if (generatingOpCodeForSpecConst) {
std::vector<Id> operands(3);
operands[0] = op1;
operands[1] = op2;
operands[2] = op3;
return createSpecConstantOp(
opCode, typeId, operands, std::vector<Id>());
}
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
op->addIdOperand(op1);
op->addIdOperand(op2);
@ -1250,6 +1319,20 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
return op->getResultId();
}
Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals)
{
Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
op->addImmediateOperand((unsigned) opCode);
for (auto it = operands.cbegin(); it != operands.cend(); ++it)
op->addIdOperand(*it);
for (auto it = literals.cbegin(); it != literals.cend(); ++it)
op->addImmediateOperand(*it);
module.mapInstruction(op);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(op));
return op->getResultId();
}
Id Builder::createFunctionCall(spv::Function* function, std::vector<spv::Id>& args)
{
Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall);
@ -1268,6 +1351,11 @@ Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source,
if (channels.size() == 1)
return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision);
if (generatingOpCodeForSpecConst) {
std::vector<Id> operands(2);
operands[0] = operands[1] = source;
return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, operands, channels), precision);
}
Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
assert(isVector(source));
swizzle->addIdOperand(source);
@ -1335,10 +1423,25 @@ Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType)
if (numComponents == 1)
return scalar;
Instruction* smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
for (int c = 0; c < numComponents; ++c)
smear->addIdOperand(scalar);
buildPoint->addInstruction(std::unique_ptr<Instruction>(smear));
Instruction* smear = nullptr;
if (generatingOpCodeForSpecConst) {
auto members = std::vector<spv::Id>(numComponents, scalar);
// Sometime even in spec-constant-op mode, the temporary vector created by
// promoting a scalar might not be a spec constant. This should depend on
// the scalar.
// e.g.:
// const vec2 spec_const_result = a_spec_const_vec2 + a_front_end_const_scalar;
// In such cases, the temporary vector created from a_front_end_const_scalar
// is not a spec constant vector, even though the binary operation node is marked
// as 'specConstant' and we are in spec-constant-op mode.
auto result_id = makeCompositeConstant(vectorType, members, isSpecConstant(scalar));
smear = module.getInstruction(result_id);
} else {
smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
for (int c = 0; c < numComponents; ++c)
smear->addIdOperand(scalar);
buildPoint->addInstruction(std::unique_ptr<Instruction>(smear));
}
return setPrecision(smear->getResultId(), precision);
}
@ -1413,8 +1516,10 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
{
if (isConstant(parameters.offset))
mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetMask);
else
else {
addCapability(CapabilityImageGatherExtended);
mask = (ImageOperandsMask)(mask | ImageOperandsOffsetMask);
}
texArgs[numArgs++] = parameters.offset;
}
if (parameters.offsets)
@ -1723,6 +1828,20 @@ Id Builder::createCompositeConstruct(Id typeId, std::vector<Id>& constituents)
assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 &&
getNumTypeConstituents(typeId) == (int)constituents.size()));
if (generatingOpCodeForSpecConst) {
// Sometime, even in spec-constant-op mode, the constant composite to be
// constructed may not be a specialization constant.
// e.g.:
// const mat2 m2 = mat2(a_spec_const, a_front_end_const, another_front_end_const, third_front_end_const);
// The first column vector should be a spec constant one, as a_spec_const is a spec constant.
// The second column vector should NOT be spec constant, as it does not contain any spec constants.
// To handle such cases, we check the constituents of the constant vector to determine whether this
// vector should be created as a spec constant.
return makeCompositeConstant(typeId, constituents,
std::any_of(constituents.begin(), constituents.end(),
[&](spv::Id id) { return isSpecConstant(id); }));
}
Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
for (int c = 0; c < (int)constituents.size(); ++c)
op->addIdOperand(constituents[c]);
@ -1788,6 +1907,9 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
int numCols = getTypeNumColumns(resultTypeId);
int numRows = getTypeNumRows(resultTypeId);
Instruction* instr = module.getInstruction(componentTypeId);
Id bitCount = instr->getIdOperand(0);
// Will use a two step process
// 1. make a compile-time 2D array of values
// 2. construct a matrix from that array
@ -1796,12 +1918,10 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
// initialize the array to the identity matrix
Id ids[maxMatrixSize][maxMatrixSize];
Id one = makeFloatConstant(1.0);
Id zero = makeFloatConstant(0.0);
for (int col = 0; col < 4; ++col)
{
for (int row = 0; row < 4; ++row)
{
Id one = (bitCount == 64 ? makeDoubleConstant(1.0) : makeFloatConstant(1.0));
Id zero = (bitCount == 64 ? makeDoubleConstant(0.0) : makeFloatConstant(0.0));
for (int col = 0; col < 4; ++col) {
for (int row = 0; row < 4; ++row) {
if (col == row)
ids[col][row] = one;
else
@ -2077,7 +2197,7 @@ void Builder::accessChainStore(Id rvalue)
Id base = collapseAccessChain();
if (accessChain.swizzle.size() && accessChain.component != NoResult)
MissingFunctionality("simultaneous l-value swizzle and dynamic component selection");
logger->missingFunctionality("simultaneous l-value swizzle and dynamic component selection");
// If swizzle still exists, it is out-of-order or not full, we must load the target vector,
// extract and insert elements to perform writeMask and/or swizzle.
@ -2265,12 +2385,12 @@ void Builder::eliminateDeadDecorations()
}
}
decorations.erase(std::remove_if(decorations.begin(), decorations.end(),
[&unreachable_definitions](std::unique_ptr<Instruction>& I) {
Instruction* inst = I.get();
Id decoration_id = inst->getIdOperand(0);
return unreachable_definitions.count(decoration_id) != 0;
}),
decorations.end());
[&unreachable_definitions](std::unique_ptr<Instruction>& I) -> bool {
Instruction* inst = I.get();
Id decoration_id = inst->getIdOperand(0);
return unreachable_definitions.count(decoration_id) != 0;
}),
decorations.end());
}
void Builder::dump(std::vector<unsigned int>& out) const
@ -2383,7 +2503,7 @@ void Builder::simplifyAccessChainSwizzle()
// To the extent any swizzling can become part of the chain
// of accesses instead of a post operation, make it so.
// If 'dynamic' is true, include transfering a non-static component index,
// If 'dynamic' is true, include transferring a non-static component index,
// otherwise, only transfer static indexes.
//
// Also, Boolean vectors are likely to be special. While
@ -2484,16 +2604,4 @@ void Builder::dumpInstructions(std::vector<unsigned int>& out,
}
}
void TbdFunctionality(const char* tbd)
{
static std::unordered_set<const char*> issued;
if (issued.find(tbd) == issued.end())
{
printf("TBD functionality: %s\n", tbd);
issued.insert(tbd);
}
}
void MissingFunctionality(const char* fun) { printf("Missing functionality: %s\n", fun); }
}; // end spv namespace
}; // end spv namespace

View file

@ -33,10 +33,6 @@
//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),
@ -49,6 +45,7 @@
#ifndef SpvBuilder_H
#define SpvBuilder_H
#include "Logger.h"
#include "spirv.hpp"
#include "spvIR.h"
@ -56,13 +53,14 @@
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <stack>
namespace spv {
class Builder {
public:
Builder(unsigned int userNumber);
Builder(unsigned int userNumber, SpvBuildLogger* logger);
virtual ~Builder();
static const int maxMatrixSize = 4;
@ -155,16 +153,12 @@ public:
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
bool isConstantOpCode(Op opcode) const;
bool isSpecConstantOpCode(Op opcode) const;
bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
unsigned int getConstantScalar(Id resultId) const
{
return module.getInstruction(resultId)->getImmediateOperand(0);
}
StorageClass getStorageClass(Id resultId) const
{
return getTypeStorageClass(getTypeId(resultId));
}
bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
int getTypeNumColumns(Id typeId) const
{
@ -197,14 +191,10 @@ public:
// For making new constants (will return old constant if the requested one was already made).
Id makeBoolConstant(bool b, bool specConstant = false);
Id makeIntConstant(int i, bool specConstant = false)
{
return makeIntConstant(makeIntType(32), (unsigned)i, specConstant);
}
Id makeUintConstant(unsigned u, bool specConstant = false)
{
return makeIntConstant(makeUintType(32), u, specConstant);
}
Id makeIntConstant(int i, bool specConstant = false) { return makeIntConstant(makeIntType(32), (unsigned)i, specConstant); }
Id makeUintConstant(unsigned u, bool specConstant = false) { return makeIntConstant(makeUintType(32), u, specConstant); }
Id makeInt64Constant(long long i, bool specConstant = false) { return makeInt64Constant(makeIntType(64), (unsigned long long)i, specConstant); }
Id makeUint64Constant(unsigned long long u, bool specConstant = false) { return makeInt64Constant(makeUintType(64), u, specConstant); }
Id makeFloatConstant(float f, bool specConstant = false);
Id makeDoubleConstant(double d, bool specConstant = false);
@ -224,9 +214,10 @@ public:
// 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. The returned pointer is only valid
// Make the entry-point function. The returned pointer is only valid
// for the lifetime of this builder.
Function* makeMain();
Function* makeEntrypoint(const char*);
// Make a shader-style function, and create its entry block if entry is non-zero.
// Return the function, pass back the entry.
@ -282,6 +273,7 @@ public:
Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
Id createOp(Op, Id typeId, const std::vector<Id>& operands);
Id createFunctionCall(spv::Function*, std::vector<spv::Id>&);
Id createSpecConstantOp(Op, Id typeId, const std::vector<spv::Id>& operands, const std::vector<unsigned>& literals);
// Take an rvalue (source) and a set of channels to extract from it to
// make a new rvalue, which is returned.
@ -544,8 +536,16 @@ public:
void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control);
protected:
// Sets to generate opcode for specialization constants.
void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
// Sets to generate opcode for non-specialization constants (normal mode).
void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; }
// Check if the builder is generating code for spec constants.
bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; }
protected:
Id makeIntConstant(Id typeId, unsigned value, bool specConstant);
Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant);
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const;
Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) const;
Id findCompositeConstant(Op typeClass, std::vector<Id>& comps) const;
@ -568,6 +568,7 @@ protected:
Block* buildPoint;
Id uniqueId;
Function* mainFunction;
bool generatingOpCodeForSpecConst;
AccessChain accessChain;
// special blocks of instructions for output
@ -590,14 +591,11 @@ protected:
// Our loop stack.
std::stack<LoopBlocks> loops;
// The stream for outputing warnings and errors.
SpvBuildLogger* logger;
}; // end Builder class
// Use for non-fatal notes about what's not complete
void TbdFunctionality(const char*);
// Use for fatal missing functionality
void MissingFunctionality(const char*);
}; // end spv namespace
#endif // SpvBuilder_H

View file

@ -32,10 +32,6 @@
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
// Author: John Kessenich, LunarG
//
//
// Disassembler for SPIR-V.
//

View file

@ -32,10 +32,6 @@
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
// Author: John Kessenich, LunarG
//
//
// Disassembler for SPIR-V.
//

View file

@ -32,10 +32,6 @@
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
// Author: John Kessenich, LunarG
//
//
// 1) Programatically fill in instruction/operand information.
// This can be used for disassembly, printing documentation, etc.
@ -64,7 +60,7 @@ namespace spv {
// (for non-sparse mask enums, this is the number of enumurants)
//
const int SourceLanguageCeiling = 5;
const int SourceLanguageCeiling = 6; // HLSL todo: need official enumerant
const char* SourceString(int source)
{
@ -74,6 +70,7 @@ const char* SourceString(int source)
case 2: return "GLSL";
case 3: return "OpenCL_C";
case 4: return "OpenCL_CPP";
case 5: return "HLSL";
case SourceLanguageCeiling:
default: return "Bad";

View file

@ -32,10 +32,6 @@
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
// Author: John Kessenich, LunarG
//
//
// Parameterize the SPIR-V enumerants.
//

View file

@ -61,6 +61,7 @@ enum SourceLanguage {
SourceLanguageGLSL = 2,
SourceLanguageOpenCL_C = 3,
SourceLanguageOpenCL_CPP = 4,
SourceLanguageHLSL = 5,
};
enum ExecutionModel {

View file

@ -32,10 +32,6 @@
//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