Commit 6e1d50a7 by John Kessenich

HLSL: Accept SV_Cull/ClipDistanceN, by refactoring the way semantics are mapped.

parent 229a6f7f
struct S {
float clip0 : SV_ClipDistance0;
float cull0 : SV_CullDistance0;
uint vpai : SV_ViewportArrayIndex;
uint rtai : SV_RenderTargetArrayIndex;
int ii : SV_InstanceID;
};
[maxvertexcount(4)]
S main(triangle in uint VertexID[3] : VertexID,
inout LineStream<S> OutputStream)
{
S s;
return s;
}
struct S {
float clip : SV_ClipDistance;
float clip0 : SV_ClipDistance0;
float clip7 : SV_ClipDistance7;
float cull : SV_CullDistance;
float cull2 : SV_CullDistance2;
float cull5 : SV_CullDistance5;
int ii : SV_InstanceID;
};
S main(S ins)
{
S s;
return s;
}
......@@ -218,6 +218,7 @@ enum TBuiltInVariable {
// to one of the above.
EbvFragDepthGreater,
EbvFragDepthLesser,
EbvStencilRef,
EbvLast
};
......
......@@ -2,5 +2,5 @@
// For the version, it uses the latest git tag followed by the number of commits.
// For the date, it uses the current date (when then script is run).
#define GLSLANG_REVISION "Overload400-PrecQual.1887"
#define GLSLANG_DATE "08-Mar-2017"
#define GLSLANG_REVISION "Overload400-PrecQual.1892"
#define GLSLANG_DATE "09-Mar-2017"
......@@ -240,6 +240,8 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.max.frag", "PixelShaderFunction"},
{"hlsl.precedence.frag", "PixelShaderFunction"},
{"hlsl.precedence2.frag", "PixelShaderFunction"},
{"hlsl.semantic.geom", "main"},
{"hlsl.semantic.vert", "main"},
{"hlsl.scope.frag", "PixelShaderFunction"},
{"hlsl.sin.frag", "PixelShaderFunction"},
{"hlsl.struct.frag", "PixelShaderFunction"},
......
......@@ -3401,7 +3401,7 @@ bool HlslGrammar::acceptPostDecls(TQualifier& qualifier)
parseContext.handleRegister(registerDesc.loc, qualifier, profile.string, *registerDesc.string, subComponent, spaceDesc.string);
} else {
// semantic, in idToken.string
parseContext.handleSemantic(idToken.loc, qualifier, *idToken.string);
parseContext.handleSemantic(idToken.loc, qualifier, mapSemantic(*idToken.string));
}
} else if (peekTokenClass(EHTokLeftAngle)) {
found = true;
......
......@@ -4194,118 +4194,23 @@ TFunction* HlslParseContext::handleConstructorCall(const TSourceLoc& loc, const
// Handle seeing a "COLON semantic" at the end of a type declaration,
// by updating the type according to the semantic.
//
void HlslParseContext::handleSemantic(TSourceLoc loc, TQualifier& qualifier, const TString& semantic)
{
// TODO: need to know if it's an input or an output
// The following sketches what needs to be done, but can't be right
// without taking into account stage and input/output.
TString semanticUpperCase = semantic;
std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
// in DX9, all outputs had to have a semantic associated with them, that was either consumed
// by the system or was a specific register assignment
// in DX10+, only semantics with the SV_ prefix have any meaning beyond decoration
// Fxc will only accept DX9 style semantics in compat mode
// Also, in DX10 if a SV value is present as the input of a stage, but isn't appropriate for that
// stage, it would just be ignored as it is likely there as part of an output struct from one stage
// to the next
bool bParseDX9 = false;
if (bParseDX9) {
if (semanticUpperCase == "PSIZE")
qualifier.builtIn = EbvPointSize;
else if (semantic == "FOG")
qualifier.builtIn = EbvFogFragCoord;
else if (semanticUpperCase == "DEPTH")
qualifier.builtIn = EbvFragDepth;
else if (semanticUpperCase == "VFACE")
qualifier.builtIn = EbvFace;
else if (semanticUpperCase == "VPOS")
qualifier.builtIn = EbvFragCoord;
}
// SV Position has a different meaning in vertex vs fragment
if (semanticUpperCase == "SV_POSITION" && language != EShLangFragment)
qualifier.builtIn = EbvPosition;
else if (semanticUpperCase == "SV_POSITION" && language == EShLangFragment)
qualifier.builtIn = EbvFragCoord;
else if (semanticUpperCase == "SV_CLIPDISTANCE")
qualifier.builtIn = EbvClipDistance;
else if (semanticUpperCase == "SV_CULLDISTANCE")
qualifier.builtIn = EbvCullDistance;
else if (semanticUpperCase == "SV_VERTEXID")
qualifier.builtIn = EbvVertexIndex;
else if (semanticUpperCase == "SV_VIEWPORTARRAYINDEX")
qualifier.builtIn = EbvViewportIndex;
else if (semanticUpperCase == "SV_TESSFACTOR")
qualifier.builtIn = EbvTessLevelOuter;
// Targets are defined 0-7
else if (semanticUpperCase == "SV_TARGET") {
qualifier.builtIn = EbvNone;
// qualifier.layoutLocation = 0;
} else if (semanticUpperCase == "SV_TARGET0") {
qualifier.builtIn = EbvNone;
// qualifier.layoutLocation = 0;
} else if (semanticUpperCase == "SV_TARGET1") {
qualifier.builtIn = EbvNone;
// qualifier.layoutLocation = 1;
} else if (semanticUpperCase == "SV_TARGET2") {
qualifier.builtIn = EbvNone;
// qualifier.layoutLocation = 2;
} else if (semanticUpperCase == "SV_TARGET3") {
qualifier.builtIn = EbvNone;
// qualifier.layoutLocation = 3;
} else if (semanticUpperCase == "SV_TARGET4") {
qualifier.builtIn = EbvNone;
// qualifier.layoutLocation = 4;
} else if (semanticUpperCase == "SV_TARGET5") {
qualifier.builtIn = EbvNone;
// qualifier.layoutLocation = 5;
} else if (semanticUpperCase == "SV_TARGET6") {
qualifier.builtIn = EbvNone;
// qualifier.layoutLocation = 6;
} else if (semanticUpperCase == "SV_TARGET7") {
qualifier.builtIn = EbvNone;
// qualifier.layoutLocation = 7;
} else if (semanticUpperCase == "SV_SAMPLEINDEX")
qualifier.builtIn = EbvSampleId;
else if (semanticUpperCase == "SV_RENDERTARGETARRAYINDEX")
qualifier.builtIn = EbvLayer;
else if (semanticUpperCase == "SV_PRIMITIVEID")
qualifier.builtIn = EbvPrimitiveId;
else if (semanticUpperCase == "SV_OUTPUTCONTROLPOINTID")
qualifier.builtIn = EbvInvocationId;
else if (semanticUpperCase == "SV_ISFRONTFACE")
qualifier.builtIn = EbvFace;
else if (semanticUpperCase == "SV_INSTANCEID")
qualifier.builtIn = EbvInstanceIndex;
else if (semanticUpperCase == "SV_INSIDETESSFACTOR")
qualifier.builtIn = EbvTessLevelInner;
else if (semanticUpperCase == "SV_GSINSTANCEID")
qualifier.builtIn = EbvInvocationId;
else if (semanticUpperCase == "SV_DISPATCHTHREADID")
qualifier.builtIn = EbvGlobalInvocationId;
else if (semanticUpperCase == "SV_GROUPTHREADID")
qualifier.builtIn = EbvLocalInvocationId;
else if (semanticUpperCase == "SV_GROUPINDEX")
qualifier.builtIn = EbvLocalInvocationIndex;
else if (semanticUpperCase == "SV_GROUPID")
qualifier.builtIn = EbvWorkGroupId;
else if (semanticUpperCase == "SV_DOMAINLOCATION")
qualifier.builtIn = EbvTessCoord;
else if (semanticUpperCase == "SV_DEPTH")
qualifier.builtIn = EbvFragDepth;
else if( semanticUpperCase == "SV_COVERAGE")
qualifier.builtIn = EbvSampleMask;
// TODO, these need to get refined to be more specific
else if( semanticUpperCase == "SV_DEPTHGREATEREQUAL")
qualifier.builtIn = EbvFragDepthGreater;
else if( semanticUpperCase == "SV_DEPTHLESSEQUAL")
qualifier.builtIn = EbvFragDepthLesser;
else if( semanticUpperCase == "SV_STENCILREF")
void HlslParseContext::handleSemantic(TSourceLoc loc, TQualifier& qualifier, TBuiltInVariable builtIn)
{
// adjust for stage in/out
switch(builtIn) {
case EbvPosition:
if (language == EShLangFragment)
builtIn = EbvFragCoord;
break;
case EbvStencilRef:
error(loc, "unimplemented; need ARB_shader_stencil_export", "SV_STENCILREF", "");
break;
default:
break;
}
qualifier.builtIn = builtIn;
}
//
......
......@@ -91,7 +91,7 @@ public:
TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&);
void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
TFunction* handleConstructorCall(const TSourceLoc&, const TType&);
void handleSemantic(TSourceLoc, TQualifier&, const TString& semantic);
void handleSemantic(TSourceLoc, TQualifier&, TBuiltInVariable);
void handlePackOffset(const TSourceLoc&, TQualifier&, const glslang::TString& location,
const glslang::TString* component);
void handleRegister(const TSourceLoc&, TQualifier&, const glslang::TString* profile, const glslang::TString& desc,
......
......@@ -47,7 +47,6 @@
#include "../glslang/MachineIndependent/ParseHelper.h"
#include "hlslScanContext.h"
#include "hlslTokens.h"
//#include "Scan.h"
// preprocessor includes
#include "../glslang/MachineIndependent/preprocessor/PpContext.h"
......@@ -82,6 +81,7 @@ struct str_hash
// After a single process-level initialization, this is read only and thread safe
std::unordered_map<const char*, glslang::EHlslTokenClass, str_hash, str_eq>* KeywordMap = nullptr;
std::unordered_set<const char*, str_hash, str_eq>* ReservedSet = nullptr;
std::unordered_map<const char*, glslang::TBuiltInVariable, str_hash, str_eq>* SemanticMap = nullptr;
};
......@@ -381,6 +381,73 @@ void HlslScanContext::fillInKeywordMap()
ReservedSet->insert("unsigned");
ReservedSet->insert("using");
ReservedSet->insert("virtual");
SemanticMap = new std::unordered_map<const char*, glslang::TBuiltInVariable, str_hash, str_eq>;
// in DX9, all outputs had to have a semantic associated with them, that was either consumed
// by the system or was a specific register assignment
// in DX10+, only semantics with the SV_ prefix have any meaning beyond decoration
// Fxc will only accept DX9 style semantics in compat mode
// Also, in DX10 if a SV value is present as the input of a stage, but isn't appropriate for that
// stage, it would just be ignored as it is likely there as part of an output struct from one stage
// to the next
bool bParseDX9 = false;
if (bParseDX9) {
(*SemanticMap)["PSIZE"] = EbvPointSize;
(*SemanticMap)["FOG"] = EbvFogFragCoord;
(*SemanticMap)["DEPTH"] = EbvFragDepth;
(*SemanticMap)["VFACE"] = EbvFace;
(*SemanticMap)["VPOS"] = EbvFragCoord;
}
(*SemanticMap)["SV_POSITION"] = EbvPosition;
(*SemanticMap)["SV_CLIPDISTANCE"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE0"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE1"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE2"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE3"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE4"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE5"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE6"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE7"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE8"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE9"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE10"] = EbvClipDistance;
(*SemanticMap)["SV_CLIPDISTANCE11"] = EbvClipDistance;
(*SemanticMap)["SV_CULLDISTANCE"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE0"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE1"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE2"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE3"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE4"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE5"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE6"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE7"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE8"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE9"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE10"] = EbvCullDistance;
(*SemanticMap)["SV_CULLDISTANCE11"] = EbvCullDistance;
(*SemanticMap)["SV_VERTEXID"] = EbvVertexIndex;
(*SemanticMap)["SV_VIEWPORTARRAYINDEX"] = EbvViewportIndex;
(*SemanticMap)["SV_TESSFACTOR"] = EbvTessLevelOuter;
(*SemanticMap)["SV_SAMPLEINDEX"] = EbvSampleId;
(*SemanticMap)["SV_RENDERTARGETARRAYINDEX"] = EbvLayer;
(*SemanticMap)["SV_PRIMITIVEID"] = EbvPrimitiveId;
(*SemanticMap)["SV_OUTPUTCONTROLPOINTID"] = EbvInvocationId;
(*SemanticMap)["SV_ISFRONTFACE"] = EbvFace;
(*SemanticMap)["SV_INSTANCEID"] = EbvInstanceIndex;
(*SemanticMap)["SV_INSIDETESSFACTOR"] = EbvTessLevelInner;
(*SemanticMap)["SV_GSINSTANCEID"] = EbvInvocationId;
(*SemanticMap)["SV_DISPATCHTHREADID"] = EbvGlobalInvocationId;
(*SemanticMap)["SV_GROUPTHREADID"] = EbvLocalInvocationId;
(*SemanticMap)["SV_GROUPINDEX"] = EbvLocalInvocationIndex;
(*SemanticMap)["SV_GROUPID"] = EbvWorkGroupId;
(*SemanticMap)["SV_DOMAINLOCATION"] = EbvTessCoord;
(*SemanticMap)["SV_DEPTH"] = EbvFragDepth;
(*SemanticMap)["SV_COVERAGE"] = EbvSampleMask;
(*SemanticMap)["SV_DEPTHGREATEREQUAL"] = EbvFragDepthGreater;
(*SemanticMap)["SV_DEPTHLESSEQUAL"] = EbvFragDepthLesser;
(*SemanticMap)["SV_STENCILREF"] = EbvStencilRef;
}
void HlslScanContext::deleteKeywordMap()
......@@ -389,15 +456,29 @@ void HlslScanContext::deleteKeywordMap()
KeywordMap = nullptr;
delete ReservedSet;
ReservedSet = nullptr;
delete SemanticMap;
SemanticMap = nullptr;
}
// Wrapper for tokenizeClass()"] = to get everything inside the token.
// Wrapper for tokenizeClass() to get everything inside the token.
void HlslScanContext::tokenize(HlslToken& token)
{
EHlslTokenClass tokenClass = tokenizeClass(token);
token.tokenClass = tokenClass;
}
glslang::TBuiltInVariable HlslScanContext::mapSemantic(const TString& semantic)
{
TString semanticUpperCase = semantic;
std::transform(semanticUpperCase.begin(), semanticUpperCase.end(), semanticUpperCase.begin(), ::toupper);
auto it = SemanticMap->find(semanticUpperCase.c_str());
if (it != SemanticMap->end())
return it->second;
else
return glslang::EbvNone;
}
//
// Fill in token information for the next token, except for the token class.
// Returns the enum value of the token class of the next token found.
......
......@@ -82,6 +82,7 @@ public:
static void deleteKeywordMap();
void tokenize(HlslToken&);
glslang::TBuiltInVariable mapSemantic(const TString& semantic);
protected:
HlslScanContext(HlslScanContext&);
......
......@@ -52,6 +52,7 @@ namespace glslang {
bool acceptTokenClass(EHlslTokenClass);
EHlslTokenClass peek() const;
bool peekTokenClass(EHlslTokenClass) const;
glslang::TBuiltInVariable mapSemantic(const TString& semantic) { return scanner.mapSemantic(semantic); }
protected:
HlslToken token; // the token we are currently looking at, but have not yet accepted
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment