Skip to content

Commit

Permalink
Merge pull request #1 from KhronosGroup/master
Browse files Browse the repository at this point in the history
Update from master
  • Loading branch information
gwihlidal authored Feb 17, 2017
2 parents 18adbdb + b0561d9 commit b0cfcb5
Show file tree
Hide file tree
Showing 227 changed files with 41,083 additions and 33,573 deletions.
13 changes: 11 additions & 2 deletions SPIRV/GLSL.ext.NV.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
** Copyright (c) 2014-2016 The Khronos Group Inc.
** Copyright (c) 2014-2017 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"),
Expand Down Expand Up @@ -33,7 +33,7 @@ enum Op;
enum Capability;

static const int GLSLextNVVersion = 100;
static const int GLSLextNVRevision = 4;
static const int GLSLextNVRevision = 5;

//SPV_NV_sample_mask_override_coverage
const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage";
Expand Down Expand Up @@ -71,4 +71,13 @@ static const BuiltIn BuiltInSecondaryViewportMaskNV = static_cast<BuiltIn>(5258)

static const Capability CapabilityShaderStereoViewNV = static_cast<Capability>(5259);


//SPV_NVX_multiview_per_view_attributes
const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_per_view_attributes";

static const BuiltIn BuiltInPositionPerViewNV = static_cast<BuiltIn>(5260);
static const BuiltIn BuiltInViewportMaskPerViewNV = static_cast<BuiltIn>(5261);

static const Capability CapabilityPerViewAttributesNV = static_cast<Capability>(5262);

#endif // #ifndef GLSLextNV_H
116 changes: 98 additions & 18 deletions SPIRV/GlslangToSpv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,14 @@ spv::BuiltIn TGlslangToSpvTraverser::TranslateBuiltInDecoration(glslang::TBuiltI
builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
builder.addCapability(spv::CapabilityShaderStereoViewNV);
return spv::BuiltInSecondaryViewportMaskNV;
case glslang::EbvPositionPerViewNV:
builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes);
builder.addCapability(spv::CapabilityPerViewAttributesNV);
return spv::BuiltInPositionPerViewNV;
case glslang::EbvViewportMaskPerViewNV:
builder.addExtension(spv::E_SPV_NVX_multiview_per_view_attributes);
builder.addCapability(spv::CapabilityPerViewAttributesNV);
return spv::BuiltInViewportMaskPerViewNV;
#endif
default: return spv::BuiltInMax;
}
Expand Down Expand Up @@ -1748,42 +1756,98 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt
}
}

// This path handles both if-then-else and ?:
// The if-then-else has a node type of void, while
// ?: has either a void or a non-void node type
//
// Leaving the result, when not void:
// GLSL only has r-values as the result of a :?, but
// if we have an l-value, that can be more efficient if it will
// become the base of a complex r-value expression, because the
// next layer copies r-values into memory to use the access-chain mechanism
bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang::TIntermSelection* node)
{
// This path handles both if-then-else and ?:
// The if-then-else has a node type of void, while
// ?: has a non-void node type
spv::Id result = 0;
if (node->getBasicType() != glslang::EbtVoid) {
// don't handle this as just on-the-fly temporaries, because there will be two names
// and better to leave SSA to later passes
result = builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType()));
// See if it simple and safe to generate OpSelect instead of using control flow.
// Crucially, side effects must be avoided, and there are performance trade-offs.
// Return true if good idea (and safe) for OpSelect, false otherwise.
const auto selectPolicy = [&]() -> bool {
if (node->getBasicType() == glslang::EbtVoid)
return false;

if (node->getTrueBlock() == nullptr ||
node->getFalseBlock() == nullptr)
return false;

assert(node->getType() == node->getTrueBlock() ->getAsTyped()->getType() &&
node->getType() == node->getFalseBlock()->getAsTyped()->getType());

// return true if a single operand to ? : is okay for OpSelect
const auto operandOkay = [](glslang::TIntermTyped* node) {
return node->getAsSymbolNode() || node->getType().getQualifier().isConstant();
};

return operandOkay(node->getTrueBlock() ->getAsTyped()) &&
operandOkay(node->getFalseBlock()->getAsTyped());
};

// Emit OpSelect for this selection.
const auto handleAsOpSelect = [&]() {
node->getCondition()->traverse(this);
spv::Id condition = accessChainLoad(node->getCondition()->getType());
node->getTrueBlock()->traverse(this);
spv::Id trueValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());
node->getFalseBlock()->traverse(this);
spv::Id falseValue = accessChainLoad(node->getTrueBlock()->getAsTyped()->getType());

spv::Id select = builder.createTriOp(spv::OpSelect, convertGlslangToSpvType(node->getType()), condition, trueValue, falseValue);
builder.clearAccessChain();
builder.setAccessChainRValue(select);
};

// Try for OpSelect

if (selectPolicy()) {
SpecConstantOpModeGuard spec_constant_op_mode_setter(&builder);
if (node->getType().getQualifier().isSpecConstant())
spec_constant_op_mode_setter.turnOnSpecConstantOpMode();

handleAsOpSelect();
return false;
}

// Instead, emit control flow...

// Don't handle results as temporaries, because there will be two names
// and better to leave SSA to later passes.
spv::Id result = (node->getBasicType() == glslang::EbtVoid)
? spv::NoResult
: builder.createVariable(spv::StorageClassFunction, convertGlslangToSpvType(node->getType()));

// emit the condition before doing anything with selection
node->getCondition()->traverse(this);

// make an "if" based on the value created by the condition
spv::Builder::If ifBuilder(accessChainLoad(node->getCondition()->getType()), builder);

if (node->getTrueBlock()) {
// emit the "then" statement
// emit the "then" statement
if (node->getTrueBlock() != nullptr) {
node->getTrueBlock()->traverse(this);
if (result)
builder.createStore(accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()), result);
if (result != spv::NoResult)
builder.createStore(accessChainLoad(node->getTrueBlock()->getAsTyped()->getType()), result);
}

if (node->getFalseBlock()) {
if (node->getFalseBlock() != nullptr) {
ifBuilder.makeBeginElse();
// emit the "else" statement
node->getFalseBlock()->traverse(this);
if (result)
if (result != spv::NoResult)
builder.createStore(accessChainLoad(node->getFalseBlock()->getAsTyped()->getType()), result);
}

// finish off the control flow
ifBuilder.makeEndIf();

if (result) {
if (result != spv::NoResult) {
// GLSL only has r-values as the result of a :?, but
// if we have an l-value, that can be more efficient if it will
// become the base of a complex r-value expression, because the
Expand Down Expand Up @@ -2248,8 +2312,10 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix));
addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember));
// Add interpolation and auxiliary storage decorations only to top-level members of Input and Output storage classes
if (type.getQualifier().storage == glslang::EvqVaryingIn || type.getQualifier().storage == glslang::EvqVaryingOut) {
if (type.getBasicType() == glslang::EbtBlock) {
if (type.getQualifier().storage == glslang::EvqVaryingIn ||
type.getQualifier().storage == glslang::EvqVaryingOut) {
if (type.getBasicType() == glslang::EbtBlock ||
glslangIntermediate->getSource() == glslang::EShSourceHlsl) {
addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier));
addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier));
}
Expand Down Expand Up @@ -2326,6 +2392,11 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
builder.addExtension(spv::E_SPV_NV_stereo_view_rendering);
}
}
if (glslangMember.getQualifier().layoutPassthrough) {
addMemberDecoration(spvType, member, (spv::Decoration)spv::DecorationPassthroughNV);
builder.addCapability(spv::CapabilityGeometryShaderPassthroughNV);
builder.addExtension(spv::E_SPV_NV_geometry_shader_passthrough);
}
#endif
}
}
Expand Down Expand Up @@ -2603,6 +2674,8 @@ void TGlslangToSpvTraverser::declareUseOfStructMember(const glslang::TTypeList&
case glslang::EbvViewportMaskNV:
case glslang::EbvSecondaryPositionNV:
case glslang::EbvSecondaryViewportMaskNV:
case glslang::EbvPositionPerViewNV:
case glslang::EbvViewportMaskPerViewNV:
#endif
// Generate the associated capability. Delegate to TranslateBuiltInDecoration.
// Alternately, we could just call this for any glslang built-in, since the
Expand Down Expand Up @@ -5254,11 +5327,15 @@ void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName)
}

// Write SPIR-V out to a text file with 32-bit hexadecimal words
void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName)
void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName)
{
std::ofstream out;
out.open(baseName, std::ios::binary | std::ios::out);
out << "\t// " GLSLANG_REVISION " " GLSLANG_DATE << std::endl;
if (varName != nullptr) {
out << "\t #pragma once" << std::endl;
out << "const uint32_t " << varName << "[] = {" << std::endl;
}
const int WORDS_PER_LINE = 8;
for (int i = 0; i < (int)spirv.size(); i += WORDS_PER_LINE) {
out << "\t";
Expand All @@ -5271,6 +5348,9 @@ void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName)
}
out << std::endl;
}
if (varName != nullptr) {
out << "};";
}
out.close();
}

Expand Down
2 changes: 1 addition & 1 deletion SPIRV/GlslangToSpv.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ void GetSpirvVersion(std::string&);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv);
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, spv::SpvBuildLogger* logger);
void OutputSpvBin(const std::vector<unsigned int>& spirv, const char* baseName);
void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName);
void OutputSpvHex(const std::vector<unsigned int>& spirv, const char* baseName, const char* varName);

}
9 changes: 7 additions & 2 deletions SPIRV/disassemble.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,8 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
#ifdef NV_EXTENSIONS
}else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 ||
strcmp(spv::E_SPV_NV_geometry_shader_passthrough, name) == 0 ||
strcmp(spv::E_SPV_NV_viewport_array2, name) == 0) {
strcmp(spv::E_SPV_NV_viewport_array2, name) == 0 ||
strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0) {
extInstSet = GLSLextNVInst;
#endif
}
Expand Down Expand Up @@ -659,7 +660,8 @@ static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)
if (strcmp(name, spv::E_SPV_NV_sample_mask_override_coverage) == 0 ||
strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 0 ||
strcmp(name, spv::E_ARB_shader_viewport_layer_array) == 0 ||
strcmp(name, spv::E_SPV_NV_viewport_array2) == 0){
strcmp(name, spv::E_SPV_NV_viewport_array2) == 0 ||
strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0) {
switch (entrypoint) {
case DecorationOverrideCoverageNV: return "OverrideCoverageNV";
case DecorationPassthroughNV: return "PassthroughNV";
Expand All @@ -671,6 +673,9 @@ static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)
case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV";
case BuiltInPositionPerViewNV: return "PositionPerViewNV";
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
default: return "Bad";
}
}
Expand Down
6 changes: 4 additions & 2 deletions SPIRV/doc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,8 @@ const char* BuiltInString(int builtIn)
case 5253: return "ViewportMaskNV";
case 5257: return "SecondaryPositionNV";
case 5258: return "SecondaryViewportMaskNV";
case 5260: return "PositionPerViewNV";
case 5261: return "ViewportMaskPerViewNV";
#endif
}
}
Expand Down Expand Up @@ -1169,8 +1171,8 @@ const char* OpcodeString(int op)

case 4421: return "OpSubgroupBallotKHR";
case 4422: return "OpSubgroupFirstInvocationKHR";
case 4428: return "OpSubgroupAnyKHR";
case 4429: return "OpSubgroupAllKHR";
case 4428: return "OpSubgroupAllKHR";
case 4429: return "OpSubgroupAnyKHR";
case 4430: return "OpSubgroupAllEqualKHR";
case 4432: return "OpSubgroupReadInvocationKHR";

Expand Down
18 changes: 16 additions & 2 deletions StandAlone/StandAlone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ const char* binaryFileName = nullptr;
const char* entryPointName = nullptr;
const char* sourceEntryPointName = nullptr;
const char* shaderStageName = nullptr;
const char* variableName = nullptr;

std::array<unsigned int, EShLangCount> baseSamplerBinding;
std::array<unsigned int, EShLangCount> baseTextureBinding;
Expand Down Expand Up @@ -302,7 +303,18 @@ void ProcessArguments(int argc, char* argv[])
} else if (lowerword == "no-storage-format" || // synonyms
lowerword == "nsf") {
Options |= EOptionNoStorageFormat;
} else if (lowerword == "source-entrypoint" || // synonyms
} else if (lowerword == "variable-name" || // synonyms
lowerword == "vn") {
Options |= EOptionOutputHexadecimal;
variableName = argv[1];
if (argc > 0) {
argc--;
argv++;
} else
Error("no <C-variable-name> provided for --variable-name");
break;
}
else if (lowerword == "source-entrypoint" || // synonyms
lowerword == "sep") {
sourceEntryPointName = argv[1];
if (argc > 0) {
Expand Down Expand Up @@ -650,7 +662,7 @@ void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits)
if (! (Options & EOptionMemoryLeakMode)) {
printf("%s", logger.getAllMessages().c_str());
if (Options & EOptionOutputHexadecimal) {
glslang::OutputSpvHex(spirv, GetBinaryName((EShLanguage)stage));
glslang::OutputSpvHex(spirv, GetBinaryName((EShLanguage)stage), variableName);
} else {
glslang::OutputSpvBin(spirv, GetBinaryName((EShLanguage)stage));
}
Expand Down Expand Up @@ -987,6 +999,8 @@ void usage()
"\n"
" --keep-uncalled don't eliminate uncalled functions when linking\n"
" --ku synonym for --keep-uncalled\n"
" --variable-name <name> Creates a C header file that contains a uint32_t array named <name> initialized with the shader binary code.\n"
" --vn <name> synonym for --variable-name <name>.\n"
);

exit(EFailUsage);
Expand Down
Loading

0 comments on commit b0cfcb5

Please sign in to comment.