Merge pull request #596 from steve-lunarg/hlsl-intrinsic-parsing

HLSL: use HLSL parser for HLSL intrinsic prototypes, enable int/bool mats
This commit is contained in:
John Kessenich
2016-11-23 00:19:40 -07:00
committed by GitHub
43 changed files with 3729 additions and 2033 deletions

View File

@@ -55,7 +55,7 @@
namespace { // anonymous namespace functions
const bool UseHlslTypes = false;
const bool UseHlslTypes = true;
const char* BaseTypeName(const char argOrder, const char* scalarName, const char* vecName, const char* matName)
{
@@ -246,24 +246,24 @@ glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, cons
if (UseHlslTypes) {
switch (type) {
case '-': s += "void"; break;
case 'F': s += "float"; break;
case 'D': s += "double"; break;
case 'I': s += "int"; break;
case 'U': s += "uint"; break;
case 'B': s += "bool"; break;
case 'S': s += "sampler"; break;
case 's': s += "SamplerComparisonState"; break;
case '-': s += "void"; break;
case 'F': s += "float"; break;
case 'D': s += "double"; break;
case 'I': s += "int"; break;
case 'U': s += "uint"; break;
case 'B': s += "bool"; break;
case 'S': s += "sampler"; break;
case 's': s += "SamplerComparisonState"; break;
case 'T': s += ((isBuffer && isImage) ? "RWBuffer" :
isBuffer ? "Buffer" :
isImage ? "RWTexture" : "Texture"); break;
case 'i': s += ((isBuffer && isImage) ? "RWBuffer <int4>" :
isBuffer ? "Buffer <int4>" :
isImage ? "RWTexture <int4>" : "Texture <int4>"); break;
case 'u': s += ((isBuffer && isImage) ? "RWBuffer <uint4>" :
isBuffer ? "Buffer <uint4>" :
isImage ? "RWTexture <uint4>" : "Texture <uint4>");break;
default: s += "UNKNOWN_TYPE"; break;
isImage ? "RWTexture" : "Texture"); break;
case 'i': s += ((isBuffer && isImage) ? "RWBuffer" :
isBuffer ? "Buffer" :
isImage ? "RWTexture" : "Texture"); break;
case 'u': s += ((isBuffer && isImage) ? "RWBuffer" :
isBuffer ? "Buffer" :
isImage ? "RWTexture" : "Texture"); break;
default: s += "UNKNOWN_TYPE"; break;
}
} else {
switch (type) {
@@ -336,36 +336,55 @@ glslang::TString& AppendTypeName(glslang::TString& s, const char* argOrder, cons
if (isArrayed)
s += "Array";
// For HLSL, append return type for texture types
if (UseHlslTypes) {
switch (type) {
case 'i': s += "<int4>"; break;
case 'u': s += "<uint4>"; break;
case 'T': s += "<float4>"; break;
default: break;
}
}
return s;
}
// TODO: the GLSL parser is currently used to parse HLSL prototypes. However, many valid HLSL prototypes
// The GLSL parser can be used to parse a subset of HLSL prototypes. However, many valid HLSL prototypes
// are not valid GLSL prototypes. This rejects the invalid ones. Thus, there is a single switch below
// to enable creation of the entire HLSL space.
inline bool IsValidGlsl(const char* cname, char retOrder, char retType, char argOrder, char argType,
int dim0, int dim1, int dim0Max, int dim1Max)
inline bool IsValid(const char* cname, char retOrder, char retType, char argOrder, char argType, int dim0, int dim1)
{
const bool isVec = dim0Max > 1 || argType == 'V';
const bool isMat = dim1Max > 1 || argType == 'M';
const bool isVec = (argOrder == 'V');
const bool isMat = (argOrder == 'M');
if (!IsTextureType(argOrder) &&
((isVec && dim0 == 1) || // avoid vec1
(isMat && dim0 == 1 && dim1 == 1))) // avoid mat1x1
const std::string name(cname);
// these do not have vec1 versions
if (dim0 == 1 && (name == "length" || name == "normalize" || name == "reflect" || name == "refract"))
return false;
const std::string name(cname); // for ease of comparison. slow, but temporary, until HLSL parser is online.
if (isMat && dim1 == 1) // TODO: avoid mat Nx1 until we find the right GLSL profile
if (!IsTextureType(argOrder) && (isVec && dim0 == 1)) // avoid vec1
return false;
if ((isMat && (argType == 'I' || argType == 'U' || argType == 'B')) ||
(retOrder == 'M' && (retType == 'I' || retType == 'U' || retType == 'B')))
return false;
if (UseHlslTypes) {
// NO further restrictions for HLSL
} else {
// GLSL parser restrictions
if ((isMat && (argType == 'I' || argType == 'U' || argType == 'B')) ||
(retOrder == 'M' && (retType == 'I' || retType == 'U' || retType == 'B')))
return false;
if (name == "GetRenderTargetSamplePosition" ||
name == "tex1D" ||
name == "tex1Dgrad")
return false;
if (isMat && dim0 == 1 && dim1 == 1) // avoid mat1x1
return false;
if (isMat && dim1 == 1) // TODO: avoid mat Nx1 until we find the right GLSL profile
return false;
if (name == "GetRenderTargetSamplePosition" ||
name == "tex1D" ||
name == "tex1Dgrad")
return false;
}
return true;
}
@@ -534,10 +553,10 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c
{ "abort", nullptr, nullptr, "-", "-", EShLangAll },
{ "abs", nullptr, nullptr, "SVM", "DFUI", EShLangAll },
{ "acos", nullptr, nullptr, "SVM", "F", EShLangAll },
{ "all", "S", "B", "SVM", "BFI", EShLangAll },
{ "all", "S", "B", "SVM", "BFIU", EShLangAll },
{ "AllMemoryBarrier", nullptr, nullptr, "-", "-", EShLangCS },
{ "AllMemoryBarrierWithGroupSync", nullptr, nullptr, "-", "-", EShLangCS },
{ "any", "S", "B", "SVM", "BFI", EShLangAll },
{ "any", "S", "B", "SVM", "BFIU", EShLangAll },
{ "asdouble", "S", "D", "S,", "U,", EShLangAll },
{ "asdouble", "V2", "D", "V2,", "U,", EShLangAll },
{ "asfloat", nullptr, "F", "SVM", "BFIU", EShLangAll },
@@ -682,7 +701,7 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c
{ "texCUBEgrad", "V4", "F", "V4,V3,,", "S,F,,", EShLangPS },
{ "texCUBElod", "V4", "F", "V4,", "S,F", EShLangPS },
{ "texCUBEproj", "V4", "F", "V4,", "S,F", EShLangPS },
{ "transpose", "^M", nullptr, "M", "F", EShLangAll },
{ "transpose", "^M", nullptr, "M", "FUIB", EShLangAll },
{ "trunc", nullptr, nullptr, "SVM", "F", EShLangAll },
// Texture object methods. Return type can be overridden by shader declaration.
@@ -835,10 +854,6 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c
{ nullptr, nullptr, nullptr, nullptr, nullptr, 0 },
};
// Set this to true to avoid generating prototypes that will be invalid for the GLSL parser.
// TODO: turn it off (and remove the code) when the HLSL parser can be used to parse builtins.
static const bool skipInvalidGlsl = true;
// Create prototypes for the intrinsics. TODO: Avoid ranged based for until all compilers can handle it.
for (int icount = 0; hlslIntrinsics[icount].name; ++icount) {
const auto& intrinsic = hlslIntrinsics[icount];
@@ -874,8 +889,7 @@ void TBuiltInParseablesHlsl::initialize(int /*version*/, EProfile /*profile*/, c
const char* retOrder = intrinsic.retOrder ? intrinsic.retOrder : argOrder;
const char* retType = intrinsic.retType ? intrinsic.retType : argType;
if (skipInvalidGlsl && !IsValidGlsl(intrinsic.name, *retOrder, *retType, *argOrder, *argType,
dim0, dim1, dim0Max, dim1Max))
if (!IsValid(intrinsic.name, *retOrder, *retType, *argOrder, *argType, dim0, dim1))
continue;
// Reject some forms of sample methods that don't exist.

View File

@@ -180,6 +180,22 @@ void HlslScanContext::fillInKeywordMap()
(*KeywordMap)["min16uint3"] = EHTokMin16uint3;
(*KeywordMap)["min16uint4"] = EHTokMin16uint4;
(*KeywordMap)["bool1x1"] = EHTokBool1x1;
(*KeywordMap)["bool1x2"] = EHTokBool1x2;
(*KeywordMap)["bool1x3"] = EHTokBool1x3;
(*KeywordMap)["bool1x4"] = EHTokBool1x4;
(*KeywordMap)["bool2x1"] = EHTokBool2x1;
(*KeywordMap)["bool2x2"] = EHTokBool2x2;
(*KeywordMap)["bool2x3"] = EHTokBool2x3;
(*KeywordMap)["bool2x4"] = EHTokBool2x4;
(*KeywordMap)["bool3x1"] = EHTokBool3x1;
(*KeywordMap)["bool3x2"] = EHTokBool3x2;
(*KeywordMap)["bool3x3"] = EHTokBool3x3;
(*KeywordMap)["bool3x4"] = EHTokBool3x4;
(*KeywordMap)["bool4x1"] = EHTokBool4x1;
(*KeywordMap)["bool4x2"] = EHTokBool4x2;
(*KeywordMap)["bool4x3"] = EHTokBool4x3;
(*KeywordMap)["bool4x4"] = EHTokBool4x4;
(*KeywordMap)["int1x1"] = EHTokInt1x1;
(*KeywordMap)["int1x2"] = EHTokInt1x2;
(*KeywordMap)["int1x3"] = EHTokInt1x3;
@@ -561,6 +577,22 @@ EHlslTokenClass HlslScanContext::tokenizeIdentifier()
case EHTokMin16uint4:
// matrix types
case EHTokBool1x1:
case EHTokBool1x2:
case EHTokBool1x3:
case EHTokBool1x4:
case EHTokBool2x1:
case EHTokBool2x2:
case EHTokBool2x3:
case EHTokBool2x4:
case EHTokBool3x1:
case EHTokBool3x2:
case EHTokBool3x3:
case EHTokBool3x4:
case EHTokBool4x1:
case EHTokBool4x2:
case EHTokBool4x3:
case EHTokBool4x4:
case EHTokInt1x1:
case EHTokInt1x2:
case EHTokInt1x3:
@@ -577,6 +609,22 @@ EHlslTokenClass HlslScanContext::tokenizeIdentifier()
case EHTokInt4x2:
case EHTokInt4x3:
case EHTokInt4x4:
case EHTokUint1x1:
case EHTokUint1x2:
case EHTokUint1x3:
case EHTokUint1x4:
case EHTokUint2x1:
case EHTokUint2x2:
case EHTokUint2x3:
case EHTokUint2x4:
case EHTokUint3x1:
case EHTokUint3x2:
case EHTokUint3x3:
case EHTokUint3x4:
case EHTokUint4x1:
case EHTokUint4x2:
case EHTokUint4x3:
case EHTokUint4x4:
case EHTokFloat1x1:
case EHTokFloat1x2:
case EHTokFloat1x3: