Move to revision 31 of SPIR-V.
This commit is contained in:
parent
e24a74c320
commit
5e4b1242bf
77 changed files with 6050 additions and 5450 deletions
3
SPIRV/CMakeLists.txt
Normal file → Executable file
3
SPIRV/CMakeLists.txt
Normal file → Executable file
|
|
@ -10,7 +10,8 @@ set(SOURCES
|
|||
disassemble.cpp)
|
||||
|
||||
set(HEADERS
|
||||
spirv.h
|
||||
spirv.hpp
|
||||
GLSL.std.450.h
|
||||
GlslangToSpv.h
|
||||
SpvBuilder.h
|
||||
SPVRemapper.h
|
||||
|
|
|
|||
300
SPIRV/GlslangToSpv.cpp
Normal file → Executable file
300
SPIRV/GlslangToSpv.cpp
Normal file → Executable file
|
|
@ -39,14 +39,17 @@
|
|||
// translate them to SPIR-V.
|
||||
//
|
||||
|
||||
#include "spirv.h"
|
||||
#include "spirv.hpp"
|
||||
#include "GlslangToSpv.h"
|
||||
#include "SpvBuilder.h"
|
||||
#include "GLSL450Lib.h"
|
||||
namespace spv {
|
||||
#include "GLSL.std.450.h"
|
||||
}
|
||||
|
||||
// Glslang includes
|
||||
#include "../glslang/MachineIndependent/localintermediate.h"
|
||||
#include "../glslang/MachineIndependent/SymbolTable.h"
|
||||
#include "../glslang/Include/Common.h"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
|
@ -85,6 +88,7 @@ protected:
|
|||
spv::Id createSpvVariable(const glslang::TIntermSymbol*);
|
||||
spv::Id getSampledType(const glslang::TSampler&);
|
||||
spv::Id convertGlslangToSpvType(const glslang::TType& type);
|
||||
void updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset);
|
||||
|
||||
bool isShaderEntrypoint(const glslang::TIntermAggregate* node);
|
||||
void makeFunctions(const glslang::TIntermSequence&);
|
||||
|
|
@ -93,6 +97,7 @@ protected:
|
|||
void handleFunctionEntry(const glslang::TIntermAggregate* node);
|
||||
void translateArguments(const glslang::TIntermSequence& glslangArguments, std::vector<spv::Id>& arguments);
|
||||
spv::Id handleBuiltInFunctionCall(const glslang::TIntermAggregate*);
|
||||
spv::Id handleTextureCall(spv::Decoration precision, glslang::TOperator, spv::Id typeId, glslang::TSampler, std::vector<spv::Id>& idArguments);
|
||||
spv::Id handleUserFunctionCall(const glslang::TIntermAggregate*);
|
||||
|
||||
spv::Id createBinaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, spv::Id left, spv::Id right, glslang::TBasicType typeProxy, bool reduceComparison = true);
|
||||
|
|
@ -100,7 +105,7 @@ protected:
|
|||
spv::Id createConversion(glslang::TOperator op, spv::Decoration precision, spv::Id destTypeId, spv::Id operand);
|
||||
spv::Id makeSmearedConstant(spv::Id constant, int vectorSize);
|
||||
spv::Id createAtomicOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands);
|
||||
spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands);
|
||||
spv::Id createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy);
|
||||
spv::Id createNoArgOperation(glslang::TOperator op);
|
||||
spv::Id getSymbolId(const glslang::TIntermSymbol* node);
|
||||
void addDecoration(spv::Id id, spv::Decoration dec);
|
||||
|
|
@ -208,9 +213,9 @@ spv::Dim TranslateDimensionality(const glslang::TSampler& sampler)
|
|||
spv::Decoration TranslatePrecisionDecoration(const glslang::TType& type)
|
||||
{
|
||||
switch (type.getQualifier().precision) {
|
||||
case glslang::EpqLow: return spv::DecorationPrecisionLow;
|
||||
case glslang::EpqMedium: return spv::DecorationPrecisionMedium;
|
||||
case glslang::EpqHigh: return spv::DecorationPrecisionHigh;
|
||||
case glslang::EpqLow: return spv::DecorationRelaxedPrecision; // TODO: Map instead to 16-bit types?
|
||||
case glslang::EpqMedium: return spv::DecorationRelaxedPrecision;
|
||||
case glslang::EpqHigh: return spv::NoPrecision;
|
||||
default:
|
||||
return spv::NoPrecision;
|
||||
}
|
||||
|
|
@ -255,12 +260,9 @@ spv::Decoration TranslateLayoutDecoration(const glslang::TType& type)
|
|||
case glslang::EvqBuffer:
|
||||
switch (type.getQualifier().layoutPacking) {
|
||||
case glslang::ElpShared: return spv::DecorationGLSLShared;
|
||||
case glslang::ElpStd140: return spv::DecorationGLSLStd140;
|
||||
case glslang::ElpStd430: return spv::DecorationGLSLStd430;
|
||||
case glslang::ElpPacked: return spv::DecorationGLSLPacked;
|
||||
default:
|
||||
spv::MissingFunctionality("uniform block layout");
|
||||
return spv::DecorationGLSLShared;
|
||||
return (spv::Decoration)spv::BadValue;
|
||||
}
|
||||
case glslang::EvqVaryingIn:
|
||||
case glslang::EvqVaryingOut:
|
||||
|
|
@ -309,7 +311,6 @@ spv::BuiltIn TranslateBuiltInDecoration(glslang::TBuiltInVariable builtIn)
|
|||
switch (builtIn) {
|
||||
case glslang::EbvPosition: return spv::BuiltInPosition;
|
||||
case glslang::EbvPointSize: return spv::BuiltInPointSize;
|
||||
case glslang::EbvClipVertex: return spv::BuiltInClipVertex;
|
||||
case glslang::EbvClipDistance: return spv::BuiltInClipDistance;
|
||||
case glslang::EbvCullDistance: return spv::BuiltInCullDistance;
|
||||
case glslang::EbvVertexId: return spv::BuiltInVertexId;
|
||||
|
|
@ -359,7 +360,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls
|
|||
stdBuiltins = builder.import("GLSL.std.450");
|
||||
builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450);
|
||||
shaderEntry = builder.makeMain();
|
||||
builder.addEntryPoint(executionModel, shaderEntry);
|
||||
builder.addEntryPoint(executionModel, shaderEntry, "main");
|
||||
|
||||
// Add the source extensions
|
||||
const auto& sourceExtensions = glslangIntermediate->getRequestedExtensions();
|
||||
|
|
@ -374,13 +375,16 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls
|
|||
unsigned int mode;
|
||||
switch (glslangIntermediate->getStage()) {
|
||||
case EShLangVertex:
|
||||
builder.addCapability(spv::CapabilityShader);
|
||||
break;
|
||||
|
||||
case EShLangTessControl:
|
||||
builder.addCapability(spv::CapabilityTessellation);
|
||||
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOutputVertices, glslangIntermediate->getVertices());
|
||||
break;
|
||||
|
||||
case EShLangTessEvaluation:
|
||||
builder.addCapability(spv::CapabilityTessellation);
|
||||
switch (glslangIntermediate->getInputPrimitive()) {
|
||||
case glslang::ElgTriangles: mode = spv::ExecutionModeInputTriangles; break;
|
||||
case glslang::ElgQuads: mode = spv::ExecutionModeInputQuads; break;
|
||||
|
|
@ -397,6 +401,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls
|
|||
break;
|
||||
|
||||
case EShLangGeometry:
|
||||
builder.addCapability(spv::CapabilityGeometry);
|
||||
switch (glslangIntermediate->getInputPrimitive()) {
|
||||
case glslang::ElgPoints: mode = spv::ExecutionModeInputPoints; break;
|
||||
case glslang::ElgLines: mode = spv::ExecutionModeInputLines; break;
|
||||
|
|
@ -421,13 +426,17 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(const glslang::TIntermediate* gls
|
|||
break;
|
||||
|
||||
case EShLangFragment:
|
||||
builder.addCapability(spv::CapabilityShader);
|
||||
if (glslangIntermediate->getPixelCenterInteger())
|
||||
builder.addExecutionMode(shaderEntry, spv::ExecutionModePixelCenterInteger);
|
||||
if (glslangIntermediate->getOriginUpperLeft())
|
||||
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginUpperLeft);
|
||||
else
|
||||
builder.addExecutionMode(shaderEntry, spv::ExecutionModeOriginLowerLeft);
|
||||
break;
|
||||
|
||||
case EShLangCompute:
|
||||
builder.addCapability(spv::CapabilityShader);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -1051,7 +1060,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
|||
result = createUnaryOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands.front(), node->getType().getBasicType() == glslang::EbtFloat || node->getType().getBasicType() == glslang::EbtDouble);
|
||||
break;
|
||||
default:
|
||||
result = createMiscOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands);
|
||||
result = createMiscOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()), operands, node->getBasicType());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1311,9 +1320,11 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||
case glslang::EbtSampler:
|
||||
{
|
||||
const glslang::TSampler& sampler = type.getSampler();
|
||||
spvType = builder.makeSampler(getSampledType(sampler), TranslateDimensionality(sampler),
|
||||
sampler.image ? spv::Builder::samplerContentImage : spv::Builder::samplerContentTextureFilter,
|
||||
sampler.arrayed, sampler.shadow, sampler.ms);
|
||||
spvType = builder.makeImageType(getSampledType(sampler), TranslateDimensionality(sampler), sampler.shadow, sampler.arrayed, sampler.ms,
|
||||
sampler.image ? 2 : 1, spv::ImageFormatUnknown); // TODO: translate format, needed for GLSL image ops
|
||||
// OpenGL "textures" need to be combined with a sampler
|
||||
if (! sampler.image)
|
||||
spvType = builder.makeSampledImageType(spvType);
|
||||
}
|
||||
break;
|
||||
case glslang::EbtStruct:
|
||||
|
|
@ -1350,6 +1361,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||
structMap[glslangStruct] = spvType;
|
||||
|
||||
// Name and decorate the non-hidden members
|
||||
int offset = -1;
|
||||
for (int i = 0; i < (int)glslangStruct->size(); i++) {
|
||||
glslang::TType& glslangType = *(*glslangStruct)[i].type;
|
||||
int member = i;
|
||||
|
|
@ -1368,6 +1380,14 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||
builder.addMemberDecoration(spvType, member, spv::DecorationComponent, glslangType.getQualifier().layoutComponent);
|
||||
if (glslangType.getQualifier().hasXfbOffset())
|
||||
builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangType.getQualifier().layoutXfbOffset);
|
||||
else {
|
||||
// figure out what to do with offset, which is accumulating
|
||||
int nextOffset;
|
||||
updateMemberOffset(type, glslangType, offset, nextOffset);
|
||||
if (offset >= 0)
|
||||
builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangType.getQualifier().layoutOffset);
|
||||
offset = nextOffset;
|
||||
}
|
||||
|
||||
// built-in variable decorations
|
||||
spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangType.getQualifier().builtIn);
|
||||
|
|
@ -1383,7 +1403,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||
builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream);
|
||||
if (glslangIntermediate->getXfbMode()) {
|
||||
if (type.getQualifier().hasXfbStride())
|
||||
builder.addDecoration(spvType, spv::DecorationStride, type.getQualifier().layoutXfbStride);
|
||||
builder.addDecoration(spvType, spv::DecorationXfbStride, type.getQualifier().layoutXfbStride);
|
||||
if (type.getQualifier().hasXfbBuffer())
|
||||
builder.addDecoration(spvType, spv::DecorationXfbBuffer, type.getQualifier().layoutXfbBuffer);
|
||||
}
|
||||
|
|
@ -1415,6 +1435,49 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||
return spvType;
|
||||
}
|
||||
|
||||
// Given a member type of a struct, realign the current offset for it, and compute
|
||||
// the next (not yet aligned) offset for the next member, which will get aligned
|
||||
// on the next call.
|
||||
// 'currentOffset' should be passed in already initialized, ready to modify, and reflecting
|
||||
// the migration of data from nextOffset -> currentOffset. It should be -1 on the first call.
|
||||
// -1 means a non-forced member offset (no decoration needed).
|
||||
void TGlslangToSpvTraverser::updateMemberOffset(const glslang::TType& structType, const glslang::TType& memberType, int& currentOffset, int& nextOffset)
|
||||
{
|
||||
// this will get a positive value when deemed necessary
|
||||
nextOffset = -1;
|
||||
|
||||
bool forceOffset = structType.getQualifier().layoutPacking == glslang::ElpStd140 ||
|
||||
structType.getQualifier().layoutPacking == glslang::ElpStd430;
|
||||
|
||||
// override anything in currentOffset with user-set offset
|
||||
if (memberType.getQualifier().hasOffset())
|
||||
currentOffset = memberType.getQualifier().layoutOffset;
|
||||
|
||||
// It could be that current linker usage in glslang updated all the layoutOffset,
|
||||
// in which case the following code does not matter. But, that's not quite right
|
||||
// once cross-compilation unit GLSL validation is done, as the original user
|
||||
// settings are needed in layoutOffset, and then the following will come into play.
|
||||
|
||||
if (! forceOffset) {
|
||||
if (! memberType.getQualifier().hasOffset())
|
||||
currentOffset = -1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Getting this far means we are forcing offsets
|
||||
if (currentOffset < 0)
|
||||
currentOffset = 0;
|
||||
|
||||
// Now, currentOffset is valid (either 0, or from a previous nextOffset),
|
||||
// but possibly not yet correctly aligned.
|
||||
|
||||
int memberSize;
|
||||
int memberAlignment = glslangIntermediate->getBaseAlignment(memberType, memberSize, memberType.getQualifier().layoutPacking == glslang::ElpStd140);
|
||||
glslang::RoundToPow2(currentOffset, memberAlignment);
|
||||
nextOffset = currentOffset + memberSize;
|
||||
}
|
||||
|
||||
bool TGlslangToSpvTraverser::isShaderEntrypoint(const glslang::TIntermAggregate* node)
|
||||
{
|
||||
return node->getName() == "main(";
|
||||
|
|
@ -1519,11 +1582,6 @@ spv::Id TGlslangToSpvTraverser::handleBuiltInFunctionCall(const glslang::TInterm
|
|||
{
|
||||
std::vector<spv::Id> arguments;
|
||||
translateArguments(node->getSequence(), arguments);
|
||||
|
||||
std::vector<spv::Id> argTypes;
|
||||
for (int a = 0; a < (int)arguments.size(); ++a)
|
||||
argTypes.push_back(builder.getTypeId(arguments[a]));
|
||||
|
||||
spv::Decoration precision = TranslatePrecisionDecoration(node->getType());
|
||||
|
||||
if (node->getName() == "ftransform(") {
|
||||
|
|
@ -1544,22 +1602,22 @@ spv::Id TGlslangToSpvTraverser::handleBuiltInFunctionCall(const glslang::TInterm
|
|||
if (node->getName().find("textureSize", 0) != std::string::npos) {
|
||||
if (arguments.size() > 1) {
|
||||
params.lod = arguments[1];
|
||||
return builder.createTextureQueryCall(spv::OpTextureQuerySizeLod, params);
|
||||
return builder.createTextureQueryCall(spv::OpImageQuerySizeLod, params);
|
||||
} else
|
||||
return builder.createTextureQueryCall(spv::OpTextureQuerySize, params);
|
||||
return builder.createTextureQueryCall(spv::OpImageQuerySize, params);
|
||||
}
|
||||
|
||||
// special case the number of samples query
|
||||
if (node->getName().find("textureSamples", 0) != std::string::npos)
|
||||
return builder.createTextureQueryCall(spv::OpTextureQuerySamples, params);
|
||||
return builder.createTextureQueryCall(spv::OpImageQuerySamples, params);
|
||||
|
||||
// special case the other queries
|
||||
if (node->getName().find("Query", 0) != std::string::npos) {
|
||||
if (node->getName().find("Levels", 0) != std::string::npos)
|
||||
return builder.createTextureQueryCall(spv::OpTextureQueryLevels, params);
|
||||
return builder.createTextureQueryCall(spv::OpImageQueryLevels, params);
|
||||
else if (node->getName().find("Lod", 0) != std::string::npos) {
|
||||
params.coords = arguments[1];
|
||||
return builder.createTextureQueryCall(spv::OpTextureQueryLod, params);
|
||||
return builder.createTextureQueryCall(spv::OpImageQueryLod, params);
|
||||
} else
|
||||
spv::MissingFunctionality("glslang texture query");
|
||||
}
|
||||
|
|
@ -1599,6 +1657,16 @@ spv::Id TGlslangToSpvTraverser::handleBuiltInFunctionCall(const glslang::TInterm
|
|||
int extraArgs = 0;
|
||||
if (cubeCompare)
|
||||
params.Dref = arguments[2];
|
||||
else if (sampler.shadow) {
|
||||
std::vector<spv::Id> indexes;
|
||||
int comp;
|
||||
if (proj)
|
||||
comp = 3;
|
||||
else
|
||||
comp = builder.getNumComponents(params.coords) - 1;
|
||||
indexes.push_back(comp);
|
||||
params.Dref = builder.createCompositeExtract(params.coords, builder.getScalarTypeId(builder.getTypeId(params.coords)), indexes);
|
||||
}
|
||||
if (lod) {
|
||||
params.lod = arguments[2];
|
||||
++extraArgs;
|
||||
|
|
@ -1835,7 +1903,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryOperation(glslang::TOperator op, spv
|
|||
break;
|
||||
case glslang::EOpLogicalXor:
|
||||
needMatchingVectors = false;
|
||||
binOp = spv::OpLogicalXor;
|
||||
binOp = spv::OpLogicalNotEqual;
|
||||
break;
|
||||
|
||||
case glslang::EOpLessThan:
|
||||
|
|
@ -1974,107 +2042,109 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
|
|||
|
||||
case glslang::EOpLogicalNot:
|
||||
case glslang::EOpVectorLogicalNot:
|
||||
unaryOp = spv::OpLogicalNot;
|
||||
break;
|
||||
case glslang::EOpBitwiseNot:
|
||||
unaryOp = spv::OpNot;
|
||||
break;
|
||||
|
||||
|
||||
case glslang::EOpDeterminant:
|
||||
libCall = GLSL_STD_450::Determinant;
|
||||
libCall = spv::GLSLstd450Determinant;
|
||||
break;
|
||||
case glslang::EOpMatrixInverse:
|
||||
libCall = GLSL_STD_450::MatrixInverse;
|
||||
libCall = spv::GLSLstd450MatrixInverse;
|
||||
break;
|
||||
case glslang::EOpTranspose:
|
||||
unaryOp = spv::OpTranspose;
|
||||
break;
|
||||
|
||||
case glslang::EOpRadians:
|
||||
libCall = GLSL_STD_450::Radians;
|
||||
libCall = spv::GLSLstd450Radians;
|
||||
break;
|
||||
case glslang::EOpDegrees:
|
||||
libCall = GLSL_STD_450::Degrees;
|
||||
libCall = spv::GLSLstd450Degrees;
|
||||
break;
|
||||
case glslang::EOpSin:
|
||||
libCall = GLSL_STD_450::Sin;
|
||||
libCall = spv::GLSLstd450Sin;
|
||||
break;
|
||||
case glslang::EOpCos:
|
||||
libCall = GLSL_STD_450::Cos;
|
||||
libCall = spv::GLSLstd450Cos;
|
||||
break;
|
||||
case glslang::EOpTan:
|
||||
libCall = GLSL_STD_450::Tan;
|
||||
libCall = spv::GLSLstd450Tan;
|
||||
break;
|
||||
case glslang::EOpAcos:
|
||||
libCall = GLSL_STD_450::Acos;
|
||||
libCall = spv::GLSLstd450Acos;
|
||||
break;
|
||||
case glslang::EOpAsin:
|
||||
libCall = GLSL_STD_450::Asin;
|
||||
libCall = spv::GLSLstd450Asin;
|
||||
break;
|
||||
case glslang::EOpAtan:
|
||||
libCall = GLSL_STD_450::Atan;
|
||||
libCall = spv::GLSLstd450Atan;
|
||||
break;
|
||||
|
||||
case glslang::EOpAcosh:
|
||||
libCall = GLSL_STD_450::Acosh;
|
||||
libCall = spv::GLSLstd450Acosh;
|
||||
break;
|
||||
case glslang::EOpAsinh:
|
||||
libCall = GLSL_STD_450::Asinh;
|
||||
libCall = spv::GLSLstd450Asinh;
|
||||
break;
|
||||
case glslang::EOpAtanh:
|
||||
libCall = GLSL_STD_450::Atanh;
|
||||
libCall = spv::GLSLstd450Atanh;
|
||||
break;
|
||||
case glslang::EOpTanh:
|
||||
libCall = GLSL_STD_450::Tanh;
|
||||
libCall = spv::GLSLstd450Tanh;
|
||||
break;
|
||||
case glslang::EOpCosh:
|
||||
libCall = GLSL_STD_450::Cosh;
|
||||
libCall = spv::GLSLstd450Cosh;
|
||||
break;
|
||||
case glslang::EOpSinh:
|
||||
libCall = GLSL_STD_450::Sinh;
|
||||
libCall = spv::GLSLstd450Sinh;
|
||||
break;
|
||||
|
||||
case glslang::EOpLength:
|
||||
libCall = GLSL_STD_450::Length;
|
||||
libCall = spv::GLSLstd450Length;
|
||||
break;
|
||||
case glslang::EOpNormalize:
|
||||
libCall = GLSL_STD_450::Normalize;
|
||||
libCall = spv::GLSLstd450Normalize;
|
||||
break;
|
||||
|
||||
case glslang::EOpExp:
|
||||
libCall = GLSL_STD_450::Exp;
|
||||
libCall = spv::GLSLstd450Exp;
|
||||
break;
|
||||
case glslang::EOpLog:
|
||||
libCall = GLSL_STD_450::Log;
|
||||
libCall = spv::GLSLstd450Log;
|
||||
break;
|
||||
case glslang::EOpExp2:
|
||||
libCall = GLSL_STD_450::Exp2;
|
||||
libCall = spv::GLSLstd450Exp2;
|
||||
break;
|
||||
case glslang::EOpLog2:
|
||||
libCall = GLSL_STD_450::Log2;
|
||||
libCall = spv::GLSLstd450Log2;
|
||||
break;
|
||||
case glslang::EOpSqrt:
|
||||
libCall = GLSL_STD_450::Sqrt;
|
||||
libCall = spv::GLSLstd450Sqrt;
|
||||
break;
|
||||
case glslang::EOpInverseSqrt:
|
||||
libCall = GLSL_STD_450::InverseSqrt;
|
||||
libCall = spv::GLSLstd450InverseSqrt;
|
||||
break;
|
||||
|
||||
case glslang::EOpFloor:
|
||||
libCall = GLSL_STD_450::Floor;
|
||||
libCall = spv::GLSLstd450Floor;
|
||||
break;
|
||||
case glslang::EOpTrunc:
|
||||
libCall = GLSL_STD_450::Trunc;
|
||||
libCall = spv::GLSLstd450Trunc;
|
||||
break;
|
||||
case glslang::EOpRound:
|
||||
libCall = GLSL_STD_450::Round;
|
||||
libCall = spv::GLSLstd450Round;
|
||||
break;
|
||||
case glslang::EOpRoundEven:
|
||||
libCall = GLSL_STD_450::RoundEven;
|
||||
libCall = spv::GLSLstd450RoundEven;
|
||||
break;
|
||||
case glslang::EOpCeil:
|
||||
libCall = GLSL_STD_450::Ceil;
|
||||
libCall = spv::GLSLstd450Ceil;
|
||||
break;
|
||||
case glslang::EOpFract:
|
||||
libCall = GLSL_STD_450::Fract;
|
||||
libCall = spv::GLSLstd450Fract;
|
||||
break;
|
||||
|
||||
case glslang::EOpIsNan:
|
||||
|
|
@ -2084,35 +2154,23 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
|
|||
unaryOp = spv::OpIsInf;
|
||||
break;
|
||||
|
||||
case glslang::EOpFloatBitsToInt:
|
||||
libCall = GLSL_STD_450::FloatBitsToInt;
|
||||
break;
|
||||
case glslang::EOpFloatBitsToUint:
|
||||
libCall = GLSL_STD_450::FloatBitsToUint;
|
||||
break;
|
||||
case glslang::EOpIntBitsToFloat:
|
||||
libCall = GLSL_STD_450::IntBitsToFloat;
|
||||
break;
|
||||
case glslang::EOpUintBitsToFloat:
|
||||
libCall = GLSL_STD_450::UintBitsToFloat;
|
||||
break;
|
||||
case glslang::EOpPackSnorm2x16:
|
||||
libCall = GLSL_STD_450::PackSnorm2x16;
|
||||
libCall = spv::GLSLstd450PackSnorm2x16;
|
||||
break;
|
||||
case glslang::EOpUnpackSnorm2x16:
|
||||
libCall = GLSL_STD_450::UnpackSnorm2x16;
|
||||
libCall = spv::GLSLstd450UnpackSnorm2x16;
|
||||
break;
|
||||
case glslang::EOpPackUnorm2x16:
|
||||
libCall = GLSL_STD_450::PackUnorm2x16;
|
||||
libCall = spv::GLSLstd450PackUnorm2x16;
|
||||
break;
|
||||
case glslang::EOpUnpackUnorm2x16:
|
||||
libCall = GLSL_STD_450::UnpackUnorm2x16;
|
||||
libCall = spv::GLSLstd450UnpackUnorm2x16;
|
||||
break;
|
||||
case glslang::EOpPackHalf2x16:
|
||||
libCall = GLSL_STD_450::PackHalf2x16;
|
||||
libCall = spv::GLSLstd450PackHalf2x16;
|
||||
break;
|
||||
case glslang::EOpUnpackHalf2x16:
|
||||
libCall = GLSL_STD_450::UnpackHalf2x16;
|
||||
libCall = spv::GLSLstd450UnpackHalf2x16;
|
||||
break;
|
||||
|
||||
case glslang::EOpDPdx:
|
||||
|
|
@ -2151,10 +2209,16 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
|
|||
break;
|
||||
|
||||
case glslang::EOpAbs:
|
||||
libCall = GLSL_STD_450::Abs;
|
||||
if (isFloat)
|
||||
libCall = spv::GLSLstd450FAbs;
|
||||
else
|
||||
libCall = spv::GLSLstd450SAbs;
|
||||
break;
|
||||
case glslang::EOpSign:
|
||||
libCall = GLSL_STD_450::Sign;
|
||||
if (isFloat)
|
||||
libCall = spv::GLSLstd450FSign;
|
||||
else
|
||||
libCall = spv::GLSLstd450SSign;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -2291,10 +2355,10 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
|
|||
opCode = spv::OpAtomicIAdd;
|
||||
break;
|
||||
case glslang::EOpAtomicMin:
|
||||
opCode = spv::OpAtomicIMin;
|
||||
opCode = spv::OpAtomicSMin;
|
||||
break;
|
||||
case glslang::EOpAtomicMax:
|
||||
opCode = spv::OpAtomicIMax;
|
||||
opCode = spv::OpAtomicSMax;
|
||||
break;
|
||||
case glslang::EOpAtomicAnd:
|
||||
opCode = spv::OpAtomicAnd;
|
||||
|
|
@ -2331,8 +2395,8 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
|
|||
std::vector<spv::Id> spvAtomicOperands; // hold the spv operands
|
||||
auto opIt = operands.begin(); // walk the glslang operands
|
||||
spvAtomicOperands.push_back(*(opIt++));
|
||||
spvAtomicOperands.push_back(spv::ExecutionScopeDevice); // TBD: what is the correct scope?
|
||||
spvAtomicOperands.push_back( spv::MemorySemanticsMaskNone); // TBD: what are the correct memory semantics?
|
||||
spvAtomicOperands.push_back(builder.makeUintConstant(spv::ScopeDevice)); // TBD: what is the correct scope?
|
||||
spvAtomicOperands.push_back(builder.makeUintConstant(spv::MemorySemanticsMaskNone)); // TBD: what are the correct memory semantics?
|
||||
|
||||
// Add the rest of the operands, skipping the first one, which was dealt with above.
|
||||
// For some ops, there are none, for some 1, for compare-exchange, 2.
|
||||
|
|
@ -2342,58 +2406,76 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
|
|||
return builder.createOp(opCode, typeId, spvAtomicOperands);
|
||||
}
|
||||
|
||||
spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands)
|
||||
spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId, std::vector<spv::Id>& operands, glslang::TBasicType typeProxy)
|
||||
{
|
||||
bool isUnsigned = typeProxy == glslang::EbtUint;
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
|
||||
|
||||
spv::Op opCode = spv::OpNop;
|
||||
int libCall = -1;
|
||||
|
||||
switch (op) {
|
||||
case glslang::EOpMin:
|
||||
libCall = GLSL_STD_450::Min;
|
||||
if (isFloat)
|
||||
libCall = spv::GLSLstd450FMin;
|
||||
else if (isUnsigned)
|
||||
libCall = spv::GLSLstd450UMin;
|
||||
else
|
||||
libCall = spv::GLSLstd450SMin;
|
||||
break;
|
||||
case glslang::EOpModf:
|
||||
libCall = GLSL_STD_450::Modf;
|
||||
libCall = spv::GLSLstd450Modf;
|
||||
break;
|
||||
case glslang::EOpMax:
|
||||
libCall = GLSL_STD_450::Max;
|
||||
if (isFloat)
|
||||
libCall = spv::GLSLstd450FMax;
|
||||
else if (isUnsigned)
|
||||
libCall = spv::GLSLstd450UMax;
|
||||
else
|
||||
libCall = spv::GLSLstd450SMax;
|
||||
break;
|
||||
case glslang::EOpPow:
|
||||
libCall = GLSL_STD_450::Pow;
|
||||
libCall = spv::GLSLstd450Pow;
|
||||
break;
|
||||
case glslang::EOpDot:
|
||||
opCode = spv::OpDot;
|
||||
break;
|
||||
case glslang::EOpAtan:
|
||||
libCall = GLSL_STD_450::Atan2;
|
||||
libCall = spv::GLSLstd450Atan2;
|
||||
break;
|
||||
|
||||
case glslang::EOpClamp:
|
||||
libCall = GLSL_STD_450::Clamp;
|
||||
if (isFloat)
|
||||
libCall = spv::GLSLstd450FClamp;
|
||||
else if (isUnsigned)
|
||||
libCall = spv::GLSLstd450UClamp;
|
||||
else
|
||||
libCall = spv::GLSLstd450SClamp;
|
||||
break;
|
||||
case glslang::EOpMix:
|
||||
libCall = GLSL_STD_450::Mix;
|
||||
libCall = spv::GLSLstd450Mix;
|
||||
break;
|
||||
case glslang::EOpStep:
|
||||
libCall = GLSL_STD_450::Step;
|
||||
libCall = spv::GLSLstd450Step;
|
||||
break;
|
||||
case glslang::EOpSmoothStep:
|
||||
libCall = GLSL_STD_450::SmoothStep;
|
||||
libCall = spv::GLSLstd450SmoothStep;
|
||||
break;
|
||||
|
||||
case glslang::EOpDistance:
|
||||
libCall = GLSL_STD_450::Distance;
|
||||
libCall = spv::GLSLstd450Distance;
|
||||
break;
|
||||
case glslang::EOpCross:
|
||||
libCall = GLSL_STD_450::Cross;
|
||||
libCall = spv::GLSLstd450Cross;
|
||||
break;
|
||||
case glslang::EOpFaceForward:
|
||||
libCall = GLSL_STD_450::FaceForward;
|
||||
libCall = spv::GLSLstd450FaceForward;
|
||||
break;
|
||||
case glslang::EOpReflect:
|
||||
libCall = GLSL_STD_450::Reflect;
|
||||
libCall = spv::GLSLstd450Reflect;
|
||||
break;
|
||||
case glslang::EOpRefract:
|
||||
libCall = GLSL_STD_450::Refract;
|
||||
libCall = spv::GLSLstd450Refract;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -2444,26 +2526,26 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op)
|
|||
builder.createNoResultOp(spv::OpEndPrimitive);
|
||||
return 0;
|
||||
case glslang::EOpBarrier:
|
||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsAllMemory);
|
||||
builder.createControlBarrier(spv::ExecutionScopeDevice);
|
||||
builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAllMemory);
|
||||
builder.createControlBarrier(spv::ScopeDevice, spv::ScopeDevice, spv::MemorySemanticsMaskNone);
|
||||
return 0;
|
||||
case glslang::EOpMemoryBarrier:
|
||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsAllMemory);
|
||||
builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAllMemory);
|
||||
return 0;
|
||||
case glslang::EOpMemoryBarrierAtomicCounter:
|
||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsAtomicCounterMemoryMask);
|
||||
builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsAtomicCounterMemoryMask);
|
||||
return 0;
|
||||
case glslang::EOpMemoryBarrierBuffer:
|
||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsUniformMemoryMask);
|
||||
builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsUniformMemoryMask);
|
||||
return 0;
|
||||
case glslang::EOpMemoryBarrierImage:
|
||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsImageMemoryMask);
|
||||
builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsImageMemoryMask);
|
||||
return 0;
|
||||
case glslang::EOpMemoryBarrierShared:
|
||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsWorkgroupLocalMemoryMask);
|
||||
builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsWorkgroupLocalMemoryMask);
|
||||
return 0;
|
||||
case glslang::EOpGroupMemoryBarrier:
|
||||
builder.createMemoryBarrier(spv::ExecutionScopeDevice, spv::MemorySemanticsWorkgroupGlobalMemoryMask);
|
||||
builder.createMemoryBarrier(spv::ScopeDevice, spv::MemorySemanticsWorkgroupGlobalMemoryMask);
|
||||
return 0;
|
||||
default:
|
||||
spv::MissingFunctionality("operation with no arguments");
|
||||
|
|
@ -2495,7 +2577,7 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
|
|||
builder.addDecoration(id, spv::DecorationComponent, symbol->getQualifier().layoutComponent);
|
||||
if (glslangIntermediate->getXfbMode()) {
|
||||
if (symbol->getQualifier().hasXfbStride())
|
||||
builder.addDecoration(id, spv::DecorationStride, symbol->getQualifier().layoutXfbStride);
|
||||
builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride);
|
||||
if (symbol->getQualifier().hasXfbBuffer())
|
||||
builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
|
||||
if (symbol->getQualifier().hasXfbOffset())
|
||||
|
|
@ -2512,14 +2594,14 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
|
|||
builder.addDecoration(id, spv::DecorationBinding, symbol->getQualifier().layoutBinding);
|
||||
if (glslangIntermediate->getXfbMode()) {
|
||||
if (symbol->getQualifier().hasXfbStride())
|
||||
builder.addDecoration(id, spv::DecorationStride, symbol->getQualifier().layoutXfbStride);
|
||||
builder.addDecoration(id, spv::DecorationXfbStride, symbol->getQualifier().layoutXfbStride);
|
||||
if (symbol->getQualifier().hasXfbBuffer())
|
||||
builder.addDecoration(id, spv::DecorationXfbBuffer, symbol->getQualifier().layoutXfbBuffer);
|
||||
}
|
||||
|
||||
// built-in variable decorations
|
||||
spv::BuiltIn builtIn = TranslateBuiltInDecoration(symbol->getQualifier().builtIn);
|
||||
if ((unsigned int)builtIn != spv::BadValue)
|
||||
if (builtIn != spv::BadValue)
|
||||
builder.addDecoration(id, spv::DecorationBuiltIn, (int)builtIn);
|
||||
|
||||
if (linkageOnly)
|
||||
|
|
|
|||
50
SPIRV/SPVRemapper.cpp
Normal file → Executable file
50
SPIRV/SPVRemapper.cpp
Normal file → Executable file
|
|
@ -82,6 +82,8 @@ namespace spv {
|
|||
case spv::OpTypeFloat: // fall through...
|
||||
case spv::OpTypePointer: return range_t(2, 3);
|
||||
case spv::OpTypeInt: return range_t(2, 4);
|
||||
// TODO: case spv::OpTypeImage:
|
||||
// TODO: case spv::OpTypeSampledImage:
|
||||
case spv::OpTypeSampler: return range_t(3, 8);
|
||||
case spv::OpTypeVector: // fall through
|
||||
case spv::OpTypeMatrix: // ...
|
||||
|
|
@ -164,8 +166,8 @@ namespace spv {
|
|||
case spv::OpTypeFloat:
|
||||
case spv::OpTypeVector:
|
||||
case spv::OpTypeMatrix:
|
||||
case spv::OpTypeImage:
|
||||
case spv::OpTypeSampler:
|
||||
case spv::OpTypeFilter:
|
||||
case spv::OpTypeArray:
|
||||
case spv::OpTypeRuntimeArray:
|
||||
case spv::OpTypeStruct:
|
||||
|
|
@ -184,12 +186,11 @@ namespace spv {
|
|||
bool spirvbin_t::isConstOp(spv::Op opCode) const
|
||||
{
|
||||
switch (opCode) {
|
||||
case spv::OpConstantNullObject: error("unimplemented constant type");
|
||||
case spv::OpConstantNull: error("unimplemented constant type");
|
||||
case spv::OpConstantSampler: error("unimplemented constant type");
|
||||
|
||||
case spv::OpConstantTrue:
|
||||
case spv::OpConstantFalse:
|
||||
case spv::OpConstantNullPointer:
|
||||
case spv::OpConstantComposite:
|
||||
case spv::OpConstant: return true;
|
||||
default: return false;
|
||||
|
|
@ -486,7 +487,7 @@ namespace spv {
|
|||
case spv::OperandFunction:
|
||||
case spv::OperandMemorySemantics:
|
||||
case spv::OperandMemoryAccess:
|
||||
case spv::OperandExecutionScope:
|
||||
case spv::OperandScope:
|
||||
case spv::OperandGroupOperation:
|
||||
case spv::OperandKernelEnqueueFlags:
|
||||
case spv::OperandKernelProfilingInfo:
|
||||
|
|
@ -610,19 +611,14 @@ namespace spv {
|
|||
fnId = asId(start + 2);
|
||||
break;
|
||||
|
||||
case spv::OpTextureSample:
|
||||
case spv::OpTextureSampleDref:
|
||||
case spv::OpTextureSampleLod:
|
||||
case spv::OpTextureSampleProj:
|
||||
case spv::OpTextureSampleGrad:
|
||||
case spv::OpTextureSampleOffset:
|
||||
case spv::OpTextureSampleProjLod:
|
||||
case spv::OpTextureSampleProjGrad:
|
||||
case spv::OpTextureSampleLodOffset:
|
||||
case spv::OpTextureSampleProjOffset:
|
||||
case spv::OpTextureSampleGradOffset:
|
||||
case spv::OpTextureSampleProjLodOffset:
|
||||
case spv::OpTextureSampleProjGradOffset:
|
||||
case spv::OpImageSampleImplicitLod:
|
||||
case spv::OpImageSampleExplicitLod:
|
||||
case spv::OpImageSampleDrefImplicitLod:
|
||||
case spv::OpImageSampleDrefExplicitLod:
|
||||
case spv::OpImageSampleProjImplicitLod:
|
||||
case spv::OpImageSampleProjExplicitLod:
|
||||
case spv::OpImageSampleProjDrefImplicitLod:
|
||||
case spv::OpImageSampleProjDrefExplicitLod:
|
||||
case spv::OpDot:
|
||||
case spv::OpCompositeExtract:
|
||||
case spv::OpCompositeInsert:
|
||||
|
|
@ -668,7 +664,7 @@ namespace spv {
|
|||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
// Add inputs and uniforms to the map
|
||||
if (((opCode == spv::OpVariable && asWordCount(start) == 4) || (opCode == spv::OpVariableArray)) &&
|
||||
if ((opCode == spv::OpVariable && asWordCount(start) == 4) &&
|
||||
(spv[start+3] == spv::StorageClassUniform ||
|
||||
spv[start+3] == spv::StorageClassUniformConstant ||
|
||||
spv[start+3] == spv::StorageClassInput))
|
||||
|
|
@ -695,7 +691,7 @@ namespace spv {
|
|||
process(
|
||||
[&](spv::Op opCode, unsigned start) {
|
||||
// Add inputs and uniforms to the map
|
||||
if (((opCode == spv::OpVariable && asWordCount(start) == 4) || (opCode == spv::OpVariableArray)) &&
|
||||
if ((opCode == spv::OpVariable && asWordCount(start) == 4) &&
|
||||
(spv[start+3] == spv::StorageClassOutput))
|
||||
fnLocalVars.insert(asId(start+2));
|
||||
|
||||
|
|
@ -729,8 +725,7 @@ namespace spv {
|
|||
const int wordCount = asWordCount(start);
|
||||
|
||||
// Add local variables to the map
|
||||
if ((opCode == spv::OpVariable && spv[start+3] == spv::StorageClassFunction && asWordCount(start) == 4) ||
|
||||
(opCode == spv::OpVariableArray && spv[start+3] == spv::StorageClassFunction))
|
||||
if ((opCode == spv::OpVariable && spv[start+3] == spv::StorageClassFunction && asWordCount(start) == 4))
|
||||
fnLocalVars.insert(asId(start+2));
|
||||
|
||||
// Ignore process vars referenced via access chain
|
||||
|
|
@ -1008,14 +1003,14 @@ namespace spv {
|
|||
return 6 + hashType(typePos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
|
||||
case spv::OpTypeMatrix:
|
||||
return 30 + hashType(typePos(spv[typeStart+2])) * (spv[typeStart+3] - 1);
|
||||
case spv::OpTypeSampler:
|
||||
case spv::OpTypeImage:
|
||||
return 120 + hashType(typePos(spv[typeStart+2])) +
|
||||
spv[typeStart+3] + // dimensionality
|
||||
spv[typeStart+4] * 8 * 16 + // content
|
||||
spv[typeStart+4] * 8 * 16 + // depth
|
||||
spv[typeStart+5] * 4 * 16 + // arrayed
|
||||
spv[typeStart+6] * 2 * 16 + // compare
|
||||
spv[typeStart+7] * 1 * 16; // multisampled
|
||||
case spv::OpTypeFilter:
|
||||
spv[typeStart+6] * 2 * 16 + // multisampled
|
||||
spv[typeStart+7] * 1 * 16; // format
|
||||
case spv::OpTypeSampler:
|
||||
return 500;
|
||||
case spv::OpTypeArray:
|
||||
return 501 + hashType(typePos(spv[typeStart+2])) * spv[typeStart+3];
|
||||
|
|
@ -1045,12 +1040,11 @@ namespace spv {
|
|||
case spv::OpTypeQueue: return 300003;
|
||||
case spv::OpTypePipe: return 300004;
|
||||
|
||||
case spv::OpConstantNullObject: return 300005;
|
||||
case spv::OpConstantNull: return 300005;
|
||||
case spv::OpConstantSampler: return 300006;
|
||||
|
||||
case spv::OpConstantTrue: return 300007;
|
||||
case spv::OpConstantFalse: return 300008;
|
||||
case spv::OpConstantNullPointer: return 300009;
|
||||
case spv::OpConstantComposite:
|
||||
{
|
||||
std::uint32_t hash = 300011 + hashType(typePos(spv[typeStart+1]));
|
||||
|
|
|
|||
2
SPIRV/SPVRemapper.h
Normal file → Executable file
2
SPIRV/SPVRemapper.h
Normal file → Executable file
|
|
@ -101,7 +101,7 @@ public:
|
|||
#include <set>
|
||||
#include <cassert>
|
||||
|
||||
#include "spirv.h"
|
||||
#include "spirv.hpp"
|
||||
#include "spvIR.h"
|
||||
|
||||
namespace spv {
|
||||
|
|
|
|||
198
SPIRV/SpvBuilder.cpp
Normal file → Executable file
198
SPIRV/SpvBuilder.cpp
Normal file → Executable file
|
|
@ -295,31 +295,54 @@ Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
|
|||
return type->getResultId();
|
||||
}
|
||||
|
||||
Id Builder::makeSampler(Id sampledType, Dim dim, samplerContent content, bool arrayed, bool shadow, bool ms)
|
||||
Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
|
||||
{
|
||||
// try to find it
|
||||
Instruction* type;
|
||||
for (int t = 0; t < (int)groupedTypes[OpTypeSampler].size(); ++t) {
|
||||
type = groupedTypes[OpTypeSampler][t];
|
||||
for (int t = 0; t < (int)groupedTypes[OpTypeImage].size(); ++t) {
|
||||
type = groupedTypes[OpTypeImage][t];
|
||||
if (type->getIdOperand(0) == sampledType &&
|
||||
type->getImmediateOperand(1) == (unsigned int)dim &&
|
||||
type->getImmediateOperand(2) == (unsigned int)content &&
|
||||
type->getImmediateOperand(2) == ( depth ? 1u : 0u) &&
|
||||
type->getImmediateOperand(3) == (arrayed ? 1u : 0u) &&
|
||||
type->getImmediateOperand(4) == ( shadow ? 1u : 0u) &&
|
||||
type->getImmediateOperand(5) == ( ms ? 1u : 0u))
|
||||
type->getImmediateOperand(4) == ( ms ? 1u : 0u) &&
|
||||
type->getImmediateOperand(5) == sampled &&
|
||||
type->getImmediateOperand(6) == (unsigned int)format)
|
||||
return type->getResultId();
|
||||
}
|
||||
|
||||
// not found, make it
|
||||
type = new Instruction(getUniqueId(), NoType, OpTypeSampler);
|
||||
type = new Instruction(getUniqueId(), NoType, OpTypeImage);
|
||||
type->addIdOperand(sampledType);
|
||||
type->addImmediateOperand( dim);
|
||||
type->addImmediateOperand(content);
|
||||
type->addImmediateOperand( depth ? 1 : 0);
|
||||
type->addImmediateOperand(arrayed ? 1 : 0);
|
||||
type->addImmediateOperand( shadow ? 1 : 0);
|
||||
type->addImmediateOperand( ms ? 1 : 0);
|
||||
type->addImmediateOperand(sampled);
|
||||
type->addImmediateOperand((unsigned int)format);
|
||||
|
||||
groupedTypes[OpTypeSampler].push_back(type);
|
||||
groupedTypes[OpTypeImage].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
module.mapInstruction(type);
|
||||
|
||||
return type->getResultId();
|
||||
}
|
||||
|
||||
Id Builder::makeSampledImageType(Id imageType)
|
||||
{
|
||||
// try to find it
|
||||
Instruction* type;
|
||||
for (int t = 0; t < (int)groupedTypes[OpTypeSampledImage].size(); ++t) {
|
||||
type = groupedTypes[OpTypeSampledImage][t];
|
||||
if (type->getIdOperand(0) == imageType)
|
||||
return type->getResultId();
|
||||
}
|
||||
|
||||
// not found, make it
|
||||
type = new Instruction(getUniqueId(), NoType, OpTypeSampledImage);
|
||||
type->addIdOperand(imageType);
|
||||
|
||||
groupedTypes[OpTypeSampledImage].push_back(type);
|
||||
constantsTypesGlobals.push_back(type);
|
||||
module.mapInstruction(type);
|
||||
|
||||
|
|
@ -606,11 +629,12 @@ Id Builder::makeCompositeConstant(Id typeId, std::vector<Id>& members)
|
|||
return c->getResultId();
|
||||
}
|
||||
|
||||
void Builder::addEntryPoint(ExecutionModel model, Function* function)
|
||||
void Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name)
|
||||
{
|
||||
Instruction* entryPoint = new Instruction(OpEntryPoint);
|
||||
entryPoint->addImmediateOperand(model);
|
||||
entryPoint->addIdOperand(function->getId());
|
||||
entryPoint->addStringOperand(name);
|
||||
|
||||
entryPoints.push_back(entryPoint);
|
||||
}
|
||||
|
|
@ -945,18 +969,20 @@ void Builder::createNoResultOp(Op opCode, Id operand)
|
|||
buildPoint->addInstruction(op);
|
||||
}
|
||||
|
||||
void Builder::createControlBarrier(unsigned executionScope)
|
||||
void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics)
|
||||
{
|
||||
Instruction* op = new Instruction(OpControlBarrier);
|
||||
op->addImmediateOperand(executionScope);
|
||||
op->addImmediateOperand(makeUintConstant(execution));
|
||||
op->addImmediateOperand(makeUintConstant(memory));
|
||||
op->addImmediateOperand(makeUintConstant(semantics));
|
||||
buildPoint->addInstruction(op);
|
||||
}
|
||||
|
||||
void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics)
|
||||
{
|
||||
Instruction* op = new Instruction(OpMemoryBarrier);
|
||||
op->addImmediateOperand(executionScope);
|
||||
op->addImmediateOperand(memorySemantics);
|
||||
op->addImmediateOperand(makeUintConstant(executionScope));
|
||||
op->addImmediateOperand(makeUintConstant(memorySemantics));
|
||||
buildPoint->addInstruction(op);
|
||||
}
|
||||
|
||||
|
|
@ -991,7 +1017,7 @@ Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
|
|||
return op->getResultId();
|
||||
}
|
||||
|
||||
Id Builder::createOp(Op opCode, Id typeId, std::vector<Id>& operands)
|
||||
Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
|
||||
{
|
||||
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
|
||||
for (auto operand : operands)
|
||||
|
|
@ -1107,64 +1133,95 @@ Id Builder::createBuiltinCall(Decoration /*precision*/, Id resultType, Id builti
|
|||
// Create the correct instruction based on the inputs, and make the call.
|
||||
Id Builder::createTextureCall(Decoration precision, Id resultType, bool proj, const TextureParameters& parameters)
|
||||
{
|
||||
static const int maxTextureArgs = 5;
|
||||
static const int maxTextureArgs = 10;
|
||||
Id texArgs[maxTextureArgs] = {};
|
||||
|
||||
//
|
||||
// Set up the arguments
|
||||
// Set up the fixed arguments
|
||||
//
|
||||
|
||||
int numArgs = 0;
|
||||
bool xplicit = false;
|
||||
texArgs[numArgs++] = parameters.sampler;
|
||||
texArgs[numArgs++] = parameters.coords;
|
||||
|
||||
if (parameters.gradX) {
|
||||
texArgs[numArgs++] = parameters.gradX;
|
||||
texArgs[numArgs++] = parameters.gradY;
|
||||
}
|
||||
if (parameters.lod)
|
||||
texArgs[numArgs++] = parameters.lod;
|
||||
if (parameters.offset)
|
||||
texArgs[numArgs++] = parameters.offset;
|
||||
if (parameters.bias)
|
||||
texArgs[numArgs++] = parameters.bias;
|
||||
if (parameters.Dref)
|
||||
texArgs[numArgs++] = parameters.Dref;
|
||||
|
||||
//
|
||||
// Set up the optional arguments
|
||||
//
|
||||
int optArgNum = numArgs; // track which operand, if it exists, is the mask of optional arguments
|
||||
++numArgs; // speculatively make room for the mask operand
|
||||
ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand
|
||||
if (parameters.bias) {
|
||||
mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask);
|
||||
texArgs[numArgs++] = parameters.bias;
|
||||
}
|
||||
if (parameters.lod) {
|
||||
mask = (ImageOperandsMask)(mask | ImageOperandsLodMask);
|
||||
texArgs[numArgs++] = parameters.lod;
|
||||
xplicit = true;
|
||||
}
|
||||
if (parameters.gradX) {
|
||||
mask = (ImageOperandsMask)(mask | ImageOperandsGradMask);
|
||||
texArgs[numArgs++] = parameters.gradX;
|
||||
texArgs[numArgs++] = parameters.gradY;
|
||||
xplicit = true;
|
||||
}
|
||||
if (parameters.offset) {
|
||||
mask = (ImageOperandsMask)(mask | ImageOperandsOffsetMask);
|
||||
texArgs[numArgs++] = parameters.offset;
|
||||
}
|
||||
// TBD: if Offset is constant, use ImageOperandsConstOffsetMask
|
||||
if (parameters.offsets) {
|
||||
mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetsMask);
|
||||
texArgs[numArgs++] = parameters.offsets;
|
||||
}
|
||||
if (parameters.sample) {
|
||||
mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask);
|
||||
texArgs[numArgs++] = parameters.sample;
|
||||
}
|
||||
if (mask == ImageOperandsMaskNone)
|
||||
--numArgs; // undo speculative reservation for the mask argument
|
||||
else
|
||||
texArgs[optArgNum] = mask;
|
||||
|
||||
//
|
||||
// Set up the instruction
|
||||
//
|
||||
|
||||
Op opCode;
|
||||
if (proj && parameters.gradX && parameters.offset)
|
||||
opCode = OpTextureSampleProjGradOffset;
|
||||
else if (proj && parameters.lod && parameters.offset)
|
||||
opCode = OpTextureSampleProjLodOffset;
|
||||
else if (parameters.gradX && parameters.offset)
|
||||
opCode = OpTextureSampleGradOffset;
|
||||
else if (proj && parameters.offset)
|
||||
opCode = OpTextureSampleProjOffset;
|
||||
else if (parameters.lod && parameters.offset)
|
||||
opCode = OpTextureSampleLodOffset;
|
||||
else if (proj && parameters.gradX)
|
||||
opCode = OpTextureSampleProjGrad;
|
||||
else if (proj && parameters.lod)
|
||||
opCode = OpTextureSampleProjLod;
|
||||
else if (parameters.offset)
|
||||
opCode = OpTextureSampleOffset;
|
||||
else if (parameters.gradX)
|
||||
opCode = OpTextureSampleGrad;
|
||||
else if (proj)
|
||||
opCode = OpTextureSampleProj;
|
||||
else if (parameters.lod)
|
||||
opCode = OpTextureSampleLod;
|
||||
else if (parameters.Dref)
|
||||
opCode = OpTextureSampleDref;
|
||||
else
|
||||
opCode = OpTextureSample;
|
||||
opCode = OpImageSampleImplicitLod;
|
||||
if (xplicit) {
|
||||
if (parameters.Dref) {
|
||||
if (proj)
|
||||
opCode = OpImageSampleProjDrefExplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleDrefExplicitLod;
|
||||
} else {
|
||||
if (proj)
|
||||
opCode = OpImageSampleProjExplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleExplicitLod;
|
||||
}
|
||||
} else {
|
||||
if (parameters.Dref) {
|
||||
if (proj)
|
||||
opCode = OpImageSampleProjDrefImplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleDrefImplicitLod;
|
||||
} else {
|
||||
if (proj)
|
||||
opCode = OpImageSampleProjImplicitLod;
|
||||
else
|
||||
opCode = OpImageSampleImplicitLod;
|
||||
}
|
||||
}
|
||||
|
||||
Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode);
|
||||
for (int op = 0; op < numArgs; ++op)
|
||||
for (int op = 0; op < optArgNum; ++op)
|
||||
textureInst->addIdOperand(texArgs[op]);
|
||||
if (optArgNum < numArgs)
|
||||
textureInst->addImmediateOperand(texArgs[optArgNum]);
|
||||
for (int op = optArgNum + 1; op < numArgs; ++op)
|
||||
textureInst->addIdOperand(texArgs[op]);
|
||||
setPrecision(textureInst->getResultId(), precision);
|
||||
buildPoint->addInstruction(textureInst);
|
||||
|
|
@ -1176,13 +1233,13 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool proj, co
|
|||
Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters)
|
||||
{
|
||||
// Figure out the result type
|
||||
Id resultType = NoType;
|
||||
Id resultType = 0;
|
||||
switch (opCode) {
|
||||
case OpTextureQuerySize:
|
||||
case OpTextureQuerySizeLod:
|
||||
case OpImageQuerySize:
|
||||
case OpImageQuerySizeLod:
|
||||
{
|
||||
int numComponents;
|
||||
switch (getDimensionality(parameters.sampler)) {
|
||||
switch (getTypeDimensionality(getImageType(parameters.sampler))) {
|
||||
case Dim1D:
|
||||
case DimBuffer:
|
||||
numComponents = 1;
|
||||
|
|
@ -1199,7 +1256,7 @@ Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameter
|
|||
MissingFunctionality("texture query dimensionality");
|
||||
break;
|
||||
}
|
||||
if (isArrayedSampler(parameters.sampler))
|
||||
if (isArrayedImageType(getImageType(parameters.sampler)))
|
||||
++numComponents;
|
||||
if (numComponents == 1)
|
||||
resultType = makeIntType(32);
|
||||
|
|
@ -1208,11 +1265,11 @@ Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameter
|
|||
|
||||
break;
|
||||
}
|
||||
case OpTextureQueryLod:
|
||||
case OpImageQueryLod:
|
||||
resultType = makeVectorType(makeFloatType(32), 2);
|
||||
break;
|
||||
case OpTextureQueryLevels:
|
||||
case OpTextureQuerySamples:
|
||||
case OpImageQueryLevels:
|
||||
case OpImageQuerySamples:
|
||||
resultType = makeIntType(32);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -2040,7 +2097,16 @@ void Builder::dump(std::vector<unsigned int>& out) const
|
|||
extInst.addStringOperand(extensions[e]);
|
||||
extInst.dump(out);
|
||||
}
|
||||
|
||||
// TBD: OpExtension ...
|
||||
|
||||
// Capabilities
|
||||
for (auto cap : capabilities) {
|
||||
Instruction capInst(0, 0, OpCapability);
|
||||
capInst.addImmediateOperand(cap);
|
||||
capInst.dump(out);
|
||||
}
|
||||
|
||||
dumpInstructions(out, imports);
|
||||
Instruction memInst(0, 0, OpMemoryModel);
|
||||
memInst.addImmediateOperand(addressModel);
|
||||
|
|
|
|||
40
SPIRV/SpvBuilder.h
Normal file → Executable file
40
SPIRV/SpvBuilder.h
Normal file → Executable file
|
|
@ -48,7 +48,7 @@
|
|||
#ifndef SpvBuilder_H
|
||||
#define SpvBuilder_H
|
||||
|
||||
#include "spirv.h"
|
||||
#include "spirv.hpp"
|
||||
#include "spvIR.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
|
@ -77,6 +77,8 @@ public:
|
|||
memoryModel = mem;
|
||||
}
|
||||
|
||||
void addCapability(spv::Capability cap) { capabilities.push_back(cap); }
|
||||
|
||||
// To get a new <id> for anything needing a new one.
|
||||
Id getUniqueId() { return ++uniqueId; }
|
||||
|
||||
|
|
@ -101,12 +103,8 @@ public:
|
|||
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, Dim, samplerContent, bool arrayed, bool shadow, bool ms);
|
||||
Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
|
||||
Id makeSampledImageType(Id imageType);
|
||||
|
||||
// For querying about types.
|
||||
Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
|
||||
|
|
@ -133,7 +131,9 @@ public:
|
|||
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 isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
|
||||
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
|
||||
bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
|
||||
|
||||
bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
|
||||
unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
|
||||
|
|
@ -151,15 +151,20 @@ public:
|
|||
}
|
||||
int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
|
||||
|
||||
Dim getDimensionality(Id resultId) const
|
||||
Dim getTypeDimensionality(Id typeId) const
|
||||
{
|
||||
assert(isSamplerType(getTypeId(resultId)));
|
||||
return (Dim)module.getInstruction(getTypeId(resultId))->getImmediateOperand(1);
|
||||
assert(isImageType(typeId));
|
||||
return (Dim)module.getInstruction(typeId)->getImmediateOperand(1);
|
||||
}
|
||||
bool isArrayedSampler(Id resultId) const
|
||||
Id getImageType(Id resultId) const
|
||||
{
|
||||
assert(isSamplerType(getTypeId(resultId)));
|
||||
return module.getInstruction(getTypeId(resultId))->getImmediateOperand(3) != 0;
|
||||
assert(isSampledImageType(getTypeId(resultId)));
|
||||
return module.getInstruction(getTypeId(resultId))->getIdOperand(0);
|
||||
}
|
||||
bool isArrayedImageType(Id typeId) const
|
||||
{
|
||||
assert(isImageType(typeId));
|
||||
return module.getInstruction(typeId)->getImmediateOperand(3) != 0;
|
||||
}
|
||||
|
||||
// For making new constants (will return old constant if the requested one was already made).
|
||||
|
|
@ -174,7 +179,7 @@ public:
|
|||
Id makeCompositeConstant(Id type, std::vector<Id>& comps);
|
||||
|
||||
// Methods for adding information outside the CFG.
|
||||
void addEntryPoint(ExecutionModel, Function*);
|
||||
void addEntryPoint(ExecutionModel, Function*, const char* name);
|
||||
void addExecutionMode(Function*, ExecutionMode mode, int value = -1);
|
||||
void addName(Id, const char* name);
|
||||
void addMemberName(Id, int member, const char* name);
|
||||
|
|
@ -233,12 +238,12 @@ public:
|
|||
|
||||
void createNoResultOp(Op);
|
||||
void createNoResultOp(Op, Id operand);
|
||||
void createControlBarrier(unsigned executionScope);
|
||||
void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask);
|
||||
void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics);
|
||||
Id createUnaryOp(Op, Id typeId, Id operand);
|
||||
Id createBinOp(Op, Id typeId, Id operand1, Id operand2);
|
||||
Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
|
||||
Id createOp(Op, Id typeId, std::vector<Id>& operands);
|
||||
Id createOp(Op, Id typeId, const std::vector<Id>& operands);
|
||||
Id createFunctionCall(spv::Function*, std::vector<spv::Id>&);
|
||||
|
||||
// Take an rvalue (source) and a set of channels to extract from it to
|
||||
|
|
@ -283,8 +288,10 @@ public:
|
|||
Id lod;
|
||||
Id Dref;
|
||||
Id offset;
|
||||
Id offsets;
|
||||
Id gradX;
|
||||
Id gradY;
|
||||
Id sample;
|
||||
};
|
||||
|
||||
// Select the correct texture operation based on all inputs, and emit the correct instruction
|
||||
|
|
@ -497,6 +504,7 @@ protected:
|
|||
std::vector<const char*> extensions;
|
||||
AddressingModel addressModel;
|
||||
MemoryModel memoryModel;
|
||||
std::vector<spv::Capability> capabilities;
|
||||
int builderNumber;
|
||||
Module module;
|
||||
Block* buildPoint;
|
||||
|
|
|
|||
209
SPIRV/disassemble.cpp
Normal file → Executable file
209
SPIRV/disassemble.cpp
Normal file → Executable file
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
|
|
@ -21,16 +21,16 @@
|
|||
//
|
||||
//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 MERCHANTAstreamITY AND FITNESS
|
||||
//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 LIAstreamITY, WHETHER IN CONTRACT, STRICT
|
||||
//LIAstreamITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
//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
|
||||
//POSSIstreamITY OF SUCH DAMAGE.
|
||||
//POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// Author: John Kessenich, LunarG
|
||||
|
|
@ -41,25 +41,34 @@
|
|||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <iomanip>
|
||||
#include <stack>
|
||||
#include <sstream>
|
||||
|
||||
#include "GLSL450Lib.h"
|
||||
extern const char* GlslStd450DebugNames[GLSL_STD_450::Count];
|
||||
#include <cstring>
|
||||
|
||||
#include "disassemble.h"
|
||||
#include "doc.h"
|
||||
|
||||
namespace spv {
|
||||
|
||||
#include "GLSL.std.450.h"
|
||||
|
||||
const char* GlslStd450DebugNames[spv::GLSLstd450Count];
|
||||
|
||||
void Kill(std::ostream& out, const char* message)
|
||||
{
|
||||
out << std::endl << "Disassembly failed: " << message << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// used to identify the extended instruction library imported when printing
|
||||
enum ExtInstSet {
|
||||
GLSL450Inst,
|
||||
OpenCLExtInst,
|
||||
};
|
||||
|
||||
// Container class for a single instance of a SPIR-V stream, with methods for disassembly.
|
||||
class SpirvStream {
|
||||
public:
|
||||
|
|
@ -70,9 +79,8 @@ public:
|
|||
void processInstructions();
|
||||
|
||||
protected:
|
||||
SpirvStream(SpirvStream&);
|
||||
SpirvStream& operator=(SpirvStream&);
|
||||
|
||||
SpirvStream(const SpirvStream&);
|
||||
SpirvStream& operator=(const SpirvStream&);
|
||||
Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; }
|
||||
|
||||
// Output methods
|
||||
|
|
@ -81,6 +89,7 @@ protected:
|
|||
void outputResultId(Id id);
|
||||
void outputTypeId(Id id);
|
||||
void outputId(Id id);
|
||||
void outputMask(OperandClass operandClass, unsigned mask);
|
||||
void disassembleImmediates(int numOperands);
|
||||
void disassembleIds(int numOperands);
|
||||
void disassembleString();
|
||||
|
|
@ -241,6 +250,18 @@ void SpirvStream::outputId(Id id)
|
|||
out << "(" << idDescriptor[id] << ")";
|
||||
}
|
||||
|
||||
void SpirvStream::outputMask(OperandClass operandClass, unsigned mask)
|
||||
{
|
||||
if (mask == 0)
|
||||
out << "None";
|
||||
else {
|
||||
for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {
|
||||
if (mask & (1 << m))
|
||||
out << OperandClassParams[operandClass].getName(m) << " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpirvStream::disassembleImmediates(int numOperands)
|
||||
{
|
||||
for (int i = 0; i < numOperands; ++i) {
|
||||
|
|
@ -294,8 +315,9 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
|
|||
nestedControl.push(nextNestedControl);
|
||||
nextNestedControl = 0;
|
||||
}
|
||||
} else if (opCode == OpExtInstImport)
|
||||
} else if (opCode == OpExtInstImport) {
|
||||
idDescriptor[resultId] = (char*)(&stream[word]);
|
||||
}
|
||||
else {
|
||||
if (idDescriptor[resultId].size() == 0) {
|
||||
switch (opCode) {
|
||||
|
|
@ -337,27 +359,35 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
|
|||
// Process the operands. Note, a new context-dependent set could be
|
||||
// swapped in mid-traversal.
|
||||
|
||||
// Handle textures specially, so can put out helpful strings.
|
||||
if (opCode == OpTypeSampler) {
|
||||
// Handle images specially, so can put out helpful strings.
|
||||
if (opCode == OpTypeImage) {
|
||||
out << " ";
|
||||
disassembleIds(1);
|
||||
out << " " << DimensionString((Dim)stream[word++]);
|
||||
switch (stream[word++]) {
|
||||
case 0: out << " texture"; break;
|
||||
case 1: out << " image"; break;
|
||||
case 2: out << " filter+texture"; break;
|
||||
}
|
||||
out << (stream[word++] != 0 ? " array" : "");
|
||||
out << (stream[word++] != 0 ? " depth" : "");
|
||||
out << (stream[word++] != 0 ? " array" : "");
|
||||
out << (stream[word++] != 0 ? " multi-sampled" : "");
|
||||
switch (stream[word++]) {
|
||||
case 0: out << " runtime"; break;
|
||||
case 1: out << " sampled"; break;
|
||||
case 2: out << " nonsampled"; break;
|
||||
}
|
||||
out << " format:" << ImageFormatString((ImageFormat)stream[word++]);
|
||||
|
||||
if (numOperands == 8) {
|
||||
out << " " << AccessQualifierString(stream[word++]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle all the parameterized operands
|
||||
for (int op = 0; op < InstructionDesc[opCode].operands.getNum(); ++op) {
|
||||
for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) {
|
||||
out << " ";
|
||||
OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op);
|
||||
switch (operandClass) {
|
||||
case OperandId:
|
||||
case OperandScope:
|
||||
case OperandMemorySemantics:
|
||||
disassembleIds(1);
|
||||
// Get names for printing "(XXX)" for readability, *after* this id
|
||||
if (opCode == OpName)
|
||||
|
|
@ -367,15 +397,34 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
|
|||
case OperandVariableIds:
|
||||
disassembleIds(numOperands);
|
||||
return;
|
||||
case OperandOptionalImage:
|
||||
outputMask(operandClass, stream[word++]);
|
||||
--numOperands;
|
||||
disassembleIds(numOperands);
|
||||
return;
|
||||
case OperandOptionalLiteral:
|
||||
case OperandVariableLiterals:
|
||||
if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) ||
|
||||
(opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) {
|
||||
if (opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn ||
|
||||
opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn) {
|
||||
out << BuiltInString(stream[word++]);
|
||||
--numOperands;
|
||||
++op;
|
||||
}
|
||||
disassembleImmediates(numOperands);
|
||||
return;
|
||||
case OperandVariableIdLiteral:
|
||||
while (numOperands > 0) {
|
||||
out << std::endl;
|
||||
outputResultId(0);
|
||||
outputTypeId(0);
|
||||
outputIndent();
|
||||
out << " Type ";
|
||||
disassembleIds(1);
|
||||
out << ", member ";
|
||||
disassembleImmediates(1);
|
||||
numOperands -= 2;
|
||||
}
|
||||
return;
|
||||
case OperandVariableLiteralId:
|
||||
while (numOperands > 0) {
|
||||
out << std::endl;
|
||||
|
|
@ -392,9 +441,16 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
|
|||
case OperandLiteralNumber:
|
||||
disassembleImmediates(1);
|
||||
if (opCode == OpExtInst) {
|
||||
ExtInstSet extInstSet = GLSL450Inst;
|
||||
if (0 == memcmp("OpenCL", (char*)(idDescriptor[stream[word-2]].c_str()), 6)) {
|
||||
extInstSet = OpenCLExtInst;
|
||||
}
|
||||
unsigned entrypoint = stream[word - 1];
|
||||
if (entrypoint < GLSL_STD_450::Count)
|
||||
out << "(" << GlslStd450DebugNames[entrypoint] << ")";
|
||||
if (extInstSet == GLSL450Inst) {
|
||||
if (entrypoint < spv::GLSLstd450Count) {
|
||||
out << "(" << GlslStd450DebugNames[entrypoint] << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OperandLiteralString:
|
||||
|
|
@ -403,18 +459,9 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
|
|||
default:
|
||||
assert(operandClass >= OperandSource && operandClass < OperandOpcode);
|
||||
|
||||
if (OperandClassParams[operandClass].bitmask) {
|
||||
unsigned int mask = stream[word++];
|
||||
if (mask == 0)
|
||||
out << "None";
|
||||
else {
|
||||
for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {
|
||||
if (mask & (1 << m))
|
||||
out << OperandClassParams[operandClass].getName(m) << " ";
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else
|
||||
if (OperandClassParams[operandClass].bitmask)
|
||||
outputMask(operandClass, stream[word++]);
|
||||
else
|
||||
out << OperandClassParams[operandClass].getName(stream[word++]);
|
||||
|
||||
break;
|
||||
|
|
@ -425,9 +472,97 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
|
|||
return;
|
||||
}
|
||||
|
||||
void GLSLstd450GetDebugNames(const char** names)
|
||||
{
|
||||
for (int i = 0; i < GLSLstd450Count; ++i)
|
||||
names[i] = "Unknown";
|
||||
|
||||
names[GLSLstd450Round] = "Round";
|
||||
names[GLSLstd450RoundEven] = "RoundEven";
|
||||
names[GLSLstd450Trunc] = "Trunc";
|
||||
names[GLSLstd450FAbs] = "FAbs";
|
||||
names[GLSLstd450SAbs] = "SAbs";
|
||||
names[GLSLstd450FSign] = "FSign";
|
||||
names[GLSLstd450SSign] = "SSign";
|
||||
names[GLSLstd450Floor] = "Floor";
|
||||
names[GLSLstd450Ceil] = "Ceil";
|
||||
names[GLSLstd450Fract] = "Fract";
|
||||
names[GLSLstd450Radians] = "Radians";
|
||||
names[GLSLstd450Degrees] = "Degrees";
|
||||
names[GLSLstd450Sin] = "Sin";
|
||||
names[GLSLstd450Cos] = "Cos";
|
||||
names[GLSLstd450Tan] = "Tan";
|
||||
names[GLSLstd450Asin] = "Asin";
|
||||
names[GLSLstd450Acos] = "Acos";
|
||||
names[GLSLstd450Atan] = "Atan";
|
||||
names[GLSLstd450Sinh] = "Sinh";
|
||||
names[GLSLstd450Cosh] = "Cosh";
|
||||
names[GLSLstd450Tanh] = "Tanh";
|
||||
names[GLSLstd450Asinh] = "Asinh";
|
||||
names[GLSLstd450Acosh] = "Acosh";
|
||||
names[GLSLstd450Atanh] = "Atanh";
|
||||
names[GLSLstd450Atan2] = "Atan2";
|
||||
names[GLSLstd450Pow] = "Pow";
|
||||
names[GLSLstd450Exp] = "Exp";
|
||||
names[GLSLstd450Log] = "Log";
|
||||
names[GLSLstd450Exp2] = "Exp2";
|
||||
names[GLSLstd450Log2] = "Log2";
|
||||
names[GLSLstd450Sqrt] = "Sqrt";
|
||||
names[GLSLstd450InverseSqrt] = "Inversesqrt";
|
||||
names[GLSLstd450Determinant] = "Determinant";
|
||||
names[GLSLstd450MatrixInverse] = "Inverse";
|
||||
names[GLSLstd450Modf] = "Modf";
|
||||
names[GLSLstd450ModfStruct] = "ModfStruct";
|
||||
names[GLSLstd450FMin] = "FMin";
|
||||
names[GLSLstd450SMin] = "SMin";
|
||||
names[GLSLstd450UMin] = "UMin";
|
||||
names[GLSLstd450FMax] = "FMax";
|
||||
names[GLSLstd450SMax] = "SMax";
|
||||
names[GLSLstd450UMax] = "UMax";
|
||||
names[GLSLstd450FClamp] = "FClamp";
|
||||
names[GLSLstd450SClamp] = "SClamp";
|
||||
names[GLSLstd450UClamp] = "UClamp";
|
||||
names[GLSLstd450Mix] = "Mix";
|
||||
names[GLSLstd450Step] = "Step";
|
||||
names[GLSLstd450SmoothStep] = "Smoothstep";
|
||||
names[GLSLstd450Fma] = "Fma";
|
||||
names[GLSLstd450Frexp] = "Frexp";
|
||||
names[GLSLstd450FrexpStruct] = "FrexpStruct";
|
||||
names[GLSLstd450Ldexp] = "Ldexp";
|
||||
names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8";
|
||||
names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8";
|
||||
names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16";
|
||||
names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16";
|
||||
names[GLSLstd450PackHalf2x16] = "PackHalf2x16";
|
||||
names[GLSLstd450PackDouble2x32] = "PackDouble2x32";
|
||||
names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16";
|
||||
names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16";
|
||||
names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16";
|
||||
names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8";
|
||||
names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8";
|
||||
names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32";
|
||||
names[GLSLstd450Length] = "Length";
|
||||
names[GLSLstd450Distance] = "Distance";
|
||||
names[GLSLstd450Cross] = "Cross";
|
||||
names[GLSLstd450Normalize] = "Normalize";
|
||||
names[GLSLstd450FaceForward] = "Faceforward";
|
||||
names[GLSLstd450Reflect] = "Reflect";
|
||||
names[GLSLstd450Refract] = "Refract";
|
||||
names[GLSLstd450AddCarry] = "UaddCarry";
|
||||
names[GLSLstd450SubBorrow] = "UsubBorrow";
|
||||
names[GLSLstd450MulExtended] = "UmulExtended";
|
||||
names[GLSLstd450FindILSB] = "FindILsb";
|
||||
names[GLSLstd450FindSMSB] = "FindSMsb";
|
||||
names[GLSLstd450FindUMSB] = "FindUMsb";
|
||||
names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid";
|
||||
names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample";
|
||||
names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset";
|
||||
}
|
||||
|
||||
void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
|
||||
{
|
||||
SpirvStream SpirvStream(out, stream);
|
||||
GLSLstd450GetDebugNames(GlslStd450DebugNames);
|
||||
SpirvStream.validate();
|
||||
SpirvStream.processInstructions();
|
||||
}
|
||||
|
|
|
|||
2
SPIRV/disassemble.h
Normal file → Executable file
2
SPIRV/disassemble.h
Normal file → Executable file
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
|
|
|
|||
1977
SPIRV/doc.cpp
Normal file → Executable file
1977
SPIRV/doc.cpp
Normal file → Executable file
File diff suppressed because it is too large
Load diff
46
SPIRV/doc.h
Normal file → Executable file
46
SPIRV/doc.h
Normal file → Executable file
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
//Copyright (C) 2014 LunarG, Inc.
|
||||
//Copyright (C) 2014-2015 LunarG, Inc.
|
||||
//
|
||||
//All rights reserved.
|
||||
//
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
// Parameterize the SPIR-V enumerants.
|
||||
//
|
||||
|
||||
#include "spirv.h"
|
||||
#include "spirv.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -64,6 +64,10 @@ const char* LoopControlString(int);
|
|||
const char* FunctionControlString(int);
|
||||
const char* SamplerAddressingModeString(int);
|
||||
const char* SamplerFilterModeString(int);
|
||||
const char* ImageFormatString(int);
|
||||
const char* ImageChannelOrderString(int);
|
||||
const char* ImageChannelTypeString(int);
|
||||
const char* ImageOperands(int);
|
||||
const char* FPFastMathString(int);
|
||||
const char* FPRoundingModeString(int);
|
||||
const char* LinkageTypeString(int);
|
||||
|
|
@ -75,11 +79,12 @@ const char* ExecutionScopeString(int);
|
|||
const char* GroupOperationString(int);
|
||||
const char* KernelEnqueueFlagsString(int);
|
||||
const char* KernelProfilingInfoString(int);
|
||||
const char* CapabilityString(int);
|
||||
const char* OpcodeString(int);
|
||||
|
||||
// For grouping opcodes into subsections
|
||||
enum OpcodeClass {
|
||||
OpClassMisc, // default, until opcode is classified
|
||||
OpClassMisc,
|
||||
OpClassDebug,
|
||||
OpClassAnnotate,
|
||||
OpClassExtension,
|
||||
|
|
@ -88,10 +93,11 @@ enum OpcodeClass {
|
|||
OpClassConstant,
|
||||
OpClassMemory,
|
||||
OpClassFunction,
|
||||
OpClassTexture,
|
||||
OpClassImage,
|
||||
OpClassConvert,
|
||||
OpClassComposite,
|
||||
OpClassArithmetic,
|
||||
OpClassBit,
|
||||
OpClassRelationalLogical,
|
||||
OpClassDerivative,
|
||||
OpClassFlowControl,
|
||||
|
|
@ -102,7 +108,8 @@ enum OpcodeClass {
|
|||
OpClassDeviceSideEnqueue,
|
||||
OpClassPipe,
|
||||
|
||||
OpClassCount
|
||||
OpClassCount,
|
||||
OpClassMissing // all instructions start out as missing
|
||||
};
|
||||
|
||||
// For parameterizing operands.
|
||||
|
|
@ -110,8 +117,11 @@ enum OperandClass {
|
|||
OperandNone,
|
||||
OperandId,
|
||||
OperandOptionalId,
|
||||
OperandOptionalImage,
|
||||
OperandVariableIds,
|
||||
OperandOptionalLiteral,
|
||||
OperandVariableLiterals,
|
||||
OperandVariableIdLiteral,
|
||||
OperandVariableLiteralId,
|
||||
OperandLiteralNumber,
|
||||
OperandLiteralString,
|
||||
|
|
@ -124,6 +134,10 @@ enum OperandClass {
|
|||
OperandDimensionality,
|
||||
OperandSamplerAddressingMode,
|
||||
OperandSamplerFilterMode,
|
||||
OperandSamplerImageFormat,
|
||||
OperandImageChannelOrder,
|
||||
OperandImageChannelDataType,
|
||||
OperandImageOperands,
|
||||
OperandFPFastMath,
|
||||
OperandFPRoundingMode,
|
||||
OperandLinkageType,
|
||||
|
|
@ -136,29 +150,17 @@ enum OperandClass {
|
|||
OperandFunction,
|
||||
OperandMemorySemantics,
|
||||
OperandMemoryAccess,
|
||||
OperandExecutionScope,
|
||||
OperandScope,
|
||||
OperandGroupOperation,
|
||||
OperandKernelEnqueueFlags,
|
||||
OperandKernelProfilingInfo,
|
||||
OperandCapability,
|
||||
|
||||
OperandOpcode,
|
||||
|
||||
OperandCount
|
||||
};
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
// Any specific enum can have a set of capabilities that allow it:
|
||||
typedef std::vector<Capability> EnumCaps;
|
||||
|
||||
|
|
@ -213,8 +215,8 @@ public:
|
|||
class InstructionParameters {
|
||||
public:
|
||||
InstructionParameters() :
|
||||
opDesc(0),
|
||||
opClass(OpClassMisc),
|
||||
opDesc("TBD"),
|
||||
opClass(OpClassMissing),
|
||||
typePresent(true), // most normal, only exceptions have to be spelled out
|
||||
resultPresent(true) // most normal, only exceptions have to be spelled out
|
||||
{ }
|
||||
|
|
@ -238,7 +240,7 @@ protected:
|
|||
int resultPresent : 1;
|
||||
};
|
||||
|
||||
const int OpcodeCeiling = 267;
|
||||
const int OpcodeCeiling = 305;
|
||||
|
||||
// The set of objects that hold all the instruction/operand
|
||||
// parameterization information.
|
||||
|
|
|
|||
2
SPIRV/spvIR.h
Normal file → Executable file
2
SPIRV/spvIR.h
Normal file → Executable file
|
|
@ -50,7 +50,7 @@
|
|||
#ifndef spvIR_H
|
||||
#define spvIR_H
|
||||
|
||||
#include "spirv.h"
|
||||
#include "spirv.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue