Add --no-link option
Adds the --no-link option which outputs the compiled shader binaries without linking them. This is a first step towards allowing users to create SPIR-v binary, non-executable libraries. When using the --no-link option, all functions are decorated with the Export linkage attribute.
This commit is contained in:
parent
a4aceb57de
commit
4c57db1595
24 changed files with 1671 additions and 1454 deletions
|
|
@ -101,6 +101,8 @@ namespace glslang {
|
|||
|
||||
if (name == "nonwritable") return EatNonWritable;
|
||||
if (name == "nonreadable") return EatNonReadable;
|
||||
|
||||
if (name == "export") return EatExport;
|
||||
} else if (nameSpace.size() > 0)
|
||||
return EatNone;
|
||||
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@ typedef struct glslang_spv_options_s {
|
|||
bool validate;
|
||||
bool emit_nonsemantic_shader_debug_info;
|
||||
bool emit_nonsemantic_shader_debug_source;
|
||||
bool compile_only;
|
||||
} glslang_spv_options_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -1108,6 +1108,11 @@ enum TOperator {
|
|||
EOpImageBlockMatchSSDQCOM,
|
||||
};
|
||||
|
||||
enum TLinkType {
|
||||
ELinkNone,
|
||||
ELinkExport,
|
||||
};
|
||||
|
||||
class TIntermTraverser;
|
||||
class TIntermOperator;
|
||||
class TIntermAggregate;
|
||||
|
|
@ -1325,9 +1330,11 @@ public:
|
|||
virtual const TString& getMethodName() const { return method; }
|
||||
virtual TIntermTyped* getObject() const { return object; }
|
||||
virtual void traverse(TIntermTraverser*);
|
||||
void setExport() { linkType = ELinkExport; }
|
||||
protected:
|
||||
TIntermTyped* object;
|
||||
TString method;
|
||||
TLinkType linkType;
|
||||
};
|
||||
|
||||
//
|
||||
|
|
@ -1700,6 +1707,9 @@ public:
|
|||
const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
|
||||
void setSpirvInstruction(const TSpirvInstruction& inst) { spirvInst = inst; }
|
||||
const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; }
|
||||
|
||||
void setLinkType(TLinkType l) { linkType = l; }
|
||||
TLinkType getLinkType() const { return linkType; }
|
||||
protected:
|
||||
TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
|
||||
TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
|
||||
|
|
@ -1711,6 +1721,7 @@ protected:
|
|||
bool debug;
|
||||
TPragmaTable* pragmaTable;
|
||||
TSpirvInstruction spirvInst;
|
||||
TLinkType linkType = ELinkNone;
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1243,6 +1243,8 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc,
|
|||
error(loc, "function cannot take any parameter(s)", function.getName().c_str(), "");
|
||||
if (function.getType().getBasicType() != EbtVoid)
|
||||
error(loc, "", function.getType().getBasicTypeString().c_str(), "entry point cannot return a value");
|
||||
if (function.getLinkType() != ELinkNone)
|
||||
error(loc, "main function cannot be exported", "", "");
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -1279,6 +1281,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc,
|
|||
} else
|
||||
paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc);
|
||||
}
|
||||
paramNodes->setLinkType(function.getLinkType());
|
||||
intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc);
|
||||
loopNestingLevel = 0;
|
||||
statementNestingLevel = 0;
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ public:
|
|||
struct TPragma contextPragma;
|
||||
int beginInvocationInterlockCount;
|
||||
int endInvocationInterlockCount;
|
||||
bool compileOnly = false;
|
||||
|
||||
protected:
|
||||
TParseContextBase(TParseContextBase&);
|
||||
|
|
|
|||
|
|
@ -796,7 +796,8 @@ bool ProcessDeferred(
|
|||
bool requireNonempty,
|
||||
TShader::Includer& includer,
|
||||
const std::string sourceEntryPointName = "",
|
||||
const TEnvironment* environment = nullptr) // optional way of fully setting all versions, overriding the above
|
||||
const TEnvironment* environment = nullptr, // optional way of fully setting all versions, overriding the above
|
||||
bool compileOnly = false)
|
||||
{
|
||||
// This must be undone (.pop()) by the caller, after it finishes consuming the created tree.
|
||||
GetThreadPoolAllocator().push();
|
||||
|
|
@ -942,6 +943,7 @@ bool ProcessDeferred(
|
|||
std::unique_ptr<TParseContextBase> parseContext(CreateParseContext(*symbolTable, intermediate, version, profile, source,
|
||||
stage, compiler->infoSink,
|
||||
spvVersion, forwardCompatible, messages, false, sourceEntryPointName));
|
||||
parseContext->compileOnly = compileOnly;
|
||||
TPpContext ppContext(*parseContext, names[numPre] ? names[numPre] : "", includer);
|
||||
|
||||
// only GLSL (bison triggered, really) needs an externally set scan context
|
||||
|
|
@ -1279,14 +1281,15 @@ bool CompileDeferred(
|
|||
TIntermediate& intermediate,// returned tree, etc.
|
||||
TShader::Includer& includer,
|
||||
const std::string sourceEntryPointName = "",
|
||||
TEnvironment* environment = nullptr)
|
||||
TEnvironment* environment = nullptr,
|
||||
bool compileOnly = false)
|
||||
{
|
||||
DoFullParse parser;
|
||||
return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames,
|
||||
preamble, optLevel, resources, defaultVersion,
|
||||
defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
|
||||
forwardCompatible, messages, intermediate, parser,
|
||||
true, includer, sourceEntryPointName, environment);
|
||||
true, includer, sourceEntryPointName, environment, compileOnly);
|
||||
}
|
||||
|
||||
} // end anonymous namespace for local functions
|
||||
|
|
@ -1867,7 +1870,7 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
|
|||
preamble, EShOptNone, builtInResources, defaultVersion,
|
||||
defaultProfile, forceDefaultVersionAndProfile, overrideVersion,
|
||||
forwardCompatible, messages, *intermediate, includer, sourceEntryPointName,
|
||||
&environment);
|
||||
&environment, compileOnly);
|
||||
}
|
||||
|
||||
// Fill in a string with the result of preprocessing ShaderStrings
|
||||
|
|
|
|||
|
|
@ -246,7 +246,8 @@ public:
|
|||
TSymbol(name),
|
||||
mangledName(*name + '('),
|
||||
op(tOp),
|
||||
defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0)
|
||||
defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0),
|
||||
linkType(ELinkNone)
|
||||
{
|
||||
returnType.shallowCopy(retType);
|
||||
declaredBuiltIn = retType.getQualifier().builtIn;
|
||||
|
|
@ -326,6 +327,9 @@ public:
|
|||
|
||||
virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
|
||||
|
||||
void setExport() { linkType = ELinkExport; }
|
||||
TLinkType getLinkType() const { return linkType; }
|
||||
|
||||
protected:
|
||||
explicit TFunction(const TFunction&);
|
||||
TFunction& operator=(const TFunction&);
|
||||
|
|
@ -347,6 +351,7 @@ protected:
|
|||
int defaultParamCount;
|
||||
|
||||
TSpirvInstruction spirvInst; // SPIR-V instruction qualifiers
|
||||
TLinkType linkType;
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -123,6 +123,8 @@ TAttributeType TParseContext::attributeFromName(const TString& name) const
|
|||
return EatPartialCount;
|
||||
else if (name == "subgroup_uniform_control_flow")
|
||||
return EatSubgroupUniformControlFlow;
|
||||
else if (name == "export")
|
||||
return EatExport;
|
||||
else
|
||||
return EatNone;
|
||||
}
|
||||
|
|
@ -355,6 +357,7 @@ void TParseContext::handleFunctionAttributes(const TSourceLoc& loc, const TAttri
|
|||
|
||||
switch (it->name) {
|
||||
case EatSubgroupUniformControlFlow:
|
||||
requireExtensions(loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
|
||||
intermediate.setSubgroupUniformControlFlow();
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ namespace glslang {
|
|||
EatNonWritable,
|
||||
EatNonReadable,
|
||||
EatSubgroupUniformControlFlow,
|
||||
EatExport,
|
||||
};
|
||||
|
||||
class TIntermAggregate;
|
||||
|
|
|
|||
|
|
@ -941,24 +941,25 @@ identifier_list
|
|||
function_prototype
|
||||
: function_declarator RIGHT_PAREN {
|
||||
$$.function = $1;
|
||||
if (parseContext.compileOnly) $$.function->setExport();
|
||||
$$.loc = $2.loc;
|
||||
}
|
||||
| function_declarator RIGHT_PAREN attribute {
|
||||
$$.function = $1;
|
||||
if (parseContext.compileOnly) $$.function->setExport();
|
||||
$$.loc = $2.loc;
|
||||
parseContext.requireExtensions($2.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
|
||||
parseContext.handleFunctionAttributes($2.loc, *$3);
|
||||
}
|
||||
| attribute function_declarator RIGHT_PAREN {
|
||||
$$.function = $2;
|
||||
if (parseContext.compileOnly) $$.function->setExport();
|
||||
$$.loc = $3.loc;
|
||||
parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
|
||||
parseContext.handleFunctionAttributes($3.loc, *$1);
|
||||
}
|
||||
| attribute function_declarator RIGHT_PAREN attribute {
|
||||
$$.function = $2;
|
||||
if (parseContext.compileOnly) $$.function->setExport();
|
||||
$$.loc = $3.loc;
|
||||
parseContext.requireExtensions($3.loc, 1, &E_GL_EXT_subgroup_uniform_control_flow, "attribute");
|
||||
parseContext.handleFunctionAttributes($3.loc, *$1);
|
||||
parseContext.handleFunctionAttributes($3.loc, *$4);
|
||||
}
|
||||
|
|
@ -4088,6 +4089,7 @@ function_definition
|
|||
parseContext.error($1.loc, "function does not return a value:", "", $1.function->getName().c_str());
|
||||
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
|
||||
$$ = parseContext.intermediate.growAggregate($1.intermNode, $3);
|
||||
$$->getAsAggregate()->setLinkType($1.function->getLinkType());
|
||||
parseContext.intermediate.setAggregateOperator($$, EOpFunction, $1.function->getType(), $1.loc);
|
||||
$$->getAsAggregate()->setName($1.function->getMangledName().c_str());
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -524,7 +524,7 @@ extern int yydebug;
|
|||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
union YYSTYPE
|
||||
{
|
||||
#line 97 "MachineIndependent/glslang.y"
|
||||
#line 72 "MachineIndependent/glslang.y"
|
||||
|
||||
struct {
|
||||
glslang::TSourceLoc loc;
|
||||
|
|
|
|||
|
|
@ -573,6 +573,9 @@ public:
|
|||
void setEnvInputVulkanRulesRelaxed() { environment.input.vulkanRulesRelaxed = true; }
|
||||
bool getEnvInputVulkanRulesRelaxed() const { return environment.input.vulkanRulesRelaxed; }
|
||||
|
||||
void setCompileOnly() { compileOnly = true; }
|
||||
bool getCompileOnly() const { return compileOnly; }
|
||||
|
||||
// Interface to #include handlers.
|
||||
//
|
||||
// To support #include, a client of Glslang does the following:
|
||||
|
|
@ -722,6 +725,9 @@ protected:
|
|||
|
||||
TEnvironment environment;
|
||||
|
||||
// Indicates this shader is meant to be used without linking
|
||||
bool compileOnly = false;
|
||||
|
||||
friend class TProgram;
|
||||
|
||||
private:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue