mirror of
https://github.com/RPCS3/glslang.git
synced 2025-01-02 00:18:33 +00:00
307b6507b3
HLSL allows several variables to be declared. There are packing rules involved: e.g, a float3 and a float1 can be packed into a single array[4], while for a float3 and another float3, the second one will skip the third array entry to avoid straddling This is implements that ability. Because there can be multiple variables involved, and the final output array will often be a different type altogether (to fuse the values into a single destination), a new variable is synthesized, unlike the prior clip/cull support which used the declared variable. The new variable name is taken from one of the declared ones, so the old tests are unchanged. Several new tests are added to test various packing scenarios. Only two semantic IDs are supported: 0, and 1, per HLSL rules. This is encapsulated in static const int maxClipCullRegs = 2; and the algorithm (probably :) ) generalizes to larger values, although there are a few issues around how HLSL would pack (e.g, would 4 scalars be packed into a single HLSL float4 out reg? Probably, and this algorithm assumes so).
890 lines
35 KiB
C++
Executable File
890 lines
35 KiB
C++
Executable File
//
|
|
// Copyright (C) 2016 Google, Inc.
|
|
// Copyright (C) 2016 LunarG, Inc.
|
|
//
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
//
|
|
// Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
//
|
|
// Redistributions in binary form must reproduce the above
|
|
// copyright notice, this list of conditions and the following
|
|
// disclaimer in the documentation and/or other materials provided
|
|
// with the distribution.
|
|
//
|
|
// Neither the name of Google, Inc., nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
// COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
|
|
//
|
|
// HLSL scanning, leveraging the scanning done by the preprocessor.
|
|
//
|
|
|
|
#include <cstring>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
|
|
#include "../glslang/Include/Types.h"
|
|
#include "../glslang/MachineIndependent/SymbolTable.h"
|
|
#include "../glslang/MachineIndependent/ParseHelper.h"
|
|
#include "hlslScanContext.h"
|
|
#include "hlslTokens.h"
|
|
|
|
// preprocessor includes
|
|
#include "../glslang/MachineIndependent/preprocessor/PpContext.h"
|
|
#include "../glslang/MachineIndependent/preprocessor/PpTokens.h"
|
|
|
|
namespace {
|
|
|
|
struct str_eq
|
|
{
|
|
bool operator()(const char* lhs, const char* rhs) const
|
|
{
|
|
return strcmp(lhs, rhs) == 0;
|
|
}
|
|
};
|
|
|
|
struct str_hash
|
|
{
|
|
size_t operator()(const char* str) const
|
|
{
|
|
// djb2
|
|
unsigned long hash = 5381;
|
|
int c;
|
|
|
|
while ((c = *str++) != 0)
|
|
hash = ((hash << 5) + hash) + c;
|
|
|
|
return hash;
|
|
}
|
|
};
|
|
|
|
// A single global usable by all threads, by all versions, by all languages.
|
|
// 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;
|
|
|
|
};
|
|
|
|
namespace glslang {
|
|
|
|
void HlslScanContext::fillInKeywordMap()
|
|
{
|
|
if (KeywordMap != nullptr) {
|
|
// this is really an error, as this should called only once per process
|
|
// but, the only risk is if two threads called simultaneously
|
|
return;
|
|
}
|
|
KeywordMap = new std::unordered_map<const char*, EHlslTokenClass, str_hash, str_eq>;
|
|
|
|
(*KeywordMap)["static"] = EHTokStatic;
|
|
(*KeywordMap)["const"] = EHTokConst;
|
|
(*KeywordMap)["unorm"] = EHTokUnorm;
|
|
(*KeywordMap)["snorm"] = EHTokSNorm;
|
|
(*KeywordMap)["extern"] = EHTokExtern;
|
|
(*KeywordMap)["uniform"] = EHTokUniform;
|
|
(*KeywordMap)["volatile"] = EHTokVolatile;
|
|
(*KeywordMap)["precise"] = EHTokPrecise;
|
|
(*KeywordMap)["shared"] = EHTokShared;
|
|
(*KeywordMap)["groupshared"] = EHTokGroupShared;
|
|
(*KeywordMap)["linear"] = EHTokLinear;
|
|
(*KeywordMap)["centroid"] = EHTokCentroid;
|
|
(*KeywordMap)["nointerpolation"] = EHTokNointerpolation;
|
|
(*KeywordMap)["noperspective"] = EHTokNoperspective;
|
|
(*KeywordMap)["sample"] = EHTokSample;
|
|
(*KeywordMap)["row_major"] = EHTokRowMajor;
|
|
(*KeywordMap)["column_major"] = EHTokColumnMajor;
|
|
(*KeywordMap)["packoffset"] = EHTokPackOffset;
|
|
(*KeywordMap)["in"] = EHTokIn;
|
|
(*KeywordMap)["out"] = EHTokOut;
|
|
(*KeywordMap)["inout"] = EHTokInOut;
|
|
(*KeywordMap)["layout"] = EHTokLayout;
|
|
(*KeywordMap)["globallycoherent"] = EHTokGloballyCoherent;
|
|
(*KeywordMap)["inline"] = EHTokInline;
|
|
|
|
(*KeywordMap)["point"] = EHTokPoint;
|
|
(*KeywordMap)["line"] = EHTokLine;
|
|
(*KeywordMap)["triangle"] = EHTokTriangle;
|
|
(*KeywordMap)["lineadj"] = EHTokLineAdj;
|
|
(*KeywordMap)["triangleadj"] = EHTokTriangleAdj;
|
|
|
|
(*KeywordMap)["PointStream"] = EHTokPointStream;
|
|
(*KeywordMap)["LineStream"] = EHTokLineStream;
|
|
(*KeywordMap)["TriangleStream"] = EHTokTriangleStream;
|
|
|
|
(*KeywordMap)["InputPatch"] = EHTokInputPatch;
|
|
(*KeywordMap)["OutputPatch"] = EHTokOutputPatch;
|
|
|
|
(*KeywordMap)["Buffer"] = EHTokBuffer;
|
|
(*KeywordMap)["vector"] = EHTokVector;
|
|
(*KeywordMap)["matrix"] = EHTokMatrix;
|
|
|
|
(*KeywordMap)["void"] = EHTokVoid;
|
|
(*KeywordMap)["string"] = EHTokString;
|
|
(*KeywordMap)["bool"] = EHTokBool;
|
|
(*KeywordMap)["int"] = EHTokInt;
|
|
(*KeywordMap)["uint"] = EHTokUint;
|
|
(*KeywordMap)["dword"] = EHTokDword;
|
|
(*KeywordMap)["half"] = EHTokHalf;
|
|
(*KeywordMap)["float"] = EHTokFloat;
|
|
(*KeywordMap)["double"] = EHTokDouble;
|
|
(*KeywordMap)["min16float"] = EHTokMin16float;
|
|
(*KeywordMap)["min10float"] = EHTokMin10float;
|
|
(*KeywordMap)["min16int"] = EHTokMin16int;
|
|
(*KeywordMap)["min12int"] = EHTokMin12int;
|
|
(*KeywordMap)["min16uint"] = EHTokMin16uint;
|
|
|
|
(*KeywordMap)["bool1"] = EHTokBool1;
|
|
(*KeywordMap)["bool2"] = EHTokBool2;
|
|
(*KeywordMap)["bool3"] = EHTokBool3;
|
|
(*KeywordMap)["bool4"] = EHTokBool4;
|
|
(*KeywordMap)["float1"] = EHTokFloat1;
|
|
(*KeywordMap)["float2"] = EHTokFloat2;
|
|
(*KeywordMap)["float3"] = EHTokFloat3;
|
|
(*KeywordMap)["float4"] = EHTokFloat4;
|
|
(*KeywordMap)["int1"] = EHTokInt1;
|
|
(*KeywordMap)["int2"] = EHTokInt2;
|
|
(*KeywordMap)["int3"] = EHTokInt3;
|
|
(*KeywordMap)["int4"] = EHTokInt4;
|
|
(*KeywordMap)["double1"] = EHTokDouble1;
|
|
(*KeywordMap)["double2"] = EHTokDouble2;
|
|
(*KeywordMap)["double3"] = EHTokDouble3;
|
|
(*KeywordMap)["double4"] = EHTokDouble4;
|
|
(*KeywordMap)["uint1"] = EHTokUint1;
|
|
(*KeywordMap)["uint2"] = EHTokUint2;
|
|
(*KeywordMap)["uint3"] = EHTokUint3;
|
|
(*KeywordMap)["uint4"] = EHTokUint4;
|
|
|
|
(*KeywordMap)["half1"] = EHTokHalf1;
|
|
(*KeywordMap)["half2"] = EHTokHalf2;
|
|
(*KeywordMap)["half3"] = EHTokHalf3;
|
|
(*KeywordMap)["half4"] = EHTokHalf4;
|
|
(*KeywordMap)["min16float1"] = EHTokMin16float1;
|
|
(*KeywordMap)["min16float2"] = EHTokMin16float2;
|
|
(*KeywordMap)["min16float3"] = EHTokMin16float3;
|
|
(*KeywordMap)["min16float4"] = EHTokMin16float4;
|
|
(*KeywordMap)["min10float1"] = EHTokMin10float1;
|
|
(*KeywordMap)["min10float2"] = EHTokMin10float2;
|
|
(*KeywordMap)["min10float3"] = EHTokMin10float3;
|
|
(*KeywordMap)["min10float4"] = EHTokMin10float4;
|
|
(*KeywordMap)["min16int1"] = EHTokMin16int1;
|
|
(*KeywordMap)["min16int2"] = EHTokMin16int2;
|
|
(*KeywordMap)["min16int3"] = EHTokMin16int3;
|
|
(*KeywordMap)["min16int4"] = EHTokMin16int4;
|
|
(*KeywordMap)["min12int1"] = EHTokMin12int1;
|
|
(*KeywordMap)["min12int2"] = EHTokMin12int2;
|
|
(*KeywordMap)["min12int3"] = EHTokMin12int3;
|
|
(*KeywordMap)["min12int4"] = EHTokMin12int4;
|
|
(*KeywordMap)["min16uint1"] = EHTokMin16uint1;
|
|
(*KeywordMap)["min16uint2"] = EHTokMin16uint2;
|
|
(*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;
|
|
(*KeywordMap)["int1x4"] = EHTokInt1x4;
|
|
(*KeywordMap)["int2x1"] = EHTokInt2x1;
|
|
(*KeywordMap)["int2x2"] = EHTokInt2x2;
|
|
(*KeywordMap)["int2x3"] = EHTokInt2x3;
|
|
(*KeywordMap)["int2x4"] = EHTokInt2x4;
|
|
(*KeywordMap)["int3x1"] = EHTokInt3x1;
|
|
(*KeywordMap)["int3x2"] = EHTokInt3x2;
|
|
(*KeywordMap)["int3x3"] = EHTokInt3x3;
|
|
(*KeywordMap)["int3x4"] = EHTokInt3x4;
|
|
(*KeywordMap)["int4x1"] = EHTokInt4x1;
|
|
(*KeywordMap)["int4x2"] = EHTokInt4x2;
|
|
(*KeywordMap)["int4x3"] = EHTokInt4x3;
|
|
(*KeywordMap)["int4x4"] = EHTokInt4x4;
|
|
(*KeywordMap)["uint1x1"] = EHTokUint1x1;
|
|
(*KeywordMap)["uint1x2"] = EHTokUint1x2;
|
|
(*KeywordMap)["uint1x3"] = EHTokUint1x3;
|
|
(*KeywordMap)["uint1x4"] = EHTokUint1x4;
|
|
(*KeywordMap)["uint2x1"] = EHTokUint2x1;
|
|
(*KeywordMap)["uint2x2"] = EHTokUint2x2;
|
|
(*KeywordMap)["uint2x3"] = EHTokUint2x3;
|
|
(*KeywordMap)["uint2x4"] = EHTokUint2x4;
|
|
(*KeywordMap)["uint3x1"] = EHTokUint3x1;
|
|
(*KeywordMap)["uint3x2"] = EHTokUint3x2;
|
|
(*KeywordMap)["uint3x3"] = EHTokUint3x3;
|
|
(*KeywordMap)["uint3x4"] = EHTokUint3x4;
|
|
(*KeywordMap)["uint4x1"] = EHTokUint4x1;
|
|
(*KeywordMap)["uint4x2"] = EHTokUint4x2;
|
|
(*KeywordMap)["uint4x3"] = EHTokUint4x3;
|
|
(*KeywordMap)["uint4x4"] = EHTokUint4x4;
|
|
(*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)["float1x1"] = EHTokFloat1x1;
|
|
(*KeywordMap)["float1x2"] = EHTokFloat1x2;
|
|
(*KeywordMap)["float1x3"] = EHTokFloat1x3;
|
|
(*KeywordMap)["float1x4"] = EHTokFloat1x4;
|
|
(*KeywordMap)["float2x1"] = EHTokFloat2x1;
|
|
(*KeywordMap)["float2x2"] = EHTokFloat2x2;
|
|
(*KeywordMap)["float2x3"] = EHTokFloat2x3;
|
|
(*KeywordMap)["float2x4"] = EHTokFloat2x4;
|
|
(*KeywordMap)["float3x1"] = EHTokFloat3x1;
|
|
(*KeywordMap)["float3x2"] = EHTokFloat3x2;
|
|
(*KeywordMap)["float3x3"] = EHTokFloat3x3;
|
|
(*KeywordMap)["float3x4"] = EHTokFloat3x4;
|
|
(*KeywordMap)["float4x1"] = EHTokFloat4x1;
|
|
(*KeywordMap)["float4x2"] = EHTokFloat4x2;
|
|
(*KeywordMap)["float4x3"] = EHTokFloat4x3;
|
|
(*KeywordMap)["float4x4"] = EHTokFloat4x4;
|
|
(*KeywordMap)["half1x1"] = EHTokHalf1x1;
|
|
(*KeywordMap)["half1x2"] = EHTokHalf1x2;
|
|
(*KeywordMap)["half1x3"] = EHTokHalf1x3;
|
|
(*KeywordMap)["half1x4"] = EHTokHalf1x4;
|
|
(*KeywordMap)["half2x1"] = EHTokHalf2x1;
|
|
(*KeywordMap)["half2x2"] = EHTokHalf2x2;
|
|
(*KeywordMap)["half2x3"] = EHTokHalf2x3;
|
|
(*KeywordMap)["half2x4"] = EHTokHalf2x4;
|
|
(*KeywordMap)["half3x1"] = EHTokHalf3x1;
|
|
(*KeywordMap)["half3x2"] = EHTokHalf3x2;
|
|
(*KeywordMap)["half3x3"] = EHTokHalf3x3;
|
|
(*KeywordMap)["half3x4"] = EHTokHalf3x4;
|
|
(*KeywordMap)["half4x1"] = EHTokHalf4x1;
|
|
(*KeywordMap)["half4x2"] = EHTokHalf4x2;
|
|
(*KeywordMap)["half4x3"] = EHTokHalf4x3;
|
|
(*KeywordMap)["half4x4"] = EHTokHalf4x4;
|
|
(*KeywordMap)["double1x1"] = EHTokDouble1x1;
|
|
(*KeywordMap)["double1x2"] = EHTokDouble1x2;
|
|
(*KeywordMap)["double1x3"] = EHTokDouble1x3;
|
|
(*KeywordMap)["double1x4"] = EHTokDouble1x4;
|
|
(*KeywordMap)["double2x1"] = EHTokDouble2x1;
|
|
(*KeywordMap)["double2x2"] = EHTokDouble2x2;
|
|
(*KeywordMap)["double2x3"] = EHTokDouble2x3;
|
|
(*KeywordMap)["double2x4"] = EHTokDouble2x4;
|
|
(*KeywordMap)["double3x1"] = EHTokDouble3x1;
|
|
(*KeywordMap)["double3x2"] = EHTokDouble3x2;
|
|
(*KeywordMap)["double3x3"] = EHTokDouble3x3;
|
|
(*KeywordMap)["double3x4"] = EHTokDouble3x4;
|
|
(*KeywordMap)["double4x1"] = EHTokDouble4x1;
|
|
(*KeywordMap)["double4x2"] = EHTokDouble4x2;
|
|
(*KeywordMap)["double4x3"] = EHTokDouble4x3;
|
|
(*KeywordMap)["double4x4"] = EHTokDouble4x4;
|
|
|
|
(*KeywordMap)["sampler"] = EHTokSampler;
|
|
(*KeywordMap)["sampler1D"] = EHTokSampler1d;
|
|
(*KeywordMap)["sampler2D"] = EHTokSampler2d;
|
|
(*KeywordMap)["sampler3D"] = EHTokSampler3d;
|
|
(*KeywordMap)["samplerCube"] = EHTokSamplerCube;
|
|
(*KeywordMap)["sampler_state"] = EHTokSamplerState;
|
|
(*KeywordMap)["SamplerState"] = EHTokSamplerState;
|
|
(*KeywordMap)["SamplerComparisonState"] = EHTokSamplerComparisonState;
|
|
(*KeywordMap)["texture"] = EHTokTexture;
|
|
(*KeywordMap)["Texture1D"] = EHTokTexture1d;
|
|
(*KeywordMap)["Texture1DArray"] = EHTokTexture1darray;
|
|
(*KeywordMap)["Texture2D"] = EHTokTexture2d;
|
|
(*KeywordMap)["Texture2DArray"] = EHTokTexture2darray;
|
|
(*KeywordMap)["Texture3D"] = EHTokTexture3d;
|
|
(*KeywordMap)["TextureCube"] = EHTokTextureCube;
|
|
(*KeywordMap)["TextureCubeArray"] = EHTokTextureCubearray;
|
|
(*KeywordMap)["Texture2DMS"] = EHTokTexture2DMS;
|
|
(*KeywordMap)["Texture2DMSArray"] = EHTokTexture2DMSarray;
|
|
(*KeywordMap)["RWTexture1D"] = EHTokRWTexture1d;
|
|
(*KeywordMap)["RWTexture1DArray"] = EHTokRWTexture1darray;
|
|
(*KeywordMap)["RWTexture2D"] = EHTokRWTexture2d;
|
|
(*KeywordMap)["RWTexture2DArray"] = EHTokRWTexture2darray;
|
|
(*KeywordMap)["RWTexture3D"] = EHTokRWTexture3d;
|
|
(*KeywordMap)["RWBuffer"] = EHTokRWBuffer;
|
|
|
|
(*KeywordMap)["AppendStructuredBuffer"] = EHTokAppendStructuredBuffer;
|
|
(*KeywordMap)["ByteAddressBuffer"] = EHTokByteAddressBuffer;
|
|
(*KeywordMap)["ConsumeStructuredBuffer"] = EHTokConsumeStructuredBuffer;
|
|
(*KeywordMap)["RWByteAddressBuffer"] = EHTokRWByteAddressBuffer;
|
|
(*KeywordMap)["RWStructuredBuffer"] = EHTokRWStructuredBuffer;
|
|
(*KeywordMap)["StructuredBuffer"] = EHTokStructuredBuffer;
|
|
|
|
(*KeywordMap)["class"] = EHTokClass;
|
|
(*KeywordMap)["struct"] = EHTokStruct;
|
|
(*KeywordMap)["cbuffer"] = EHTokCBuffer;
|
|
(*KeywordMap)["ConstantBuffer"] = EHTokConstantBuffer;
|
|
(*KeywordMap)["tbuffer"] = EHTokTBuffer;
|
|
(*KeywordMap)["typedef"] = EHTokTypedef;
|
|
(*KeywordMap)["this"] = EHTokThis;
|
|
(*KeywordMap)["namespace"] = EHTokNamespace;
|
|
|
|
(*KeywordMap)["true"] = EHTokBoolConstant;
|
|
(*KeywordMap)["false"] = EHTokBoolConstant;
|
|
|
|
(*KeywordMap)["for"] = EHTokFor;
|
|
(*KeywordMap)["do"] = EHTokDo;
|
|
(*KeywordMap)["while"] = EHTokWhile;
|
|
(*KeywordMap)["break"] = EHTokBreak;
|
|
(*KeywordMap)["continue"] = EHTokContinue;
|
|
(*KeywordMap)["if"] = EHTokIf;
|
|
(*KeywordMap)["else"] = EHTokElse;
|
|
(*KeywordMap)["discard"] = EHTokDiscard;
|
|
(*KeywordMap)["return"] = EHTokReturn;
|
|
(*KeywordMap)["switch"] = EHTokSwitch;
|
|
(*KeywordMap)["case"] = EHTokCase;
|
|
(*KeywordMap)["default"] = EHTokDefault;
|
|
|
|
// TODO: get correct set here
|
|
ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
|
|
|
|
ReservedSet->insert("auto");
|
|
ReservedSet->insert("catch");
|
|
ReservedSet->insert("char");
|
|
ReservedSet->insert("const_cast");
|
|
ReservedSet->insert("enum");
|
|
ReservedSet->insert("explicit");
|
|
ReservedSet->insert("friend");
|
|
ReservedSet->insert("goto");
|
|
ReservedSet->insert("long");
|
|
ReservedSet->insert("mutable");
|
|
ReservedSet->insert("new");
|
|
ReservedSet->insert("operator");
|
|
ReservedSet->insert("private");
|
|
ReservedSet->insert("protected");
|
|
ReservedSet->insert("public");
|
|
ReservedSet->insert("reinterpret_cast");
|
|
ReservedSet->insert("short");
|
|
ReservedSet->insert("signed");
|
|
ReservedSet->insert("sizeof");
|
|
ReservedSet->insert("static_cast");
|
|
ReservedSet->insert("template");
|
|
ReservedSet->insert("throw");
|
|
ReservedSet->insert("try");
|
|
ReservedSet->insert("typename");
|
|
ReservedSet->insert("union");
|
|
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_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"] = EbvFragStencilRef;
|
|
}
|
|
|
|
void HlslScanContext::deleteKeywordMap()
|
|
{
|
|
delete KeywordMap;
|
|
KeywordMap = nullptr;
|
|
delete ReservedSet;
|
|
ReservedSet = nullptr;
|
|
delete SemanticMap;
|
|
SemanticMap = nullptr;
|
|
}
|
|
|
|
// 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 char* upperCase)
|
|
{
|
|
auto it = SemanticMap->find(upperCase);
|
|
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.
|
|
// Return 0 (EndOfTokens) on end of input.
|
|
//
|
|
EHlslTokenClass HlslScanContext::tokenizeClass(HlslToken& token)
|
|
{
|
|
do {
|
|
parserToken = &token;
|
|
TPpToken ppToken;
|
|
int token = ppContext.tokenize(ppToken);
|
|
if (token == EndOfInput)
|
|
return EHTokNone;
|
|
|
|
tokenText = ppToken.name;
|
|
loc = ppToken.loc;
|
|
parserToken->loc = loc;
|
|
switch (token) {
|
|
case ';': return EHTokSemicolon;
|
|
case ',': return EHTokComma;
|
|
case ':': return EHTokColon;
|
|
case '=': return EHTokAssign;
|
|
case '(': return EHTokLeftParen;
|
|
case ')': return EHTokRightParen;
|
|
case '.': return EHTokDot;
|
|
case '!': return EHTokBang;
|
|
case '-': return EHTokDash;
|
|
case '~': return EHTokTilde;
|
|
case '+': return EHTokPlus;
|
|
case '*': return EHTokStar;
|
|
case '/': return EHTokSlash;
|
|
case '%': return EHTokPercent;
|
|
case '<': return EHTokLeftAngle;
|
|
case '>': return EHTokRightAngle;
|
|
case '|': return EHTokVerticalBar;
|
|
case '^': return EHTokCaret;
|
|
case '&': return EHTokAmpersand;
|
|
case '?': return EHTokQuestion;
|
|
case '[': return EHTokLeftBracket;
|
|
case ']': return EHTokRightBracket;
|
|
case '{': return EHTokLeftBrace;
|
|
case '}': return EHTokRightBrace;
|
|
case '\\':
|
|
parseContext.error(loc, "illegal use of escape character", "\\", "");
|
|
break;
|
|
|
|
case PPAtomAddAssign: return EHTokAddAssign;
|
|
case PPAtomSubAssign: return EHTokSubAssign;
|
|
case PPAtomMulAssign: return EHTokMulAssign;
|
|
case PPAtomDivAssign: return EHTokDivAssign;
|
|
case PPAtomModAssign: return EHTokModAssign;
|
|
|
|
case PpAtomRight: return EHTokRightOp;
|
|
case PpAtomLeft: return EHTokLeftOp;
|
|
|
|
case PpAtomRightAssign: return EHTokRightAssign;
|
|
case PpAtomLeftAssign: return EHTokLeftAssign;
|
|
case PpAtomAndAssign: return EHTokAndAssign;
|
|
case PpAtomOrAssign: return EHTokOrAssign;
|
|
case PpAtomXorAssign: return EHTokXorAssign;
|
|
|
|
case PpAtomAnd: return EHTokAndOp;
|
|
case PpAtomOr: return EHTokOrOp;
|
|
case PpAtomXor: return EHTokXorOp;
|
|
|
|
case PpAtomEQ: return EHTokEqOp;
|
|
case PpAtomGE: return EHTokGeOp;
|
|
case PpAtomNE: return EHTokNeOp;
|
|
case PpAtomLE: return EHTokLeOp;
|
|
|
|
case PpAtomDecrement: return EHTokDecOp;
|
|
case PpAtomIncrement: return EHTokIncOp;
|
|
|
|
case PpAtomColonColon: return EHTokColonColon;
|
|
|
|
case PpAtomConstInt: parserToken->i = ppToken.ival; return EHTokIntConstant;
|
|
case PpAtomConstUint: parserToken->i = ppToken.ival; return EHTokUintConstant;
|
|
case PpAtomConstFloat: parserToken->d = ppToken.dval; return EHTokFloatConstant;
|
|
case PpAtomConstDouble: parserToken->d = ppToken.dval; return EHTokDoubleConstant;
|
|
case PpAtomIdentifier:
|
|
{
|
|
EHlslTokenClass token = tokenizeIdentifier();
|
|
return token;
|
|
}
|
|
|
|
case PpAtomConstString: {
|
|
parserToken->string = NewPoolTString(tokenText);
|
|
return EHTokStringConstant;
|
|
}
|
|
|
|
case EndOfInput: return EHTokNone;
|
|
|
|
default:
|
|
char buf[2];
|
|
buf[0] = (char)token;
|
|
buf[1] = 0;
|
|
parseContext.error(loc, "unexpected token", buf, "");
|
|
break;
|
|
}
|
|
} while (true);
|
|
}
|
|
|
|
EHlslTokenClass HlslScanContext::tokenizeIdentifier()
|
|
{
|
|
if (ReservedSet->find(tokenText) != ReservedSet->end())
|
|
return reservedWord();
|
|
|
|
auto it = KeywordMap->find(tokenText);
|
|
if (it == KeywordMap->end()) {
|
|
// Should have an identifier of some sort
|
|
return identifierOrType();
|
|
}
|
|
keyword = it->second;
|
|
|
|
switch (keyword) {
|
|
|
|
// qualifiers
|
|
case EHTokStatic:
|
|
case EHTokConst:
|
|
case EHTokSNorm:
|
|
case EHTokUnorm:
|
|
case EHTokExtern:
|
|
case EHTokUniform:
|
|
case EHTokVolatile:
|
|
case EHTokShared:
|
|
case EHTokGroupShared:
|
|
case EHTokLinear:
|
|
case EHTokCentroid:
|
|
case EHTokNointerpolation:
|
|
case EHTokNoperspective:
|
|
case EHTokSample:
|
|
case EHTokRowMajor:
|
|
case EHTokColumnMajor:
|
|
case EHTokPackOffset:
|
|
case EHTokIn:
|
|
case EHTokOut:
|
|
case EHTokInOut:
|
|
case EHTokPrecise:
|
|
case EHTokLayout:
|
|
case EHTokGloballyCoherent:
|
|
case EHTokInline:
|
|
return keyword;
|
|
|
|
// primitive types
|
|
case EHTokPoint:
|
|
case EHTokLine:
|
|
case EHTokTriangle:
|
|
case EHTokLineAdj:
|
|
case EHTokTriangleAdj:
|
|
return keyword;
|
|
|
|
// stream out types
|
|
case EHTokPointStream:
|
|
case EHTokLineStream:
|
|
case EHTokTriangleStream:
|
|
return keyword;
|
|
|
|
// Tessellation patches
|
|
case EHTokInputPatch:
|
|
case EHTokOutputPatch:
|
|
return keyword;
|
|
|
|
case EHTokBuffer:
|
|
case EHTokVector:
|
|
case EHTokMatrix:
|
|
return keyword;
|
|
|
|
// scalar types
|
|
case EHTokVoid:
|
|
case EHTokString:
|
|
case EHTokBool:
|
|
case EHTokInt:
|
|
case EHTokUint:
|
|
case EHTokDword:
|
|
case EHTokHalf:
|
|
case EHTokFloat:
|
|
case EHTokDouble:
|
|
case EHTokMin16float:
|
|
case EHTokMin10float:
|
|
case EHTokMin16int:
|
|
case EHTokMin12int:
|
|
case EHTokMin16uint:
|
|
|
|
// vector types
|
|
case EHTokBool1:
|
|
case EHTokBool2:
|
|
case EHTokBool3:
|
|
case EHTokBool4:
|
|
case EHTokFloat1:
|
|
case EHTokFloat2:
|
|
case EHTokFloat3:
|
|
case EHTokFloat4:
|
|
case EHTokInt1:
|
|
case EHTokInt2:
|
|
case EHTokInt3:
|
|
case EHTokInt4:
|
|
case EHTokDouble1:
|
|
case EHTokDouble2:
|
|
case EHTokDouble3:
|
|
case EHTokDouble4:
|
|
case EHTokUint1:
|
|
case EHTokUint2:
|
|
case EHTokUint3:
|
|
case EHTokUint4:
|
|
case EHTokHalf1:
|
|
case EHTokHalf2:
|
|
case EHTokHalf3:
|
|
case EHTokHalf4:
|
|
case EHTokMin16float1:
|
|
case EHTokMin16float2:
|
|
case EHTokMin16float3:
|
|
case EHTokMin16float4:
|
|
case EHTokMin10float1:
|
|
case EHTokMin10float2:
|
|
case EHTokMin10float3:
|
|
case EHTokMin10float4:
|
|
case EHTokMin16int1:
|
|
case EHTokMin16int2:
|
|
case EHTokMin16int3:
|
|
case EHTokMin16int4:
|
|
case EHTokMin12int1:
|
|
case EHTokMin12int2:
|
|
case EHTokMin12int3:
|
|
case EHTokMin12int4:
|
|
case EHTokMin16uint1:
|
|
case EHTokMin16uint2:
|
|
case EHTokMin16uint3:
|
|
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:
|
|
case EHTokInt1x4:
|
|
case EHTokInt2x1:
|
|
case EHTokInt2x2:
|
|
case EHTokInt2x3:
|
|
case EHTokInt2x4:
|
|
case EHTokInt3x1:
|
|
case EHTokInt3x2:
|
|
case EHTokInt3x3:
|
|
case EHTokInt3x4:
|
|
case EHTokInt4x1:
|
|
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:
|
|
case EHTokFloat1x4:
|
|
case EHTokFloat2x1:
|
|
case EHTokFloat2x2:
|
|
case EHTokFloat2x3:
|
|
case EHTokFloat2x4:
|
|
case EHTokFloat3x1:
|
|
case EHTokFloat3x2:
|
|
case EHTokFloat3x3:
|
|
case EHTokFloat3x4:
|
|
case EHTokFloat4x1:
|
|
case EHTokFloat4x2:
|
|
case EHTokFloat4x3:
|
|
case EHTokFloat4x4:
|
|
case EHTokHalf1x1:
|
|
case EHTokHalf1x2:
|
|
case EHTokHalf1x3:
|
|
case EHTokHalf1x4:
|
|
case EHTokHalf2x1:
|
|
case EHTokHalf2x2:
|
|
case EHTokHalf2x3:
|
|
case EHTokHalf2x4:
|
|
case EHTokHalf3x1:
|
|
case EHTokHalf3x2:
|
|
case EHTokHalf3x3:
|
|
case EHTokHalf3x4:
|
|
case EHTokHalf4x1:
|
|
case EHTokHalf4x2:
|
|
case EHTokHalf4x3:
|
|
case EHTokHalf4x4:
|
|
case EHTokDouble1x1:
|
|
case EHTokDouble1x2:
|
|
case EHTokDouble1x3:
|
|
case EHTokDouble1x4:
|
|
case EHTokDouble2x1:
|
|
case EHTokDouble2x2:
|
|
case EHTokDouble2x3:
|
|
case EHTokDouble2x4:
|
|
case EHTokDouble3x1:
|
|
case EHTokDouble3x2:
|
|
case EHTokDouble3x3:
|
|
case EHTokDouble3x4:
|
|
case EHTokDouble4x1:
|
|
case EHTokDouble4x2:
|
|
case EHTokDouble4x3:
|
|
case EHTokDouble4x4:
|
|
return keyword;
|
|
|
|
// texturing types
|
|
case EHTokSampler:
|
|
case EHTokSampler1d:
|
|
case EHTokSampler2d:
|
|
case EHTokSampler3d:
|
|
case EHTokSamplerCube:
|
|
case EHTokSamplerState:
|
|
case EHTokSamplerComparisonState:
|
|
case EHTokTexture:
|
|
case EHTokTexture1d:
|
|
case EHTokTexture1darray:
|
|
case EHTokTexture2d:
|
|
case EHTokTexture2darray:
|
|
case EHTokTexture3d:
|
|
case EHTokTextureCube:
|
|
case EHTokTextureCubearray:
|
|
case EHTokTexture2DMS:
|
|
case EHTokTexture2DMSarray:
|
|
case EHTokRWTexture1d:
|
|
case EHTokRWTexture1darray:
|
|
case EHTokRWTexture2d:
|
|
case EHTokRWTexture2darray:
|
|
case EHTokRWTexture3d:
|
|
case EHTokRWBuffer:
|
|
case EHTokAppendStructuredBuffer:
|
|
case EHTokByteAddressBuffer:
|
|
case EHTokConsumeStructuredBuffer:
|
|
case EHTokRWByteAddressBuffer:
|
|
case EHTokRWStructuredBuffer:
|
|
case EHTokStructuredBuffer:
|
|
return keyword;
|
|
|
|
// variable, user type, ...
|
|
case EHTokClass:
|
|
case EHTokStruct:
|
|
case EHTokTypedef:
|
|
case EHTokCBuffer:
|
|
case EHTokConstantBuffer:
|
|
case EHTokTBuffer:
|
|
case EHTokThis:
|
|
case EHTokNamespace:
|
|
return keyword;
|
|
|
|
case EHTokBoolConstant:
|
|
if (strcmp("true", tokenText) == 0)
|
|
parserToken->b = true;
|
|
else
|
|
parserToken->b = false;
|
|
return keyword;
|
|
|
|
// control flow
|
|
case EHTokFor:
|
|
case EHTokDo:
|
|
case EHTokWhile:
|
|
case EHTokBreak:
|
|
case EHTokContinue:
|
|
case EHTokIf:
|
|
case EHTokElse:
|
|
case EHTokDiscard:
|
|
case EHTokReturn:
|
|
case EHTokCase:
|
|
case EHTokSwitch:
|
|
case EHTokDefault:
|
|
return keyword;
|
|
|
|
default:
|
|
parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
|
|
return EHTokNone;
|
|
}
|
|
}
|
|
|
|
EHlslTokenClass HlslScanContext::identifierOrType()
|
|
{
|
|
parserToken->string = NewPoolTString(tokenText);
|
|
|
|
return EHTokIdentifier;
|
|
}
|
|
|
|
// Give an error for use of a reserved symbol.
|
|
// However, allow built-in declarations to use reserved words, to allow
|
|
// extension support before the extension is enabled.
|
|
EHlslTokenClass HlslScanContext::reservedWord()
|
|
{
|
|
if (! parseContext.symbolTable.atBuiltInLevel())
|
|
parseContext.error(loc, "Reserved word.", tokenText, "", "");
|
|
|
|
return EHTokNone;
|
|
}
|
|
|
|
} // end namespace glslang
|