Skip to content

Commit

Permalink
Make modifications of GL_EXT_spirv_intrinsics
Browse files Browse the repository at this point in the history
1. spirv_execution_mode_id and spirv_decorate_id could support
   specialization constants. The original implementation always
   assume only normal frontend constants are valid. It is not true.

2. spirv_type donesn't support type_specifier as an option of
   spirv_type_parameter. At present, only constant_expression is the
   valid option.
  • Loading branch information
amdrexu committed Oct 13, 2021
1 parent b9ba4c5 commit f9ed601
Show file tree
Hide file tree
Showing 7 changed files with 2,145 additions and 2,191 deletions.
106 changes: 44 additions & 62 deletions SPIRV/GlslangToSpv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1829,12 +1829,8 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
for (auto& modeId : spirvExecutionMode.modeIds) {
std::vector<spv::Id> operandIds;
assert(!modeId.second.empty());
for (auto extraOperand : modeId.second) {
int nextConst = 0;
spv::Id operandId = createSpvConstantFromConstUnionArray(
extraOperand->getType(), extraOperand->getConstArray(), nextConst, false);
operandIds.push_back(operandId);
}
for (auto extraOperand : modeId.second)
operandIds.push_back(createSpvConstant(*extraOperand));
builder.addExecutionModeId(shaderEntry, static_cast<spv::ExecutionMode>(modeId.first), operandIds);
}
}
Expand Down Expand Up @@ -4150,58 +4146,48 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty

std::vector<spv::Id> operands;
for (const auto& typeParam : spirvType.typeParams) {
if (typeParam.isConstant) {
// Constant expression
if (typeParam.constant->isLiteral()) {
if (typeParam.constant->getBasicType() == glslang::EbtFloat) {
float floatValue = static_cast<float>(typeParam.constant->getConstArray()[0].getDConst());
unsigned literal = *reinterpret_cast<unsigned*>(&floatValue);
operands.push_back(literal);
} else if (typeParam.constant->getBasicType() == glslang::EbtInt) {
unsigned literal = typeParam.constant->getConstArray()[0].getIConst();
operands.push_back(literal);
} else if (typeParam.constant->getBasicType() == glslang::EbtUint) {
unsigned literal = typeParam.constant->getConstArray()[0].getUConst();
operands.push_back(literal);
} else if (typeParam.constant->getBasicType() == glslang::EbtBool) {
unsigned literal = typeParam.constant->getConstArray()[0].getBConst();
operands.push_back(literal);
} else if (typeParam.constant->getBasicType() == glslang::EbtString) {
auto str = typeParam.constant->getConstArray()[0].getSConst()->c_str();
unsigned literal = 0;
char* literalPtr = reinterpret_cast<char*>(&literal);
unsigned charCount = 0;
char ch = 0;
do {
ch = *(str++);
*(literalPtr++) = ch;
++charCount;
if (charCount == 4) {
operands.push_back(literal);
literalPtr = reinterpret_cast<char*>(&literal);
charCount = 0;
}
} while (ch != 0);

// Partial literal is padded with 0
if (charCount > 0) {
for (; charCount < 4; ++charCount)
*(literalPtr++) = 0;
// Constant expression
if (typeParam.constant->isLiteral()) {
if (typeParam.constant->getBasicType() == glslang::EbtFloat) {
float floatValue = static_cast<float>(typeParam.constant->getConstArray()[0].getDConst());
unsigned literal = *reinterpret_cast<unsigned*>(&floatValue);
operands.push_back(literal);
} else if (typeParam.constant->getBasicType() == glslang::EbtInt) {
unsigned literal = typeParam.constant->getConstArray()[0].getIConst();
operands.push_back(literal);
} else if (typeParam.constant->getBasicType() == glslang::EbtUint) {
unsigned literal = typeParam.constant->getConstArray()[0].getUConst();
operands.push_back(literal);
} else if (typeParam.constant->getBasicType() == glslang::EbtBool) {
unsigned literal = typeParam.constant->getConstArray()[0].getBConst();
operands.push_back(literal);
} else if (typeParam.constant->getBasicType() == glslang::EbtString) {
auto str = typeParam.constant->getConstArray()[0].getSConst()->c_str();
unsigned literal = 0;
char* literalPtr = reinterpret_cast<char*>(&literal);
unsigned charCount = 0;
char ch = 0;
do {
ch = *(str++);
*(literalPtr++) = ch;
++charCount;
if (charCount == 4) {
operands.push_back(literal);
literalPtr = reinterpret_cast<char*>(&literal);
charCount = 0;
}
} else
assert(0); // Unexpected type
} else {
int nextConst = 0;
spv::Id constant = createSpvConstantFromConstUnionArray(
typeParam.constant->getType(), typeParam.constant->getConstArray(), nextConst, false);
operands.push_back(constant);
}
} else {
// Type specifier
spv::Id typeId = convertGlslangToSpvType(*typeParam.type);
operands.push_back(typeId);
}
} while (ch != 0);

// Partial literal is padded with 0
if (charCount > 0) {
for (; charCount < 4; ++charCount)
*(literalPtr++) = 0;
operands.push_back(literal);
}
} else
assert(0); // Unexpected type
} else
operands.push_back(createSpvConstant(*typeParam.constant));
}

if (spirvInst.set == "")
Expand Down Expand Up @@ -8846,12 +8832,8 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
for (auto& decorateId : spirvDecorate.decorateIds) {
std::vector<spv::Id> operandIds;
assert(!decorateId.second.empty());
for (auto extraOperand : decorateId.second) {
int nextConst = 0;
spv::Id operandId = createSpvConstantFromConstUnionArray(
extraOperand->getType(), extraOperand->getConstArray(), nextConst, false);
operandIds.push_back(operandId);
}
for (auto extraOperand : decorateId.second)
operandIds.push_back(createSpvConstant(*extraOperand));
builder.addDecoration(id, static_cast<spv::Decoration>(decorateId.first), operandIds);
}

Expand Down
18 changes: 5 additions & 13 deletions glslang/Include/SpirvIntrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ struct TSpirvExecutionMode {
// spirv_execution_mode
TMap<int, TVector<const TIntermConstantUnion*>> modes;
// spirv_execution_mode_id
TMap<int, TVector<const TIntermConstantUnion*> > modeIds;
TMap<int, TVector<const TIntermTyped*> > modeIds;
};

// SPIR-V decorations
Expand All @@ -75,7 +75,7 @@ struct TSpirvDecorate {
// spirv_decorate
TMap<int, TVector<const TIntermConstantUnion*> > decorates;
// spirv_decorate_id
TMap<int, TVector<const TIntermConstantUnion*> > decorateIds;
TMap<int, TVector<const TIntermTyped*>> decorateIds;
// spirv_decorate_string
TMap<int, TVector<const TIntermConstantUnion*> > decorateStrings;
};
Expand All @@ -98,20 +98,12 @@ struct TSpirvInstruction {
struct TSpirvTypeParameter {
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())

TSpirvTypeParameter(const TIntermConstantUnion* arg) { isConstant = true; constant = arg; }
TSpirvTypeParameter(const TType* arg) { isConstant = false; type = arg; }
TSpirvTypeParameter(const TIntermConstantUnion* arg) { constant = arg; }

bool operator==(const TSpirvTypeParameter& rhs) const
{
return isConstant == rhs.isConstant && ((isConstant && constant == rhs.constant) || (!isConstant && type == rhs.type));
}
bool operator==(const TSpirvTypeParameter& rhs) const { return constant == rhs.constant; }
bool operator!=(const TSpirvTypeParameter& rhs) const { return !operator==(rhs); }

bool isConstant;
union {
const TIntermConstantUnion* constant;
const TType* type;
};
const TIntermConstantUnion* constant;
};

typedef TVector<TSpirvTypeParameter> TSpirvTypeParameters;
Expand Down
1 change: 0 additions & 1 deletion glslang/MachineIndependent/ParseHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,6 @@ class TParseContext : public TParseContextBase {
TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1,
TSpirvRequirement* spirvReq2);
TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant);
TSpirvTypeParameters* makeSpirvTypeParameters(const TPublicType& type);
TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1,
TSpirvTypeParameters* spirvTypeParams2);
TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value);
Expand Down
33 changes: 14 additions & 19 deletions glslang/MachineIndependent/SpirvIntrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,11 @@ void TIntermediate::insertSpirvExecutionModeId(int executionMode, const TIntermA
spirvExecutionMode = new TSpirvExecutionMode;

assert(args);
TVector<const TIntermConstantUnion*> extraOperands;
TVector<const TIntermTyped*> extraOperands;

for (auto arg : args->getSequence()) {
auto extraOperand = arg->getAsConstantUnion();
assert(extraOperand != nullptr);
auto extraOperand = arg->getAsTyped();
assert(extraOperand != nullptr && extraOperand->getQualifier().isConstant());
extraOperands.push_back(extraOperand);
}
spirvExecutionMode->modeIds[executionMode] = extraOperands;
Expand Down Expand Up @@ -165,10 +165,10 @@ void TQualifier::setSpirvDecorateId(int decoration, const TIntermAggregate* args
spirvDecorate = new TSpirvDecorate;

assert(args);
TVector<const TIntermConstantUnion*> extraOperands;
TVector<const TIntermTyped*> extraOperands;
for (auto arg : args->getSequence()) {
auto extraOperand = arg->getAsConstantUnion();
assert(extraOperand != nullptr);
auto extraOperand = arg->getAsTyped();
assert(extraOperand != nullptr && extraOperand->getQualifier().isConstant());
extraOperands.push_back(extraOperand);
}
spirvDecorate->decorateIds[decoration] = extraOperands;
Expand Down Expand Up @@ -201,25 +201,27 @@ TString TQualifier::getSpirvDecorateQualifierString() const
const auto appendBool = [&](bool b) { qualifierString.append(std::to_string(b).c_str()); };
const auto appendStr = [&](const char* s) { qualifierString.append(s); };

const auto appendDecorate = [&](const TIntermConstantUnion* constant) {
const auto appendDecorate = [&](const TIntermTyped* constant) {
auto& constArray = constant->getAsConstantUnion() != nullptr ? constant->getAsConstantUnion()->getConstArray()
: constant->getAsSymbolNode()->getConstArray();
if (constant->getBasicType() == EbtFloat) {
float value = static_cast<float>(constant->getConstArray()[0].getDConst());
float value = static_cast<float>(constArray[0].getDConst());
appendFloat(value);
}
else if (constant->getBasicType() == EbtInt) {
int value = constant->getConstArray()[0].getIConst();
int value = constArray[0].getIConst();
appendInt(value);
}
else if (constant->getBasicType() == EbtUint) {
unsigned value = constant->getConstArray()[0].getUConst();
unsigned value = constArray[0].getUConst();
appendUint(value);
}
else if (constant->getBasicType() == EbtBool) {
bool value = constant->getConstArray()[0].getBConst();
bool value = constArray[0].getBConst();
appendBool(value);
}
else if (constant->getBasicType() == EbtString) {
const TString* value = constant->getConstArray()[0].getSConst();
const TString* value = constArray[0].getSConst();
appendStr(value->c_str());
}
else
Expand Down Expand Up @@ -290,13 +292,6 @@ TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TSourceLoc& l
return spirvTypeParams;
}

TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TPublicType& type)
{
TSpirvTypeParameters* spirvTypeParams = new TSpirvTypeParameters;
spirvTypeParams->push_back(TSpirvTypeParameter(new TType(type)));
return spirvTypeParams;
}

TSpirvTypeParameters* TParseContext::mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, TSpirvTypeParameters* spirvTypeParams2)
{
// Merge SPIR-V type parameters of the second one to the first one
Expand Down
3 changes: 0 additions & 3 deletions glslang/MachineIndependent/glslang.m4
Original file line number Diff line number Diff line change
Expand Up @@ -4367,9 +4367,6 @@ spirv_type_parameter
: constant_expression {
$$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion());
}
| type_specifier {
$$ = parseContext.makeSpirvTypeParameters($1);
}

spirv_instruction_qualifier
: SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {
Expand Down
3 changes: 0 additions & 3 deletions glslang/MachineIndependent/glslang.y
Original file line number Diff line number Diff line change
Expand Up @@ -4367,9 +4367,6 @@ spirv_type_parameter
: constant_expression {
$$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion());
}
| type_specifier {
$$ = parseContext.makeSpirvTypeParameters($1);
}

spirv_instruction_qualifier
: SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {
Expand Down
Loading

0 comments on commit f9ed601

Please sign in to comment.