Make modifications of GL_EXT_spirv_intrinsics
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.
This commit is contained in:
parent
b9ba4c5743
commit
07aec25f82
@ -1830,10 +1830,10 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion,
|
|||||||
std::vector<spv::Id> operandIds;
|
std::vector<spv::Id> operandIds;
|
||||||
assert(!modeId.second.empty());
|
assert(!modeId.second.empty());
|
||||||
for (auto extraOperand : modeId.second) {
|
for (auto extraOperand : modeId.second) {
|
||||||
int nextConst = 0;
|
if (extraOperand->getType().getQualifier().isSpecConstant())
|
||||||
spv::Id operandId = createSpvConstantFromConstUnionArray(
|
operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode()));
|
||||||
extraOperand->getType(), extraOperand->getConstArray(), nextConst, false);
|
else
|
||||||
operandIds.push_back(operandId);
|
operandIds.push_back(createSpvConstant(*extraOperand));
|
||||||
}
|
}
|
||||||
builder.addExecutionModeId(shaderEntry, static_cast<spv::ExecutionMode>(modeId.first), operandIds);
|
builder.addExecutionModeId(shaderEntry, static_cast<spv::ExecutionMode>(modeId.first), operandIds);
|
||||||
}
|
}
|
||||||
@ -4150,58 +4150,48 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
|
|||||||
|
|
||||||
std::vector<spv::Id> operands;
|
std::vector<spv::Id> operands;
|
||||||
for (const auto& typeParam : spirvType.typeParams) {
|
for (const auto& typeParam : spirvType.typeParams) {
|
||||||
if (typeParam.isConstant) {
|
// Constant expression
|
||||||
// Constant expression
|
if (typeParam.constant->isLiteral()) {
|
||||||
if (typeParam.constant->isLiteral()) {
|
if (typeParam.constant->getBasicType() == glslang::EbtFloat) {
|
||||||
if (typeParam.constant->getBasicType() == glslang::EbtFloat) {
|
float floatValue = static_cast<float>(typeParam.constant->getConstArray()[0].getDConst());
|
||||||
float floatValue = static_cast<float>(typeParam.constant->getConstArray()[0].getDConst());
|
unsigned literal = *reinterpret_cast<unsigned*>(&floatValue);
|
||||||
unsigned literal = *reinterpret_cast<unsigned*>(&floatValue);
|
operands.push_back(literal);
|
||||||
operands.push_back(literal);
|
} else if (typeParam.constant->getBasicType() == glslang::EbtInt) {
|
||||||
} else if (typeParam.constant->getBasicType() == glslang::EbtInt) {
|
unsigned literal = typeParam.constant->getConstArray()[0].getIConst();
|
||||||
unsigned literal = typeParam.constant->getConstArray()[0].getIConst();
|
operands.push_back(literal);
|
||||||
operands.push_back(literal);
|
} else if (typeParam.constant->getBasicType() == glslang::EbtUint) {
|
||||||
} else if (typeParam.constant->getBasicType() == glslang::EbtUint) {
|
unsigned literal = typeParam.constant->getConstArray()[0].getUConst();
|
||||||
unsigned literal = typeParam.constant->getConstArray()[0].getUConst();
|
operands.push_back(literal);
|
||||||
operands.push_back(literal);
|
} else if (typeParam.constant->getBasicType() == glslang::EbtBool) {
|
||||||
} else if (typeParam.constant->getBasicType() == glslang::EbtBool) {
|
unsigned literal = typeParam.constant->getConstArray()[0].getBConst();
|
||||||
unsigned literal = typeParam.constant->getConstArray()[0].getBConst();
|
operands.push_back(literal);
|
||||||
operands.push_back(literal);
|
} else if (typeParam.constant->getBasicType() == glslang::EbtString) {
|
||||||
} else if (typeParam.constant->getBasicType() == glslang::EbtString) {
|
auto str = typeParam.constant->getConstArray()[0].getSConst()->c_str();
|
||||||
auto str = typeParam.constant->getConstArray()[0].getSConst()->c_str();
|
unsigned literal = 0;
|
||||||
unsigned literal = 0;
|
char* literalPtr = reinterpret_cast<char*>(&literal);
|
||||||
char* literalPtr = reinterpret_cast<char*>(&literal);
|
unsigned charCount = 0;
|
||||||
unsigned charCount = 0;
|
char ch = 0;
|
||||||
char ch = 0;
|
do {
|
||||||
do {
|
ch = *(str++);
|
||||||
ch = *(str++);
|
*(literalPtr++) = ch;
|
||||||
*(literalPtr++) = ch;
|
++charCount;
|
||||||
++charCount;
|
if (charCount == 4) {
|
||||||
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;
|
|
||||||
operands.push_back(literal);
|
operands.push_back(literal);
|
||||||
|
literalPtr = reinterpret_cast<char*>(&literal);
|
||||||
|
charCount = 0;
|
||||||
}
|
}
|
||||||
} else
|
} while (ch != 0);
|
||||||
assert(0); // Unexpected type
|
|
||||||
} else {
|
// Partial literal is padded with 0
|
||||||
int nextConst = 0;
|
if (charCount > 0) {
|
||||||
spv::Id constant = createSpvConstantFromConstUnionArray(
|
for (; charCount < 4; ++charCount)
|
||||||
typeParam.constant->getType(), typeParam.constant->getConstArray(), nextConst, false);
|
*(literalPtr++) = 0;
|
||||||
operands.push_back(constant);
|
operands.push_back(literal);
|
||||||
}
|
}
|
||||||
} else {
|
} else
|
||||||
// Type specifier
|
assert(0); // Unexpected type
|
||||||
spv::Id typeId = convertGlslangToSpvType(*typeParam.type);
|
} else
|
||||||
operands.push_back(typeId);
|
operands.push_back(createSpvConstant(*typeParam.constant));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spirvInst.set == "")
|
if (spirvInst.set == "")
|
||||||
@ -8847,12 +8837,12 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
|
|||||||
std::vector<spv::Id> operandIds;
|
std::vector<spv::Id> operandIds;
|
||||||
assert(!decorateId.second.empty());
|
assert(!decorateId.second.empty());
|
||||||
for (auto extraOperand : decorateId.second) {
|
for (auto extraOperand : decorateId.second) {
|
||||||
int nextConst = 0;
|
if (extraOperand->getQualifier().isSpecConstant())
|
||||||
spv::Id operandId = createSpvConstantFromConstUnionArray(
|
operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode()));
|
||||||
extraOperand->getType(), extraOperand->getConstArray(), nextConst, false);
|
else
|
||||||
operandIds.push_back(operandId);
|
operandIds.push_back(createSpvConstant(*extraOperand));
|
||||||
}
|
}
|
||||||
builder.addDecoration(id, static_cast<spv::Decoration>(decorateId.first), operandIds);
|
builder.addDecorationId(id, static_cast<spv::Decoration>(decorateId.first), operandIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add spirv_decorate_string
|
// Add spirv_decorate_string
|
||||||
|
35
Test/baseResults/spv.intrinsicsSpecConst.vert.out
Normal file
35
Test/baseResults/spv.intrinsicsSpecConst.vert.out
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
spv.intrinsicsSpecConst.vert
|
||||||
|
Validation failed
|
||||||
|
// Module Version 10000
|
||||||
|
// Generated by (magic number): 8000a
|
||||||
|
// Id's are bound by 13
|
||||||
|
|
||||||
|
Capability Shader
|
||||||
|
1: ExtInstImport "GLSL.std.450"
|
||||||
|
MemoryModel Logical GLSL450
|
||||||
|
EntryPoint Vertex 4 "main" 10
|
||||||
|
ExecutionModeId 4 DenormFlushToZero 7
|
||||||
|
Source GLSL 450
|
||||||
|
SourceExtension "GL_EXT_spirv_intrinsics"
|
||||||
|
Name 4 "main"
|
||||||
|
Name 7 "targetWidth"
|
||||||
|
Name 10 "pointSize"
|
||||||
|
Name 11 "builtIn"
|
||||||
|
Decorate 7(targetWidth) SpecId 5
|
||||||
|
Decorate 10(pointSize) Location 0
|
||||||
|
Decorate 11(builtIn) SpecId 6
|
||||||
|
DecorateId 10(pointSize) BuiltIn 11(builtIn)
|
||||||
|
2: TypeVoid
|
||||||
|
3: TypeFunction 2
|
||||||
|
6: TypeInt 32 0
|
||||||
|
7(targetWidth): 6(int) SpecConstant 32
|
||||||
|
8: TypeFloat 32
|
||||||
|
9: TypePointer Output 8(float)
|
||||||
|
10(pointSize): 9(ptr) Variable Output
|
||||||
|
11(builtIn): 6(int) SpecConstant 1
|
||||||
|
12: 8(float) Constant 1082130432
|
||||||
|
4(main): 2 Function None 3
|
||||||
|
5: Label
|
||||||
|
Store 10(pointSize) 12
|
||||||
|
Return
|
||||||
|
FunctionEnd
|
14
Test/spv.intrinsicsSpecConst.vert
Normal file
14
Test/spv.intrinsicsSpecConst.vert
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#version 450 core
|
||||||
|
|
||||||
|
#extension GL_EXT_spirv_intrinsics: enable
|
||||||
|
|
||||||
|
layout(constant_id = 5) const uint targetWidth = 32;
|
||||||
|
spirv_execution_mode_id(4460/*=DenormFlushToZero*/, targetWidth);
|
||||||
|
|
||||||
|
layout(constant_id = 6) const uint builtIn = 1;
|
||||||
|
spirv_decorate_id(11/*=BuiltIn*/, builtIn) out float pointSize;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
pointSize = 4.0;
|
||||||
|
}
|
@ -65,7 +65,7 @@ struct TSpirvExecutionMode {
|
|||||||
// spirv_execution_mode
|
// spirv_execution_mode
|
||||||
TMap<int, TVector<const TIntermConstantUnion*>> modes;
|
TMap<int, TVector<const TIntermConstantUnion*>> modes;
|
||||||
// spirv_execution_mode_id
|
// spirv_execution_mode_id
|
||||||
TMap<int, TVector<const TIntermConstantUnion*> > modeIds;
|
TMap<int, TVector<const TIntermTyped*> > modeIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
// SPIR-V decorations
|
// SPIR-V decorations
|
||||||
@ -75,7 +75,7 @@ struct TSpirvDecorate {
|
|||||||
// spirv_decorate
|
// spirv_decorate
|
||||||
TMap<int, TVector<const TIntermConstantUnion*> > decorates;
|
TMap<int, TVector<const TIntermConstantUnion*> > decorates;
|
||||||
// spirv_decorate_id
|
// spirv_decorate_id
|
||||||
TMap<int, TVector<const TIntermConstantUnion*> > decorateIds;
|
TMap<int, TVector<const TIntermTyped*>> decorateIds;
|
||||||
// spirv_decorate_string
|
// spirv_decorate_string
|
||||||
TMap<int, TVector<const TIntermConstantUnion*> > decorateStrings;
|
TMap<int, TVector<const TIntermConstantUnion*> > decorateStrings;
|
||||||
};
|
};
|
||||||
@ -98,20 +98,12 @@ struct TSpirvInstruction {
|
|||||||
struct TSpirvTypeParameter {
|
struct TSpirvTypeParameter {
|
||||||
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
|
||||||
|
|
||||||
TSpirvTypeParameter(const TIntermConstantUnion* arg) { isConstant = true; constant = arg; }
|
TSpirvTypeParameter(const TIntermConstantUnion* arg) { constant = arg; }
|
||||||
TSpirvTypeParameter(const TType* arg) { isConstant = false; type = arg; }
|
|
||||||
|
|
||||||
bool operator==(const TSpirvTypeParameter& rhs) const
|
bool operator==(const TSpirvTypeParameter& rhs) const { return constant == rhs.constant; }
|
||||||
{
|
|
||||||
return isConstant == rhs.isConstant && ((isConstant && constant == rhs.constant) || (!isConstant && type == rhs.type));
|
|
||||||
}
|
|
||||||
bool operator!=(const TSpirvTypeParameter& rhs) const { return !operator==(rhs); }
|
bool operator!=(const TSpirvTypeParameter& rhs) const { return !operator==(rhs); }
|
||||||
|
|
||||||
bool isConstant;
|
const TIntermConstantUnion* constant;
|
||||||
union {
|
|
||||||
const TIntermConstantUnion* constant;
|
|
||||||
const TType* type;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef TVector<TSpirvTypeParameter> TSpirvTypeParameters;
|
typedef TVector<TSpirvTypeParameter> TSpirvTypeParameters;
|
||||||
|
@ -480,7 +480,6 @@ public:
|
|||||||
TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1,
|
TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1,
|
||||||
TSpirvRequirement* spirvReq2);
|
TSpirvRequirement* spirvReq2);
|
||||||
TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant);
|
TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant);
|
||||||
TSpirvTypeParameters* makeSpirvTypeParameters(const TPublicType& type);
|
|
||||||
TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1,
|
TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1,
|
||||||
TSpirvTypeParameters* spirvTypeParams2);
|
TSpirvTypeParameters* spirvTypeParams2);
|
||||||
TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value);
|
TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value);
|
||||||
|
@ -130,11 +130,11 @@ void TIntermediate::insertSpirvExecutionModeId(int executionMode, const TIntermA
|
|||||||
spirvExecutionMode = new TSpirvExecutionMode;
|
spirvExecutionMode = new TSpirvExecutionMode;
|
||||||
|
|
||||||
assert(args);
|
assert(args);
|
||||||
TVector<const TIntermConstantUnion*> extraOperands;
|
TVector<const TIntermTyped*> extraOperands;
|
||||||
|
|
||||||
for (auto arg : args->getSequence()) {
|
for (auto arg : args->getSequence()) {
|
||||||
auto extraOperand = arg->getAsConstantUnion();
|
auto extraOperand = arg->getAsTyped();
|
||||||
assert(extraOperand != nullptr);
|
assert(extraOperand != nullptr && extraOperand->getQualifier().isConstant());
|
||||||
extraOperands.push_back(extraOperand);
|
extraOperands.push_back(extraOperand);
|
||||||
}
|
}
|
||||||
spirvExecutionMode->modeIds[executionMode] = extraOperands;
|
spirvExecutionMode->modeIds[executionMode] = extraOperands;
|
||||||
@ -165,10 +165,10 @@ void TQualifier::setSpirvDecorateId(int decoration, const TIntermAggregate* args
|
|||||||
spirvDecorate = new TSpirvDecorate;
|
spirvDecorate = new TSpirvDecorate;
|
||||||
|
|
||||||
assert(args);
|
assert(args);
|
||||||
TVector<const TIntermConstantUnion*> extraOperands;
|
TVector<const TIntermTyped*> extraOperands;
|
||||||
for (auto arg : args->getSequence()) {
|
for (auto arg : args->getSequence()) {
|
||||||
auto extraOperand = arg->getAsConstantUnion();
|
auto extraOperand = arg->getAsTyped();
|
||||||
assert(extraOperand != nullptr);
|
assert(extraOperand != nullptr && extraOperand->getQualifier().isConstant());
|
||||||
extraOperands.push_back(extraOperand);
|
extraOperands.push_back(extraOperand);
|
||||||
}
|
}
|
||||||
spirvDecorate->decorateIds[decoration] = extraOperands;
|
spirvDecorate->decorateIds[decoration] = extraOperands;
|
||||||
@ -201,25 +201,27 @@ TString TQualifier::getSpirvDecorateQualifierString() const
|
|||||||
const auto appendBool = [&](bool b) { qualifierString.append(std::to_string(b).c_str()); };
|
const auto appendBool = [&](bool b) { qualifierString.append(std::to_string(b).c_str()); };
|
||||||
const auto appendStr = [&](const char* s) { qualifierString.append(s); };
|
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) {
|
if (constant->getBasicType() == EbtFloat) {
|
||||||
float value = static_cast<float>(constant->getConstArray()[0].getDConst());
|
float value = static_cast<float>(constArray[0].getDConst());
|
||||||
appendFloat(value);
|
appendFloat(value);
|
||||||
}
|
}
|
||||||
else if (constant->getBasicType() == EbtInt) {
|
else if (constant->getBasicType() == EbtInt) {
|
||||||
int value = constant->getConstArray()[0].getIConst();
|
int value = constArray[0].getIConst();
|
||||||
appendInt(value);
|
appendInt(value);
|
||||||
}
|
}
|
||||||
else if (constant->getBasicType() == EbtUint) {
|
else if (constant->getBasicType() == EbtUint) {
|
||||||
unsigned value = constant->getConstArray()[0].getUConst();
|
unsigned value = constArray[0].getUConst();
|
||||||
appendUint(value);
|
appendUint(value);
|
||||||
}
|
}
|
||||||
else if (constant->getBasicType() == EbtBool) {
|
else if (constant->getBasicType() == EbtBool) {
|
||||||
bool value = constant->getConstArray()[0].getBConst();
|
bool value = constArray[0].getBConst();
|
||||||
appendBool(value);
|
appendBool(value);
|
||||||
}
|
}
|
||||||
else if (constant->getBasicType() == EbtString) {
|
else if (constant->getBasicType() == EbtString) {
|
||||||
const TString* value = constant->getConstArray()[0].getSConst();
|
const TString* value = constArray[0].getSConst();
|
||||||
appendStr(value->c_str());
|
appendStr(value->c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -290,13 +292,6 @@ TSpirvTypeParameters* TParseContext::makeSpirvTypeParameters(const TSourceLoc& l
|
|||||||
return spirvTypeParams;
|
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)
|
TSpirvTypeParameters* TParseContext::mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, TSpirvTypeParameters* spirvTypeParams2)
|
||||||
{
|
{
|
||||||
// Merge SPIR-V type parameters of the second one to the first one
|
// Merge SPIR-V type parameters of the second one to the first one
|
||||||
|
@ -4367,9 +4367,6 @@ spirv_type_parameter
|
|||||||
: constant_expression {
|
: constant_expression {
|
||||||
$$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion());
|
$$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion());
|
||||||
}
|
}
|
||||||
| type_specifier {
|
|
||||||
$$ = parseContext.makeSpirvTypeParameters($1);
|
|
||||||
}
|
|
||||||
|
|
||||||
spirv_instruction_qualifier
|
spirv_instruction_qualifier
|
||||||
: SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {
|
: SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {
|
||||||
|
@ -4367,9 +4367,6 @@ spirv_type_parameter
|
|||||||
: constant_expression {
|
: constant_expression {
|
||||||
$$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion());
|
$$ = parseContext.makeSpirvTypeParameters($1->getLoc(), $1->getAsConstantUnion());
|
||||||
}
|
}
|
||||||
| type_specifier {
|
|
||||||
$$ = parseContext.makeSpirvTypeParameters($1);
|
|
||||||
}
|
|
||||||
|
|
||||||
spirv_instruction_qualifier
|
spirv_instruction_qualifier
|
||||||
: SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {
|
: SPIRV_INSTRUCTION LEFT_PAREN spirv_instruction_qualifier_list RIGHT_PAREN {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -365,6 +365,7 @@ INSTANTIATE_TEST_SUITE_P(
|
|||||||
"spv.int64.frag",
|
"spv.int64.frag",
|
||||||
"spv.intcoopmat.comp",
|
"spv.intcoopmat.comp",
|
||||||
"spv.intOps.vert",
|
"spv.intOps.vert",
|
||||||
|
"spv.intrinsicsSpecConst.vert",
|
||||||
"spv.intrinsicsSpirvByReference.vert",
|
"spv.intrinsicsSpirvByReference.vert",
|
||||||
"spv.intrinsicsSpirvDecorate.frag",
|
"spv.intrinsicsSpirvDecorate.frag",
|
||||||
"spv.intrinsicsSpirvExecutionMode.frag",
|
"spv.intrinsicsSpirvExecutionMode.frag",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user