Implement 4 AMD-specific extensions.
- Support GL_AMD_shader_ballot (SPV_AMD_shader_ballot). - Support GL_AMD_shader_trinary_minmax (SPV_AMD_shader_trinary_minmax). - Support GL_AMD_shader_explicit_vertex_parameter (SPV_AMD_shader_explicit_vertex_parameter). - Support GL_AMD_gcn_shader (SPV_AMD_gcn_shader).
This commit is contained in:
@@ -18,6 +18,11 @@ set(HEADERS
|
||||
doc.h
|
||||
disassemble.h)
|
||||
|
||||
if(ENABLE_AMD_EXTENSIONS)
|
||||
set(HEADERS
|
||||
GLSL.ext.AMD.h)
|
||||
endif(ENABLE_AMD_EXTENSIONS)
|
||||
|
||||
add_library(SPIRV STATIC ${SOURCES} ${HEADERS})
|
||||
set_property(TARGET SPIRV PROPERTY FOLDER glslang)
|
||||
|
||||
|
||||
113
SPIRV/GLSL.ext.AMD.h
Normal file
113
SPIRV/GLSL.ext.AMD.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
** Copyright (c) 2014-2016 The Khronos Group Inc.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
** of this software and/or associated documentation files (the "Materials"),
|
||||
** to deal in the Materials without restriction, including without limitation
|
||||
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
** and/or sell copies of the Materials, and to permit persons to whom the
|
||||
** Materials are furnished to do so, subject to the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be included in
|
||||
** all copies or substantial portions of the Materials.
|
||||
**
|
||||
** MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
** STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
** HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
**
|
||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
** THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
** FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS
|
||||
** IN THE MATERIALS.
|
||||
*/
|
||||
|
||||
#ifndef GLSLextAMD_H
|
||||
#define GLSLextAMD_H
|
||||
|
||||
enum BuiltIn;
|
||||
enum Decoration;
|
||||
enum Op;
|
||||
|
||||
static const int GLSLextAMDVersion = 100;
|
||||
static const int GLSLextAMDRevision = 1;
|
||||
|
||||
// SPV_AMD_shader_ballot
|
||||
static const char* const E_SPV_AMD_shader_ballot = "SPV_AMD_shader_ballot";
|
||||
|
||||
static const Op OpGroupIAddNonUniformAMD = static_cast<Op>(5000);
|
||||
static const Op OpGroupFAddNonUniformAMD = static_cast<Op>(5001);
|
||||
static const Op OpGroupFMinNonUniformAMD = static_cast<Op>(5002);
|
||||
static const Op OpGroupUMinNonUniformAMD = static_cast<Op>(5003);
|
||||
static const Op OpGroupSMinNonUniformAMD = static_cast<Op>(5004);
|
||||
static const Op OpGroupFMaxNonUniformAMD = static_cast<Op>(5005);
|
||||
static const Op OpGroupUMaxNonUniformAMD = static_cast<Op>(5006);
|
||||
static const Op OpGroupSMaxNonUniformAMD = static_cast<Op>(5007);
|
||||
|
||||
enum ShaderBallotAMD {
|
||||
ShaderBallotBadAMD = 0, // Don't use
|
||||
|
||||
SwizzleInvocationsAMD = 1,
|
||||
SwizzleInvocationsMaskedAMD = 2,
|
||||
WriteInvocationAMD = 3,
|
||||
MbcntAMD = 4,
|
||||
|
||||
ShaderBallotCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_shader_trinary_minmax
|
||||
static const char* const E_SPV_AMD_shader_trinary_minmax = "SPV_AMD_shader_trinary_minmax";
|
||||
|
||||
enum ShaderTrinaryMinMaxAMD {
|
||||
ShaderTrinaryMinMaxBadAMD = 0, // Don't use
|
||||
|
||||
FMin3AMD = 1,
|
||||
UMin3AMD = 2,
|
||||
SMin3AMD = 3,
|
||||
FMax3AMD = 4,
|
||||
UMax3AMD = 5,
|
||||
SMax3AMD = 6,
|
||||
FMid3AMD = 7,
|
||||
UMid3AMD = 8,
|
||||
SMid3AMD = 9,
|
||||
|
||||
ShaderTrinaryMinMaxCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_shader_explicit_vertex_parameter
|
||||
static const char* const E_SPV_AMD_shader_explicit_vertex_parameter = "SPV_AMD_shader_explicit_vertex_parameter";
|
||||
|
||||
static const BuiltIn BuiltInBaryCoordNoPerspAMD = static_cast<BuiltIn>(4992);
|
||||
static const BuiltIn BuiltInBaryCoordNoPerspCentroidAMD = static_cast<BuiltIn>(4993);
|
||||
static const BuiltIn BuiltInBaryCoordNoPerspSampleAMD = static_cast<BuiltIn>(4994);
|
||||
static const BuiltIn BuiltInBaryCoordSmoothAMD = static_cast<BuiltIn>(4995);
|
||||
static const BuiltIn BuiltInBaryCoordSmoothCentroidAMD = static_cast<BuiltIn>(4996);
|
||||
static const BuiltIn BuiltInBaryCoordSmoothSampleAMD = static_cast<BuiltIn>(4997);
|
||||
static const BuiltIn BuiltInBaryCoordPullModelAMD = static_cast<BuiltIn>(4998);
|
||||
|
||||
static const Decoration DecorationExplicitInterpAMD = static_cast<Decoration>(4999);
|
||||
|
||||
enum ShaderExplicitVertexParameterAMD {
|
||||
ShaderExplicitVertexParameterBadAMD = 0, // Don't use
|
||||
|
||||
InterpolateAtVertexAMD = 1,
|
||||
|
||||
ShaderExplicitVertexParameterCountAMD
|
||||
};
|
||||
|
||||
// SPV_AMD_gcn_shader
|
||||
static const char* const E_SPV_AMD_gcn_shader = "SPV_AMD_gcn_shader";
|
||||
|
||||
enum GcnShaderAMD {
|
||||
GcnShaderBadAMD = 0, // Don't use
|
||||
|
||||
CubeFaceIndexAMD = 1,
|
||||
CubeFaceCoordAMD = 2,
|
||||
TimeAMD = 3,
|
||||
|
||||
GcnShaderCountAMD
|
||||
};
|
||||
|
||||
#endif // #ifndef GLSLextAMD_H
|
||||
@@ -43,6 +43,9 @@
|
||||
#include "SpvBuilder.h"
|
||||
namespace spv {
|
||||
#include "GLSL.std.450.h"
|
||||
#ifdef AMD_EXTENSIONS
|
||||
#include "GLSL.ext.AMD.h"
|
||||
#endif
|
||||
}
|
||||
|
||||
// Glslang includes
|
||||
@@ -147,9 +150,9 @@ protected:
|
||||
spv::Id createConversion(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id destTypeId, spv::Id operand, glslang::TBasicType typeProxy);
|
||||
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, glslang::TBasicType typeProxy);
|
||||
spv::Id createInvocationsOperation(glslang::TOperator, spv::Id typeId, spv::Id operand);
|
||||
spv::Id createInvocationsOperation(glslang::TOperator, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy);
|
||||
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 createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId);
|
||||
spv::Id getSymbolId(const glslang::TIntermSymbol* node);
|
||||
void addDecoration(spv::Id id, spv::Decoration dec);
|
||||
void addDecoration(spv::Id id, spv::Decoration dec, unsigned value);
|
||||
@@ -160,6 +163,7 @@ protected:
|
||||
bool isTrivialLeaf(const glslang::TIntermTyped* node);
|
||||
bool isTrivial(const glslang::TIntermTyped* node);
|
||||
spv::Id createShortCircuit(glslang::TOperator, glslang::TIntermTyped& left, glslang::TIntermTyped& right);
|
||||
spv::Id getExtBuiltins(const char* name);
|
||||
|
||||
spv::Function* shaderEntry;
|
||||
spv::Instruction* entryPoint;
|
||||
@@ -175,6 +179,7 @@ protected:
|
||||
std::set<spv::Id> iOSet; // all input/output variables from either static use or declaration of interface
|
||||
const glslang::TIntermediate* glslangIntermediate;
|
||||
spv::Id stdBuiltins;
|
||||
std::unordered_map<const char*, spv::Id> extBuiltinMap;
|
||||
|
||||
std::unordered_map<int, spv::Id> symbolValues;
|
||||
std::unordered_set<int> constReadOnlyParameters; // set of formal function parameters that have glslang qualifier constReadOnly, so we know they are not local function "const" that are write-once
|
||||
@@ -371,6 +376,10 @@ spv::Decoration TranslateInterpolationDecoration(const glslang::TQualifier& qual
|
||||
return spv::DecorationNoPerspective;
|
||||
else if (qualifier.flat)
|
||||
return spv::DecorationFlat;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
else if (qualifier.explicitInterp)
|
||||
return spv::DecorationExplicitInterpAMD;
|
||||
#endif
|
||||
else
|
||||
return spv::DecorationMax;
|
||||
}
|
||||
@@ -508,6 +517,15 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
|
||||
// TODO: Add SPIR-V builtin ID.
|
||||
logger->missingFunctionality("shader ballot");
|
||||
return spv::BuiltInMax;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EbvBaryCoordNoPersp: return spv::BuiltInBaryCoordNoPerspAMD;
|
||||
case glslang::EbvBaryCoordNoPerspCentroid: return spv::BuiltInBaryCoordNoPerspCentroidAMD;
|
||||
case glslang::EbvBaryCoordNoPerspSample: return spv::BuiltInBaryCoordNoPerspSampleAMD;
|
||||
case glslang::EbvBaryCoordSmooth: return spv::BuiltInBaryCoordSmoothAMD;
|
||||
case glslang::EbvBaryCoordSmoothCentroid: return spv::BuiltInBaryCoordSmoothCentroidAMD;
|
||||
case glslang::EbvBaryCoordSmoothSample: return spv::BuiltInBaryCoordSmoothSampleAMD;
|
||||
case glslang::EbvBaryCoordPullModel: return spv::BuiltInBaryCoordPullModelAMD;
|
||||
#endif
|
||||
default: return spv::BuiltInMax;
|
||||
}
|
||||
}
|
||||
@@ -628,6 +646,10 @@ void InheritQualifiers(glslang::TQualifier& child, const glslang::TQualifier& pa
|
||||
child.invariant = true;
|
||||
if (parent.nopersp)
|
||||
child.nopersp = true;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
if (parent.explicitInterp)
|
||||
child.explicitInterp = true;
|
||||
#endif
|
||||
if (parent.flat)
|
||||
child.flat = true;
|
||||
if (parent.centroid)
|
||||
@@ -1484,6 +1506,9 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
break;
|
||||
case glslang::EOpInterpolateAtSample:
|
||||
case glslang::EOpInterpolateAtOffset:
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpInterpolateAtVertex:
|
||||
#endif
|
||||
if (arg == 0)
|
||||
lvalue = true;
|
||||
break;
|
||||
@@ -1524,7 +1549,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
|
||||
// Pass through to generic operations.
|
||||
switch (glslangOperands.size()) {
|
||||
case 0:
|
||||
result = createNoArgOperation(node->getOp());
|
||||
result = createNoArgOperation(node->getOp(), precision, convertGlslangToSpvType(node->getType()));
|
||||
break;
|
||||
case 1:
|
||||
result = createUnaryOperation(
|
||||
@@ -3169,6 +3194,7 @@ spv::Id TGlslangToSpvTraverser::createBinaryMatrixOperation(spv::Op op, spv::Dec
|
||||
spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv::Decoration precision, spv::Decoration noContraction, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy)
|
||||
{
|
||||
spv::Op unaryOp = spv::OpNop;
|
||||
int extBuiltins = -1;
|
||||
int libCall = -1;
|
||||
bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64;
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
|
||||
@@ -3448,7 +3474,32 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
|
||||
case glslang::EOpAnyInvocation:
|
||||
case glslang::EOpAllInvocations:
|
||||
case glslang::EOpAllInvocationsEqual:
|
||||
return createInvocationsOperation(op, typeId, operand);
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpMinInvocations:
|
||||
case glslang::EOpMaxInvocations:
|
||||
case glslang::EOpAddInvocations:
|
||||
case glslang::EOpMinInvocationsNonUniform:
|
||||
case glslang::EOpMaxInvocationsNonUniform:
|
||||
case glslang::EOpAddInvocationsNonUniform:
|
||||
#endif
|
||||
return createInvocationsOperation(op, typeId, operand, typeProxy);
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpMbcnt:
|
||||
extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
|
||||
libCall = spv::MbcntAMD;
|
||||
break;
|
||||
|
||||
case glslang::EOpCubeFaceIndex:
|
||||
extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader);
|
||||
libCall = spv::CubeFaceIndexAMD;
|
||||
break;
|
||||
|
||||
case glslang::EOpCubeFaceCoord:
|
||||
extBuiltins = getExtBuiltins(spv::E_SPV_AMD_gcn_shader);
|
||||
libCall = spv::CubeFaceCoordAMD;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return 0;
|
||||
@@ -3458,7 +3509,7 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, spv:
|
||||
if (libCall >= 0) {
|
||||
std::vector<spv::Id> args;
|
||||
args.push_back(operand);
|
||||
id = builder.createBuiltinCall(typeId, stdBuiltins, libCall, args);
|
||||
id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, args);
|
||||
} else {
|
||||
id = builder.createUnaryOp(unaryOp, typeId, operand);
|
||||
}
|
||||
@@ -3765,12 +3816,20 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv
|
||||
}
|
||||
|
||||
// Create group invocation operations.
|
||||
spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, spv::Id operand)
|
||||
spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op, spv::Id typeId, spv::Id operand, glslang::TBasicType typeProxy)
|
||||
{
|
||||
bool isUnsigned = typeProxy == glslang::EbtUint || typeProxy == glslang::EbtUint64;
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
|
||||
|
||||
builder.addCapability(spv::CapabilityGroups);
|
||||
|
||||
std::vector<spv::Id> operands;
|
||||
operands.push_back(builder.makeUintConstant(spv::ScopeSubgroup));
|
||||
#ifdef AMD_EXTENSIONS
|
||||
if (op == glslang::EOpMinInvocations || op == glslang::EOpMaxInvocations || op == glslang::EOpAddInvocations ||
|
||||
op == glslang::EOpMinInvocationsNonUniform || op == glslang::EOpMaxInvocationsNonUniform || op == glslang::EOpAddInvocationsNonUniform)
|
||||
operands.push_back(spv::GroupOperationReduce);
|
||||
#endif
|
||||
operands.push_back(operand);
|
||||
|
||||
switch (op) {
|
||||
@@ -3786,6 +3845,74 @@ spv::Id TGlslangToSpvTraverser::createInvocationsOperation(glslang::TOperator op
|
||||
return builder.createBinOp(spv::OpLogicalOr, typeId, groupAll,
|
||||
builder.createUnaryOp(spv::OpLogicalNot, typeId, groupAny));
|
||||
}
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpMinInvocations:
|
||||
case glslang::EOpMaxInvocations:
|
||||
case glslang::EOpAddInvocations:
|
||||
{
|
||||
spv::Op spvOp = spv::OpNop;
|
||||
if (op == glslang::EOpMinInvocations) {
|
||||
if (isFloat)
|
||||
spvOp = spv::OpGroupFMin;
|
||||
else {
|
||||
if (isUnsigned)
|
||||
spvOp = spv::OpGroupUMin;
|
||||
else
|
||||
spvOp = spv::OpGroupSMin;
|
||||
}
|
||||
} else if (op == glslang::EOpMaxInvocations) {
|
||||
if (isFloat)
|
||||
spvOp = spv::OpGroupFMax;
|
||||
else {
|
||||
if (isUnsigned)
|
||||
spvOp = spv::OpGroupUMax;
|
||||
else
|
||||
spvOp = spv::OpGroupSMax;
|
||||
}
|
||||
} else {
|
||||
if (isFloat)
|
||||
spvOp = spv::OpGroupFAdd;
|
||||
else
|
||||
spvOp = spv::OpGroupIAdd;
|
||||
}
|
||||
|
||||
return builder.createOp(spvOp, typeId, operands);
|
||||
}
|
||||
case glslang::EOpMinInvocationsNonUniform:
|
||||
case glslang::EOpMaxInvocationsNonUniform:
|
||||
case glslang::EOpAddInvocationsNonUniform:
|
||||
{
|
||||
spv::Op spvOp = spv::OpNop;
|
||||
if (op == glslang::EOpMinInvocationsNonUniform) {
|
||||
if (isFloat)
|
||||
spvOp = spv::OpGroupFMinNonUniformAMD;
|
||||
else {
|
||||
if (isUnsigned)
|
||||
spvOp = spv::OpGroupUMinNonUniformAMD;
|
||||
else
|
||||
spvOp = spv::OpGroupSMinNonUniformAMD;
|
||||
}
|
||||
}
|
||||
else if (op == glslang::EOpMaxInvocationsNonUniform) {
|
||||
if (isFloat)
|
||||
spvOp = spv::OpGroupFMaxNonUniformAMD;
|
||||
else {
|
||||
if (isUnsigned)
|
||||
spvOp = spv::OpGroupUMaxNonUniformAMD;
|
||||
else
|
||||
spvOp = spv::OpGroupSMaxNonUniformAMD;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isFloat)
|
||||
spvOp = spv::OpGroupFAddNonUniformAMD;
|
||||
else
|
||||
spvOp = spv::OpGroupIAddNonUniformAMD;
|
||||
}
|
||||
|
||||
return builder.createOp(spvOp, typeId, operands);
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
logger->missingFunctionality("invocation operation");
|
||||
return spv::NoResult;
|
||||
@@ -3798,6 +3925,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
|
||||
bool isFloat = typeProxy == glslang::EbtFloat || typeProxy == glslang::EbtDouble;
|
||||
|
||||
spv::Op opCode = spv::OpNop;
|
||||
int extBuiltins = -1;
|
||||
int libCall = -1;
|
||||
size_t consumedOperands = operands.size();
|
||||
spv::Id typeId0 = 0;
|
||||
@@ -3941,6 +4069,60 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
|
||||
libCall = spv::GLSLstd450Bad;
|
||||
break;
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpSwizzleInvocations:
|
||||
extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
|
||||
libCall = spv::SwizzleInvocationsAMD;
|
||||
break;
|
||||
case glslang::EOpSwizzleInvocationsMasked:
|
||||
extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
|
||||
libCall = spv::SwizzleInvocationsMaskedAMD;
|
||||
break;
|
||||
case glslang::EOpWriteInvocation:
|
||||
extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_ballot);
|
||||
libCall = spv::WriteInvocationAMD;
|
||||
break;
|
||||
|
||||
case glslang::EOpMin3:
|
||||
extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax);
|
||||
if (isFloat)
|
||||
libCall = spv::FMin3AMD;
|
||||
else {
|
||||
if (isUnsigned)
|
||||
libCall = spv::UMin3AMD;
|
||||
else
|
||||
libCall = spv::SMin3AMD;
|
||||
}
|
||||
break;
|
||||
case glslang::EOpMax3:
|
||||
extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax);
|
||||
if (isFloat)
|
||||
libCall = spv::FMax3AMD;
|
||||
else {
|
||||
if (isUnsigned)
|
||||
libCall = spv::UMax3AMD;
|
||||
else
|
||||
libCall = spv::SMax3AMD;
|
||||
}
|
||||
break;
|
||||
case glslang::EOpMid3:
|
||||
extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_trinary_minmax);
|
||||
if (isFloat)
|
||||
libCall = spv::FMid3AMD;
|
||||
else {
|
||||
if (isUnsigned)
|
||||
libCall = spv::UMid3AMD;
|
||||
else
|
||||
libCall = spv::SMid3AMD;
|
||||
}
|
||||
break;
|
||||
|
||||
case glslang::EOpInterpolateAtVertex:
|
||||
extBuiltins = getExtBuiltins(spv::E_SPV_AMD_shader_explicit_vertex_parameter);
|
||||
libCall = spv::InterpolateAtVertexAMD;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -3951,7 +4133,7 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
|
||||
// Construct the call arguments, without modifying the original operands vector.
|
||||
// We might need the remaining arguments, e.g. in the EOpFrexp case.
|
||||
std::vector<spv::Id> callArguments(operands.begin(), operands.begin() + consumedOperands);
|
||||
id = builder.createBuiltinCall(typeId, stdBuiltins, libCall, callArguments);
|
||||
id = builder.createBuiltinCall(typeId, extBuiltins >= 0 ? extBuiltins : stdBuiltins, libCall, callArguments);
|
||||
} else {
|
||||
switch (consumedOperands) {
|
||||
case 0:
|
||||
@@ -3997,8 +4179,8 @@ spv::Id TGlslangToSpvTraverser::createMiscOperation(glslang::TOperator op, spv::
|
||||
return builder.setPrecision(id, precision);
|
||||
}
|
||||
|
||||
// Intrinsics with no arguments, no return value, and no precision.
|
||||
spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op)
|
||||
// Intrinsics with no arguments (or no return value, and no precision).
|
||||
spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op, spv::Decoration precision, spv::Id typeId)
|
||||
{
|
||||
// TODO: get the barrier operands correct
|
||||
|
||||
@@ -4045,6 +4227,14 @@ spv::Id TGlslangToSpvTraverser::createNoArgOperation(glslang::TOperator op)
|
||||
// Control barrier with non-"None" semantic is also a memory barrier.
|
||||
builder.createControlBarrier(spv::ScopeWorkgroup, spv::ScopeWorkgroup, spv::MemorySemanticsWorkgroupMemoryMask);
|
||||
return 0;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case glslang::EOpTime:
|
||||
{
|
||||
std::vector<spv::Id> args; // Dummy arguments
|
||||
spv::Id id = builder.createBuiltinCall(typeId, getExtBuiltins(spv::E_SPV_AMD_gcn_shader), spv::TimeAMD, args);
|
||||
return builder.setPrecision(id, precision);
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
logger->missingFunctionality("unknown operation with no arguments");
|
||||
return 0;
|
||||
@@ -4437,6 +4627,20 @@ spv::Id TGlslangToSpvTraverser::createShortCircuit(glslang::TOperator op, glslan
|
||||
return builder.createOp(spv::OpPhi, boolTypeId, phiOperands);
|
||||
}
|
||||
|
||||
// Return type Id of the imported set of extended instructions corresponds to the name.
|
||||
// Import this set if it has not been imported yet.
|
||||
spv::Id TGlslangToSpvTraverser::getExtBuiltins(const char* name)
|
||||
{
|
||||
if (extBuiltinMap.find(name) != extBuiltinMap.end())
|
||||
return extBuiltinMap[name];
|
||||
else {
|
||||
builder.addExtensions(name);
|
||||
spv::Id extBuiltins = builder.import(name);
|
||||
extBuiltinMap[name] = extBuiltins;
|
||||
return extBuiltins;
|
||||
}
|
||||
}
|
||||
|
||||
}; // end anonymous namespace
|
||||
|
||||
namespace glslang {
|
||||
|
||||
@@ -2312,7 +2312,11 @@ void Builder::dump(std::vector<unsigned int>& out) const
|
||||
capInst.dump(out);
|
||||
}
|
||||
|
||||
// TBD: OpExtension ...
|
||||
for (int e = 0; e < (int)extensions.size(); ++e) {
|
||||
Instruction extInst(0, 0, OpExtension);
|
||||
extInst.addStringOperand(extensions[e]);
|
||||
extInst.dump(out);
|
||||
}
|
||||
|
||||
dumpInstructions(out, imports);
|
||||
Instruction memInst(0, 0, OpMemoryModel);
|
||||
@@ -2331,10 +2335,10 @@ void Builder::dump(std::vector<unsigned int>& out) const
|
||||
sourceInst.addImmediateOperand(sourceVersion);
|
||||
sourceInst.dump(out);
|
||||
}
|
||||
for (int e = 0; e < (int)extensions.size(); ++e) {
|
||||
Instruction extInst(0, 0, OpSourceExtension);
|
||||
extInst.addStringOperand(extensions[e]);
|
||||
extInst.dump(out);
|
||||
for (int e = 0; e < (int)sourceExtensions.size(); ++e) {
|
||||
Instruction sourceExtInst(0, 0, OpSourceExtension);
|
||||
sourceExtInst.addStringOperand(sourceExtensions[e]);
|
||||
sourceExtInst.dump(out);
|
||||
}
|
||||
dumpInstructions(out, names);
|
||||
dumpInstructions(out, lines);
|
||||
|
||||
@@ -70,7 +70,8 @@ public:
|
||||
source = lang;
|
||||
sourceVersion = version;
|
||||
}
|
||||
void addSourceExtension(const char* ext) { extensions.push_back(ext); }
|
||||
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
|
||||
void addExtensions(const char* ext) { extensions.push_back(ext); }
|
||||
Id import(const char*);
|
||||
void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
|
||||
{
|
||||
@@ -552,6 +553,7 @@ public:
|
||||
SourceLanguage source;
|
||||
int sourceVersion;
|
||||
std::vector<const char*> extensions;
|
||||
std::vector<const char*> sourceExtensions;
|
||||
AddressingModel addressModel;
|
||||
MemoryModel memoryModel;
|
||||
std::set<spv::Capability> capabilities;
|
||||
|
||||
@@ -44,16 +44,25 @@
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
|
||||
namespace spv {
|
||||
// Include C-based headers that don't have a namespace
|
||||
#include "GLSL.std.450.h"
|
||||
}
|
||||
const char* GlslStd450DebugNames[spv::GLSLstd450Count];
|
||||
|
||||
#include "disassemble.h"
|
||||
#include "doc.h"
|
||||
|
||||
namespace spv {
|
||||
extern "C" {
|
||||
// Include C-based headers that don't have a namespace
|
||||
#include "GLSL.std.450.h"
|
||||
#ifdef AMD_EXTENSIONS
|
||||
#include "GLSL.ext.AMD.h"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
const char* GlslStd450DebugNames[spv::GLSLstd450Count];
|
||||
|
||||
namespace spv {
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
static const char* GLSLextAMDGetDebugNames(const char*, unsigned);
|
||||
#endif
|
||||
|
||||
static void Kill(std::ostream& out, const char* message)
|
||||
{
|
||||
@@ -64,6 +73,9 @@ static void Kill(std::ostream& out, const char* message)
|
||||
// used to identify the extended instruction library imported when printing
|
||||
enum ExtInstSet {
|
||||
GLSL450Inst,
|
||||
#ifdef AMD_EXTENSIONS
|
||||
GLSLextAMDInst,
|
||||
#endif
|
||||
OpenCLExtInst,
|
||||
};
|
||||
|
||||
@@ -446,14 +458,26 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
|
||||
--numOperands;
|
||||
if (opCode == OpExtInst) {
|
||||
ExtInstSet extInstSet = GLSL450Inst;
|
||||
if (0 == memcmp("OpenCL", (const char*)(idDescriptor[stream[word-2]].c_str()), 6)) {
|
||||
const char* name = idDescriptor[stream[word - 2]].c_str();
|
||||
if (0 == memcmp("OpenCL", name, 6)) {
|
||||
extInstSet = OpenCLExtInst;
|
||||
#ifdef AMD_EXTENSIONS
|
||||
} else if (strcmp(spv::E_SPV_AMD_shader_ballot, name) == 0 ||
|
||||
strcmp(spv::E_SPV_AMD_shader_trinary_minmax, name) == 0 ||
|
||||
strcmp(spv::E_SPV_AMD_shader_explicit_vertex_parameter, name) == 0 ||
|
||||
strcmp(spv::E_SPV_AMD_gcn_shader, name) == 0) {
|
||||
extInstSet = GLSLextAMDInst;
|
||||
#endif
|
||||
}
|
||||
unsigned entrypoint = stream[word - 1];
|
||||
if (extInstSet == GLSL450Inst) {
|
||||
if (entrypoint < GLSLstd450Count) {
|
||||
out << "(" << GlslStd450DebugNames[entrypoint] << ")";
|
||||
}
|
||||
#ifdef AMD_EXTENSIONS
|
||||
} else if (extInstSet == GLSLextAMDInst) {
|
||||
out << "(" << GLSLextAMDGetDebugNames(name, entrypoint) << ")";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -561,6 +585,50 @@ static void GLSLstd450GetDebugNames(const char** names)
|
||||
names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset";
|
||||
}
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
static const char* GLSLextAMDGetDebugNames(const char* name, unsigned entrypoint)
|
||||
{
|
||||
if (strcmp(name, spv::E_SPV_AMD_shader_ballot) == 0) {
|
||||
switch (entrypoint) {
|
||||
case SwizzleInvocationsAMD: return "SwizzleInvocationsAMD";
|
||||
case SwizzleInvocationsMaskedAMD: return "SwizzleInvocationsMaskedAMD";
|
||||
case WriteInvocationAMD: return "WriteInvocationAMD";
|
||||
case MbcntAMD: return "MbcntAMD";
|
||||
default: return "Bad";
|
||||
}
|
||||
} else if (strcmp(name, spv::E_SPV_AMD_shader_trinary_minmax) == 0) {
|
||||
switch (entrypoint) {
|
||||
case FMin3AMD: return "FMin3AMD";
|
||||
case UMin3AMD: return "UMin3AMD";
|
||||
case SMin3AMD: return "SMin3AMD";
|
||||
case FMax3AMD: return "FMax3AMD";
|
||||
case UMax3AMD: return "UMax3AMD";
|
||||
case SMax3AMD: return "SMax3AMD";
|
||||
case FMid3AMD: return "FMid3AMD";
|
||||
case UMid3AMD: return "UMid3AMD";
|
||||
case SMid3AMD: return "SMid3AMD";
|
||||
default: return "Bad";
|
||||
}
|
||||
} else if (strcmp(name, spv::E_SPV_AMD_shader_explicit_vertex_parameter) == 0) {
|
||||
switch (entrypoint) {
|
||||
case InterpolateAtVertexAMD: return "InterpolateAtVertexAMD";
|
||||
default: return "Bad";
|
||||
}
|
||||
}
|
||||
else if (strcmp(name, spv::E_SPV_AMD_gcn_shader) == 0) {
|
||||
switch (entrypoint) {
|
||||
case CubeFaceIndexAMD: return "CubeFaceIndexAMD";
|
||||
case CubeFaceCoordAMD: return "CubeFaceCoordAMD";
|
||||
case TimeAMD: return "TimeAMD";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return "Bad";
|
||||
}
|
||||
#endif
|
||||
|
||||
void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
|
||||
{
|
||||
SpirvStream SpirvStream(out, stream);
|
||||
|
||||
@@ -45,6 +45,15 @@
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
namespace spv {
|
||||
extern "C" {
|
||||
// Include C-based headers that don't have a namespace
|
||||
#include "GLSL.ext.AMD.h"
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace spv {
|
||||
|
||||
//
|
||||
@@ -243,6 +252,10 @@ const char* DecorationString(int decoration)
|
||||
|
||||
case DecorationCeiling:
|
||||
default: return "Bad";
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case 4999: return "ExplicitInterpAMD";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,6 +311,16 @@ const char* BuiltInString(int builtIn)
|
||||
|
||||
case BuiltInCeiling:
|
||||
default: return "Bad";
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case 4992: return "BaryCoordNoPerspAMD";
|
||||
case 4993: return "BaryCoordNoPerspCentroidAMD";
|
||||
case 4994: return "BaryCoordNoPerspSampleAMD";
|
||||
case 4995: return "BaryCoordSmoothAMD";
|
||||
case 4996: return "BaryCoordSmoothCentroidAMD";
|
||||
case 4997: return "BaryCoordSmoothSampleAMD";
|
||||
case 4998: return "BaryCoordPullModelAMD";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1107,12 +1130,27 @@ const char* OpcodeString(int op)
|
||||
case OpcodeCeiling:
|
||||
default:
|
||||
return "Bad";
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
case 5000: return "OpGroupIAddNonUniformAMD";
|
||||
case 5001: return "OpGroupFAddNonUniformAMD";
|
||||
case 5002: return "OpGroupFMinNonUniformAMD";
|
||||
case 5003: return "OpGroupUMinNonUniformAMD";
|
||||
case 5004: return "OpGroupSMinNonUniformAMD";
|
||||
case 5005: return "OpGroupFMaxNonUniformAMD";
|
||||
case 5006: return "OpGroupUMaxNonUniformAMD";
|
||||
case 5007: return "OpGroupSMaxNonUniformAMD";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// The set of objects that hold all the instruction/operand
|
||||
// parameterization information.
|
||||
#ifdef AMD_EXTENSIONS
|
||||
InstructionParameters InstructionDesc[OpCodeMask + 1];
|
||||
#else
|
||||
InstructionParameters InstructionDesc[OpcodeCeiling];
|
||||
#endif
|
||||
OperandParameters ExecutionModeOperands[ExecutionModeCeiling];
|
||||
OperandParameters DecorationOperands[DecorationCeiling];
|
||||
|
||||
@@ -2703,6 +2741,48 @@ void Parameterize()
|
||||
InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Num Events'");
|
||||
InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Wait Events'");
|
||||
InstructionDesc[OpEnqueueMarker].operands.push(OperandId, "'Ret Event'");
|
||||
|
||||
#ifdef AMD_EXTENSIONS
|
||||
InstructionDesc[OpGroupIAddNonUniformAMD].capabilities.push_back(CapabilityGroups);
|
||||
InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandScope, "'Execution'");
|
||||
InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
|
||||
InstructionDesc[OpGroupIAddNonUniformAMD].operands.push(OperandId, "'X'");
|
||||
|
||||
InstructionDesc[OpGroupFAddNonUniformAMD].capabilities.push_back(CapabilityGroups);
|
||||
InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandScope, "'Execution'");
|
||||
InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
|
||||
InstructionDesc[OpGroupFAddNonUniformAMD].operands.push(OperandId, "'X'");
|
||||
|
||||
InstructionDesc[OpGroupUMinNonUniformAMD].capabilities.push_back(CapabilityGroups);
|
||||
InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandScope, "'Execution'");
|
||||
InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
|
||||
InstructionDesc[OpGroupUMinNonUniformAMD].operands.push(OperandId, "'X'");
|
||||
|
||||
InstructionDesc[OpGroupSMinNonUniformAMD].capabilities.push_back(CapabilityGroups);
|
||||
InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandScope, "'Execution'");
|
||||
InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
|
||||
InstructionDesc[OpGroupSMinNonUniformAMD].operands.push(OperandId, "X");
|
||||
|
||||
InstructionDesc[OpGroupFMinNonUniformAMD].capabilities.push_back(CapabilityGroups);
|
||||
InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandScope, "'Execution'");
|
||||
InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
|
||||
InstructionDesc[OpGroupFMinNonUniformAMD].operands.push(OperandId, "X");
|
||||
|
||||
InstructionDesc[OpGroupUMaxNonUniformAMD].capabilities.push_back(CapabilityGroups);
|
||||
InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandScope, "'Execution'");
|
||||
InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
|
||||
InstructionDesc[OpGroupUMaxNonUniformAMD].operands.push(OperandId, "X");
|
||||
|
||||
InstructionDesc[OpGroupSMaxNonUniformAMD].capabilities.push_back(CapabilityGroups);
|
||||
InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandScope, "'Execution'");
|
||||
InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
|
||||
InstructionDesc[OpGroupSMaxNonUniformAMD].operands.push(OperandId, "X");
|
||||
|
||||
InstructionDesc[OpGroupFMaxNonUniformAMD].capabilities.push_back(CapabilityGroups);
|
||||
InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandScope, "'Execution'");
|
||||
InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandGroupOperation, "'Operation'");
|
||||
InstructionDesc[OpGroupFMaxNonUniformAMD].operands.push(OperandId, "X");
|
||||
#endif
|
||||
}
|
||||
|
||||
}; // end spv namespace
|
||||
|
||||
Reference in New Issue
Block a user