Add a helper applySpirvDecorate to handle spirv_decorate_xxx directives

Some code paths could be shared.
This commit is contained in:
Rex Xu 2023-11-06 15:59:20 +08:00 committed by arcady-lunarg
parent 091b9fd979
commit a8d39f97cd

View file

@ -66,6 +66,7 @@ namespace spv {
#include <iomanip>
#include <list>
#include <map>
#include <optional>
#include <stack>
#include <string>
#include <vector>
@ -164,6 +165,7 @@ protected:
spv::Id convertGlslangToSpvType(const glslang::TType& type, bool forwardReferenceOnly = false);
spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&,
bool lastBufferBlockMember, bool forwardReferenceOnly = false);
void applySpirvDecorate(const glslang::TType& type, spv::Id id, std::optional<int> member);
bool filterMember(const glslang::TType& member);
spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct,
glslang::TLayoutPacking, const glslang::TQualifier&);
@ -4705,6 +4707,64 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty
return spvType;
}
// Apply SPIR-V decorations to the SPIR-V object (provided by SPIR-V ID). If member index is provided, the
// decorations are applied to this member.
void TGlslangToSpvTraverser::applySpirvDecorate(const glslang::TType& type, spv::Id id, std::optional<int> member)
{
assert(type.getQualifier().hasSpirvDecorate());
const glslang::TSpirvDecorate& spirvDecorate = type.getQualifier().getSpirvDecorate();
// Add spirv_decorate
for (auto& decorate : spirvDecorate.decorates) {
if (!decorate.second.empty()) {
std::vector<unsigned> literals;
TranslateLiterals(decorate.second, literals);
if (member.has_value())
builder.addMemberDecoration(id, *member, static_cast<spv::Decoration>(decorate.first), literals);
else
builder.addDecoration(id, static_cast<spv::Decoration>(decorate.first), literals);
} else {
if (member.has_value())
builder.addMemberDecoration(id, *member, static_cast<spv::Decoration>(decorate.first));
else
builder.addDecoration(id, static_cast<spv::Decoration>(decorate.first));
}
}
// Add spirv_decorate_id
if (member.has_value()) {
// spirv_decorate_id not applied to members
assert(spirvDecorate.decorateIds.empty());
} else {
for (auto& decorateId : spirvDecorate.decorateIds) {
std::vector<spv::Id> operandIds;
assert(!decorateId.second.empty());
for (auto extraOperand : decorateId.second) {
if (extraOperand->getQualifier().isFrontEndConstant())
operandIds.push_back(createSpvConstant(*extraOperand));
else
operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode()));
}
builder.addDecorationId(id, static_cast<spv::Decoration>(decorateId.first), operandIds);
}
}
// Add spirv_decorate_string
for (auto& decorateString : spirvDecorate.decorateStrings) {
std::vector<const char*> strings;
assert(!decorateString.second.empty());
for (auto extraOperand : decorateString.second) {
const char* string = extraOperand->getConstArray()[0].getSConst()->c_str();
strings.push_back(string);
}
if (member.has_value())
builder.addMemberDecoration(id, *member, static_cast<spv::Decoration>(decorateString.first), strings);
else
builder.addDecoration(id, static_cast<spv::Decoration>(decorateString.first), strings);
}
}
// TODO: this functionality should exist at a higher level, in creating the AST
//
// Identify interface members that don't have their required extension turned on.
@ -4943,37 +5003,9 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
}
//
// Add SPIR-V decorations for members (GL_EXT_spirv_intrinsics)
//
if (glslangMember.getQualifier().hasSpirvDecorate()) {
const glslang::TSpirvDecorate& spirvDecorate = glslangMember.getQualifier().getSpirvDecorate();
// Add spirv_decorate
for (auto& decorate : spirvDecorate.decorates) {
if (!decorate.second.empty()) {
std::vector<unsigned> literals;
TranslateLiterals(decorate.second, literals);
builder.addMemberDecoration(spvType, member, static_cast<spv::Decoration>(decorate.first), literals);
}
else
builder.addMemberDecoration(spvType, member, static_cast<spv::Decoration>(decorate.first));
}
// spirv_decorate_id not applied to members
assert(spirvDecorate.decorateIds.empty());
// Add spirv_decorate_string
for (auto& decorateString : spirvDecorate.decorateStrings) {
std::vector<const char*> strings;
assert(!decorateString.second.empty());
for (auto extraOperand : decorateString.second) {
const char* string = extraOperand->getConstArray()[0].getSConst()->c_str();
strings.push_back(string);
}
builder.addDecoration(spvType, static_cast<spv::Decoration>(decorateString.first), strings);
}
}
// Add SPIR-V decorations (GL_EXT_spirv_intrinsics)
if (glslangMember.getQualifier().hasSpirvDecorate())
applySpirvDecorate(glslangMember, spvType, member);
}
// Decorate the structure
@ -9598,47 +9630,9 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol
spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
}
//
// Add SPIR-V decorations (GL_EXT_spirv_intrinsics)
//
if (symbol->getType().getQualifier().hasSpirvDecorate()) {
const glslang::TSpirvDecorate& spirvDecorate = symbol->getType().getQualifier().getSpirvDecorate();
// Add spirv_decorate
for (auto& decorate : spirvDecorate.decorates) {
if (!decorate.second.empty()) {
std::vector<unsigned> literals;
TranslateLiterals(decorate.second, literals);
builder.addDecoration(id, static_cast<spv::Decoration>(decorate.first), literals);
}
else
builder.addDecoration(id, static_cast<spv::Decoration>(decorate.first));
}
// Add spirv_decorate_id
for (auto& decorateId : spirvDecorate.decorateIds) {
std::vector<spv::Id> operandIds;
assert(!decorateId.second.empty());
for (auto extraOperand : decorateId.second) {
if (extraOperand->getQualifier().isFrontEndConstant())
operandIds.push_back(createSpvConstant(*extraOperand));
else
operandIds.push_back(getSymbolId(extraOperand->getAsSymbolNode()));
}
builder.addDecorationId(id, static_cast<spv::Decoration>(decorateId.first), operandIds);
}
// Add spirv_decorate_string
for (auto& decorateString : spirvDecorate.decorateStrings) {
std::vector<const char*> strings;
assert(!decorateString.second.empty());
for (auto extraOperand : decorateString.second) {
const char* string = extraOperand->getConstArray()[0].getSConst()->c_str();
strings.push_back(string);
}
builder.addDecoration(id, static_cast<spv::Decoration>(decorateString.first), strings);
}
}
if (symbol->getType().getQualifier().hasSpirvDecorate())
applySpirvDecorate(symbol->getType(), id, {});
return id;
}