Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions SPIRV/GLSL.ext.KHR.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,6 @@ static const char* const E_SPV_NV_cooperative_vector = "SPV_NV_cooper
static const char* const E_SPV_KHR_bfloat16 = "SPV_KHR_bfloat16";
static const char* const E_SPV_EXT_descriptor_heap = "SPV_EXT_descriptor_heap";
static const char* const E_SPV_KHR_untyped_pointers = "SPV_KHR_untyped_pointers";
static const char* const E_SPV_KHR_abort = "SPV_KHR_abort";
static const char* const E_SPV_KHR_constant_data = "SPV_KHR_constant_data";
#endif // #ifndef GLSLextKHR_H
101 changes: 101 additions & 0 deletions SPIRV/GlslangToSpv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ class TGlslangToSpvTraverser : public glslang::TIntermTraverser {
spv::Id translateForcedType(spv::Id object);
spv::Id createCompositeConstruct(spv::Id typeId, std::vector<spv::Id> constituents);
void recordDescHeapAccessChainInfo(glslang::TIntermBinary* node);
void createAbortEXT(const glslang::TIntermSequence glslangOperands);

glslang::SpvOptions& options;
spv::Function* shaderEntry;
Expand Down Expand Up @@ -3136,6 +3137,101 @@ spv::Id TGlslangToSpvTraverser::createCompositeConstruct(spv::Id resultTypeId, s
return builder.createCompositeConstruct(resultTypeId, constituents);
}

void TGlslangToSpvTraverser::createAbortEXT(const glslang::TIntermSequence glslangOperands)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will copy the vector on every call. Pass it by const reference, please.

{
bool isEmptyMsg = glslangOperands.size() == 0;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/.size() == 0/.empty()/

// Add Capability and extensions.
builder.addCapability(spv::Capability::AbortKHR);
builder.addCapability(spv::Capability::ConstantDataKHR);
builder.addExtension(spv::E_SPV_KHR_constant_data);
builder.addExtension(spv::E_SPV_KHR_abort);

typedef struct constStrInfo {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit. No typedef necessary. This can use strInfo or constStrInfo. No need to have both.

glslang::TString string;
int specifierIndex; // -1 if not a specifier.
constStrInfo(glslang::TString str, int spec) : string(str), specifierIndex(spec){};
} strInfo;

std::vector<strInfo> splitedStr, tempSplitedStr;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

grammar nit: s/splitedStr/splitStr/ and s/tempSplitedStr/tempSplitStr/

const uint32_t formatSpecifiersSize = 4;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't recall whether this string splitting is required by the spec or whether the spec allows a simpler representation like a single OpConstantDataKHR for the entire string. If it doesn't, maybe this could use a simpler lowering like we do in debugPrintfEXT. Can you confirm whether the spec mandates this and also what are the rules about padding?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://gitlab.khronos.org/GLSL/GLSL/-/merge_requests/132/diffs

Spec mentioned in the end as:

The set of format specifiers is implementation-dependent, but must
include at least "%d" and "%i" (int), "%u" (uint), and "%f" (float).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly, data is not simple char type now, but sub-strings. Discussed internally before.
https://gitlab.khronos.org/GLSL/glslang/-/merge_requests/125

const char* formatSpecifiers[formatSpecifiersSize] = {"%d", "%i", "%f", "%u"};
// 1. Split original message string with format specifiers.
const glslang::TString* msg = !isEmptyMsg ? glslangOperands[0]->getAsConstantUnion()->getConstArray()[0].getSConst()
: new glslang::TString("\0");
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msg will own the heap allocation if the message is empty. This will likely create leaks. Could you either allocate on the stack or restructure the branches so no heap allocation is needed?

splitedStr.push_back(strInfo(*const_cast<glslang::TString*>(msg), -1));
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to const_cast here. The constructor takes str by value. This can be strInfo(*msg, -1).

for (uint32_t i = 0; i < formatSpecifiersSize; i++) {
for (uint32_t j = 0; j < splitedStr.size(); j++) {
auto str = splitedStr[j].string;
int specifierIndex = splitedStr[j].specifierIndex;
auto pos = str.find(formatSpecifiers[i]);
while (pos != std::string::npos) {
tempSplitedStr.push_back(strInfo(str.substr(0, pos), specifierIndex));
tempSplitedStr.push_back(strInfo(glslang::TString(formatSpecifiers[i]), i));
str = str.substr(pos + strlen(formatSpecifiers[i]));
pos = str.find(formatSpecifiers[i]);
}
if (str.size() > 0 || isEmptyMsg)
tempSplitedStr.push_back(strInfo(str, specifierIndex));
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Check for !str.empty() instead of str.size() > 0.

Note that isEmptyMsg is set when glslangOperands is empty (no arguments). If the caller passes an empty string (e.g., abortEXT("", v);) then msg will have size 0. This will make the loop not push anything into tempSplitedStr. When it goes on to pop from structMemberOffsets, it will leave the vector empty. So when the code tries to access structMemberOffsets.back() the vector is empty (undefined behaviour).

This needs a test for an empty string and special handling for empty string literals ("").

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea. I'm now treating it as an empty string.

}
splitedStr.clear();
splitedStr = tempSplitedStr;
tempSplitedStr.clear();
}
// 2. Prepare to construct message struct variable, record members' types, data and offsets.
std::vector<int> structMemberOffsets;
std::vector<spv::Id> structMemberType;
std::vector<spv::Id> structLoadMemberType;
std::vector<spv::Id> structMemberData;
structMemberOffsets.push_back(0);
auto charType = builder.makeIntType(8);
for (auto elem : splitedStr) {
// 2.1 get sub string's length (if specifier, be spec const).
unsigned int strElemLen = isEmptyMsg ? 1 : elem.string.size();
spv::Id constLen = builder.makeUintConstant(strElemLen);
spv::Op constDataOp = spv::Op::OpConstantDataKHR;
if (elem.specifierIndex >= 0) {
constLen = builder.createSpecConst(spv::Op::OpSpecConstant, builder.makeUintType(32), strElemLen);
constDataOp = spv::Op::OpSpecConstantDataKHR;
}
// 2.2 get sub string's array type (if specifier, be spec const).
auto strElemArrType = builder.makeArrayType(charType, constLen, 1);
auto strElemLoadArrType = builder.makeArrayType(charType, constLen, 1);
// 2.3 add sub string constant data
auto strElemConstData = builder.createConstData(constDataOp, strElemArrType, {elem.string.c_str()});
// 2.4 add decoration for those sub string.
builder.addDecoration(strElemArrType, spv::Decoration::UTFCodePointsKHR);
builder.addDecoration(strElemLoadArrType, spv::Decoration::UTFCodePointsKHR);
builder.addDecoration(strElemLoadArrType, spv::Decoration::ArrayStride, 1);
// 2.5 Collect data and type for construct an internal message structure member.
structMemberType.push_back(strElemArrType);
structLoadMemberType.push_back(strElemLoadArrType);
structMemberOffsets.push_back(structMemberOffsets.back() + strElemLen);
structMemberData.push_back(strElemConstData);
}
structMemberOffsets.pop_back();
// 3. Add extra following arguments/variables' types in member structure.
for (unsigned int i = 1; i < glslangOperands.size(); i++) {
spv::Builder::AccessChain save = builder.getAccessChain();
builder.clearAccessChain();
auto width = GetNumBits(glslangOperands[i]->getAsTyped()->getBasicType());
structMemberOffsets.push_back(structMemberOffsets.back() + width / 8);
glslangOperands[i]->traverse(this);
structMemberData.push_back(accessChainLoad(glslangOperands[i]->getAsTyped()->getType()));
spv::Id reservedOpType = builder.getTypeId(structMemberData.back());
structMemberType.push_back(reservedOpType);
structLoadMemberType.push_back(reservedOpType);

builder.setAccessChain(save);
}
// 4. Construct struct message variable, add abortExt instruction.
auto structLoadType = builder.makeStructType(structLoadMemberType, {}, "abortMessageLoadType");
for (unsigned int i = 0; i < structMemberOffsets.size(); i++)
builder.addMemberDecoration(structLoadType, i, spv::Decoration::Offset, structMemberOffsets[i]);
auto structType = builder.makeStructType(structMemberType, {}, "abortMessage");
auto messageVar = builder.createCompositeConstruct(structType, structMemberData);
builder.makeStatementTerminator(spv::Op::OpAbortKHR, {structLoadType, messageVar}, "post-abort");
}

bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TIntermAggregate* node)
{
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
Expand Down Expand Up @@ -3873,6 +3969,10 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
glslang::TIntermSequence& glslangOperands = node->getSequence();
std::vector<spv::Id> operands;
std::vector<spv::IdImmediate> memoryAccessOperands;
if (node->getOp() == glslang::EOpAbortEXT) {
createAbortEXT(glslangOperands);
return false;
}
for (int arg = 0; arg < (int)glslangOperands.size(); ++arg) {
// special case l-value operands; there are just a few
bool lvalue = false;
Expand Down Expand Up @@ -4073,6 +4173,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
break;
}
builder.clearAccessChain();

if (invertedType != spv::NoType && arg == 0)
glslangOperands[0]->getAsBinaryNode()->getLeft()->traverse(this);
else
Expand Down
26 changes: 26 additions & 0 deletions SPIRV/SpvBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1778,13 +1778,15 @@ bool Builder::isConstantOpCode(Op opcode) const
case Op::OpConstantTrue:
case Op::OpConstantFalse:
case Op::OpConstant:
case Op::OpConstantDataKHR:
case Op::OpConstantComposite:
case Op::OpConstantCompositeReplicateEXT:
case Op::OpConstantSampler:
case Op::OpConstantNull:
case Op::OpSpecConstantTrue:
case Op::OpSpecConstantFalse:
case Op::OpSpecConstant:
case Op::OpSpecConstantDataKHR:
case Op::OpSpecConstantComposite:
case Op::OpSpecConstantCompositeReplicateEXT:
case Op::OpSpecConstantOp:
Expand All @@ -1802,6 +1804,7 @@ bool Builder::isSpecConstantOpCode(Op opcode) const
case Op::OpSpecConstantTrue:
case Op::OpSpecConstantFalse:
case Op::OpSpecConstant:
case Op::OpSpecConstantDataKHR:
case Op::OpSpecConstantComposite:
case Op::OpSpecConstantOp:
case Op::OpSpecConstantCompositeReplicateEXT:
Expand Down Expand Up @@ -3468,6 +3471,29 @@ Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
return op->getResultId();
}

Id Builder::createConstData(Op opCode, Id typeId, const std::vector<const char*> operands)
{
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
op->reserveOperands(operands.size());
for (auto id : operands)
op->addStringOperand(id);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the encoding use LiteralString or LiteralBytes?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

module.mapInstruction(op);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(op));

return op->getResultId();
}

Id Builder::createSpecConst(Op opCode, Id typeId, const unsigned int literalOp)
{
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is equivalent to builder.makeUintConstant(strElemLen, /specConstant=/true). Could you remove createSpecConst and use the existing overload?

Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
op->reserveOperands(1);
op->addImmediateOperand(literalOp);
module.mapInstruction(op);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(op));

return op->getResultId();
}

Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
{
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
Expand Down
2 changes: 2 additions & 0 deletions SPIRV/SpvBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,8 @@ class Builder {
Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
Id createOp(Op, Id typeId, const std::vector<Id>& operands);
Id createOp(Op, Id typeId, const std::vector<IdImmediate>& operands);
Id createConstData(Op opCode, Id typeId, const std::vector<const char*> operands);
Id createSpecConst(Op opCode, Id typeId, const unsigned int literalOp);
Id createFunctionCall(spv::Function*, const std::vector<spv::Id>&);
Id createSpecConstantOp(Op, Id typeId, const std::vector<spv::Id>& operands, const std::vector<unsigned>& literals);

Expand Down
13 changes: 13 additions & 0 deletions SPIRV/doc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,9 @@ const char* CapabilityString(int info)

case (int)Capability::ExpectAssumeKHR: return "ExpectAssumeKHR";

case (int)Capability::AbortKHR: return "AbortKHR";
case (int)Capability::ConstantDataKHR: return "ConstantDataKHR";

case (int)Capability::AtomicFloat16AddEXT: return "AtomicFloat16AddEXT";
case (int)Capability::AtomicFloat32AddEXT: return "AtomicFloat32AddEXT";
case (int)Capability::AtomicFloat64AddEXT: return "AtomicFloat64AddEXT";
Expand Down Expand Up @@ -1545,6 +1548,10 @@ const char* OpcodeString(int op)
case (int)Op::OpMemberDecorateIdEXT: return "OpMemberDecorateIdEXT";
case (int)Op::OpUntypedImageTexelPointerEXT: return "OpUntypedImageTexelPointerEXT";

case (int)Op::OpAbortKHR: return "OpAbortKHR";
case (int)Op::OpConstantDataKHR: return "OpConstantDataKHR";
case (int)Op::OpSpecConstantDataKHR: return "OpSpecConstantDataKHR";

case (int)Op::OpAtomicFAddEXT: return "OpAtomicFAddEXT";
case (int)Op::OpAtomicFMinEXT: return "OpAtomicFMinEXT";
case (int)Op::OpAtomicFMaxEXT: return "OpAtomicFMaxEXT";
Expand Down Expand Up @@ -3214,6 +3221,12 @@ void Parameterize()
InstructionDesc[enumCast(Op::OpGroupNonUniformQuadAnyKHR)].operands.push(OperandId, "'Predicate'");
InstructionDesc[enumCast(Op::OpTypeAccelerationStructureKHR)].setResultAndType(true, false);

InstructionDesc[enumCast(Op::OpConstantDataKHR)].operands.push(OperandLiteralString, "'Data'");
InstructionDesc[enumCast(Op::OpSpecConstantDataKHR)].operands.push(OperandLiteralString, "'Data'");
InstructionDesc[enumCast(Op::OpAbortKHR)].operands.push(OperandId, "'Message Type'");
InstructionDesc[enumCast(Op::OpAbortKHR)].operands.push(OperandId, "'Message'");
InstructionDesc[enumCast(Op::OpAbortKHR)].setResultAndType(false, false);

InstructionDesc[enumCast(Op::OpTraceNV)].operands.push(OperandId, "'Acceleration Structure'");
InstructionDesc[enumCast(Op::OpTraceNV)].operands.push(OperandId, "'Ray Flags'");
InstructionDesc[enumCast(Op::OpTraceNV)].operands.push(OperandId, "'Cull Mask'");
Expand Down
15 changes: 15 additions & 0 deletions SPIRV/spirv.hpp11
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ enum class Decoration : unsigned {
PayloadDispatchIndirectAMDX = 5105,
ArrayStrideIdEXT = 5124,
OffsetIdEXT = 5125,
UTFCodePointsKHR = 5145,
OverrideCoverageNV = 5248,
PassthroughNV = 5250,
ViewportRelativeNV = 5252,
Expand Down Expand Up @@ -1133,7 +1134,9 @@ enum class Capability : unsigned {
BFloat16TypeKHR = 5116,
BFloat16DotProductKHR = 5117,
BFloat16CooperativeMatrixKHR = 5118,
AbortKHR = 5120,
DescriptorHeapEXT = 5128,
ConstantDataKHR = 5146,
SampleMaskOverrideCoverageNV = 5249,
GeometryShaderPassthroughNV = 5251,
ShaderViewportIndexLayerEXT = 5254,
Expand Down Expand Up @@ -2042,9 +2045,12 @@ enum class Op : unsigned {
OpGroupNonUniformQuadAnyKHR = 5111,
OpTypeBufferEXT = 5115,
OpBufferPointerEXT = 5119,
OpAbortKHR = 5121,
OpUntypedImageTexelPointerEXT = 5126,
OpMemberDecorateIdEXT = 5127,
OpConstantSizeOfEXT = 5129,
OpConstantDataKHR = 5147,
OpSpecConstantDataKHR = 5148,
OpHitObjectRecordHitMotionNV = 5249,
OpHitObjectRecordHitWithIndexMotionNV = 5250,
OpHitObjectRecordMissMotionNV = 5251,
Expand Down Expand Up @@ -2898,6 +2904,9 @@ inline void HasResultAndType(Op opcode, bool *hasResult, bool *hasResultType) {
case Op::OpSpecConstantStringAMDX: *hasResult = true; *hasResultType = false; break;
case Op::OpGroupNonUniformQuadAllKHR: *hasResult = true; *hasResultType = true; break;
case Op::OpGroupNonUniformQuadAnyKHR: *hasResult = true; *hasResultType = true; break;
case Op::OpAbortKHR: *hasResult = false; *hasResultType = false; break;
case Op::OpConstantDataKHR: *hasResult = true; *hasResultType = true; break;
case Op::OpSpecConstantDataKHR : *hasResult = true; *hasResultType = true; break;
case Op::OpHitObjectRecordHitMotionNV: *hasResult = false; *hasResultType = false; break;
case Op::OpHitObjectRecordHitWithIndexMotionNV: *hasResult = false; *hasResultType = false; break;
case Op::OpHitObjectRecordMissMotionNV: *hasResult = false; *hasResultType = false; break;
Expand Down Expand Up @@ -3745,6 +3754,7 @@ inline const char* DecorationToString(Decoration value) {
case Decoration::PayloadNodeSparseArrayAMDX: return "PayloadNodeSparseArrayAMDX";
case Decoration::PayloadNodeArraySizeAMDX: return "PayloadNodeArraySizeAMDX";
case Decoration::PayloadDispatchIndirectAMDX: return "PayloadDispatchIndirectAMDX";
case Decoration::UTFCodePointsKHR: return "UTFCodePointsKHR";
case Decoration::OverrideCoverageNV: return "OverrideCoverageNV";
case Decoration::PassthroughNV: return "PassthroughNV";
case Decoration::ViewportRelativeNV: return "ViewportRelativeNV";
Expand Down Expand Up @@ -4128,6 +4138,8 @@ inline const char* CapabilityToString(Capability value) {
case Capability::BFloat16TypeKHR: return "BFloat16TypeKHR";
case Capability::BFloat16DotProductKHR: return "BFloat16DotProductKHR";
case Capability::BFloat16CooperativeMatrixKHR: return "BFloat16CooperativeMatrixKHR";
case Capability::AbortKHR: return "AbortKHR";
case Capability::ConstantDataKHR: return "ConstantDataKHR";
case Capability::SampleMaskOverrideCoverageNV: return "SampleMaskOverrideCoverageNV";
case Capability::GeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";
case Capability::ShaderViewportIndexLayerEXT: return "ShaderViewportIndexLayerEXT";
Expand Down Expand Up @@ -4894,6 +4906,9 @@ inline const char* OpToString(Op value) {
case Op::OpSpecConstantStringAMDX: return "OpSpecConstantStringAMDX";
case Op::OpGroupNonUniformQuadAllKHR: return "OpGroupNonUniformQuadAllKHR";
case Op::OpGroupNonUniformQuadAnyKHR: return "OpGroupNonUniformQuadAnyKHR";
case Op::OpAbortKHR: return "OpAbortKHR";
case Op::OpConstantDataKHR: return "OpConstantDataKHR";
case Op::OpSpecConstantDataKHR: return "OpSpecConstantDataKHR";
case Op::OpHitObjectRecordHitMotionNV: return "OpHitObjectRecordHitMotionNV";
case Op::OpHitObjectRecordHitWithIndexMotionNV: return "OpHitObjectRecordHitWithIndexMotionNV";
case Op::OpHitObjectRecordMissMotionNV: return "OpHitObjectRecordMissMotionNV";
Expand Down
1 change: 1 addition & 0 deletions SPIRV/spvIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ class Block {
case Op::OpReturn:
case Op::OpReturnValue:
case Op::OpUnreachable:
case Op::OpAbortKHR:
return true;
default:
return false;
Expand Down
1 change: 1 addition & 0 deletions Test/baseResults/cppBad.vert.out
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ ERROR: 0:6: 'string' : End of line in string
ERROR: 0:6: 'string literal' : required extension not requested: Possible extensions include:
GL_EXT_debug_printf
GL_EXT_spirv_intrinsics
GL_EXT_abort
ERROR: 0:6: '' : syntax error, unexpected INT, expecting COMMA or SEMICOLON
ERROR: 6 compilation errors. No code generated.

Expand Down
2 changes: 2 additions & 0 deletions Test/baseResults/cppSimple.vert.out
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ ERROR: 0:122: '#endif' : unexpected tokens following directive
ERROR: 0:135: 'string literal' : required extension not requested: Possible extensions include:
GL_EXT_debug_printf
GL_EXT_spirv_intrinsics
GL_EXT_abort
ERROR: 0:136: 'string literal' : required extension not requested: Possible extensions include:
GL_EXT_debug_printf
GL_EXT_spirv_intrinsics
GL_EXT_abort
ERROR: 0:136: 'length' : no matching overloaded function found
ERROR: 0:136: '=' : cannot convert from ' const float' to ' global int'
ERROR: 0:138: ''' : character literals not supported
Expand Down
3 changes: 3 additions & 0 deletions glslang/Include/intermediate.h
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,9 @@ enum TOperator {
EOpAssumeEXT,
EOpExpectEXT,

// GL_EXT_abort
EOpAbortEXT,

// Shader Clock Ops
EOpReadClockSubgroupKHR,
EOpReadClockDeviceKHR,
Expand Down
3 changes: 3 additions & 0 deletions glslang/MachineIndependent/Initialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4831,6 +4831,7 @@ void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvV
"void memoryBarrier(int, int, int);\n");

commonBuiltins.append("void debugPrintfEXT();\n");
commonBuiltins.append("void abortEXT();\n");

if (profile != EEsProfile && version >= 450) {
// coopMatStoreNV perhaps ought to have "out" on the buf parameter, but
Expand Down Expand Up @@ -10015,6 +10016,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion

symbolTable.setFunctionExtensions("controlBarrier", 1, &E_GL_KHR_memory_scope_semantics);
symbolTable.setFunctionExtensions("debugPrintfEXT", 1, &E_GL_EXT_debug_printf);
symbolTable.setFunctionExtensions("abortEXT", 1, &E_GL_EXT_abort);

// GL_ARB_shader_ballot
if (profile != EEsProfile) {
Expand Down Expand Up @@ -11060,6 +11062,7 @@ void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion
symbolTable.relateToOperator("debugPrintfEXT", EOpDebugPrintf);
symbolTable.relateToOperator("assumeEXT", EOpAssumeEXT);
symbolTable.relateToOperator("expectEXT", EOpExpectEXT);
symbolTable.relateToOperator("abortEXT", EOpAbortEXT);


if (PureOperatorBuiltins) {
Expand Down
8 changes: 8 additions & 0 deletions glslang/MachineIndependent/ParseHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2349,6 +2349,7 @@ void TParseContext::computeBuiltinPrecisions(TIntermTyped& node, const TFunction
numArgs = 1;
break;
case EOpDebugPrintf:
case EOpAbortEXT:
case EOpCooperativeMatrixPerElementOpNV:
case EOpCooperativeMatrixReduceNV:
case EOpConstructSaturated:
Expand Down Expand Up @@ -8230,6 +8231,13 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& loc, const TFunct
return symbol->getAsFunction();
}

// abortEXT has usage (var args) as similar as debugPrintfEXT.
if (call.getName() == "abortEXT") {
TSymbol* symbol = symbolTable.find("abortEXT(", &builtIn);
if (symbol)
return symbol->getAsFunction();
}

// coopMatPerElementNV is variadic. There is some function signature error
// checking in handleCoopMat2FunctionCall.
if (call.getName() == "coopMatPerElementNV") {
Expand Down
Loading