- update glslang to 7.11.3113 (stable release February 8, 2019). This fixes the SPIR-V validation error reported for the shadowmap shader

This commit is contained in:
Magnus Norddahl 2019-04-15 04:53:43 +02:00
parent b5e0451805
commit 06222a1fbf
59 changed files with 12135 additions and 5836 deletions

View file

@ -106,6 +106,20 @@ set(HEADERS
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) # WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# set(BISON_GLSLParser_OUTPUT_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp) # set(BISON_GLSLParser_OUTPUT_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/MachineIndependent/glslang_tab.cpp)
# Precompiled header macro. Parameters are source file list and filename for pch cpp file.
macro(glslang_pch SRCS PCHCPP)
if(MSVC AND CMAKE_GENERATOR MATCHES "^Visual Studio")
set(PCH_NAME "$(IntDir)\\pch.pch")
# make source files use/depend on PCH_NAME
set_source_files_properties(${${SRCS}} PROPERTIES COMPILE_FLAGS "/Yupch.h /FIpch.h /Fp${PCH_NAME} /Zm300" OBJECT_DEPENDS "${PCH_NAME}")
# make PCHCPP file compile and generate PCH_NAME
set_source_files_properties(${PCHCPP} PROPERTIES COMPILE_FLAGS "/Ycpch.h /Fp${PCH_NAME} /Zm300" OBJECT_OUTPUTS "${PCH_NAME}")
list(APPEND ${SRCS} "${PCHCPP}")
endif()
endmacro(glslang_pch)
glslang_pch(SOURCES MachineIndependent/pch.cpp)
add_library(glslang ${LIB_TYPE} ${BISON_GLSLParser_OUTPUT_SOURCE} ${SOURCES} ${HEADERS}) add_library(glslang ${LIB_TYPE} ${BISON_GLSLParser_OUTPUT_SOURCE} ${SOURCES} ${HEADERS})
set_property(TARGET glslang PROPERTY FOLDER glslang) set_property(TARGET glslang PROPERTY FOLDER glslang)
set_property(TARGET glslang PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET glslang PROPERTY POSITION_INDEPENDENT_CODE ON)

View file

@ -62,6 +62,12 @@ enum TBasicType {
EbtStruct, EbtStruct,
EbtBlock, EbtBlock,
#ifdef NV_EXTENSIONS
EbtAccStructNV,
#endif
EbtReference,
// HLSL types that live only temporarily. // HLSL types that live only temporarily.
EbtString, EbtString,
@ -88,6 +94,14 @@ enum TStorageQualifier {
EvqBuffer, // read/write, shared with app EvqBuffer, // read/write, shared with app
EvqShared, // compute shader's read/write 'shared' qualifier EvqShared, // compute shader's read/write 'shared' qualifier
#ifdef NV_EXTENSIONS
EvqPayloadNV,
EvqPayloadInNV,
EvqHitAttrNV,
EvqCallableDataNV,
EvqCallableDataInNV,
#endif
// parameters // parameters
EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter
@ -220,6 +234,9 @@ enum TBuiltInVariable {
EbvViewIndex, EbvViewIndex,
EbvDeviceIndex, EbvDeviceIndex,
EbvFragSizeEXT,
EbvFragInvocationCountEXT,
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
EbvViewportMaskNV, EbvViewportMaskNV,
EbvSecondaryPositionNV, EbvSecondaryPositionNV,
@ -227,6 +244,33 @@ enum TBuiltInVariable {
EbvPositionPerViewNV, EbvPositionPerViewNV,
EbvViewportMaskPerViewNV, EbvViewportMaskPerViewNV,
EbvFragFullyCoveredNV, EbvFragFullyCoveredNV,
EbvFragmentSizeNV,
EbvInvocationsPerPixelNV,
// raytracing
EbvLaunchIdNV,
EbvLaunchSizeNV,
EbvInstanceCustomIndexNV,
EbvWorldRayOriginNV,
EbvWorldRayDirectionNV,
EbvObjectRayOriginNV,
EbvObjectRayDirectionNV,
EbvRayTminNV,
EbvRayTmaxNV,
EbvHitTNV,
EbvHitKindNV,
EbvObjectToWorldNV,
EbvWorldToObjectNV,
EbvIncomingRayFlagsNV,
EbvBaryCoordNV,
EbvBaryCoordNoPerspNV,
EbvTaskCountNV,
EbvPrimitiveCountNV,
EbvPrimitiveIndicesNV,
EbvClipDistancePerViewNV,
EbvCullDistancePerViewNV,
EbvLayerPerViewNV,
EbvMeshViewCountNV,
EbvMeshViewIndicesNV,
#endif #endif
// HLSL built-ins that live only temporarily, until they get remapped // HLSL built-ins that live only temporarily, until they get remapped
@ -273,6 +317,13 @@ __inline const char* GetStorageQualifierString(TStorageQualifier q)
case EvqPointCoord: return "gl_PointCoord"; break; case EvqPointCoord: return "gl_PointCoord"; break;
case EvqFragColor: return "fragColor"; break; case EvqFragColor: return "fragColor"; break;
case EvqFragDepth: return "gl_FragDepth"; break; case EvqFragDepth: return "gl_FragDepth"; break;
#ifdef NV_EXTENSIONS
case EvqPayloadNV: return "rayPayloadNV"; break;
case EvqPayloadInNV: return "rayPayloadInNV"; break;
case EvqHitAttrNV: return "hitAttributeNV"; break;
case EvqCallableDataNV: return "callableDataNV"; break;
case EvqCallableDataInNV: return "callableDataInNV"; break;
#endif
default: return "unknown qualifier"; default: return "unknown qualifier";
} }
} }
@ -358,6 +409,9 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvViewIndex: return "ViewIndex"; case EbvViewIndex: return "ViewIndex";
case EbvDeviceIndex: return "DeviceIndex"; case EbvDeviceIndex: return "DeviceIndex";
case EbvFragSizeEXT: return "FragSizeEXT";
case EbvFragInvocationCountEXT: return "FragInvocationCountEXT";
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
case EbvViewportMaskNV: return "ViewportMaskNV"; case EbvViewportMaskNV: return "ViewportMaskNV";
case EbvSecondaryPositionNV: return "SecondaryPositionNV"; case EbvSecondaryPositionNV: return "SecondaryPositionNV";
@ -365,6 +419,33 @@ __inline const char* GetBuiltInVariableString(TBuiltInVariable v)
case EbvPositionPerViewNV: return "PositionPerViewNV"; case EbvPositionPerViewNV: return "PositionPerViewNV";
case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; case EbvViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
case EbvFragFullyCoveredNV: return "FragFullyCoveredNV"; case EbvFragFullyCoveredNV: return "FragFullyCoveredNV";
case EbvFragmentSizeNV: return "FragmentSizeNV";
case EbvInvocationsPerPixelNV: return "InvocationsPerPixelNV";
case EbvLaunchIdNV: return "LaunchIdNV";
case EbvLaunchSizeNV: return "LaunchSizeNV";
case EbvInstanceCustomIndexNV: return "InstanceCustomIndexNV";
case EbvWorldRayOriginNV: return "WorldRayOriginNV";
case EbvWorldRayDirectionNV: return "WorldRayDirectionNV";
case EbvObjectRayOriginNV: return "ObjectRayOriginNV";
case EbvObjectRayDirectionNV: return "ObjectRayDirectionNV";
case EbvRayTminNV: return "ObjectRayTminNV";
case EbvRayTmaxNV: return "ObjectRayTmaxNV";
case EbvHitTNV: return "HitTNV";
case EbvHitKindNV: return "HitKindNV";
case EbvIncomingRayFlagsNV: return "IncomingRayFlagsNV";
case EbvObjectToWorldNV: return "ObjectToWorldNV";
case EbvWorldToObjectNV: return "WorldToObjectNV";
case EbvBaryCoordNV: return "BaryCoordNV";
case EbvBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
case EbvTaskCountNV: return "TaskCountNV";
case EbvPrimitiveCountNV: return "PrimitiveCountNV";
case EbvPrimitiveIndicesNV: return "PrimitiveIndicesNV";
case EbvClipDistancePerViewNV: return "ClipDistancePerViewNV";
case EbvCullDistancePerViewNV: return "CullDistancePerViewNV";
case EbvLayerPerViewNV: return "LayerPerViewNV";
case EbvMeshViewCountNV: return "MeshViewCountNV";
case EbvMeshViewIndicesNV: return "MeshViewIndicesNV";
#endif #endif
default: return "unknown built-in variable"; default: return "unknown built-in variable";
} }

View file

@ -229,16 +229,29 @@ inline const TString String(const int i, const int /*base*/ = 10)
#endif #endif
struct TSourceLoc { struct TSourceLoc {
void init() { name = nullptr; string = 0; line = 0; column = 0; } void init()
{
name = nullptr; string = 0; line = 0; column = 0;
}
void init(int stringNum) { init(); string = stringNum; } void init(int stringNum) { init(); string = stringNum; }
// Returns the name if it exists. Otherwise, returns the string number. // Returns the name if it exists. Otherwise, returns the string number.
std::string getStringNameOrNum(bool quoteStringName = true) const std::string getStringNameOrNum(bool quoteStringName = true) const
{ {
if (name != nullptr) if (name != nullptr) {
return quoteStringName ? ("\"" + std::string(name) + "\"") : name; TString qstr = quoteStringName ? ("\"" + *name + "\"") : *name;
std::string ret_str(qstr.c_str());
return ret_str;
}
return std::to_string((long long)string); return std::to_string((long long)string);
} }
const char* name; // descriptive name for this string const char* getFilename() const
{
if (name == nullptr)
return nullptr;
return name->c_str();
}
const char* getFilenameStr() const { return name == nullptr ? "" : name->c_str(); }
TString* name; // descriptive name for this string, when a textual name is available, otherwise nullptr
int string; int string;
int line; int line;
int column; int column;

View file

@ -133,6 +133,15 @@ struct TBuiltInResource {
int maxCullDistances; int maxCullDistances;
int maxCombinedClipAndCullDistances; int maxCombinedClipAndCullDistances;
int maxSamples; int maxSamples;
int maxMeshOutputVerticesNV;
int maxMeshOutputPrimitivesNV;
int maxMeshWorkGroupSizeX_NV;
int maxMeshWorkGroupSizeY_NV;
int maxMeshWorkGroupSizeZ_NV;
int maxTaskWorkGroupSizeX_NV;
int maxTaskWorkGroupSizeY_NV;
int maxTaskWorkGroupSizeZ_NV;
int maxMeshViewCountNV;
TLimits limits; TLimits limits;
}; };

View file

@ -81,6 +81,7 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler bool combined : 1; // true means texture is combined with a sampler, false means texture with no sampler
bool sampler : 1; // true means a pure sampler, other fields should be clear() bool sampler : 1; // true means a pure sampler, other fields should be clear()
bool external : 1; // GL_OES_EGL_image_external bool external : 1; // GL_OES_EGL_image_external
bool yuv : 1; // GL_EXT_YUV_target
unsigned int vectorSize : 3; // vector return type size. unsigned int vectorSize : 3; // vector return type size.
// Some languages support structures as sample results. Storing the whole structure in the // Some languages support structures as sample results. Storing the whole structure in the
@ -116,6 +117,7 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
combined = false; combined = false;
sampler = false; sampler = false;
external = false; external = false;
yuv = false;
structReturnIndex = noReturnStruct; structReturnIndex = noReturnStruct;
// by default, returns a single vec4; // by default, returns a single vec4;
@ -186,6 +188,7 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
combined == right.combined && combined == right.combined &&
sampler == right.sampler && sampler == right.sampler &&
external == right.external && external == right.external &&
yuv == right.yuv &&
vectorSize == right.vectorSize && vectorSize == right.vectorSize &&
structReturnIndex == right.structReturnIndex; structReturnIndex == right.structReturnIndex;
} }
@ -233,6 +236,9 @@ struct TSampler { // misnomer now; includes images, textures without sampler,
s.append("ExternalOES"); s.append("ExternalOES");
return s; return s;
} }
if (yuv) {
return "__" + s + "External2DY2YEXT";
}
switch (dim) { switch (dim) {
case Esd1D: s.append("1D"); break; case Esd1D: s.append("1D"); break;
case Esd2D: s.append("2D"); break; case Esd2D: s.append("2D"); break;
@ -277,6 +283,7 @@ enum TLayoutPacking {
ElpStd140, ElpStd140,
ElpStd430, ElpStd430,
ElpPacked, ElpPacked,
ElpScalar,
ElpCount // If expanding, see bitfield width below ElpCount // If expanding, see bitfield width below
}; };
@ -456,12 +463,23 @@ public:
nopersp = false; nopersp = false;
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
explicitInterp = false; explicitInterp = false;
#endif
#ifdef NV_EXTENSIONS
pervertexNV = false;
perPrimitiveNV = false;
perViewNV = false;
perTaskNV = false;
#endif #endif
} }
void clearMemory() void clearMemory()
{ {
coherent = false; coherent = false;
devicecoherent = false;
queuefamilycoherent = false;
workgroupcoherent = false;
subgroupcoherent = false;
nonprivate = false;
volatil = false; volatil = false;
restrict = false; restrict = false;
readonly = false; readonly = false;
@ -495,10 +513,21 @@ public:
bool nopersp : 1; bool nopersp : 1;
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
bool explicitInterp : 1; bool explicitInterp : 1;
#endif
#ifdef NV_EXTENSIONS
bool pervertexNV : 1;
bool perPrimitiveNV : 1;
bool perViewNV : 1;
bool perTaskNV : 1;
#endif #endif
bool patch : 1; bool patch : 1;
bool sample : 1; bool sample : 1;
bool coherent : 1; bool coherent : 1;
bool devicecoherent : 1;
bool queuefamilycoherent : 1;
bool workgroupcoherent : 1;
bool subgroupcoherent : 1;
bool nonprivate : 1;
bool volatil : 1; bool volatil : 1;
bool restrict : 1; bool restrict : 1;
bool readonly : 1; bool readonly : 1;
@ -508,8 +537,18 @@ public:
bool isMemory() const bool isMemory() const
{ {
return coherent || volatil || restrict || readonly || writeonly; return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly || nonprivate;
} }
bool isMemoryQualifierImageAndSSBOOnly() const
{
return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || volatil || restrict || readonly || writeonly;
}
bool bufferReferenceNeedsVulkanMemoryModel() const
{
// include qualifiers that map to load/store availability/visibility/nonprivate memory access operands
return subgroupcoherent || workgroupcoherent || queuefamilycoherent || devicecoherent || coherent || nonprivate;
}
bool isInterpolation() const bool isInterpolation() const
{ {
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
@ -518,15 +557,21 @@ public:
return flat || smooth || nopersp; return flat || smooth || nopersp;
#endif #endif
} }
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
bool isExplicitInterpolation() const bool isExplicitInterpolation() const
{ {
return explicitInterp; return explicitInterp;
} }
#endif #endif
bool isAuxiliary() const bool isAuxiliary() const
{ {
#ifdef NV_EXTENSIONS
return centroid || patch || sample || pervertexNV;
#else
return centroid || patch || sample; return centroid || patch || sample;
#endif
} }
bool isPipeInput() const bool isPipeInput() const
@ -593,6 +638,33 @@ public:
} }
} }
bool isPerPrimitive() const
{
#ifdef NV_EXTENSIONS
return perPrimitiveNV;
#else
return false;
#endif
}
bool isPerView() const
{
#ifdef NV_EXTENSIONS
return perViewNV;
#else
return false;
#endif
}
bool isTaskMemory() const
{
#ifdef NV_EXTENSIONS
return perTaskNV;
#else
return false;
#endif
}
bool isIo() const bool isIo() const
{ {
switch (storage) { switch (storage) {
@ -616,6 +688,22 @@ public:
} }
} }
// non-built-in symbols that might link between compilation units
bool isLinkable() const
{
switch (storage) {
case EvqGlobal:
case EvqVaryingIn:
case EvqVaryingOut:
case EvqUniform:
case EvqBuffer:
case EvqShared:
return true;
default:
return false;
}
}
// True if this type of IO is supposed to be arrayed with extra level for per-vertex data // True if this type of IO is supposed to be arrayed with extra level for per-vertex data
bool isArrayedIo(EShLanguage language) const bool isArrayedIo(EShLanguage language) const
{ {
@ -626,6 +714,13 @@ public:
return ! patch && (isPipeInput() || isPipeOutput()); return ! patch && (isPipeInput() || isPipeOutput());
case EShLangTessEvaluation: case EShLangTessEvaluation:
return ! patch && isPipeInput(); return ! patch && isPipeInput();
#ifdef NV_EXTENSIONS
case EShLangFragment:
return pervertexNV && isPipeInput();
case EShLangMeshNV:
return ! perTaskNV && isPipeOutput();
#endif
default: default:
return false; return false;
} }
@ -637,13 +732,17 @@ public:
clearUniformLayout(); clearUniformLayout();
layoutPushConstant = false; layoutPushConstant = false;
layoutBufferReference = false;
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
layoutPassthrough = false; layoutPassthrough = false;
layoutViewportRelative = false; layoutViewportRelative = false;
// -2048 as the default value indicating layoutSecondaryViewportRelative is not set // -2048 as the default value indicating layoutSecondaryViewportRelative is not set
layoutSecondaryViewportRelativeOffset = -2048; layoutSecondaryViewportRelativeOffset = -2048;
layoutShaderRecordNV = false;
#endif #endif
layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd;
clearInterstageLayout(); clearInterstageLayout();
layoutSpecConstantId = layoutSpecConstantIdEnd; layoutSpecConstantId = layoutSpecConstantIdEnd;
@ -675,7 +774,11 @@ public:
hasAnyLocation() || hasAnyLocation() ||
hasStream() || hasStream() ||
hasFormat() || hasFormat() ||
layoutPushConstant; #ifdef NV_EXTENSIONS
layoutShaderRecordNV ||
#endif
layoutPushConstant ||
layoutBufferReference;
} }
bool hasLayout() const bool hasLayout() const
{ {
@ -687,47 +790,53 @@ public:
int layoutOffset; int layoutOffset;
int layoutAlign; int layoutAlign;
unsigned int layoutLocation :12; unsigned int layoutLocation : 12;
static const unsigned int layoutLocationEnd = 0xFFF; static const unsigned int layoutLocationEnd = 0xFFF;
unsigned int layoutComponent : 3; unsigned int layoutComponent : 3;
static const unsigned int layoutComponentEnd = 4; static const unsigned int layoutComponentEnd = 4;
unsigned int layoutSet : 7; unsigned int layoutSet : 7;
static const unsigned int layoutSetEnd = 0x3F; static const unsigned int layoutSetEnd = 0x3F;
unsigned int layoutBinding : 16; unsigned int layoutBinding : 16;
static const unsigned int layoutBindingEnd = 0xFFFF; static const unsigned int layoutBindingEnd = 0xFFFF;
unsigned int layoutIndex : 8; unsigned int layoutIndex : 8;
static const unsigned int layoutIndexEnd = 0xFF; static const unsigned int layoutIndexEnd = 0xFF;
unsigned int layoutStream : 8; unsigned int layoutStream : 8;
static const unsigned int layoutStreamEnd = 0xFF; static const unsigned int layoutStreamEnd = 0xFF;
unsigned int layoutXfbBuffer : 4; unsigned int layoutXfbBuffer : 4;
static const unsigned int layoutXfbBufferEnd = 0xF; static const unsigned int layoutXfbBufferEnd = 0xF;
unsigned int layoutXfbStride : 10; unsigned int layoutXfbStride : 14;
static const unsigned int layoutXfbStrideEnd = 0x3FF; static const unsigned int layoutXfbStrideEnd = 0x3FFF;
unsigned int layoutXfbOffset : 10; unsigned int layoutXfbOffset : 13;
static const unsigned int layoutXfbOffsetEnd = 0x3FF; static const unsigned int layoutXfbOffsetEnd = 0x1FFF;
unsigned int layoutAttachment : 8; // for input_attachment_index unsigned int layoutAttachment : 8; // for input_attachment_index
static const unsigned int layoutAttachmentEnd = 0XFF; static const unsigned int layoutAttachmentEnd = 0XFF;
unsigned int layoutSpecConstantId : 11; unsigned int layoutSpecConstantId : 11;
static const unsigned int layoutSpecConstantIdEnd = 0x7FF; static const unsigned int layoutSpecConstantIdEnd = 0x7FF;
TLayoutFormat layoutFormat : 8; // stored as log2 of the actual alignment value
unsigned int layoutBufferReferenceAlign : 6;
static const unsigned int layoutBufferReferenceAlignEnd = 0x3F;
TLayoutFormat layoutFormat : 8;
bool layoutPushConstant; bool layoutPushConstant;
bool layoutBufferReference;
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
bool layoutPassthrough; bool layoutPassthrough;
bool layoutViewportRelative; bool layoutViewportRelative;
int layoutSecondaryViewportRelativeOffset; int layoutSecondaryViewportRelativeOffset;
bool layoutShaderRecordNV;
#endif #endif
bool hasUniformLayout() const bool hasUniformLayout() const
@ -829,6 +938,10 @@ public:
// is just whether or not it was declared with an ID. // is just whether or not it was declared with an ID.
return layoutSpecConstantId != layoutSpecConstantIdEnd; return layoutSpecConstantId != layoutSpecConstantIdEnd;
} }
bool hasBufferReferenceAlign() const
{
return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd;
}
bool isSpecConstant() const bool isSpecConstant() const
{ {
// True if type is a specialization constant, whether or not it // True if type is a specialization constant, whether or not it
@ -863,6 +976,7 @@ public:
case ElpShared: return "shared"; case ElpShared: return "shared";
case ElpStd140: return "std140"; case ElpStd140: return "std140";
case ElpStd430: return "std430"; case ElpStd430: return "std430";
case ElpScalar: return "scalar";
default: return "none"; default: return "none";
} }
} }
@ -1005,7 +1119,7 @@ struct TShaderQualifiers {
bool pixelCenterInteger; // fragment shader bool pixelCenterInteger; // fragment shader
bool originUpperLeft; // fragment shader bool originUpperLeft; // fragment shader
int invocations; int invocations;
int vertices; // both for tessellation "vertices" and geometry "max_vertices" int vertices; // for tessellation "vertices", geometry & mesh "max_vertices"
TVertexSpacing spacing; TVertexSpacing spacing;
TVertexOrder order; TVertexOrder order;
bool pointMode; bool pointMode;
@ -1018,7 +1132,10 @@ struct TShaderQualifiers {
int numViews; // multiview extenstions int numViews; // multiview extenstions
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
bool layoutOverrideCoverage; // true if layout override_coverage set bool layoutOverrideCoverage; // true if layout override_coverage set
bool layoutDerivativeGroupQuads; // true if layout derivative_group_quadsNV set
bool layoutDerivativeGroupLinear; // true if layout derivative_group_linearNV set
int primitives; // mesh shader "max_primitives"DerivativeGroupLinear; // true if layout derivative_group_linearNV set
#endif #endif
void init() void init()
@ -1043,7 +1160,10 @@ struct TShaderQualifiers {
blendEquation = false; blendEquation = false;
numViews = TQualifier::layoutNotSet; numViews = TQualifier::layoutNotSet;
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
layoutOverrideCoverage = false; layoutOverrideCoverage = false;
layoutDerivativeGroupQuads = false;
layoutDerivativeGroupLinear = false;
primitives = TQualifier::layoutNotSet;
#endif #endif
} }
@ -1088,6 +1208,12 @@ struct TShaderQualifiers {
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
if (src.layoutOverrideCoverage) if (src.layoutOverrideCoverage)
layoutOverrideCoverage = src.layoutOverrideCoverage; layoutOverrideCoverage = src.layoutOverrideCoverage;
if (src.layoutDerivativeGroupQuads)
layoutDerivativeGroupQuads = src.layoutDerivativeGroupQuads;
if (src.layoutDerivativeGroupLinear)
layoutDerivativeGroupLinear = src.layoutDerivativeGroupLinear;
if (src.primitives != TQualifier::layoutNotSet)
primitives = src.primitives;
#endif #endif
} }
}; };
@ -1206,7 +1332,12 @@ public:
sampler.clear(); sampler.clear();
qualifier = p.qualifier; qualifier = p.qualifier;
if (p.userDef) { if (p.userDef) {
structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues if (p.userDef->basicType == EbtReference) {
basicType = EbtReference;
referentType = p.userDef->referentType;
} else {
structure = p.userDef->getWritableStruct(); // public type is short-lived; there are no sharing issues
}
typeName = NewPoolTString(p.userDef->getTypeName().c_str()); typeName = NewPoolTString(p.userDef->getTypeName().c_str());
} }
} }
@ -1275,6 +1406,17 @@ public:
sampler.clear(); sampler.clear();
typeName = NewPoolTString(n.c_str()); typeName = NewPoolTString(n.c_str());
} }
// for block reference (first parameter must be EbtReference)
explicit TType(TBasicType t, const TType &p, const TString& n) :
basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
{
assert(t == EbtReference);
typeName = NewPoolTString(n.c_str());
qualifier.clear();
qualifier.storage = p.qualifier.storage;
referentType = p.clone();
}
virtual ~TType() {} virtual ~TType() {}
// Not for use across pool pops; it will cause multiple instances of TType to point to the same information. // Not for use across pool pops; it will cause multiple instances of TType to point to the same information.
@ -1290,9 +1432,13 @@ public:
matrixRows = copyOf.matrixRows; matrixRows = copyOf.matrixRows;
vector1 = copyOf.vector1; vector1 = copyOf.vector1;
arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents arraySizes = copyOf.arraySizes; // copying the pointer only, not the contents
structure = copyOf.structure;
fieldName = copyOf.fieldName; fieldName = copyOf.fieldName;
typeName = copyOf.typeName; typeName = copyOf.typeName;
if (isStruct()) {
structure = copyOf.structure;
} else {
referentType = copyOf.referentType;
}
} }
// Make complete copy of the whole type graph rooted at 'copyOf'. // Make complete copy of the whole type graph rooted at 'copyOf'.
@ -1355,6 +1501,7 @@ public:
virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); } virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
virtual const TArraySizes* getArraySizes() const { return arraySizes; } virtual const TArraySizes* getArraySizes() const { return arraySizes; }
virtual TArraySizes* getArraySizes() { return arraySizes; } virtual TArraySizes* getArraySizes() { return arraySizes; }
virtual TType* getReferentType() const { return referentType; }
virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); } virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
virtual bool isScalarOrVec1() const { return isScalar() || vector1; } virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
@ -1366,7 +1513,7 @@ public:
virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); } virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); } virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); } virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
virtual bool isStruct() const { return structure != nullptr; } virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; }
virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; } virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
virtual bool isIntegerDomain() const virtual bool isIntegerDomain() const
{ {
@ -1386,7 +1533,11 @@ public:
} }
return false; return false;
} }
virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint; } virtual bool isOpaque() const { return basicType == EbtSampler || basicType == EbtAtomicUint
#ifdef NV_EXTENSIONS
|| basicType == EbtAccStructNV
#endif
; }
virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; } virtual bool isBuiltIn() const { return getQualifier().builtIn != EbvNone; }
// "Image" is a superset of "Subpass" // "Image" is a superset of "Subpass"
@ -1403,7 +1554,7 @@ public:
const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); }; const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); };
return structure && std::any_of(structure->begin(), structure->end(), hasa); return isStruct() && std::any_of(structure->begin(), structure->end(), hasa);
} }
// Recursively checks if the type contains the given basic type // Recursively checks if the type contains the given basic type
@ -1540,6 +1691,11 @@ public:
{ {
if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed())) if (isUnsizedArray() && !(skipNonvariablyIndexed || isArrayVariablyIndexed()))
changeOuterArraySize(getImplicitArraySize()); changeOuterArraySize(getImplicitArraySize());
#ifdef NV_EXTENSIONS
// For multi-dim per-view arrays, set unsized inner dimension size to 1
if (qualifier.isPerView() && arraySizes && arraySizes->isInnerUnsized())
arraySizes->clearInnerUnsized();
#endif
if (isStruct() && structure->size() > 0) { if (isStruct() && structure->size() > 0) {
int lastMember = (int)structure->size() - 1; int lastMember = (int)structure->size() - 1;
for (int i = 0; i < lastMember; ++i) for (int i = 0; i < lastMember; ++i)
@ -1574,6 +1730,10 @@ public:
case EbtSampler: return "sampler/image"; case EbtSampler: return "sampler/image";
case EbtStruct: return "structure"; case EbtStruct: return "structure";
case EbtBlock: return "block"; case EbtBlock: return "block";
#ifdef NV_EXTENSIONS
case EbtAccStructNV: return "accelerationStructureNV";
#endif
case EbtReference: return "reference";
default: return "unknown type"; default: return "unknown type";
} }
} }
@ -1659,6 +1819,12 @@ public:
} }
if (qualifier.layoutPushConstant) if (qualifier.layoutPushConstant)
appendStr(" push_constant"); appendStr(" push_constant");
if (qualifier.layoutBufferReference)
appendStr(" buffer_reference");
if (qualifier.hasBufferReferenceAlign()) {
appendStr(" buffer_reference_align=");
appendUint(1u << qualifier.layoutBufferReferenceAlign);
}
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
if (qualifier.layoutPassthrough) if (qualifier.layoutPassthrough)
@ -1669,6 +1835,8 @@ public:
appendStr(" layoutSecondaryViewportRelativeOffset="); appendStr(" layoutSecondaryViewportRelativeOffset=");
appendInt(qualifier.layoutSecondaryViewportRelativeOffset); appendInt(qualifier.layoutSecondaryViewportRelativeOffset);
} }
if (qualifier.layoutShaderRecordNV)
appendStr(" shaderRecordNV");
#endif #endif
appendStr(")"); appendStr(")");
@ -1690,6 +1858,16 @@ public:
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
if (qualifier.explicitInterp) if (qualifier.explicitInterp)
appendStr(" __explicitInterpAMD"); appendStr(" __explicitInterpAMD");
#endif
#ifdef NV_EXTENSIONS
if (qualifier.pervertexNV)
appendStr(" pervertexNV");
if (qualifier.perPrimitiveNV)
appendStr(" perprimitiveNV");
if (qualifier.perViewNV)
appendStr(" perviewNV");
if (qualifier.perTaskNV)
appendStr(" taskNV");
#endif #endif
if (qualifier.patch) if (qualifier.patch)
appendStr(" patch"); appendStr(" patch");
@ -1697,6 +1875,16 @@ public:
appendStr(" sample"); appendStr(" sample");
if (qualifier.coherent) if (qualifier.coherent)
appendStr(" coherent"); appendStr(" coherent");
if (qualifier.devicecoherent)
appendStr(" devicecoherent");
if (qualifier.queuefamilycoherent)
appendStr(" queuefamilycoherent");
if (qualifier.workgroupcoherent)
appendStr(" workgroupcoherent");
if (qualifier.subgroupcoherent)
appendStr(" subgroupcoherent");
if (qualifier.nonprivate)
appendStr(" nonprivate");
if (qualifier.volatil) if (qualifier.volatil)
appendStr(" volatile"); appendStr(" volatile");
if (qualifier.restrict) if (qualifier.restrict)
@ -1756,7 +1944,7 @@ public:
} }
// Add struct/block members // Add struct/block members
if (structure) { if (isStruct()) {
appendStr("{"); appendStr("{");
for (size_t i = 0; i < structure->size(); ++i) { for (size_t i = 0; i < structure->size(); ++i) {
if (! (*structure)[i].type->hiddenMember()) { if (! (*structure)[i].type->hiddenMember()) {
@ -1784,9 +1972,9 @@ public:
const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); } const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); }
const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); } const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); }
const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); } const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); }
const TTypeList* getStruct() const { return structure; } const TTypeList* getStruct() const { assert(isStruct()); return structure; }
void setStruct(TTypeList* s) { structure = s; } void setStruct(TTypeList* s) { assert(isStruct()); structure = s; }
TTypeList* getWritableStruct() const { return structure; } // This should only be used when known to not be sharing with other threads TTypeList* getWritableStruct() const { assert(isStruct()); return structure; } // This should only be used when known to not be sharing with other threads
int computeNumComponents() const int computeNumComponents() const
{ {
@ -1825,11 +2013,12 @@ public:
bool sameStructType(const TType& right) const bool sameStructType(const TType& right) const
{ {
// Most commonly, they are both nullptr, or the same pointer to the same actual structure // Most commonly, they are both nullptr, or the same pointer to the same actual structure
if (structure == right.structure) if ((!isStruct() && !right.isStruct()) ||
(isStruct() && right.isStruct() && structure == right.structure))
return true; return true;
// Both being nullptr was caught above, now they both have to be structures of the same number of elements // Both being nullptr was caught above, now they both have to be structures of the same number of elements
if (structure == nullptr || right.structure == nullptr || if (!isStruct() || !right.isStruct() ||
structure->size() != right.structure->size()) structure->size() != right.structure->size())
return false; return false;
@ -1849,6 +2038,23 @@ public:
return true; return true;
} }
bool sameReferenceType(const TType& right) const
{
if ((basicType == EbtReference) != (right.basicType == EbtReference))
return false;
if ((basicType != EbtReference) && (right.basicType != EbtReference))
return true;
assert(referentType != nullptr);
assert(right.referentType != nullptr);
if (referentType == right.referentType)
return true;
return *referentType == *right.referentType;
}
// See if two types match, in all aspects except arrayness // See if two types match, in all aspects except arrayness
bool sameElementType(const TType& right) const bool sameElementType(const TType& right) const
{ {
@ -1877,7 +2083,8 @@ public:
matrixCols == right.matrixCols && matrixCols == right.matrixCols &&
matrixRows == right.matrixRows && matrixRows == right.matrixRows &&
vector1 == right.vector1 && vector1 == right.vector1 &&
sameStructType(right); sameStructType(right) &&
sameReferenceType(right);
} }
// See if two types match in all ways (just the actual type, not qualification) // See if two types match in all ways (just the actual type, not qualification)
@ -1908,7 +2115,7 @@ protected:
*arraySizes = *copyOf.arraySizes; *arraySizes = *copyOf.arraySizes;
} }
if (copyOf.structure) { if (copyOf.isStruct() && copyOf.structure) {
auto prevCopy = copiedMap.find(copyOf.structure); auto prevCopy = copiedMap.find(copyOf.structure);
if (prevCopy != copiedMap.end()) if (prevCopy != copiedMap.end())
structure = prevCopy->second; structure = prevCopy->second;
@ -1946,7 +2153,12 @@ protected:
TQualifier qualifier; TQualifier qualifier;
TArraySizes* arraySizes; // nullptr unless an array; can be shared across types TArraySizes* arraySizes; // nullptr unless an array; can be shared across types
TTypeList* structure; // nullptr unless this is a struct; can be shared across types // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so
// conserve space by making these a union
union {
TTypeList* structure; // invalid unless this is a struct; can be shared across types
TType *referentType; // invalid unless this is an EbtReference
};
TString *fieldName; // for structure field names TString *fieldName; // for structure field names
TString *typeName; // for structure type name TString *typeName; // for structure type name
TSampler sampler; TSampler sampler;

View file

@ -269,6 +269,10 @@ enum TOperator {
EOpConvDoubleToFloat16, EOpConvDoubleToFloat16,
EOpConvDoubleToFloat, EOpConvDoubleToFloat,
// uint64_t <-> pointer
EOpConvUint64ToPtr,
EOpConvPtrToUint64,
// //
// binary operations // binary operations
// //
@ -592,6 +596,8 @@ enum TOperator {
EOpAtomicXor, EOpAtomicXor,
EOpAtomicExchange, EOpAtomicExchange,
EOpAtomicCompSwap, EOpAtomicCompSwap,
EOpAtomicLoad,
EOpAtomicStore,
EOpAtomicCounterIncrement, // results in pre-increment value EOpAtomicCounterIncrement, // results in pre-increment value
EOpAtomicCounterDecrement, // results in post-decrement value EOpAtomicCounterDecrement, // results in post-decrement value
@ -730,6 +736,7 @@ enum TOperator {
EOpConstructStruct, EOpConstructStruct,
EOpConstructTextureSampler, EOpConstructTextureSampler,
EOpConstructNonuniform, // expected to be transformed away, not present in final AST EOpConstructNonuniform, // expected to be transformed away, not present in final AST
EOpConstructReference,
EOpConstructGuardEnd, EOpConstructGuardEnd,
// //
@ -784,6 +791,8 @@ enum TOperator {
EOpImageAtomicXor, EOpImageAtomicXor,
EOpImageAtomicExchange, EOpImageAtomicExchange,
EOpImageAtomicCompSwap, EOpImageAtomicCompSwap,
EOpImageAtomicLoad,
EOpImageAtomicStore,
EOpSubpassLoad, EOpSubpassLoad,
EOpSubpassLoadMS, EOpSubpassLoadMS,
@ -861,6 +870,16 @@ enum TOperator {
#endif #endif
EOpSparseTextureGuardEnd, EOpSparseTextureGuardEnd,
#ifdef NV_EXTENSIONS
EOpImageFootprintGuardBegin,
EOpImageSampleFootprintNV,
EOpImageSampleFootprintClampNV,
EOpImageSampleFootprintLodNV,
EOpImageSampleFootprintGradNV,
EOpImageSampleFootprintGradClampNV,
EOpImageFootprintGuardEnd,
#endif
EOpSamplingGuardEnd, EOpSamplingGuardEnd,
EOpTextureGuardEnd, EOpTextureGuardEnd,
@ -879,6 +898,14 @@ enum TOperator {
EOpFindLSB, EOpFindLSB,
EOpFindMSB, EOpFindMSB,
#ifdef NV_EXTENSIONS
EOpTraceNV,
EOpReportIntersectionNV,
EOpIgnoreIntersectionNV,
EOpTerminateRayNV,
EOpExecuteCallableNV,
EOpWritePackedPrimitiveIndices4x8NV,
#endif
// //
// HLSL operations // HLSL operations
// //
@ -1164,6 +1191,7 @@ public:
constSubtree(nullptr) constSubtree(nullptr)
{ name = n; } { name = n; }
virtual int getId() const { return id; } virtual int getId() const { return id; }
virtual void changeId(int i) { id = i; }
virtual const TString& getName() const { return name; } virtual const TString& getName() const { return name; }
virtual void traverse(TIntermTraverser*); virtual void traverse(TIntermTraverser*);
virtual TIntermSymbol* getAsSymbolNode() { return this; } virtual TIntermSymbol* getAsSymbolNode() { return this; }
@ -1243,6 +1271,9 @@ public:
bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; } bool isSampling() const { return op > EOpSamplingGuardBegin && op < EOpSamplingGuardEnd; }
bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; } bool isImage() const { return op > EOpImageGuardBegin && op < EOpImageGuardEnd; }
bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; } bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; }
#ifdef NV_EXTENSIONS
bool isImageFootprint() const { return op > EOpImageFootprintGuardBegin && op < EOpImageFootprintGuardEnd; }
#endif
bool isSparseImage() const { return op == EOpSparseImageLoad; } bool isSparseImage() const { return op == EOpSparseImageLoad; }
void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; } void setOperationPrecision(TPrecisionQualifier p) { operationPrecision = p; }
@ -1415,6 +1446,23 @@ public:
cracked.subpass = sampler.dim == EsdSubpass; cracked.subpass = sampler.dim == EsdSubpass;
cracked.fragMask = true; cracked.fragMask = true;
break; break;
#endif
#ifdef NV_EXTENSIONS
case EOpImageSampleFootprintNV:
break;
case EOpImageSampleFootprintClampNV:
cracked.lodClamp = true;
break;
case EOpImageSampleFootprintLodNV:
cracked.lod = true;
break;
case EOpImageSampleFootprintGradNV:
cracked.grad = true;
break;
case EOpImageSampleFootprintGradClampNV:
cracked.lodClamp = true;
cracked.grad = true;
break;
#endif #endif
case EOpSubpassLoad: case EOpSubpassLoad:
case EOpSubpassLoadMS: case EOpSubpassLoadMS:

View file

@ -1,3 +1,3 @@
// This header is generated by the make-revision script. // This header is generated by the make-revision script.
#define GLSLANG_PATCH_LEVEL 2801 #define GLSLANG_PATCH_LEVEL 3057

View file

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -184,7 +185,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right
else if (leftUnionArray[i].getDConst() > 0.0) else if (leftUnionArray[i].getDConst() > 0.0)
newConstArray[i].setDConst((double)INFINITY); newConstArray[i].setDConst((double)INFINITY);
else if (leftUnionArray[i].getDConst() < 0.0) else if (leftUnionArray[i].getDConst() < 0.0)
newConstArray[i].setDConst((double)-INFINITY); newConstArray[i].setDConst(-(double)INFINITY);
else else
newConstArray[i].setDConst((double)NAN); newConstArray[i].setDConst((double)NAN);
break; break;
@ -223,8 +224,8 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right
case EbtInt: case EbtInt:
if (rightUnionArray[i] == 0) if (rightUnionArray[i] == 0)
newConstArray[i].setIConst(0x7FFFFFFF); newConstArray[i].setIConst(0x7FFFFFFF);
else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == -(int)0x80000000) else if (rightUnionArray[i].getIConst() == -1 && leftUnionArray[i].getIConst() == (int)-0x80000000ll)
newConstArray[i].setIConst(-(int)0x80000000); newConstArray[i].setIConst((int)-0x80000000ll);
else else
newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst()); newConstArray[i].setIConst(leftUnionArray[i].getIConst() / rightUnionArray[i].getIConst());
break; break;
@ -239,8 +240,8 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TIntermTyped* right
case EbtInt64: case EbtInt64:
if (rightUnionArray[i] == 0ll) if (rightUnionArray[i] == 0ll)
newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll); newConstArray[i].setI64Const(0x7FFFFFFFFFFFFFFFll);
else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == -0x8000000000000000ll) else if (rightUnionArray[i].getI64Const() == -1 && leftUnionArray[i].getI64Const() == (long long)-0x8000000000000000ll)
newConstArray[i].setI64Const(-0x8000000000000000ll); newConstArray[i].setI64Const((long long)-0x8000000000000000ll);
else else
newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const()); newConstArray[i].setI64Const(leftUnionArray[i].getI64Const() / rightUnionArray[i].getI64Const());
break; break;
@ -670,6 +671,279 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, const TType& returnType)
break; break;
} }
case EOpConvInt8ToBool:
newConstArray[i].setBConst(unionArray[i].getI8Const() != 0); break;
case EOpConvUint8ToBool:
newConstArray[i].setBConst(unionArray[i].getU8Const() != 0); break;
case EOpConvInt16ToBool:
newConstArray[i].setBConst(unionArray[i].getI16Const() != 0); break;
case EOpConvUint16ToBool:
newConstArray[i].setBConst(unionArray[i].getU16Const() != 0); break;
case EOpConvIntToBool:
newConstArray[i].setBConst(unionArray[i].getIConst() != 0); break;
case EOpConvUintToBool:
newConstArray[i].setBConst(unionArray[i].getUConst() != 0); break;
case EOpConvInt64ToBool:
newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
case EOpConvUint64ToBool:
newConstArray[i].setBConst(unionArray[i].getI64Const() != 0); break;
case EOpConvFloat16ToBool:
newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
case EOpConvFloatToBool:
newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
case EOpConvDoubleToBool:
newConstArray[i].setBConst(unionArray[i].getDConst() != 0); break;
case EOpConvBoolToInt8:
newConstArray[i].setI8Const(unionArray[i].getBConst()); break;
case EOpConvBoolToUint8:
newConstArray[i].setU8Const(unionArray[i].getBConst()); break;
case EOpConvBoolToInt16:
newConstArray[i].setI16Const(unionArray[i].getBConst()); break;
case EOpConvBoolToUint16:
newConstArray[i].setU16Const(unionArray[i].getBConst()); break;
case EOpConvBoolToInt:
newConstArray[i].setIConst(unionArray[i].getBConst()); break;
case EOpConvBoolToUint:
newConstArray[i].setUConst(unionArray[i].getBConst()); break;
case EOpConvBoolToInt64:
newConstArray[i].setI64Const(unionArray[i].getBConst()); break;
case EOpConvBoolToUint64:
newConstArray[i].setU64Const(unionArray[i].getBConst()); break;
case EOpConvBoolToFloat16:
newConstArray[i].setDConst(unionArray[i].getBConst()); break;
case EOpConvBoolToFloat:
newConstArray[i].setDConst(unionArray[i].getBConst()); break;
case EOpConvBoolToDouble:
newConstArray[i].setDConst(unionArray[i].getBConst()); break;
case EOpConvInt8ToInt16:
newConstArray[i].setI16Const(unionArray[i].getI8Const()); break;
case EOpConvInt8ToInt:
newConstArray[i].setIConst(unionArray[i].getI8Const()); break;
case EOpConvInt8ToInt64:
newConstArray[i].setI64Const(unionArray[i].getI8Const()); break;
case EOpConvInt8ToUint8:
newConstArray[i].setU8Const(unionArray[i].getI8Const()); break;
case EOpConvInt8ToUint16:
newConstArray[i].setU16Const(unionArray[i].getI8Const()); break;
case EOpConvInt8ToUint:
newConstArray[i].setUConst(unionArray[i].getI8Const()); break;
case EOpConvInt8ToUint64:
newConstArray[i].setU64Const(unionArray[i].getI8Const()); break;
case EOpConvUint8ToInt8:
newConstArray[i].setI8Const(unionArray[i].getU8Const()); break;
case EOpConvUint8ToInt16:
newConstArray[i].setI16Const(unionArray[i].getU8Const()); break;
case EOpConvUint8ToInt:
newConstArray[i].setIConst(unionArray[i].getU8Const()); break;
case EOpConvUint8ToInt64:
newConstArray[i].setI64Const(unionArray[i].getU8Const()); break;
case EOpConvUint8ToUint16:
newConstArray[i].setU16Const(unionArray[i].getU8Const()); break;
case EOpConvUint8ToUint:
newConstArray[i].setUConst(unionArray[i].getU8Const()); break;
case EOpConvUint8ToUint64:
newConstArray[i].setU64Const(unionArray[i].getU8Const()); break;
case EOpConvInt8ToFloat16:
newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
case EOpConvInt8ToFloat:
newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
case EOpConvInt8ToDouble:
newConstArray[i].setDConst(unionArray[i].getI8Const()); break;
case EOpConvUint8ToFloat16:
newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
case EOpConvUint8ToFloat:
newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
case EOpConvUint8ToDouble:
newConstArray[i].setDConst(unionArray[i].getU8Const()); break;
case EOpConvInt16ToInt8:
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI16Const())); break;
case EOpConvInt16ToInt:
newConstArray[i].setIConst(unionArray[i].getI16Const()); break;
case EOpConvInt16ToInt64:
newConstArray[i].setI64Const(unionArray[i].getI16Const()); break;
case EOpConvInt16ToUint8:
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI16Const())); break;
case EOpConvInt16ToUint16:
newConstArray[i].setU16Const(unionArray[i].getI16Const()); break;
case EOpConvInt16ToUint:
newConstArray[i].setUConst(unionArray[i].getI16Const()); break;
case EOpConvInt16ToUint64:
newConstArray[i].setU64Const(unionArray[i].getI16Const()); break;
case EOpConvUint16ToInt8:
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU16Const())); break;
case EOpConvUint16ToInt16:
newConstArray[i].setI16Const(unionArray[i].getU16Const()); break;
case EOpConvUint16ToInt:
newConstArray[i].setIConst(unionArray[i].getU16Const()); break;
case EOpConvUint16ToInt64:
newConstArray[i].setI64Const(unionArray[i].getU16Const()); break;
case EOpConvUint16ToUint8:
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU16Const())); break;
case EOpConvUint16ToUint:
newConstArray[i].setUConst(unionArray[i].getU16Const()); break;
case EOpConvUint16ToUint64:
newConstArray[i].setU64Const(unionArray[i].getU16Const()); break;
case EOpConvInt16ToFloat16:
newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
case EOpConvInt16ToFloat:
newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
case EOpConvInt16ToDouble:
newConstArray[i].setDConst(unionArray[i].getI16Const()); break;
case EOpConvUint16ToFloat16:
newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
case EOpConvUint16ToFloat:
newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
case EOpConvUint16ToDouble:
newConstArray[i].setDConst(unionArray[i].getU16Const()); break;
case EOpConvIntToInt8:
newConstArray[i].setI8Const((signed char)unionArray[i].getIConst()); break;
case EOpConvIntToInt16:
newConstArray[i].setI16Const((signed short)unionArray[i].getIConst()); break;
case EOpConvIntToInt64:
newConstArray[i].setI64Const(unionArray[i].getIConst()); break;
case EOpConvIntToUint8:
newConstArray[i].setU8Const((unsigned char)unionArray[i].getIConst()); break;
case EOpConvIntToUint16:
newConstArray[i].setU16Const((unsigned char)unionArray[i].getIConst()); break;
case EOpConvIntToUint:
newConstArray[i].setUConst(unionArray[i].getIConst()); break;
case EOpConvIntToUint64:
newConstArray[i].setU64Const(unionArray[i].getIConst()); break;
case EOpConvUintToInt8:
newConstArray[i].setI8Const((signed char)unionArray[i].getUConst()); break;
case EOpConvUintToInt16:
newConstArray[i].setI16Const((signed short)unionArray[i].getUConst()); break;
case EOpConvUintToInt:
newConstArray[i].setIConst(unionArray[i].getUConst()); break;
case EOpConvUintToInt64:
newConstArray[i].setI64Const(unionArray[i].getUConst()); break;
case EOpConvUintToUint8:
newConstArray[i].setU8Const((unsigned char)unionArray[i].getUConst()); break;
case EOpConvUintToUint16:
newConstArray[i].setU16Const((unsigned short)unionArray[i].getUConst()); break;
case EOpConvUintToUint64:
newConstArray[i].setU64Const(unionArray[i].getUConst()); break;
case EOpConvIntToFloat16:
newConstArray[i].setDConst(unionArray[i].getIConst()); break;
case EOpConvIntToFloat:
newConstArray[i].setDConst(unionArray[i].getIConst()); break;
case EOpConvIntToDouble:
newConstArray[i].setDConst(unionArray[i].getIConst()); break;
case EOpConvUintToFloat16:
newConstArray[i].setDConst(unionArray[i].getUConst()); break;
case EOpConvUintToFloat:
newConstArray[i].setDConst(unionArray[i].getUConst()); break;
case EOpConvUintToDouble:
newConstArray[i].setDConst(unionArray[i].getUConst()); break;
case EOpConvInt64ToInt8:
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getI64Const())); break;
case EOpConvInt64ToInt16:
newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getI64Const())); break;
case EOpConvInt64ToInt:
newConstArray[i].setIConst(static_cast<int>(unionArray[i].getI64Const())); break;
case EOpConvInt64ToUint8:
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getI64Const())); break;
case EOpConvInt64ToUint16:
newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getI64Const())); break;
case EOpConvInt64ToUint:
newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getI64Const())); break;
case EOpConvInt64ToUint64:
newConstArray[i].setU64Const(unionArray[i].getI64Const()); break;
case EOpConvUint64ToInt8:
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getU64Const())); break;
case EOpConvUint64ToInt16:
newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getU64Const())); break;
case EOpConvUint64ToInt:
newConstArray[i].setIConst(static_cast<int>(unionArray[i].getU64Const())); break;
case EOpConvUint64ToInt64:
newConstArray[i].setI64Const(unionArray[i].getU64Const()); break;
case EOpConvUint64ToUint8:
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getU64Const())); break;
case EOpConvUint64ToUint16:
newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getU64Const())); break;
case EOpConvUint64ToUint:
newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getU64Const())); break;
case EOpConvInt64ToFloat16:
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
case EOpConvInt64ToFloat:
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
case EOpConvInt64ToDouble:
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getI64Const())); break;
case EOpConvUint64ToFloat16:
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
case EOpConvUint64ToFloat:
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
case EOpConvUint64ToDouble:
newConstArray[i].setDConst(static_cast<double>(unionArray[i].getU64Const())); break;
case EOpConvFloat16ToInt8:
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
case EOpConvFloat16ToInt16:
newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
case EOpConvFloat16ToInt:
newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
case EOpConvFloat16ToInt64:
newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
case EOpConvFloat16ToUint8:
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
case EOpConvFloat16ToUint16:
newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
case EOpConvFloat16ToUint:
newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
case EOpConvFloat16ToUint64:
newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
case EOpConvFloat16ToFloat:
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
case EOpConvFloat16ToDouble:
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
case EOpConvFloatToInt8:
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
case EOpConvFloatToInt16:
newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
case EOpConvFloatToInt:
newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
case EOpConvFloatToInt64:
newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
case EOpConvFloatToUint8:
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
case EOpConvFloatToUint16:
newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
case EOpConvFloatToUint:
newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
case EOpConvFloatToUint64:
newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
case EOpConvFloatToFloat16:
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
case EOpConvFloatToDouble:
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
case EOpConvDoubleToInt8:
newConstArray[i].setI8Const(static_cast<signed char>(unionArray[i].getDConst())); break;
case EOpConvDoubleToInt16:
newConstArray[i].setI16Const(static_cast<signed short>(unionArray[i].getDConst())); break;
case EOpConvDoubleToInt:
newConstArray[i].setIConst(static_cast<int>(unionArray[i].getDConst())); break;
case EOpConvDoubleToInt64:
newConstArray[i].setI64Const(static_cast<long long>(unionArray[i].getDConst())); break;
case EOpConvDoubleToUint8:
newConstArray[i].setU8Const(static_cast<unsigned char>(unionArray[i].getDConst())); break;
case EOpConvDoubleToUint16:
newConstArray[i].setU16Const(static_cast<unsigned short>(unionArray[i].getDConst())); break;
case EOpConvDoubleToUint:
newConstArray[i].setUConst(static_cast<unsigned int>(unionArray[i].getDConst())); break;
case EOpConvDoubleToUint64:
newConstArray[i].setU64Const(static_cast<unsigned long long>(unionArray[i].getDConst())); break;
case EOpConvDoubleToFloat16:
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
case EOpConvDoubleToFloat:
newConstArray[i].setDConst(unionArray[i].getDConst()); break;
// TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out // TODO: 3.0 Functionality: unary constant folding: the rest of the ops have to be fleshed out
case EOpSinh: case EOpSinh:

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2015 LunarG, Inc. // Copyright (C) 2012-2015 LunarG, Inc.
// Copyright (C) 2015-2016 Google, Inc. // Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// //
// All rights reserved. // All rights reserved.
@ -460,6 +460,9 @@ bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const
return false; return false;
case EbtAtomicUint: case EbtAtomicUint:
case EbtSampler: case EbtSampler:
#ifdef NV_EXTENSIONS
case EbtAccStructNV:
#endif
// opaque types can be passed to functions // opaque types can be passed to functions
if (op == EOpFunction) if (op == EOpFunction)
break; break;
@ -486,7 +489,7 @@ bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const
// This is 'mechanism' here, it does any conversion told. // This is 'mechanism' here, it does any conversion told.
// It is about basic type, not about shape. // It is about basic type, not about shape.
// The policy comes from the shader or the calling code. // The policy comes from the shader or the calling code.
TIntermUnary* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped* node) const TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped* node) const
{ {
// //
// Add a new newNode for the conversion. // Add a new newNode for the conversion.
@ -709,7 +712,11 @@ TIntermUnary* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped
TType newType(convertTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows()); TType newType(convertTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows());
newNode = addUnaryNode(newOp, node, node->getLoc(), newType); newNode = addUnaryNode(newOp, node, node->getLoc(), newType);
// TODO: it seems that some unary folding operations should occur here, but are not if (node->getAsConstantUnion()) {
TIntermTyped* folded = node->getAsConstantUnion()->fold(newOp, newType);
if (folded)
return folded;
}
// Propagate specialization-constant-ness, if allowed // Propagate specialization-constant-ness, if allowed
if (node->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*newNode)) if (node->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*newNode))
@ -900,28 +907,28 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
break; break;
case EOpConstructFloat16: case EOpConstructFloat16:
promoteTo = EbtFloat16; promoteTo = EbtFloat16;
canPromoteConstant = extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types) || canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_float16); extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16);
break; break;
case EOpConstructInt8: case EOpConstructInt8:
promoteTo = EbtInt8; promoteTo = EbtInt8;
canPromoteConstant = extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types) || canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int8); extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
break; break;
case EOpConstructUint8: case EOpConstructUint8:
promoteTo = EbtUint8; promoteTo = EbtUint8;
canPromoteConstant = extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types) || canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int8); extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
break; break;
case EOpConstructInt16: case EOpConstructInt16:
promoteTo = EbtInt16; promoteTo = EbtInt16;
canPromoteConstant = extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types) || canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int16); extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
break; break;
case EOpConstructUint16: case EOpConstructUint16:
promoteTo = EbtUint16; promoteTo = EbtUint16;
canPromoteConstant = extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types) || canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int16); extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
break; break;
case EOpConstructInt: case EOpConstructInt:
promoteTo = EbtInt; promoteTo = EbtInt;
@ -977,6 +984,14 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
case EOpSequence: case EOpSequence:
case EOpConstructStruct: case EOpConstructStruct:
if (type.getBasicType() == EbtReference || node->getType().getBasicType() == EbtReference) {
// types must match to assign a reference
if (type == node->getType())
return node;
else
return nullptr;
}
if (type.getBasicType() == node->getType().getBasicType()) if (type.getBasicType() == node->getType().getBasicType())
return node; return node;
@ -1018,7 +1033,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
// //
// Add a new newNode for the conversion. // Add a new newNode for the conversion.
// //
TIntermUnary* newNode = createConversion(promoteTo, node); TIntermTyped* newNode = createConversion(promoteTo, node);
return newNode; return newNode;
} }
@ -1116,9 +1131,12 @@ void TIntermediate::addBiShapeConversion(TOperator op, TIntermTyped*& lhsNode, T
rhsNode = addUniShapeConversion(op, lhsNode->getType(), rhsNode); rhsNode = addUniShapeConversion(op, lhsNode->getType(), rhsNode);
return; return;
case EOpMul:
// matrix multiply does not change shapes
if (lhsNode->isMatrix() && rhsNode->isMatrix())
return;
case EOpAdd: case EOpAdd:
case EOpSub: case EOpSub:
case EOpMul:
case EOpDiv: case EOpDiv:
// want to support vector * scalar native ops in AST and lower, not smear, similarly for // want to support vector * scalar native ops in AST and lower, not smear, similarly for
// matrix * vector, etc. // matrix * vector, etc.
@ -1191,9 +1209,19 @@ TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped*
// The new node that handles the conversion // The new node that handles the conversion
TOperator constructorOp = mapTypeToConstructorOp(type); TOperator constructorOp = mapTypeToConstructorOp(type);
// HLSL has custom semantics for scalar->mat shape conversions.
if (source == EShSourceHlsl) { if (source == EShSourceHlsl) {
if (node->getType().isScalarOrVec1() && type.isMatrix()) { // HLSL rules for scalar, vector and matrix conversions:
// 1) scalar can become anything, initializing every component with its value
// 2) vector and matrix can become scalar, first element is used (warning: truncation)
// 3) matrix can become matrix with less rows and/or columns (warning: truncation)
// 4) vector can become vector with less rows size (warning: truncation)
// 5a) vector 4 can become 2x2 matrix (special case) (same packing layout, its a reinterpret)
// 5b) 2x2 matrix can become vector 4 (special case) (same packing layout, its a reinterpret)
const TType &sourceType = node->getType();
// rule 1 for scalar to matrix is special
if (sourceType.isScalarOrVec1() && type.isMatrix()) {
// HLSL semantics: the scalar (or vec1) is replicated to every component of the matrix. Left to its // HLSL semantics: the scalar (or vec1) is replicated to every component of the matrix. Left to its
// own devices, the constructor from a scalar would populate the diagonal. This forces replication // own devices, the constructor from a scalar would populate the diagonal. This forces replication
@ -1201,7 +1229,7 @@ TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped*
// Note that if the node is complex (e.g, a function call), we don't want to duplicate it here // Note that if the node is complex (e.g, a function call), we don't want to duplicate it here
// repeatedly, so we copy it to a temp, then use the temp. // repeatedly, so we copy it to a temp, then use the temp.
const int matSize = type.getMatrixRows() * type.getMatrixCols(); const int matSize = type.computeNumComponents();
TIntermAggregate* rhsAggregate = new TIntermAggregate(); TIntermAggregate* rhsAggregate = new TIntermAggregate();
const bool isSimple = (node->getAsSymbolNode() != nullptr) || (node->getAsConstantUnion() != nullptr); const bool isSimple = (node->getAsSymbolNode() != nullptr) || (node->getAsConstantUnion() != nullptr);
@ -1209,12 +1237,44 @@ TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped*
if (!isSimple) { if (!isSimple) {
assert(0); // TODO: use node replicator service when available. assert(0); // TODO: use node replicator service when available.
} }
for (int x=0; x<matSize; ++x) for (int x = 0; x < matSize; ++x)
rhsAggregate->getSequence().push_back(node); rhsAggregate->getSequence().push_back(node);
return setAggregateOperator(rhsAggregate, constructorOp, type, node->getLoc()); return setAggregateOperator(rhsAggregate, constructorOp, type, node->getLoc());
} }
// rule 1 and 2
if ((sourceType.isScalar() && !type.isScalar()) || (!sourceType.isScalar() && type.isScalar()))
return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
// rule 3 and 5b
if (sourceType.isMatrix()) {
// rule 3
if (type.isMatrix()) {
if ((sourceType.getMatrixCols() != type.getMatrixCols() || sourceType.getMatrixRows() != type.getMatrixRows()) &&
sourceType.getMatrixCols() >= type.getMatrixCols() && sourceType.getMatrixRows() >= type.getMatrixRows())
return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
// rule 5b
} else if (type.isVector()) {
if (type.getVectorSize() == 4 && sourceType.getMatrixCols() == 2 && sourceType.getMatrixRows() == 2)
return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
}
}
// rule 4 and 5a
if (sourceType.isVector()) {
// rule 4
if (type.isVector())
{
if (sourceType.getVectorSize() > type.getVectorSize())
return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
// rule 5a
} else if (type.isMatrix()) {
if (sourceType.getVectorSize() == 4 && type.getMatrixCols() == 2 && type.getMatrixRows() == 2)
return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
}
}
} }
// scalar -> vector or vec1 -> vector or // scalar -> vector or vec1 -> vector or
@ -1433,14 +1493,14 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
} }
} }
bool explicitTypesEnabled = extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types) || bool explicitTypesEnabled = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int8) || extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int16) || extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int32) || extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int32) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_int64) || extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int64) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_float16) || extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_float32) || extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
extensionRequested(E_GL_KHX_shader_explicit_arithmetic_types_float64); extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float64);
if (explicitTypesEnabled) { if (explicitTypesEnabled) {
// integral promotions // integral promotions
@ -1573,27 +1633,29 @@ bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperat
return false; return false;
} }
case EbtFloat16: case EbtFloat16:
switch (from) {
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
switch (from) {
case EbtInt16: case EbtInt16:
case EbtUint16: case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16); return extensionRequested(E_GL_AMD_gpu_shader_int16);
case EbtFloat16: case EbtFloat16:
return extensionRequested(E_GL_AMD_gpu_shader_half_float); return extensionRequested(E_GL_AMD_gpu_shader_half_float);
#endif
default: default:
return false; break;
} }
#endif
return false;
case EbtUint16: case EbtUint16:
switch (from) {
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
switch (from) {
case EbtInt16: case EbtInt16:
case EbtUint16: case EbtUint16:
return extensionRequested(E_GL_AMD_gpu_shader_int16); return extensionRequested(E_GL_AMD_gpu_shader_int16);
#endif
default: default:
return false; break;
} }
#endif
return false;
default: default:
return false; return false;
} }
@ -2077,6 +2139,9 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
} }
} }
break; break;
case EbtReference:
op = EOpConstructReference;
break;
default: default:
break; break;
} }

View file

@ -153,6 +153,12 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
if (node->getQualifier().readonly) if (node->getQualifier().readonly)
message = "can't modify a readonly buffer"; message = "can't modify a readonly buffer";
break; break;
#ifdef NV_EXTENSIONS
case EvqHitAttrNV:
if (language != EShLangIntersectNV)
message = "cannot modify hitAttributeNV in this stage";
break;
#endif
default: default:
// //
@ -168,6 +174,11 @@ bool TParseContextBase::lValueErrorCheck(const TSourceLoc& loc, const char* op,
case EbtVoid: case EbtVoid:
message = "can't modify void"; message = "can't modify void";
break; break;
#ifdef NV_EXTENSIONS
case EbtAccStructNV:
message = "can't modify accelerationStructureNV";
break;
#endif
default: default:
break; break;
} }

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -298,14 +299,14 @@ public:
void fixIoArraySize(const TSourceLoc&, TType&); void fixIoArraySize(const TSourceLoc&, TType&);
void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier);
void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false, bool isPerPrimitive = false);
int getIoArrayImplicitSize() const; int getIoArrayImplicitSize(bool isPerPrimitive = false) const;
void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, const TString& field); void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName);
TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
@ -323,6 +324,7 @@ public:
TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&); TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier); void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier);
void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
void assignError(const TSourceLoc&, const char* op, TString left, TString right); void assignError(const TSourceLoc&, const char* op, TString left, TString right);
void unaryOpError(const TSourceLoc&, const char* op, TString operand); void unaryOpError(const TSourceLoc&, const char* op, TString operand);
@ -347,6 +349,7 @@ public:
void boolCheck(const TSourceLoc&, const TPublicType&); void boolCheck(const TSourceLoc&, const TPublicType&);
void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
void accStructNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
void memberQualifierCheck(glslang::TPublicType&); void memberQualifierCheck(glslang::TPublicType&);
void globalQualifierFixCheck(const TSourceLoc&, TQualifier&); void globalQualifierFixCheck(const TSourceLoc&, TQualifier&);
@ -401,7 +404,7 @@ public:
void blockStageIoCheck(const TSourceLoc&, const TQualifier&); void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
void fixBlockXfbOffsets(TQualifier&, TTypeList&); void fixXfbOffsets(TQualifier&, TTypeList&);
void fixBlockUniformOffsets(TQualifier&, TTypeList&); void fixBlockUniformOffsets(TQualifier&, TTypeList&);
void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
@ -422,6 +425,8 @@ public:
// Determine loop control from attributes // Determine loop control from attributes
void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
void resizeMeshViewDimension(const TSourceLoc&, TType&);
protected: protected:
void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type); void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
void inheritGlobalDefaults(TQualifier& dst) const; void inheritGlobalDefaults(TQualifier& dst) const;

View file

@ -380,6 +380,11 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["varying"] = VARYING; (*KeywordMap)["varying"] = VARYING;
(*KeywordMap)["buffer"] = BUFFER; (*KeywordMap)["buffer"] = BUFFER;
(*KeywordMap)["coherent"] = COHERENT; (*KeywordMap)["coherent"] = COHERENT;
(*KeywordMap)["devicecoherent"] = DEVICECOHERENT;
(*KeywordMap)["queuefamilycoherent"] = QUEUEFAMILYCOHERENT;
(*KeywordMap)["workgroupcoherent"] = WORKGROUPCOHERENT;
(*KeywordMap)["subgroupcoherent"] = SUBGROUPCOHERENT;
(*KeywordMap)["nonprivate"] = NONPRIVATE;
(*KeywordMap)["restrict"] = RESTRICT; (*KeywordMap)["restrict"] = RESTRICT;
(*KeywordMap)["readonly"] = READONLY; (*KeywordMap)["readonly"] = READONLY;
(*KeywordMap)["writeonly"] = WRITEONLY; (*KeywordMap)["writeonly"] = WRITEONLY;
@ -466,7 +471,7 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["u64vec3"] = U64VEC3; (*KeywordMap)["u64vec3"] = U64VEC3;
(*KeywordMap)["u64vec4"] = U64VEC4; (*KeywordMap)["u64vec4"] = U64VEC4;
// GL_KHX_shader_explicit_arithmetic_types // GL_EXT_shader_explicit_arithmetic_types
(*KeywordMap)["int8_t"] = INT8_T; (*KeywordMap)["int8_t"] = INT8_T;
(*KeywordMap)["i8vec2"] = I8VEC2; (*KeywordMap)["i8vec2"] = I8VEC2;
(*KeywordMap)["i8vec3"] = I8VEC3; (*KeywordMap)["i8vec3"] = I8VEC3;
@ -587,6 +592,8 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["samplerExternalOES"] = SAMPLEREXTERNALOES; // GL_OES_EGL_image_external (*KeywordMap)["samplerExternalOES"] = SAMPLEREXTERNALOES; // GL_OES_EGL_image_external
(*KeywordMap)["__samplerExternal2DY2YEXT"] = SAMPLEREXTERNAL2DY2YEXT; // GL_EXT_YUV_target
(*KeywordMap)["sampler"] = SAMPLER; (*KeywordMap)["sampler"] = SAMPLER;
(*KeywordMap)["samplerShadow"] = SAMPLERSHADOW; (*KeywordMap)["samplerShadow"] = SAMPLERSHADOW;
@ -683,15 +690,30 @@ void TScanContext::fillInKeywordMap()
(*KeywordMap)["smooth"] = SMOOTH; (*KeywordMap)["smooth"] = SMOOTH;
(*KeywordMap)["flat"] = FLAT; (*KeywordMap)["flat"] = FLAT;
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
(*KeywordMap)["__explicitInterpAMD"] = __EXPLICITINTERPAMD; (*KeywordMap)["__explicitInterpAMD"] = EXPLICITINTERPAMD;
#endif #endif
(*KeywordMap)["centroid"] = CENTROID; (*KeywordMap)["centroid"] = CENTROID;
#ifdef NV_EXTENSIONS
(*KeywordMap)["pervertexNV"] = PERVERTEXNV;
#endif
(*KeywordMap)["precise"] = PRECISE; (*KeywordMap)["precise"] = PRECISE;
(*KeywordMap)["invariant"] = INVARIANT; (*KeywordMap)["invariant"] = INVARIANT;
(*KeywordMap)["packed"] = PACKED; (*KeywordMap)["packed"] = PACKED;
(*KeywordMap)["resource"] = RESOURCE; (*KeywordMap)["resource"] = RESOURCE;
(*KeywordMap)["superp"] = SUPERP; (*KeywordMap)["superp"] = SUPERP;
#ifdef NV_EXTENSIONS
(*KeywordMap)["rayPayloadNV"] = PAYLOADNV;
(*KeywordMap)["rayPayloadInNV"] = PAYLOADINNV;
(*KeywordMap)["hitAttributeNV"] = HITATTRNV;
(*KeywordMap)["callableDataNV"] = CALLDATANV;
(*KeywordMap)["callableDataInNV"] = CALLDATAINNV;
(*KeywordMap)["accelerationStructureNV"] = ACCSTRUCTNV;
(*KeywordMap)["perprimitiveNV"] = PERPRIMITIVENV;
(*KeywordMap)["perviewNV"] = PERVIEWNV;
(*KeywordMap)["taskNV"] = PERTASKNV;
#endif
ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>; ReservedSet = new std::unordered_set<const char*, str_hash, str_eq>;
ReservedSet->insert("common"); ReservedSet->insert("common");
@ -756,7 +778,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
loc = ppToken.loc; loc = ppToken.loc;
parserToken->sType.lex.loc = loc; parserToken->sType.lex.loc = loc;
switch (token) { switch (token) {
case ';': afterType = false; return SEMICOLON; case ';': afterType = false; afterBuffer = false; return SEMICOLON;
case ',': afterType = false; return COMMA; case ',': afterType = false; return COMMA;
case ':': return COLON; case ':': return COLON;
case '=': afterType = false; return EQUAL; case '=': afterType = false; return EQUAL;
@ -778,7 +800,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token)
case '?': return QUESTION; case '?': return QUESTION;
case '[': return LEFT_BRACKET; case '[': return LEFT_BRACKET;
case ']': return RIGHT_BRACKET; case ']': return RIGHT_BRACKET;
case '{': afterStruct = false; return LEFT_BRACE; case '{': afterStruct = false; afterBuffer = false; return LEFT_BRACE;
case '}': return RIGHT_BRACE; case '}': return RIGHT_BRACE;
case '\\': case '\\':
parseContext.error(loc, "illegal use of escape character", "\\", ""); parseContext.error(loc, "illegal use of escape character", "\\", "");
@ -925,11 +947,26 @@ int TScanContext::tokenizeIdentifier()
return keyword; return keyword;
case BUFFER: case BUFFER:
afterBuffer = true;
if ((parseContext.profile == EEsProfile && parseContext.version < 310) || if ((parseContext.profile == EEsProfile && parseContext.version < 310) ||
(parseContext.profile != EEsProfile && parseContext.version < 430)) (parseContext.profile != EEsProfile && parseContext.version < 430))
return identifierOrType(); return identifierOrType();
return keyword; return keyword;
#ifdef NV_EXTENSIONS
case PAYLOADNV:
case PAYLOADINNV:
case HITATTRNV:
case CALLDATANV:
case CALLDATAINNV:
case ACCSTRUCTNV:
if (parseContext.symbolTable.atBuiltInLevel() ||
(parseContext.profile != EEsProfile && parseContext.version >= 460
&& parseContext.extensionTurnedOn(E_GL_NV_ray_tracing)))
return keyword;
return identifierOrType();
#endif
case ATOMIC_UINT: case ATOMIC_UINT:
if ((parseContext.profile == EEsProfile && parseContext.version >= 310) || if ((parseContext.profile == EEsProfile && parseContext.version >= 310) ||
parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters)) parseContext.extensionTurnedOn(E_GL_ARB_shader_atomic_counters))
@ -937,6 +974,11 @@ int TScanContext::tokenizeIdentifier()
return es30ReservedFromGLSL(420); return es30ReservedFromGLSL(420);
case COHERENT: case COHERENT:
case DEVICECOHERENT:
case QUEUEFAMILYCOHERENT:
case WORKGROUPCOHERENT:
case SUBGROUPCOHERENT:
case NONPRIVATE:
case RESTRICT: case RESTRICT:
case READONLY: case READONLY:
case WRITEONLY: case WRITEONLY:
@ -1094,8 +1136,8 @@ int TScanContext::tokenizeIdentifier()
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
(parseContext.profile != EEsProfile && parseContext.version >= 450 && (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
(parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) || (parseContext.extensionTurnedOn(E_GL_ARB_gpu_shader_int64) ||
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int64)))) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int64))))
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
@ -1109,9 +1151,9 @@ int TScanContext::tokenizeIdentifier()
case U8VEC4: case U8VEC4:
afterType = true; afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
((parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_EXT_shader_8bit_storage) || parseContext.extensionTurnedOn(E_GL_EXT_shader_8bit_storage) ||
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int8)) && parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int8)) &&
parseContext.profile != EEsProfile && parseContext.version >= 450)) parseContext.profile != EEsProfile && parseContext.version >= 450))
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
@ -1132,8 +1174,8 @@ int TScanContext::tokenizeIdentifier()
parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) || parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_int16) ||
#endif #endif
parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) || parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) ||
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int16)))) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int16))))
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
case INT32_T: case INT32_T:
@ -1146,8 +1188,8 @@ int TScanContext::tokenizeIdentifier()
case U32VEC4: case U32VEC4:
afterType = true; afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
((parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_int32)) && parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_int32)) &&
parseContext.profile != EEsProfile && parseContext.version >= 450)) parseContext.profile != EEsProfile && parseContext.version >= 450))
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
@ -1169,8 +1211,8 @@ int TScanContext::tokenizeIdentifier()
case F32MAT4X4: case F32MAT4X4:
afterType = true; afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
((parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_float32)) && parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float32)) &&
parseContext.profile != EEsProfile && parseContext.version >= 450)) parseContext.profile != EEsProfile && parseContext.version >= 450))
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
@ -1193,8 +1235,8 @@ int TScanContext::tokenizeIdentifier()
case F64MAT4X4: case F64MAT4X4:
afterType = true; afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() || if (parseContext.symbolTable.atBuiltInLevel() ||
((parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || ((parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_float64)) && parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float64)) &&
parseContext.profile != EEsProfile && parseContext.version >= 450)) parseContext.profile != EEsProfile && parseContext.version >= 450))
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
@ -1211,8 +1253,8 @@ int TScanContext::tokenizeIdentifier()
parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) || parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) ||
#endif #endif
parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) || parseContext.extensionTurnedOn(E_GL_EXT_shader_16bit_storage) ||
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_float16)))) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16))))
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
@ -1236,8 +1278,8 @@ int TScanContext::tokenizeIdentifier()
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) || parseContext.extensionTurnedOn(E_GL_AMD_gpu_shader_half_float) ||
#endif #endif
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types) || parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types) ||
parseContext.extensionTurnedOn(E_GL_KHX_shader_explicit_arithmetic_types_float16)))) parseContext.extensionTurnedOn(E_GL_EXT_shader_explicit_arithmetic_types_float16))))
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
@ -1370,6 +1412,13 @@ int TScanContext::tokenizeIdentifier()
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
case SAMPLEREXTERNAL2DY2YEXT:
afterType = true;
if (parseContext.symbolTable.atBuiltInLevel() ||
parseContext.extensionTurnedOn(E_GL_EXT_YUV_target))
return keyword;
return identifierOrType();
case TEXTURE2D: case TEXTURE2D:
case TEXTURECUBE: case TEXTURECUBE:
case TEXTURECUBEARRAY: case TEXTURECUBEARRAY:
@ -1490,13 +1539,22 @@ int TScanContext::tokenizeIdentifier()
return keyword; return keyword;
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
case __EXPLICITINTERPAMD: case EXPLICITINTERPAMD:
if (parseContext.profile != EEsProfile && parseContext.version >= 450 && if (parseContext.profile != EEsProfile && parseContext.version >= 450 &&
parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter)) parseContext.extensionTurnedOn(E_GL_AMD_shader_explicit_vertex_parameter))
return keyword; return keyword;
return identifierOrType(); return identifierOrType();
#endif #endif
#ifdef NV_EXTENSIONS
case PERVERTEXNV:
if (((parseContext.profile != EEsProfile && parseContext.version >= 450) ||
(parseContext.profile == EEsProfile && parseContext.version >= 320)) &&
parseContext.extensionTurnedOn(E_GL_NV_fragment_shader_barycentric))
return keyword;
return identifierOrType();
#endif
case FLAT: case FLAT:
if (parseContext.profile == EEsProfile && parseContext.version < 300) if (parseContext.profile == EEsProfile && parseContext.version < 300)
reservedWord(); reservedWord();
@ -1543,6 +1601,17 @@ int TScanContext::tokenizeIdentifier()
return identifierOrReserved(reserved); return identifierOrReserved(reserved);
} }
#ifdef NV_EXTENSIONS
case PERPRIMITIVENV:
case PERVIEWNV:
case PERTASKNV:
if ((parseContext.profile != EEsProfile && parseContext.version >= 450) ||
(parseContext.profile == EEsProfile && parseContext.version >= 320) ||
parseContext.extensionTurnedOn(E_GL_NV_mesh_shader))
return keyword;
return identifierOrType();
#endif
default: default:
parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc); parseContext.infoSink.info.message(EPrefixInternalError, "Unknown glslang keyword", loc);
return 0; return 0;
@ -1558,7 +1627,9 @@ int TScanContext::identifierOrType()
parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string); parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string);
if ((afterType == false && afterStruct == false) && parserToken->sType.lex.symbol != nullptr) { if ((afterType == false && afterStruct == false) && parserToken->sType.lex.symbol != nullptr) {
if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) { if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) {
if (variable->isUserType()) { if (variable->isUserType() &&
// treat redeclaration of forward-declared buffer/uniform reference as an identifier
!(variable->getType().getBasicType() == EbtReference && afterBuffer)) {
afterType = true; afterType = true;
return TYPE_NAME; return TYPE_NAME;

View file

@ -65,7 +65,7 @@ public:
} }
if (names != nullptr) { if (names != nullptr) {
for (int i = 0; i < numSources; ++i) for (int i = 0; i < numSources; ++i)
loc[i].name = names[i]; loc[i].name = names[i] != nullptr ? NewPoolTString(names[i]) : nullptr;
} }
loc[currentSource].line = 1; loc[currentSource].line = 1;
logicalSourceLoc.init(1); logicalSourceLoc.init(1);
@ -170,16 +170,18 @@ public:
// for #line override in filename based parsing // for #line override in filename based parsing
void setFile(const char* filename) void setFile(const char* filename)
{ {
logicalSourceLoc.name = filename; TString* fn_tstr = NewPoolTString(filename);
loc[getLastValidSourceIndex()].name = filename; logicalSourceLoc.name = fn_tstr;
loc[getLastValidSourceIndex()].name = fn_tstr;
} }
void setFile(const char* filename, int i) void setFile(const char* filename, int i)
{ {
TString* fn_tstr = NewPoolTString(filename);
if (i == getLastValidSourceIndex()) { if (i == getLastValidSourceIndex()) {
logicalSourceLoc.name = filename; logicalSourceLoc.name = fn_tstr;
} }
loc[i].name = filename; loc[i].name = fn_tstr;
} }
void setString(int newString) void setString(int newString)

View file

@ -53,7 +53,7 @@ public:
explicit TScanContext(TParseContextBase& pc) : explicit TScanContext(TParseContextBase& pc) :
parseContext(pc), parseContext(pc),
afterType(false), afterStruct(false), afterType(false), afterStruct(false),
field(false) { } field(false), afterBuffer(false) { }
virtual ~TScanContext() { } virtual ~TScanContext() { }
static void fillInKeywordMap(); static void fillInKeywordMap();
@ -81,6 +81,7 @@ protected:
bool afterType; // true if we've recognized a type, so can only be looking for an identifier bool afterType; // true if we've recognized a type, so can only be looking for an identifier
bool afterStruct; // true if we've recognized the STRUCT keyword, so can only be looking for an identifier bool afterStruct; // true if we've recognized the STRUCT keyword, so can only be looking for an identifier
bool field; // true if we're on a field, right after a '.' bool field; // true if we're on a field, right after a '.'
bool afterBuffer; // true if we've recognized the BUFFER keyword
TSourceLoc loc; TSourceLoc loc;
TParserToken* parserToken; TParserToken* parserToken;
TPpToken* ppToken; TPpToken* ppToken;

View file

@ -1,7 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013-2016 LunarG, Inc. // Copyright (C) 2013-2016 LunarG, Inc.
// Copyright (C) 2015-2017 Google, Inc. // Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -67,6 +67,11 @@
#include "iomapper.h" #include "iomapper.h"
#include "Initialize.h" #include "Initialize.h"
// TODO: this really shouldn't be here, it is only because of the trial addition
// of printing pre-processed tokens, which requires knowing the string literal
// token to print ", but none of that seems appropriate for this file.
#include "preprocessor/PpTokens.h"
namespace { // anonymous namespace for file-local functions and symbols namespace { // anonymous namespace for file-local functions and symbols
// Total number of successful initializers of glslang: a refcount // Total number of successful initializers of glslang: a refcount
@ -342,6 +347,36 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source, InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source,
infoSink, commonTable, symbolTables); infoSink, commonTable, symbolTables);
#ifdef NV_EXTENSIONS
// check for ray tracing stages
if (profile != EEsProfile && version >= 450) {
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGenNV, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersectNV, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHitNV, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHitNV, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMissNV, source,
infoSink, commonTable, symbolTables);
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallableNV, source,
infoSink, commonTable, symbolTables);
}
// check for mesh
if ((profile != EEsProfile && version >= 450) ||
(profile == EEsProfile && version >= 320))
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMeshNV, source,
infoSink, commonTable, symbolTables);
// check for task
if ((profile != EEsProfile && version >= 450) ||
(profile == EEsProfile && version >= 320))
InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source,
infoSink, commonTable, symbolTables);
#endif
return true; return true;
} }
@ -565,6 +600,28 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo
version = profile == EEsProfile ? 310 : 420; version = profile == EEsProfile ? 310 : 420;
} }
break; break;
#ifdef NV_EXTENSIONS
case EShLangRayGenNV:
case EShLangIntersectNV:
case EShLangAnyHitNV:
case EShLangClosestHitNV:
case EShLangMissNV:
case EShLangCallableNV:
if (profile == EEsProfile || version < 460) {
correct = false;
infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above");
version = 460;
}
break;
case EShLangMeshNV:
case EShLangTaskNV:
if ((profile == EEsProfile && version < 320) ||
(profile != EEsProfile && version < 450)) {
correct = false;
infoSink.info.message(EPrefixError, "#version: mesh/task shaders require es profile with version 320 or above, or non-es profile with version 450 or above");
version = profile == EEsProfile ? 320 : 450;
}
#endif
default: default:
break; break;
} }
@ -822,8 +879,11 @@ bool ProcessDeferred(
intermediate.setHlslOffsets(); intermediate.setHlslOffsets();
if (messages & EShMsgDebugInfo) { if (messages & EShMsgDebugInfo) {
intermediate.setSourceFile(names[numPre]); intermediate.setSourceFile(names[numPre]);
for (int s = 0; s < numStrings; ++s) for (int s = 0; s < numStrings; ++s) {
intermediate.addSourceText(strings[numPre + s]); // The string may not be null-terminated, so make sure we provide
// the length along with the string.
intermediate.addSourceText(strings[numPre + s], lengths[numPre + s]);
}
} }
SetupBuiltinSymbolTable(version, profile, spvVersion, source); SetupBuiltinSymbolTable(version, profile, spvVersion, source);
@ -965,6 +1025,8 @@ private:
// DoPreprocessing is a valid ProcessingContext template argument, // DoPreprocessing is a valid ProcessingContext template argument,
// which only performs the preprocessing step of compilation. // which only performs the preprocessing step of compilation.
// It places the result in the "string" argument to its constructor. // It places the result in the "string" argument to its constructor.
//
// This is not an officially supported or fully working path.
struct DoPreprocessing { struct DoPreprocessing {
explicit DoPreprocessing(std::string* string): outputString(string) {} explicit DoPreprocessing(std::string* string): outputString(string) {}
bool operator()(TParseContextBase& parseContext, TPpContext& ppContext, bool operator()(TParseContextBase& parseContext, TPpContext& ppContext,
@ -1072,7 +1134,11 @@ struct DoPreprocessing {
outputBuffer += ' '; outputBuffer += ' ';
} }
lastToken = token; lastToken = token;
if (token == PpAtomConstString)
outputBuffer += "\"";
outputBuffer += ppToken.name; outputBuffer += ppToken.name;
if (token == PpAtomConstString)
outputBuffer += "\"";
} while (true); } while (true);
outputBuffer += '\n'; outputBuffer += '\n';
*outputString = std::move(outputBuffer); *outputString = std::move(outputBuffer);
@ -1122,6 +1188,9 @@ struct DoFullParse{
// Return: True if there were no issues found in preprocessing, // Return: True if there were no issues found in preprocessing,
// False if during preprocessing any unknown version, pragmas or // False if during preprocessing any unknown version, pragmas or
// extensions were found. // extensions were found.
//
// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
// is not an officially supported or fully working path.
bool PreprocessDeferred( bool PreprocessDeferred(
TCompiler* compiler, TCompiler* compiler,
const char* const shaderStrings[], const char* const shaderStrings[],
@ -1266,7 +1335,7 @@ void ShDestruct(ShHandle handle)
// //
// Cleanup symbol tables // Cleanup symbol tables
// //
int __fastcall ShFinalize() int ShFinalize()
{ {
glslang::GetGlobalLock(); glslang::GetGlobalLock();
--NumberOfClients; --NumberOfClients;
@ -1695,6 +1764,14 @@ void TShader::setAutoMapBindings(bool map) { intermediate->setAutoM
void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); } void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); }
// Fragile: currently within one stage: simple auto-assignment of location // Fragile: currently within one stage: simple auto-assignment of location
void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); } void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); }
void TShader::addUniformLocationOverride(const char* name, int loc)
{
intermediate->addUniformLocationOverride(name, loc);
}
void TShader::setUniformLocationBase(int base)
{
intermediate->setUniformLocationBase(base);
}
// See comment above TDefaultHlslIoMapper in iomapper.cpp: // See comment above TDefaultHlslIoMapper in iomapper.cpp:
void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); } void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); }
void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); } void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); }
@ -1726,6 +1803,9 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion
// Fill in a string with the result of preprocessing ShaderStrings // Fill in a string with the result of preprocessing ShaderStrings
// Returns true if all extensions, pragmas and version strings were valid. // Returns true if all extensions, pragmas and version strings were valid.
//
// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
// is not an officially supported or fully working path.
bool TShader::preprocess(const TBuiltInResource* builtInResources, bool TShader::preprocess(const TBuiltInResource* builtInResources,
int defaultVersion, EProfile defaultProfile, int defaultVersion, EProfile defaultProfile,
bool forceDefaultVersionAndProfile, bool forceDefaultVersionAndProfile,

View file

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -72,6 +73,9 @@ void TType::buildMangledName(TString& mangledName) const
case EbtUint64: mangledName += "u64"; break; case EbtUint64: mangledName += "u64"; break;
case EbtBool: mangledName += 'b'; break; case EbtBool: mangledName += 'b'; break;
case EbtAtomicUint: mangledName += "au"; break; case EbtAtomicUint: mangledName += "au"; break;
#ifdef NV_EXTENSIONS
case EbtAccStructNV: mangledName += "asnv"; break;
#endif
case EbtSampler: case EbtSampler:
switch (sampler.type) { switch (sampler.type) {
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
@ -95,6 +99,8 @@ void TType::buildMangledName(TString& mangledName) const
mangledName += "S"; mangledName += "S";
if (sampler.external) if (sampler.external)
mangledName += "E"; mangledName += "E";
if (sampler.yuv)
mangledName += "Y";
switch (sampler.dim) { switch (sampler.dim) {
case Esd1D: mangledName += "1"; break; case Esd1D: mangledName += "1"; break;
case Esd2D: mangledName += "2"; break; case Esd2D: mangledName += "2"; break;
@ -283,19 +289,25 @@ TVariable::TVariable(const TVariable& copyOf) : TSymbol(copyOf)
{ {
type.deepCopy(copyOf.type); type.deepCopy(copyOf.type);
userType = copyOf.userType; userType = copyOf.userType;
numExtensions = 0;
extensions = 0; // we don't support specialization-constant subtrees in cloned tables, only extensions
if (copyOf.numExtensions != 0) constSubtree = nullptr;
setExtensions(copyOf.numExtensions, copyOf.extensions); extensions = nullptr;
memberExtensions = nullptr;
if (copyOf.getNumExtensions() > 0)
setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions());
if (copyOf.hasMemberExtensions()) {
for (int m = 0; m < (int)copyOf.type.getStruct()->size(); ++m) {
if (copyOf.getNumMemberExtensions(m) > 0)
setMemberExtensions(m, copyOf.getNumMemberExtensions(m), copyOf.getMemberExtensions(m));
}
}
if (! copyOf.constArray.empty()) { if (! copyOf.constArray.empty()) {
assert(! copyOf.type.isStruct()); assert(! copyOf.type.isStruct());
TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size()); TConstUnionArray newArray(copyOf.constArray, 0, copyOf.constArray.size());
constArray = newArray; constArray = newArray;
} }
// don't support specialization-constant subtrees in cloned tables
constSubtree = nullptr;
} }
TVariable* TVariable::clone() const TVariable* TVariable::clone() const
@ -313,10 +325,9 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
parameters.back().copyParam(copyOf.parameters[i]); parameters.back().copyParam(copyOf.parameters[i]);
} }
numExtensions = 0; extensions = nullptr;
extensions = 0; if (copyOf.getNumExtensions() > 0)
if (copyOf.extensions != 0) setExtensions(copyOf.getNumExtensions(), copyOf.getExtensions());
setExtensions(copyOf.numExtensions, copyOf.extensions);
returnType.deepCopy(copyOf.returnType); returnType.deepCopy(copyOf.returnType);
mangledName = copyOf.mangledName; mangledName = copyOf.mangledName;
op = copyOf.op; op = copyOf.op;
@ -355,12 +366,12 @@ TSymbolTableLevel* TSymbolTableLevel::clone() const
const TAnonMember* anon = iter->second->getAsAnonMember(); const TAnonMember* anon = iter->second->getAsAnonMember();
if (anon) { if (anon) {
// Insert all the anonymous members of this same container at once, // Insert all the anonymous members of this same container at once,
// avoid inserting the other members in the future, once this has been done, // avoid inserting the remaining members in the future, once this has been done,
// allowing them to all be part of the same new container. // allowing them to all be part of the same new container.
if (! containerCopied[anon->getAnonId()]) { if (! containerCopied[anon->getAnonId()]) {
TVariable* container = anon->getAnonContainer().clone(); TVariable* container = anon->getAnonContainer().clone();
container->changeName(NewPoolTString("")); container->changeName(NewPoolTString(""));
// insert the whole container // insert the container and all its members
symTableLevel->insert(*container, false); symTableLevel->insert(*container, false);
containerCopied[anon->getAnonId()] = true; containerCopied[anon->getAnonId()] = true;
} }

View file

@ -1,6 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013 LunarG, Inc. // Copyright (C) 2013 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -78,10 +79,12 @@ class TVariable;
class TFunction; class TFunction;
class TAnonMember; class TAnonMember;
typedef TVector<const char*> TExtensionList;
class TSymbol { class TSymbol {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator()) POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
explicit TSymbol(const TString *n) : name(n), numExtensions(0), extensions(0), writable(true) { } explicit TSymbol(const TString *n) : name(n), extensions(0), writable(true) { }
virtual TSymbol* clone() const = 0; virtual TSymbol* clone() const = 0;
virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool virtual ~TSymbol() { } // rely on all symbol owned memory coming from the pool
@ -103,17 +106,16 @@ public:
virtual TType& getWritableType() = 0; virtual TType& getWritableType() = 0;
virtual void setUniqueId(int id) { uniqueId = id; } virtual void setUniqueId(int id) { uniqueId = id; }
virtual int getUniqueId() const { return uniqueId; } virtual int getUniqueId() const { return uniqueId; }
virtual void setExtensions(int num, const char* const exts[]) virtual void setExtensions(int numExts, const char* const exts[])
{ {
assert(extensions == 0); assert(extensions == 0);
assert(num > 0); assert(numExts > 0);
numExtensions = num; extensions = NewPoolObject(extensions);
extensions = NewPoolObject(exts[0], num); for (int e = 0; e < numExts; ++e)
for (int e = 0; e < num; ++e) extensions->push_back(exts[e]);
extensions[e] = exts[e];
} }
virtual int getNumExtensions() const { return numExtensions; } virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); }
virtual const char** getExtensions() const { return extensions; } virtual const char** getExtensions() const { return extensions->data(); }
virtual void dump(TInfoSink &infoSink) const = 0; virtual void dump(TInfoSink &infoSink) const = 0;
virtual bool isReadOnly() const { return ! writable; } virtual bool isReadOnly() const { return ! writable; }
@ -128,8 +130,7 @@ protected:
// For tracking what extensions must be present // For tracking what extensions must be present
// (don't use if correct version/profile is present). // (don't use if correct version/profile is present).
int numExtensions; TExtensionList* extensions; // an array of pointers to existing constant char strings
const char** extensions; // an array of pointers to existing constant char strings
// //
// N.B.: Non-const functions that will be generally used should assert on this, // N.B.: Non-const functions that will be generally used should assert on this,
@ -154,7 +155,9 @@ public:
: TSymbol(name), : TSymbol(name),
userType(uT), userType(uT),
constSubtree(nullptr), constSubtree(nullptr),
anonId(-1) { type.shallowCopy(t); } memberExtensions(nullptr),
anonId(-1)
{ type.shallowCopy(t); }
virtual TVariable* clone() const; virtual TVariable* clone() const;
virtual ~TVariable() { } virtual ~TVariable() { }
@ -171,6 +174,24 @@ public:
virtual void setAnonId(int i) { anonId = i; } virtual void setAnonId(int i) { anonId = i; }
virtual int getAnonId() const { return anonId; } virtual int getAnonId() const { return anonId; }
virtual void setMemberExtensions(int member, int numExts, const char* const exts[])
{
assert(type.isStruct());
assert(numExts > 0);
if (memberExtensions == nullptr) {
memberExtensions = NewPoolObject(memberExtensions);
memberExtensions->resize(type.getStruct()->size());
}
for (int e = 0; e < numExts; ++e)
(*memberExtensions)[member].push_back(exts[e]);
}
virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; }
virtual int getNumMemberExtensions(int member) const
{
return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size();
}
virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); }
virtual void dump(TInfoSink &infoSink) const; virtual void dump(TInfoSink &infoSink) const;
protected: protected:
@ -179,15 +200,14 @@ protected:
TType type; TType type;
bool userType; bool userType;
// we are assuming that Pool Allocator will free the memory allocated to unionArray // we are assuming that Pool Allocator will free the memory allocated to unionArray
// when this object is destroyed // when this object is destroyed
// TODO: these two should be a union TConstUnionArray constArray; // for compile-time constant value
// A variable could be a compile-time constant, or a specialization TIntermTyped* constSubtree; // for specialization constant computation
// constant, or neither, but never both. TVector<TExtensionList>* memberExtensions; // per-member extension list, allocated only when needed
TConstUnionArray constArray; // for compile-time constant value int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose
TIntermTyped* constSubtree; // for specialization constant computation
int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose
}; };
// //
@ -324,35 +344,42 @@ protected:
// //
class TAnonMember : public TSymbol { class TAnonMember : public TSymbol {
public: public:
TAnonMember(const TString* n, unsigned int m, const TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { } TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { }
virtual TAnonMember* clone() const; virtual TAnonMember* clone() const override;
virtual ~TAnonMember() { } virtual ~TAnonMember() { }
virtual const TAnonMember* getAsAnonMember() const { return this; } virtual const TAnonMember* getAsAnonMember() const override { return this; }
virtual const TVariable& getAnonContainer() const { return anonContainer; } virtual const TVariable& getAnonContainer() const { return anonContainer; }
virtual unsigned int getMemberNumber() const { return memberNumber; } virtual unsigned int getMemberNumber() const { return memberNumber; }
virtual const TType& getType() const virtual const TType& getType() const override
{ {
const TTypeList& types = *anonContainer.getType().getStruct(); const TTypeList& types = *anonContainer.getType().getStruct();
return *types[memberNumber].type; return *types[memberNumber].type;
} }
virtual TType& getWritableType() virtual TType& getWritableType() override
{ {
assert(writable); assert(writable);
const TTypeList& types = *anonContainer.getType().getStruct(); const TTypeList& types = *anonContainer.getType().getStruct();
return *types[memberNumber].type; return *types[memberNumber].type;
} }
virtual void setExtensions(int numExts, const char* const exts[]) override
{
anonContainer.setMemberExtensions(memberNumber, numExts, exts);
}
virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); }
virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); }
virtual int getAnonId() const { return anonId; } virtual int getAnonId() const { return anonId; }
virtual void dump(TInfoSink &infoSink) const; virtual void dump(TInfoSink &infoSink) const override;
protected: protected:
explicit TAnonMember(const TAnonMember&); explicit TAnonMember(const TAnonMember&);
TAnonMember& operator=(const TAnonMember&); TAnonMember& operator=(const TAnonMember&);
const TVariable& anonContainer; TVariable& anonContainer;
unsigned int memberNumber; unsigned int memberNumber;
int anonId; int anonId;
}; };
@ -788,11 +815,30 @@ public:
table[level]->setFunctionExtensions(name, num, extensions); table[level]->setFunctionExtensions(name, num, extensions);
} }
void setVariableExtensions(const char* name, int num, const char* const extensions[]) void setVariableExtensions(const char* name, int numExts, const char* const extensions[])
{ {
TSymbol* symbol = find(TString(name)); TSymbol* symbol = find(TString(name));
if (symbol) if (symbol == nullptr)
symbol->setExtensions(num, extensions); return;
symbol->setExtensions(numExts, extensions);
}
void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[])
{
TSymbol* symbol = find(TString(blockName));
if (symbol == nullptr)
return;
TVariable* variable = symbol->getAsVariable();
assert(variable != nullptr);
const TTypeList& structure = *variable->getAsVariable()->getType().getStruct();
for (int member = 0; member < (int)structure.size(); ++member) {
if (structure[member].type->getFieldName().compare(name) == 0) {
variable->setMemberExtensions(member, numExts, extensions);
return;
}
}
} }
int getMaxSymbolId() { return uniqueId; } int getMaxSymbolId() { return uniqueId; }

View file

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -156,6 +157,7 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable; extensionBehavior[E_GL_EXT_frag_depth] = EBhDisable;
extensionBehavior[E_GL_OES_EGL_image_external] = EBhDisable; extensionBehavior[E_GL_OES_EGL_image_external] = EBhDisable;
extensionBehavior[E_GL_OES_EGL_image_external_essl3] = EBhDisable; extensionBehavior[E_GL_OES_EGL_image_external_essl3] = EBhDisable;
extensionBehavior[E_GL_EXT_YUV_target] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_texture_lod] = EBhDisable; extensionBehavior[E_GL_EXT_shader_texture_lod] = EBhDisable;
extensionBehavior[E_GL_EXT_shadow_samplers] = EBhDisable; extensionBehavior[E_GL_EXT_shadow_samplers] = EBhDisable;
extensionBehavior[E_GL_ARB_texture_rectangle] = EBhDisable; extensionBehavior[E_GL_ARB_texture_rectangle] = EBhDisable;
@ -194,6 +196,9 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_KHR_shader_subgroup_shuffle_relative] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_shuffle_relative] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_clustered] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_clustered] = EBhDisable;
extensionBehavior[E_GL_KHR_shader_subgroup_quad] = EBhDisable; extensionBehavior[E_GL_KHR_shader_subgroup_quad] = EBhDisable;
extensionBehavior[E_GL_KHR_memory_scope_semantics] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_atomic_int64] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_non_constant_global_initializers] = EBhDisable; extensionBehavior[E_GL_EXT_shader_non_constant_global_initializers] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_image_load_formatted] = EBhDisable; extensionBehavior[E_GL_EXT_shader_image_load_formatted] = EBhDisable;
@ -201,6 +206,9 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_EXT_control_flow_attributes] = EBhDisable; extensionBehavior[E_GL_EXT_control_flow_attributes] = EBhDisable;
extensionBehavior[E_GL_EXT_nonuniform_qualifier] = EBhDisable; extensionBehavior[E_GL_EXT_nonuniform_qualifier] = EBhDisable;
extensionBehavior[E_GL_EXT_samplerless_texture_functions] = EBhDisable; extensionBehavior[E_GL_EXT_samplerless_texture_functions] = EBhDisable;
extensionBehavior[E_GL_EXT_scalar_block_layout] = EBhDisable;
extensionBehavior[E_GL_EXT_fragment_invocation_density] = EBhDisable;
extensionBehavior[E_GL_EXT_buffer_reference] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable; extensionBehavior[E_GL_EXT_shader_16bit_storage] = EBhDisable;
extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable; extensionBehavior[E_GL_EXT_shader_8bit_storage] = EBhDisable;
@ -232,6 +240,12 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_NV_conservative_raster_underestimation] = EBhDisable; extensionBehavior[E_GL_NV_conservative_raster_underestimation] = EBhDisable;
extensionBehavior[E_GL_NV_shader_noperspective_interpolation] = EBhDisable; extensionBehavior[E_GL_NV_shader_noperspective_interpolation] = EBhDisable;
extensionBehavior[E_GL_NV_shader_subgroup_partitioned] = EBhDisable; extensionBehavior[E_GL_NV_shader_subgroup_partitioned] = EBhDisable;
extensionBehavior[E_GL_NV_shading_rate_image] = EBhDisable;
extensionBehavior[E_GL_NV_ray_tracing] = EBhDisable;
extensionBehavior[E_GL_NV_fragment_shader_barycentric] = EBhDisable;
extensionBehavior[E_GL_NV_compute_shader_derivatives] = EBhDisable;
extensionBehavior[E_GL_NV_shader_texture_footprint] = EBhDisable;
extensionBehavior[E_GL_NV_mesh_shader] = EBhDisable;
#endif #endif
// AEP // AEP
@ -271,14 +285,14 @@ void TParseVersions::initializeExtensionBehavior()
extensionBehavior[E_GL_OVR_multiview2] = EBhDisable; extensionBehavior[E_GL_OVR_multiview2] = EBhDisable;
// explicit types // explicit types
extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types] = EBhDisable; extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types] = EBhDisable;
extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_int8] = EBhDisable; extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int8] = EBhDisable;
extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_int16] = EBhDisable; extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int16] = EBhDisable;
extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_int32] = EBhDisable; extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int32] = EBhDisable;
extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_int64] = EBhDisable; extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_int64] = EBhDisable;
extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_float16] = EBhDisable; extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float16] = EBhDisable;
extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_float32] = EBhDisable; extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float32] = EBhDisable;
extensionBehavior[E_GL_KHX_shader_explicit_arithmetic_types_float64] = EBhDisable; extensionBehavior[E_GL_EXT_shader_explicit_arithmetic_types_float64] = EBhDisable;
} }
// Get code that is not part of a shared symbol table, is specific to this shader, // Get code that is not part of a shared symbol table, is specific to this shader,
@ -294,6 +308,7 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_frag_depth 1\n" "#define GL_EXT_frag_depth 1\n"
"#define GL_OES_EGL_image_external 1\n" "#define GL_OES_EGL_image_external 1\n"
"#define GL_OES_EGL_image_external_essl3 1\n" "#define GL_OES_EGL_image_external_essl3 1\n"
"#define GL_EXT_YUV_target 1\n"
"#define GL_EXT_shader_texture_lod 1\n" "#define GL_EXT_shader_texture_lod 1\n"
"#define GL_EXT_shadow_samplers 1\n" "#define GL_EXT_shadow_samplers 1\n"
@ -369,6 +384,9 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_EXT_shader_16bit_storage 1\n" "#define GL_EXT_shader_16bit_storage 1\n"
"#define GL_EXT_shader_8bit_storage 1\n" "#define GL_EXT_shader_8bit_storage 1\n"
"#define GL_EXT_samplerless_texture_functions 1\n" "#define GL_EXT_samplerless_texture_functions 1\n"
"#define GL_EXT_scalar_block_layout 1\n"
"#define GL_EXT_fragment_invocation_density 1\n"
"#define GL_EXT_buffer_reference 1\n"
// GL_KHR_shader_subgroup // GL_KHR_shader_subgroup
"#define GL_KHR_shader_subgroup_basic 1\n" "#define GL_KHR_shader_subgroup_basic 1\n"
@ -380,6 +398,8 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_KHR_shader_subgroup_clustered 1\n" "#define GL_KHR_shader_subgroup_clustered 1\n"
"#define GL_KHR_shader_subgroup_quad 1\n" "#define GL_KHR_shader_subgroup_quad 1\n"
"#define E_GL_EXT_shader_atomic_int64 1\n"
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
"#define GL_AMD_shader_ballot 1\n" "#define GL_AMD_shader_ballot 1\n"
"#define GL_AMD_shader_trinary_minmax 1\n" "#define GL_AMD_shader_trinary_minmax 1\n"
@ -400,15 +420,21 @@ void TParseVersions::getPreamble(std::string& preamble)
"#define GL_NV_shader_atomic_int64 1\n" "#define GL_NV_shader_atomic_int64 1\n"
"#define GL_NV_conservative_raster_underestimation 1\n" "#define GL_NV_conservative_raster_underestimation 1\n"
"#define GL_NV_shader_subgroup_partitioned 1\n" "#define GL_NV_shader_subgroup_partitioned 1\n"
"#define GL_NV_shading_rate_image 1\n"
"#define GL_NV_ray_tracing 1\n"
"#define GL_NV_fragment_shader_barycentric 1\n"
"#define GL_NV_compute_shader_derivatives 1\n"
"#define GL_NV_shader_texture_footprint 1\n"
"#define GL_NV_mesh_shader 1\n"
#endif #endif
"#define GL_KHX_shader_explicit_arithmetic_types 1\n" "#define GL_EXT_shader_explicit_arithmetic_types 1\n"
"#define GL_KHX_shader_explicit_arithmetic_types_int8 1\n" "#define GL_EXT_shader_explicit_arithmetic_types_int8 1\n"
"#define GL_KHX_shader_explicit_arithmetic_types_int16 1\n" "#define GL_EXT_shader_explicit_arithmetic_types_int16 1\n"
"#define GL_KHX_shader_explicit_arithmetic_types_int32 1\n" "#define GL_EXT_shader_explicit_arithmetic_types_int32 1\n"
"#define GL_KHX_shader_explicit_arithmetic_types_int64 1\n" "#define GL_EXT_shader_explicit_arithmetic_types_int64 1\n"
"#define GL_KHX_shader_explicit_arithmetic_types_float16 1\n" "#define GL_EXT_shader_explicit_arithmetic_types_float16 1\n"
"#define GL_KHX_shader_explicit_arithmetic_types_float32 1\n" "#define GL_EXT_shader_explicit_arithmetic_types_float32 1\n"
"#define GL_KHX_shader_explicit_arithmetic_types_float64 1\n" "#define GL_EXT_shader_explicit_arithmetic_types_float64 1\n"
; ;
if (version >= 150) { if (version >= 150) {
@ -487,6 +513,16 @@ const char* StageName(EShLanguage stage)
case EShLangGeometry: return "geometry"; case EShLangGeometry: return "geometry";
case EShLangFragment: return "fragment"; case EShLangFragment: return "fragment";
case EShLangCompute: return "compute"; case EShLangCompute: return "compute";
#ifdef NV_EXTENSIONS
case EShLangRayGenNV: return "ray-generation";
case EShLangIntersectNV: return "intersection";
case EShLangAnyHitNV: return "any-hit";
case EShLangClosestHitNV: return "closest-hit";
case EShLangMissNV: return "miss";
case EShLangCallableNV: return "callable";
case EShLangMeshNV: return "mesh";
case EShLangTaskNV: return "task";
#endif
default: return "unknown stage"; default: return "unknown stage";
} }
} }
@ -715,6 +751,9 @@ void TParseVersions::updateExtensionBehavior(int line, const char* extension, co
return; return;
} }
// check if extension is used with correct shader stage
checkExtensionStage(getCurrentLoc(), extension);
// update the requested extension // update the requested extension
updateExtensionBehavior(extension, behavior); updateExtensionBehavior(extension, behavior);
@ -807,6 +846,20 @@ void TParseVersions::updateExtensionBehavior(const char* extension, TExtensionBe
} }
} }
// Check if extension is used with correct shader stage.
void TParseVersions::checkExtensionStage(const TSourceLoc& loc, const char * const extension)
{
#ifdef NV_EXTENSIONS
// GL_NV_mesh_shader extension is only allowed in task/mesh shaders
if (strcmp(extension, "GL_NV_mesh_shader") == 0) {
requireStage(loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask | EShLangFragmentMask),
"#extension GL_NV_mesh_shader");
profileRequires(loc, ECoreProfile, 450, 0, "#extension GL_NV_mesh_shader");
profileRequires(loc, EEsProfile, 320, 0, "#extension GL_NV_mesh_shader");
}
#endif
}
// Call for any operation needing full GLSL integer data-type support. // Call for any operation needing full GLSL integer data-type support.
void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op) void TParseVersions::fullIntegerCheck(const TSourceLoc& loc, const char* op)
{ {
@ -829,8 +882,8 @@ void TParseVersions::float16Check(const TSourceLoc& loc, const char* op, bool bu
#if AMD_EXTENSIONS #if AMD_EXTENSIONS
E_GL_AMD_gpu_shader_half_float, E_GL_AMD_gpu_shader_half_float,
#endif #endif
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_float16}; E_GL_EXT_shader_explicit_arithmetic_types_float16};
requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
} }
} }
@ -841,8 +894,8 @@ bool TParseVersions::float16Arithmetic()
#if AMD_EXTENSIONS #if AMD_EXTENSIONS
E_GL_AMD_gpu_shader_half_float, E_GL_AMD_gpu_shader_half_float,
#endif #endif
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_float16}; E_GL_EXT_shader_explicit_arithmetic_types_float16};
return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions); return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions);
} }
@ -852,16 +905,16 @@ bool TParseVersions::int16Arithmetic()
#if AMD_EXTENSIONS #if AMD_EXTENSIONS
E_GL_AMD_gpu_shader_int16, E_GL_AMD_gpu_shader_int16,
#endif #endif
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int16}; E_GL_EXT_shader_explicit_arithmetic_types_int16};
return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions); return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions);
} }
bool TParseVersions::int8Arithmetic() bool TParseVersions::int8Arithmetic()
{ {
const char* const extensions[] = { const char* const extensions[] = {
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int8}; E_GL_EXT_shader_explicit_arithmetic_types_int8};
return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions); return extensionsTurnedOn(sizeof(extensions)/sizeof(extensions[0]), extensions);
} }
@ -876,8 +929,8 @@ void TParseVersions::requireFloat16Arithmetic(const TSourceLoc& loc, const char*
#if AMD_EXTENSIONS #if AMD_EXTENSIONS
E_GL_AMD_gpu_shader_half_float, E_GL_AMD_gpu_shader_half_float,
#endif #endif
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_float16}; E_GL_EXT_shader_explicit_arithmetic_types_float16};
requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str()); requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str());
} }
@ -892,8 +945,8 @@ void TParseVersions::requireInt16Arithmetic(const TSourceLoc& loc, const char* o
#if AMD_EXTENSIONS #if AMD_EXTENSIONS
E_GL_AMD_gpu_shader_int16, E_GL_AMD_gpu_shader_int16,
#endif #endif
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int16}; E_GL_EXT_shader_explicit_arithmetic_types_int16};
requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str()); requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str());
} }
@ -905,8 +958,8 @@ void TParseVersions::requireInt8Arithmetic(const TSourceLoc& loc, const char* op
combined += featureDesc; combined += featureDesc;
const char* const extensions[] = { const char* const extensions[] = {
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int8}; E_GL_EXT_shader_explicit_arithmetic_types_int8};
requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str()); requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, combined.c_str());
} }
@ -918,8 +971,8 @@ void TParseVersions::float16ScalarVectorCheck(const TSourceLoc& loc, const char*
E_GL_AMD_gpu_shader_half_float, E_GL_AMD_gpu_shader_half_float,
#endif #endif
E_GL_EXT_shader_16bit_storage, E_GL_EXT_shader_16bit_storage,
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_float16}; E_GL_EXT_shader_explicit_arithmetic_types_float16};
requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
} }
} }
@ -928,8 +981,8 @@ void TParseVersions::float16ScalarVectorCheck(const TSourceLoc& loc, const char*
void TParseVersions::explicitFloat32Check(const TSourceLoc& loc, const char* op, bool builtIn) void TParseVersions::explicitFloat32Check(const TSourceLoc& loc, const char* op, bool builtIn)
{ {
if (!builtIn) { if (!builtIn) {
const char* const extensions[2] = {E_GL_KHX_shader_explicit_arithmetic_types, const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_float32}; E_GL_EXT_shader_explicit_arithmetic_types_float32};
requireExtensions(loc, 2, extensions, op); requireExtensions(loc, 2, extensions, op);
} }
} }
@ -938,8 +991,8 @@ void TParseVersions::explicitFloat32Check(const TSourceLoc& loc, const char* op,
void TParseVersions::explicitFloat64Check(const TSourceLoc& loc, const char* op, bool builtIn) void TParseVersions::explicitFloat64Check(const TSourceLoc& loc, const char* op, bool builtIn)
{ {
if (!builtIn) { if (!builtIn) {
const char* const extensions[2] = {E_GL_KHX_shader_explicit_arithmetic_types, const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_float64}; E_GL_EXT_shader_explicit_arithmetic_types_float64};
requireExtensions(loc, 2, extensions, op); requireExtensions(loc, 2, extensions, op);
requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op); profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op);
@ -950,8 +1003,8 @@ void TParseVersions::explicitFloat64Check(const TSourceLoc& loc, const char* op,
void TParseVersions::explicitInt8Check(const TSourceLoc& loc, const char* op, bool builtIn) void TParseVersions::explicitInt8Check(const TSourceLoc& loc, const char* op, bool builtIn)
{ {
if (! builtIn) { if (! builtIn) {
const char* const extensions[2] = {E_GL_KHX_shader_explicit_arithmetic_types, const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int8}; E_GL_EXT_shader_explicit_arithmetic_types_int8};
requireExtensions(loc, 2, extensions, op); requireExtensions(loc, 2, extensions, op);
} }
} }
@ -976,8 +1029,8 @@ void TParseVersions::explicitInt16Check(const TSourceLoc& loc, const char* op, b
#if AMD_EXTENSIONS #if AMD_EXTENSIONS
E_GL_AMD_gpu_shader_int16, E_GL_AMD_gpu_shader_int16,
#endif #endif
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int16}; E_GL_EXT_shader_explicit_arithmetic_types_int16};
requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
} }
} }
@ -990,8 +1043,8 @@ void TParseVersions::int16ScalarVectorCheck(const TSourceLoc& loc, const char* o
E_GL_AMD_gpu_shader_int16, E_GL_AMD_gpu_shader_int16,
#endif #endif
E_GL_EXT_shader_16bit_storage, E_GL_EXT_shader_16bit_storage,
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int16}; E_GL_EXT_shader_explicit_arithmetic_types_int16};
requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
} }
} }
@ -1001,8 +1054,8 @@ void TParseVersions::int8ScalarVectorCheck(const TSourceLoc& loc, const char* op
if (! builtIn) { if (! builtIn) {
const char* const extensions[] = { const char* const extensions[] = {
E_GL_EXT_shader_8bit_storage, E_GL_EXT_shader_8bit_storage,
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int8}; E_GL_EXT_shader_explicit_arithmetic_types_int8};
requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op); requireExtensions(loc, sizeof(extensions)/sizeof(extensions[0]), extensions, op);
} }
} }
@ -1011,8 +1064,8 @@ void TParseVersions::int8ScalarVectorCheck(const TSourceLoc& loc, const char* op
void TParseVersions::explicitInt32Check(const TSourceLoc& loc, const char* op, bool builtIn) void TParseVersions::explicitInt32Check(const TSourceLoc& loc, const char* op, bool builtIn)
{ {
if (! builtIn) { if (! builtIn) {
const char* const extensions[2] = {E_GL_KHX_shader_explicit_arithmetic_types, const char* const extensions[2] = {E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int32}; E_GL_EXT_shader_explicit_arithmetic_types_int32};
requireExtensions(loc, 2, extensions, op); requireExtensions(loc, 2, extensions, op);
} }
} }
@ -1022,8 +1075,8 @@ void TParseVersions::int64Check(const TSourceLoc& loc, const char* op, bool buil
{ {
if (! builtIn) { if (! builtIn) {
const char* const extensions[3] = {E_GL_ARB_gpu_shader_int64, const char* const extensions[3] = {E_GL_ARB_gpu_shader_int64,
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int64}; E_GL_EXT_shader_explicit_arithmetic_types_int64};
requireExtensions(loc, 3, extensions, op); requireExtensions(loc, 3, extensions, op);
requireProfile(loc, ECoreProfile | ECompatibilityProfile, op); requireProfile(loc, ECoreProfile | ECompatibilityProfile, op);
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op); profileRequires(loc, ECoreProfile | ECompatibilityProfile, 400, nullptr, op);

View file

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -73,7 +74,7 @@ inline const char* ProfileName(EProfile profile)
} }
// //
// What source rules, validation rules, target language, etc. are needed // What source rules, validation rules, target language, etc. are needed or
// desired for SPIR-V? // desired for SPIR-V?
// //
// 0 means a target or rule set is not enabled (ignore rules from that entity). // 0 means a target or rule set is not enabled (ignore rules from that entity).
@ -109,6 +110,7 @@ const char* const E_GL_OES_standard_derivatives = "GL_OES_standard_deriv
const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth"; const char* const E_GL_EXT_frag_depth = "GL_EXT_frag_depth";
const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external"; const char* const E_GL_OES_EGL_image_external = "GL_OES_EGL_image_external";
const char* const E_GL_OES_EGL_image_external_essl3 = "GL_OES_EGL_image_external_essl3"; const char* const E_GL_OES_EGL_image_external_essl3 = "GL_OES_EGL_image_external_essl3";
const char* const E_GL_EXT_YUV_target = "GL_EXT_YUV_target";
const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod"; const char* const E_GL_EXT_shader_texture_lod = "GL_EXT_shader_texture_lod";
const char* const E_GL_EXT_shadow_samplers = "GL_EXT_shadow_samplers"; const char* const E_GL_EXT_shadow_samplers = "GL_EXT_shadow_samplers";
@ -148,6 +150,9 @@ const char* const E_GL_KHR_shader_subgroup_shuffle = "GL_KHR_shader_sub
const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative"; const char* const E_GL_KHR_shader_subgroup_shuffle_relative = "GL_KHR_shader_subgroup_shuffle_relative";
const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered"; const char* const E_GL_KHR_shader_subgroup_clustered = "GL_KHR_shader_subgroup_clustered";
const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad"; const char* const E_GL_KHR_shader_subgroup_quad = "GL_KHR_shader_subgroup_quad";
const char* const E_GL_KHR_memory_scope_semantics = "GL_KHR_memory_scope_semantics";
const char* const E_GL_EXT_shader_atomic_int64 = "GL_EXT_shader_atomic_int64";
const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers"; const char* const E_GL_EXT_shader_non_constant_global_initializers = "GL_EXT_shader_non_constant_global_initializers";
const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted"; const char* const E_GL_EXT_shader_image_load_formatted = "GL_EXT_shader_image_load_formatted";
@ -163,6 +168,9 @@ const char* const E_GL_EXT_post_depth_coverage = "GL_EXT_post_depth
const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes"; const char* const E_GL_EXT_control_flow_attributes = "GL_EXT_control_flow_attributes";
const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier"; const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform_qualifier";
const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions"; const char* const E_GL_EXT_samplerless_texture_functions = "GL_EXT_samplerless_texture_functions";
const char* const E_GL_EXT_scalar_block_layout = "GL_EXT_scalar_block_layout";
const char* const E_GL_EXT_fragment_invocation_density = "GL_EXT_fragment_invocation_density";
const char* const E_GL_EXT_buffer_reference = "GL_EXT_buffer_reference";
// Arrays of extensions for the above viewportEXTs duplications // Arrays of extensions for the above viewportEXTs duplications
@ -204,6 +212,12 @@ const char* const E_GL_NV_shader_atomic_int64 = "GL_NV_shader_
const char* const E_GL_NV_conservative_raster_underestimation = "GL_NV_conservative_raster_underestimation"; const char* const E_GL_NV_conservative_raster_underestimation = "GL_NV_conservative_raster_underestimation";
const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_noperspective_interpolation"; const char* const E_GL_NV_shader_noperspective_interpolation = "GL_NV_shader_noperspective_interpolation";
const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned"; const char* const E_GL_NV_shader_subgroup_partitioned = "GL_NV_shader_subgroup_partitioned";
const char* const E_GL_NV_shading_rate_image = "GL_NV_shading_rate_image";
const char* const E_GL_NV_ray_tracing = "GL_NV_ray_tracing";
const char* const E_GL_NV_fragment_shader_barycentric = "GL_NV_fragment_shader_barycentric";
const char* const E_GL_NV_compute_shader_derivatives = "GL_NV_compute_shader_derivatives";
const char* const E_GL_NV_shader_texture_footprint = "GL_NV_shader_texture_footprint";
const char* const E_GL_NV_mesh_shader = "GL_NV_mesh_shader";
// Arrays of extensions for the above viewportEXTs duplications // Arrays of extensions for the above viewportEXTs duplications
@ -240,14 +254,14 @@ const char* const E_GL_OES_texture_buffer = "GL_OES_textur
const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array"; const char* const E_GL_OES_texture_cube_map_array = "GL_OES_texture_cube_map_array";
// KHX // KHX
const char* const E_GL_KHX_shader_explicit_arithmetic_types = "GL_KHX_shader_explicit_arithmetic_types"; const char* const E_GL_EXT_shader_explicit_arithmetic_types = "GL_EXT_shader_explicit_arithmetic_types";
const char* const E_GL_KHX_shader_explicit_arithmetic_types_int8 = "GL_KHX_shader_explicit_arithmetic_types_int8"; const char* const E_GL_EXT_shader_explicit_arithmetic_types_int8 = "GL_EXT_shader_explicit_arithmetic_types_int8";
const char* const E_GL_KHX_shader_explicit_arithmetic_types_int16 = "GL_KHX_shader_explicit_arithmetic_types_int16"; const char* const E_GL_EXT_shader_explicit_arithmetic_types_int16 = "GL_EXT_shader_explicit_arithmetic_types_int16";
const char* const E_GL_KHX_shader_explicit_arithmetic_types_int32 = "GL_KHX_shader_explicit_arithmetic_types_int32"; const char* const E_GL_EXT_shader_explicit_arithmetic_types_int32 = "GL_EXT_shader_explicit_arithmetic_types_int32";
const char* const E_GL_KHX_shader_explicit_arithmetic_types_int64 = "GL_KHX_shader_explicit_arithmetic_types_int64"; const char* const E_GL_EXT_shader_explicit_arithmetic_types_int64 = "GL_EXT_shader_explicit_arithmetic_types_int64";
const char* const E_GL_KHX_shader_explicit_arithmetic_types_float16 = "GL_KHX_shader_explicit_arithmetic_types_float16"; const char* const E_GL_EXT_shader_explicit_arithmetic_types_float16 = "GL_EXT_shader_explicit_arithmetic_types_float16";
const char* const E_GL_KHX_shader_explicit_arithmetic_types_float32 = "GL_KHX_shader_explicit_arithmetic_types_float32"; const char* const E_GL_EXT_shader_explicit_arithmetic_types_float32 = "GL_EXT_shader_explicit_arithmetic_types_float32";
const char* const E_GL_KHX_shader_explicit_arithmetic_types_float64 = "GL_KHX_shader_explicit_arithmetic_types_float64"; const char* const E_GL_EXT_shader_explicit_arithmetic_types_float64 = "GL_EXT_shader_explicit_arithmetic_types_float64";
// Arrays of extensions for the above AEP duplications // Arrays of extensions for the above AEP duplications

View file

@ -2,6 +2,7 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2012-2013 LunarG, Inc. // Copyright (C) 2012-2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -140,13 +141,13 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> U8VEC2 U8VEC3 U8VEC4 %token <lex> U8VEC2 U8VEC3 U8VEC4
%token <lex> VEC2 VEC3 VEC4 %token <lex> VEC2 VEC3 VEC4
%token <lex> MAT2 MAT3 MAT4 CENTROID IN OUT INOUT %token <lex> MAT2 MAT3 MAT4 CENTROID IN OUT INOUT
%token <lex> UNIFORM PATCH SAMPLE BUFFER SHARED NONUNIFORM %token <lex> UNIFORM PATCH SAMPLE BUFFER SHARED NONUNIFORM PAYLOADNV PAYLOADINNV HITATTRNV CALLDATANV CALLDATAINNV
%token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY %token <lex> COHERENT VOLATILE RESTRICT READONLY WRITEONLY DEVICECOHERENT QUEUEFAMILYCOHERENT WORKGROUPCOHERENT SUBGROUPCOHERENT NONPRIVATE
%token <lex> DVEC2 DVEC3 DVEC4 DMAT2 DMAT3 DMAT4 %token <lex> DVEC2 DVEC3 DVEC4 DMAT2 DMAT3 DMAT4
%token <lex> F16VEC2 F16VEC3 F16VEC4 F16MAT2 F16MAT3 F16MAT4 %token <lex> F16VEC2 F16VEC3 F16VEC4 F16MAT2 F16MAT3 F16MAT4
%token <lex> F32VEC2 F32VEC3 F32VEC4 F32MAT2 F32MAT3 F32MAT4 %token <lex> F32VEC2 F32VEC3 F32VEC4 F32MAT2 F32MAT3 F32MAT4
%token <lex> F64VEC2 F64VEC3 F64VEC4 F64MAT2 F64MAT3 F64MAT4 %token <lex> F64VEC2 F64VEC3 F64VEC4 F64MAT2 F64MAT3 F64MAT4
%token <lex> NOPERSPECTIVE FLAT SMOOTH LAYOUT __EXPLICITINTERPAMD %token <lex> NOPERSPECTIVE FLAT SMOOTH LAYOUT EXPLICITINTERPAMD PERVERTEXNV PERPRIMITIVENV PERVIEWNV PERTASKNV
%token <lex> MAT2X2 MAT2X3 MAT2X4 %token <lex> MAT2X2 MAT2X3 MAT2X4
%token <lex> MAT3X2 MAT3X3 MAT3X4 %token <lex> MAT3X2 MAT3X3 MAT3X4
@ -164,6 +165,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> F64MAT3X2 F64MAT3X3 F64MAT3X4 %token <lex> F64MAT3X2 F64MAT3X3 F64MAT3X4
%token <lex> F64MAT4X2 F64MAT4X3 F64MAT4X4 %token <lex> F64MAT4X2 F64MAT4X3 F64MAT4X4
%token <lex> ATOMIC_UINT %token <lex> ATOMIC_UINT
%token <lex> ACCSTRUCTNV
// combined image/sampler // combined image/sampler
%token <lex> SAMPLER1D SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER1DSHADOW SAMPLER2DSHADOW %token <lex> SAMPLER1D SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER1DSHADOW SAMPLER2DSHADOW
@ -178,6 +180,7 @@ extern int yylex(YYSTYPE*, TParseContext&);
%token <lex> SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS %token <lex> SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS
%token <lex> SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY %token <lex> SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY
%token <lex> SAMPLEREXTERNALOES %token <lex> SAMPLEREXTERNALOES
%token <lex> SAMPLEREXTERNAL2DY2YEXT
%token <lex> F16SAMPLER1D F16SAMPLER2D F16SAMPLER3D F16SAMPLER2DRECT F16SAMPLERCUBE %token <lex> F16SAMPLER1D F16SAMPLER2D F16SAMPLER3D F16SAMPLER2DRECT F16SAMPLERCUBE
%token <lex> F16SAMPLER1DARRAY F16SAMPLER2DARRAY F16SAMPLERCUBEARRAY %token <lex> F16SAMPLER1DARRAY F16SAMPLER2DARRAY F16SAMPLERCUBEARRAY
@ -1135,13 +1138,53 @@ interpolation_qualifier
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.nopersp = true; $$.qualifier.nopersp = true;
} }
| __EXPLICITINTERPAMD { | EXPLICITINTERPAMD {
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
parseContext.globalCheck($1.loc, "__explicitInterpAMD"); parseContext.globalCheck($1.loc, "__explicitInterpAMD");
parseContext.profileRequires($1.loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); parseContext.profileRequires($1.loc, ECoreProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation");
parseContext.profileRequires($1.loc, ECompatibilityProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation"); parseContext.profileRequires($1.loc, ECompatibilityProfile, 450, E_GL_AMD_shader_explicit_vertex_parameter, "explicit interpolation");
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.explicitInterp = true; $$.qualifier.explicitInterp = true;
#endif
}
| PERVERTEXNV {
#ifdef NV_EXTENSIONS
parseContext.globalCheck($1.loc, "pervertexNV");
parseContext.profileRequires($1.loc, ECoreProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric");
parseContext.profileRequires($1.loc, ECompatibilityProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric");
parseContext.profileRequires($1.loc, EEsProfile, 0, E_GL_NV_fragment_shader_barycentric, "fragment shader barycentric");
$$.init($1.loc);
$$.qualifier.pervertexNV = true;
#endif
}
| PERPRIMITIVENV {
#ifdef NV_EXTENSIONS
// No need for profile version or extension check. Shader stage already checks both.
parseContext.globalCheck($1.loc, "perprimitiveNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangFragmentMask | EShLangMeshNVMask), "perprimitiveNV");
// Fragment shader stage doesn't check for extension. So we explicitly add below extension check.
if (parseContext.language == EShLangFragment)
parseContext.requireExtensions($1.loc, 1, &E_GL_NV_mesh_shader, "perprimitiveNV");
$$.init($1.loc);
$$.qualifier.perPrimitiveNV = true;
#endif
}
| PERVIEWNV {
#ifdef NV_EXTENSIONS
// No need for profile version or extension check. Shader stage already checks both.
parseContext.globalCheck($1.loc, "perviewNV");
parseContext.requireStage($1.loc, EShLangMeshNV, "perviewNV");
$$.init($1.loc);
$$.qualifier.perViewNV = true;
#endif
}
| PERTASKNV {
#ifdef NV_EXTENSIONS
// No need for profile version or extension check. Shader stage already checks both.
parseContext.globalCheck($1.loc, "taskNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangTaskNVMask | EShLangMeshNVMask), "taskNV");
$$.init($1.loc);
$$.qualifier.perTaskNV = true;
#endif #endif
} }
; ;
@ -1305,11 +1348,64 @@ storage_qualifier
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqBuffer; $$.qualifier.storage = EvqBuffer;
} }
| HITATTRNV {
#ifdef NV_EXTENSIONS
parseContext.globalCheck($1.loc, "hitAttributeNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangIntersectNVMask | EShLangClosestHitNVMask
| EShLangAnyHitNVMask), "hitAttributeNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "hitAttributeNV");
$$.init($1.loc);
$$.qualifier.storage = EvqHitAttrNV;
#endif
}
| PAYLOADNV {
#ifdef NV_EXTENSIONS
parseContext.globalCheck($1.loc, "rayPayloadNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask | EShLangClosestHitNVMask |
EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadNV");
$$.init($1.loc);
$$.qualifier.storage = EvqPayloadNV;
#endif
}
| PAYLOADINNV {
#ifdef NV_EXTENSIONS
parseContext.globalCheck($1.loc, "rayPayloadInNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangClosestHitNVMask |
EShLangAnyHitNVMask | EShLangMissNVMask), "rayPayloadInNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "rayPayloadInNV");
$$.init($1.loc);
$$.qualifier.storage = EvqPayloadInNV;
#endif
}
| CALLDATANV {
#ifdef NV_EXTENSIONS
parseContext.globalCheck($1.loc, "callableDataNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangRayGenNVMask |
EShLangClosestHitNVMask | EShLangMissNVMask | EShLangCallableNVMask), "callableDataNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataNV");
$$.init($1.loc);
$$.qualifier.storage = EvqCallableDataNV;
#endif
}
| CALLDATAINNV {
#ifdef NV_EXTENSIONS
parseContext.globalCheck($1.loc, "callableDataInNV");
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangCallableNVMask), "callableDataInNV");
parseContext.profileRequires($1.loc, ECoreProfile, 460, E_GL_NV_ray_tracing, "callableDataInNV");
$$.init($1.loc);
$$.qualifier.storage = EvqCallableDataInNV;
#endif
}
| SHARED { | SHARED {
parseContext.globalCheck($1.loc, "shared"); parseContext.globalCheck($1.loc, "shared");
parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared"); parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 430, E_GL_ARB_compute_shader, "shared");
parseContext.profileRequires($1.loc, EEsProfile, 310, 0, "shared"); parseContext.profileRequires($1.loc, EEsProfile, 310, 0, "shared");
#ifdef NV_EXTENSIONS
parseContext.requireStage($1.loc, (EShLanguageMask)(EShLangComputeMask | EShLangMeshNVMask | EShLangTaskNVMask), "shared");
#else
parseContext.requireStage($1.loc, EShLangCompute, "shared"); parseContext.requireStage($1.loc, EShLangCompute, "shared");
#endif
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.storage = EvqShared; $$.qualifier.storage = EvqShared;
} }
@ -1317,6 +1413,31 @@ storage_qualifier
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.coherent = true; $$.qualifier.coherent = true;
} }
| DEVICECOHERENT {
$$.init($1.loc);
parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "devicecoherent");
$$.qualifier.devicecoherent = true;
}
| QUEUEFAMILYCOHERENT {
$$.init($1.loc);
parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "queuefamilycoherent");
$$.qualifier.queuefamilycoherent = true;
}
| WORKGROUPCOHERENT {
$$.init($1.loc);
parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "workgroupcoherent");
$$.qualifier.workgroupcoherent = true;
}
| SUBGROUPCOHERENT {
$$.init($1.loc);
parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "subgroupcoherent");
$$.qualifier.subgroupcoherent = true;
}
| NONPRIVATE {
$$.init($1.loc);
parseContext.requireExtensions($1.loc, 1, &E_GL_KHR_memory_scope_semantics, "nonprivate");
$$.qualifier.nonprivate = true;
}
| VOLATILE { | VOLATILE {
$$.init($1.loc); $$.init($1.loc);
$$.qualifier.volatil = true; $$.qualifier.volatil = true;
@ -2114,6 +2235,12 @@ type_specifier_nonarray
$$.basicType = EbtDouble; $$.basicType = EbtDouble;
$$.setMatrix(4, 4); $$.setMatrix(4, 4);
} }
| ACCSTRUCTNV {
#ifdef NV_EXTENSIONS
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtAccStructNV;
#endif
}
| ATOMIC_UINT { | ATOMIC_UINT {
parseContext.vulkanRemoved($1.loc, "atomic counter types"); parseContext.vulkanRemoved($1.loc, "atomic counter types");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
@ -2985,6 +3112,12 @@ type_specifier_nonarray
$$.sampler.set(EbtFloat, Esd2D); $$.sampler.set(EbtFloat, Esd2D);
$$.sampler.external = true; $$.sampler.external = true;
} }
| SAMPLEREXTERNAL2DY2YEXT { // GL_EXT_YUV_target
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.set(EbtFloat, Esd2D);
$$.sampler.yuv = true;
}
| SUBPASSINPUT { | SUBPASSINPUT {
parseContext.requireStage($1.loc, EShLangFragment, "subpass input"); parseContext.requireStage($1.loc, EShLangFragment, "subpass input");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel()); $$.init($1.loc, parseContext.symbolTable.atGlobalLevel());

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
/* A Bison parser, made by GNU Bison 3.0. */ /* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -125,323 +125,339 @@ extern int yydebug;
BUFFER = 335, BUFFER = 335,
SHARED = 336, SHARED = 336,
NONUNIFORM = 337, NONUNIFORM = 337,
COHERENT = 338, PAYLOADNV = 338,
VOLATILE = 339, PAYLOADINNV = 339,
RESTRICT = 340, HITATTRNV = 340,
READONLY = 341, CALLDATANV = 341,
WRITEONLY = 342, CALLDATAINNV = 342,
DVEC2 = 343, COHERENT = 343,
DVEC3 = 344, VOLATILE = 344,
DVEC4 = 345, RESTRICT = 345,
DMAT2 = 346, READONLY = 346,
DMAT3 = 347, WRITEONLY = 347,
DMAT4 = 348, DEVICECOHERENT = 348,
F16VEC2 = 349, QUEUEFAMILYCOHERENT = 349,
F16VEC3 = 350, WORKGROUPCOHERENT = 350,
F16VEC4 = 351, SUBGROUPCOHERENT = 351,
F16MAT2 = 352, NONPRIVATE = 352,
F16MAT3 = 353, DVEC2 = 353,
F16MAT4 = 354, DVEC3 = 354,
F32VEC2 = 355, DVEC4 = 355,
F32VEC3 = 356, DMAT2 = 356,
F32VEC4 = 357, DMAT3 = 357,
F32MAT2 = 358, DMAT4 = 358,
F32MAT3 = 359, F16VEC2 = 359,
F32MAT4 = 360, F16VEC3 = 360,
F64VEC2 = 361, F16VEC4 = 361,
F64VEC3 = 362, F16MAT2 = 362,
F64VEC4 = 363, F16MAT3 = 363,
F64MAT2 = 364, F16MAT4 = 364,
F64MAT3 = 365, F32VEC2 = 365,
F64MAT4 = 366, F32VEC3 = 366,
NOPERSPECTIVE = 367, F32VEC4 = 367,
FLAT = 368, F32MAT2 = 368,
SMOOTH = 369, F32MAT3 = 369,
LAYOUT = 370, F32MAT4 = 370,
__EXPLICITINTERPAMD = 371, F64VEC2 = 371,
MAT2X2 = 372, F64VEC3 = 372,
MAT2X3 = 373, F64VEC4 = 373,
MAT2X4 = 374, F64MAT2 = 374,
MAT3X2 = 375, F64MAT3 = 375,
MAT3X3 = 376, F64MAT4 = 376,
MAT3X4 = 377, NOPERSPECTIVE = 377,
MAT4X2 = 378, FLAT = 378,
MAT4X3 = 379, SMOOTH = 379,
MAT4X4 = 380, LAYOUT = 380,
DMAT2X2 = 381, EXPLICITINTERPAMD = 381,
DMAT2X3 = 382, PERVERTEXNV = 382,
DMAT2X4 = 383, PERPRIMITIVENV = 383,
DMAT3X2 = 384, PERVIEWNV = 384,
DMAT3X3 = 385, PERTASKNV = 385,
DMAT3X4 = 386, MAT2X2 = 386,
DMAT4X2 = 387, MAT2X3 = 387,
DMAT4X3 = 388, MAT2X4 = 388,
DMAT4X4 = 389, MAT3X2 = 389,
F16MAT2X2 = 390, MAT3X3 = 390,
F16MAT2X3 = 391, MAT3X4 = 391,
F16MAT2X4 = 392, MAT4X2 = 392,
F16MAT3X2 = 393, MAT4X3 = 393,
F16MAT3X3 = 394, MAT4X4 = 394,
F16MAT3X4 = 395, DMAT2X2 = 395,
F16MAT4X2 = 396, DMAT2X3 = 396,
F16MAT4X3 = 397, DMAT2X4 = 397,
F16MAT4X4 = 398, DMAT3X2 = 398,
F32MAT2X2 = 399, DMAT3X3 = 399,
F32MAT2X3 = 400, DMAT3X4 = 400,
F32MAT2X4 = 401, DMAT4X2 = 401,
F32MAT3X2 = 402, DMAT4X3 = 402,
F32MAT3X3 = 403, DMAT4X4 = 403,
F32MAT3X4 = 404, F16MAT2X2 = 404,
F32MAT4X2 = 405, F16MAT2X3 = 405,
F32MAT4X3 = 406, F16MAT2X4 = 406,
F32MAT4X4 = 407, F16MAT3X2 = 407,
F64MAT2X2 = 408, F16MAT3X3 = 408,
F64MAT2X3 = 409, F16MAT3X4 = 409,
F64MAT2X4 = 410, F16MAT4X2 = 410,
F64MAT3X2 = 411, F16MAT4X3 = 411,
F64MAT3X3 = 412, F16MAT4X4 = 412,
F64MAT3X4 = 413, F32MAT2X2 = 413,
F64MAT4X2 = 414, F32MAT2X3 = 414,
F64MAT4X3 = 415, F32MAT2X4 = 415,
F64MAT4X4 = 416, F32MAT3X2 = 416,
ATOMIC_UINT = 417, F32MAT3X3 = 417,
SAMPLER1D = 418, F32MAT3X4 = 418,
SAMPLER2D = 419, F32MAT4X2 = 419,
SAMPLER3D = 420, F32MAT4X3 = 420,
SAMPLERCUBE = 421, F32MAT4X4 = 421,
SAMPLER1DSHADOW = 422, F64MAT2X2 = 422,
SAMPLER2DSHADOW = 423, F64MAT2X3 = 423,
SAMPLERCUBESHADOW = 424, F64MAT2X4 = 424,
SAMPLER1DARRAY = 425, F64MAT3X2 = 425,
SAMPLER2DARRAY = 426, F64MAT3X3 = 426,
SAMPLER1DARRAYSHADOW = 427, F64MAT3X4 = 427,
SAMPLER2DARRAYSHADOW = 428, F64MAT4X2 = 428,
ISAMPLER1D = 429, F64MAT4X3 = 429,
ISAMPLER2D = 430, F64MAT4X4 = 430,
ISAMPLER3D = 431, ATOMIC_UINT = 431,
ISAMPLERCUBE = 432, ACCSTRUCTNV = 432,
ISAMPLER1DARRAY = 433, SAMPLER1D = 433,
ISAMPLER2DARRAY = 434, SAMPLER2D = 434,
USAMPLER1D = 435, SAMPLER3D = 435,
USAMPLER2D = 436, SAMPLERCUBE = 436,
USAMPLER3D = 437, SAMPLER1DSHADOW = 437,
USAMPLERCUBE = 438, SAMPLER2DSHADOW = 438,
USAMPLER1DARRAY = 439, SAMPLERCUBESHADOW = 439,
USAMPLER2DARRAY = 440, SAMPLER1DARRAY = 440,
SAMPLER2DRECT = 441, SAMPLER2DARRAY = 441,
SAMPLER2DRECTSHADOW = 442, SAMPLER1DARRAYSHADOW = 442,
ISAMPLER2DRECT = 443, SAMPLER2DARRAYSHADOW = 443,
USAMPLER2DRECT = 444, ISAMPLER1D = 444,
SAMPLERBUFFER = 445, ISAMPLER2D = 445,
ISAMPLERBUFFER = 446, ISAMPLER3D = 446,
USAMPLERBUFFER = 447, ISAMPLERCUBE = 447,
SAMPLERCUBEARRAY = 448, ISAMPLER1DARRAY = 448,
SAMPLERCUBEARRAYSHADOW = 449, ISAMPLER2DARRAY = 449,
ISAMPLERCUBEARRAY = 450, USAMPLER1D = 450,
USAMPLERCUBEARRAY = 451, USAMPLER2D = 451,
SAMPLER2DMS = 452, USAMPLER3D = 452,
ISAMPLER2DMS = 453, USAMPLERCUBE = 453,
USAMPLER2DMS = 454, USAMPLER1DARRAY = 454,
SAMPLER2DMSARRAY = 455, USAMPLER2DARRAY = 455,
ISAMPLER2DMSARRAY = 456, SAMPLER2DRECT = 456,
USAMPLER2DMSARRAY = 457, SAMPLER2DRECTSHADOW = 457,
SAMPLEREXTERNALOES = 458, ISAMPLER2DRECT = 458,
F16SAMPLER1D = 459, USAMPLER2DRECT = 459,
F16SAMPLER2D = 460, SAMPLERBUFFER = 460,
F16SAMPLER3D = 461, ISAMPLERBUFFER = 461,
F16SAMPLER2DRECT = 462, USAMPLERBUFFER = 462,
F16SAMPLERCUBE = 463, SAMPLERCUBEARRAY = 463,
F16SAMPLER1DARRAY = 464, SAMPLERCUBEARRAYSHADOW = 464,
F16SAMPLER2DARRAY = 465, ISAMPLERCUBEARRAY = 465,
F16SAMPLERCUBEARRAY = 466, USAMPLERCUBEARRAY = 466,
F16SAMPLERBUFFER = 467, SAMPLER2DMS = 467,
F16SAMPLER2DMS = 468, ISAMPLER2DMS = 468,
F16SAMPLER2DMSARRAY = 469, USAMPLER2DMS = 469,
F16SAMPLER1DSHADOW = 470, SAMPLER2DMSARRAY = 470,
F16SAMPLER2DSHADOW = 471, ISAMPLER2DMSARRAY = 471,
F16SAMPLER1DARRAYSHADOW = 472, USAMPLER2DMSARRAY = 472,
F16SAMPLER2DARRAYSHADOW = 473, SAMPLEREXTERNALOES = 473,
F16SAMPLER2DRECTSHADOW = 474, SAMPLEREXTERNAL2DY2YEXT = 474,
F16SAMPLERCUBESHADOW = 475, F16SAMPLER1D = 475,
F16SAMPLERCUBEARRAYSHADOW = 476, F16SAMPLER2D = 476,
SAMPLER = 477, F16SAMPLER3D = 477,
SAMPLERSHADOW = 478, F16SAMPLER2DRECT = 478,
TEXTURE1D = 479, F16SAMPLERCUBE = 479,
TEXTURE2D = 480, F16SAMPLER1DARRAY = 480,
TEXTURE3D = 481, F16SAMPLER2DARRAY = 481,
TEXTURECUBE = 482, F16SAMPLERCUBEARRAY = 482,
TEXTURE1DARRAY = 483, F16SAMPLERBUFFER = 483,
TEXTURE2DARRAY = 484, F16SAMPLER2DMS = 484,
ITEXTURE1D = 485, F16SAMPLER2DMSARRAY = 485,
ITEXTURE2D = 486, F16SAMPLER1DSHADOW = 486,
ITEXTURE3D = 487, F16SAMPLER2DSHADOW = 487,
ITEXTURECUBE = 488, F16SAMPLER1DARRAYSHADOW = 488,
ITEXTURE1DARRAY = 489, F16SAMPLER2DARRAYSHADOW = 489,
ITEXTURE2DARRAY = 490, F16SAMPLER2DRECTSHADOW = 490,
UTEXTURE1D = 491, F16SAMPLERCUBESHADOW = 491,
UTEXTURE2D = 492, F16SAMPLERCUBEARRAYSHADOW = 492,
UTEXTURE3D = 493, SAMPLER = 493,
UTEXTURECUBE = 494, SAMPLERSHADOW = 494,
UTEXTURE1DARRAY = 495, TEXTURE1D = 495,
UTEXTURE2DARRAY = 496, TEXTURE2D = 496,
TEXTURE2DRECT = 497, TEXTURE3D = 497,
ITEXTURE2DRECT = 498, TEXTURECUBE = 498,
UTEXTURE2DRECT = 499, TEXTURE1DARRAY = 499,
TEXTUREBUFFER = 500, TEXTURE2DARRAY = 500,
ITEXTUREBUFFER = 501, ITEXTURE1D = 501,
UTEXTUREBUFFER = 502, ITEXTURE2D = 502,
TEXTURECUBEARRAY = 503, ITEXTURE3D = 503,
ITEXTURECUBEARRAY = 504, ITEXTURECUBE = 504,
UTEXTURECUBEARRAY = 505, ITEXTURE1DARRAY = 505,
TEXTURE2DMS = 506, ITEXTURE2DARRAY = 506,
ITEXTURE2DMS = 507, UTEXTURE1D = 507,
UTEXTURE2DMS = 508, UTEXTURE2D = 508,
TEXTURE2DMSARRAY = 509, UTEXTURE3D = 509,
ITEXTURE2DMSARRAY = 510, UTEXTURECUBE = 510,
UTEXTURE2DMSARRAY = 511, UTEXTURE1DARRAY = 511,
F16TEXTURE1D = 512, UTEXTURE2DARRAY = 512,
F16TEXTURE2D = 513, TEXTURE2DRECT = 513,
F16TEXTURE3D = 514, ITEXTURE2DRECT = 514,
F16TEXTURE2DRECT = 515, UTEXTURE2DRECT = 515,
F16TEXTURECUBE = 516, TEXTUREBUFFER = 516,
F16TEXTURE1DARRAY = 517, ITEXTUREBUFFER = 517,
F16TEXTURE2DARRAY = 518, UTEXTUREBUFFER = 518,
F16TEXTURECUBEARRAY = 519, TEXTURECUBEARRAY = 519,
F16TEXTUREBUFFER = 520, ITEXTURECUBEARRAY = 520,
F16TEXTURE2DMS = 521, UTEXTURECUBEARRAY = 521,
F16TEXTURE2DMSARRAY = 522, TEXTURE2DMS = 522,
SUBPASSINPUT = 523, ITEXTURE2DMS = 523,
SUBPASSINPUTMS = 524, UTEXTURE2DMS = 524,
ISUBPASSINPUT = 525, TEXTURE2DMSARRAY = 525,
ISUBPASSINPUTMS = 526, ITEXTURE2DMSARRAY = 526,
USUBPASSINPUT = 527, UTEXTURE2DMSARRAY = 527,
USUBPASSINPUTMS = 528, F16TEXTURE1D = 528,
F16SUBPASSINPUT = 529, F16TEXTURE2D = 529,
F16SUBPASSINPUTMS = 530, F16TEXTURE3D = 530,
IMAGE1D = 531, F16TEXTURE2DRECT = 531,
IIMAGE1D = 532, F16TEXTURECUBE = 532,
UIMAGE1D = 533, F16TEXTURE1DARRAY = 533,
IMAGE2D = 534, F16TEXTURE2DARRAY = 534,
IIMAGE2D = 535, F16TEXTURECUBEARRAY = 535,
UIMAGE2D = 536, F16TEXTUREBUFFER = 536,
IMAGE3D = 537, F16TEXTURE2DMS = 537,
IIMAGE3D = 538, F16TEXTURE2DMSARRAY = 538,
UIMAGE3D = 539, SUBPASSINPUT = 539,
IMAGE2DRECT = 540, SUBPASSINPUTMS = 540,
IIMAGE2DRECT = 541, ISUBPASSINPUT = 541,
UIMAGE2DRECT = 542, ISUBPASSINPUTMS = 542,
IMAGECUBE = 543, USUBPASSINPUT = 543,
IIMAGECUBE = 544, USUBPASSINPUTMS = 544,
UIMAGECUBE = 545, F16SUBPASSINPUT = 545,
IMAGEBUFFER = 546, F16SUBPASSINPUTMS = 546,
IIMAGEBUFFER = 547, IMAGE1D = 547,
UIMAGEBUFFER = 548, IIMAGE1D = 548,
IMAGE1DARRAY = 549, UIMAGE1D = 549,
IIMAGE1DARRAY = 550, IMAGE2D = 550,
UIMAGE1DARRAY = 551, IIMAGE2D = 551,
IMAGE2DARRAY = 552, UIMAGE2D = 552,
IIMAGE2DARRAY = 553, IMAGE3D = 553,
UIMAGE2DARRAY = 554, IIMAGE3D = 554,
IMAGECUBEARRAY = 555, UIMAGE3D = 555,
IIMAGECUBEARRAY = 556, IMAGE2DRECT = 556,
UIMAGECUBEARRAY = 557, IIMAGE2DRECT = 557,
IMAGE2DMS = 558, UIMAGE2DRECT = 558,
IIMAGE2DMS = 559, IMAGECUBE = 559,
UIMAGE2DMS = 560, IIMAGECUBE = 560,
IMAGE2DMSARRAY = 561, UIMAGECUBE = 561,
IIMAGE2DMSARRAY = 562, IMAGEBUFFER = 562,
UIMAGE2DMSARRAY = 563, IIMAGEBUFFER = 563,
F16IMAGE1D = 564, UIMAGEBUFFER = 564,
F16IMAGE2D = 565, IMAGE1DARRAY = 565,
F16IMAGE3D = 566, IIMAGE1DARRAY = 566,
F16IMAGE2DRECT = 567, UIMAGE1DARRAY = 567,
F16IMAGECUBE = 568, IMAGE2DARRAY = 568,
F16IMAGE1DARRAY = 569, IIMAGE2DARRAY = 569,
F16IMAGE2DARRAY = 570, UIMAGE2DARRAY = 570,
F16IMAGECUBEARRAY = 571, IMAGECUBEARRAY = 571,
F16IMAGEBUFFER = 572, IIMAGECUBEARRAY = 572,
F16IMAGE2DMS = 573, UIMAGECUBEARRAY = 573,
F16IMAGE2DMSARRAY = 574, IMAGE2DMS = 574,
STRUCT = 575, IIMAGE2DMS = 575,
VOID = 576, UIMAGE2DMS = 576,
WHILE = 577, IMAGE2DMSARRAY = 577,
IDENTIFIER = 578, IIMAGE2DMSARRAY = 578,
TYPE_NAME = 579, UIMAGE2DMSARRAY = 579,
FLOATCONSTANT = 580, F16IMAGE1D = 580,
DOUBLECONSTANT = 581, F16IMAGE2D = 581,
INT16CONSTANT = 582, F16IMAGE3D = 582,
UINT16CONSTANT = 583, F16IMAGE2DRECT = 583,
INT32CONSTANT = 584, F16IMAGECUBE = 584,
UINT32CONSTANT = 585, F16IMAGE1DARRAY = 585,
INTCONSTANT = 586, F16IMAGE2DARRAY = 586,
UINTCONSTANT = 587, F16IMAGECUBEARRAY = 587,
INT64CONSTANT = 588, F16IMAGEBUFFER = 588,
UINT64CONSTANT = 589, F16IMAGE2DMS = 589,
BOOLCONSTANT = 590, F16IMAGE2DMSARRAY = 590,
FLOAT16CONSTANT = 591, STRUCT = 591,
LEFT_OP = 592, VOID = 592,
RIGHT_OP = 593, WHILE = 593,
INC_OP = 594, IDENTIFIER = 594,
DEC_OP = 595, TYPE_NAME = 595,
LE_OP = 596, FLOATCONSTANT = 596,
GE_OP = 597, DOUBLECONSTANT = 597,
EQ_OP = 598, INT16CONSTANT = 598,
NE_OP = 599, UINT16CONSTANT = 599,
AND_OP = 600, INT32CONSTANT = 600,
OR_OP = 601, UINT32CONSTANT = 601,
XOR_OP = 602, INTCONSTANT = 602,
MUL_ASSIGN = 603, UINTCONSTANT = 603,
DIV_ASSIGN = 604, INT64CONSTANT = 604,
ADD_ASSIGN = 605, UINT64CONSTANT = 605,
MOD_ASSIGN = 606, BOOLCONSTANT = 606,
LEFT_ASSIGN = 607, FLOAT16CONSTANT = 607,
RIGHT_ASSIGN = 608, LEFT_OP = 608,
AND_ASSIGN = 609, RIGHT_OP = 609,
XOR_ASSIGN = 610, INC_OP = 610,
OR_ASSIGN = 611, DEC_OP = 611,
SUB_ASSIGN = 612, LE_OP = 612,
LEFT_PAREN = 613, GE_OP = 613,
RIGHT_PAREN = 614, EQ_OP = 614,
LEFT_BRACKET = 615, NE_OP = 615,
RIGHT_BRACKET = 616, AND_OP = 616,
LEFT_BRACE = 617, OR_OP = 617,
RIGHT_BRACE = 618, XOR_OP = 618,
DOT = 619, MUL_ASSIGN = 619,
COMMA = 620, DIV_ASSIGN = 620,
COLON = 621, ADD_ASSIGN = 621,
EQUAL = 622, MOD_ASSIGN = 622,
SEMICOLON = 623, LEFT_ASSIGN = 623,
BANG = 624, RIGHT_ASSIGN = 624,
DASH = 625, AND_ASSIGN = 625,
TILDE = 626, XOR_ASSIGN = 626,
PLUS = 627, OR_ASSIGN = 627,
STAR = 628, SUB_ASSIGN = 628,
SLASH = 629, LEFT_PAREN = 629,
PERCENT = 630, RIGHT_PAREN = 630,
LEFT_ANGLE = 631, LEFT_BRACKET = 631,
RIGHT_ANGLE = 632, RIGHT_BRACKET = 632,
VERTICAL_BAR = 633, LEFT_BRACE = 633,
CARET = 634, RIGHT_BRACE = 634,
AMPERSAND = 635, DOT = 635,
QUESTION = 636, COMMA = 636,
INVARIANT = 637, COLON = 637,
PRECISE = 638, EQUAL = 638,
HIGH_PRECISION = 639, SEMICOLON = 639,
MEDIUM_PRECISION = 640, BANG = 640,
LOW_PRECISION = 641, DASH = 641,
PRECISION = 642, TILDE = 642,
PACKED = 643, PLUS = 643,
RESOURCE = 644, STAR = 644,
SUPERP = 645 SLASH = 645,
PERCENT = 646,
LEFT_ANGLE = 647,
RIGHT_ANGLE = 648,
VERTICAL_BAR = 649,
CARET = 650,
AMPERSAND = 651,
QUESTION = 652,
INVARIANT = 653,
PRECISE = 654,
HIGH_PRECISION = 655,
MEDIUM_PRECISION = 656,
LOW_PRECISION = 657,
PRECISION = 658,
PACKED = 659,
RESOURCE = 660,
SUPERP = 661
}; };
#endif #endif
/* Value type. */ /* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE YYSTYPE;
union YYSTYPE union YYSTYPE
{ {
#line 70 "MachineIndependent/glslang.y" /* yacc.c:1909 */ #line 71 "MachineIndependent/glslang.y" /* yacc.c:1909 */
struct { struct {
glslang::TSourceLoc loc; glslang::TSourceLoc loc;
@ -476,8 +492,10 @@ union YYSTYPE
}; };
} interm; } interm;
#line 480 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */ #line 496 "MachineIndependent/glslang_tab.cpp.h" /* yacc.c:1909 */
}; };
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_DECLARED 1
#endif #endif

View file

@ -172,8 +172,12 @@ bool TOutputTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
case EOpIndexDirect: out.debug << "direct index"; break; case EOpIndexDirect: out.debug << "direct index"; break;
case EOpIndexIndirect: out.debug << "indirect index"; break; case EOpIndexIndirect: out.debug << "indirect index"; break;
case EOpIndexDirectStruct: case EOpIndexDirectStruct:
out.debug << (*node->getLeft()->getType().getStruct())[node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()].type->getFieldName(); {
out.debug << ": direct index for structure"; break; bool reference = node->getLeft()->getType().getBasicType() == EbtReference;
const TTypeList *members = reference ? node->getLeft()->getType().getReferentType()->getStruct() : node->getLeft()->getType().getStruct();
out.debug << (*members)[node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()].type->getFieldName();
out.debug << ": direct index for structure"; break;
}
case EOpVectorSwizzle: out.debug << "vector swizzle"; break; case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
case EOpMatrixSwizzle: out.debug << "matrix swizzle"; break; case EOpMatrixSwizzle: out.debug << "matrix swizzle"; break;
@ -419,6 +423,8 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpConvDoubleToUint: out.debug << "Convert double to uint"; break; case EOpConvDoubleToUint: out.debug << "Convert double to uint"; break;
case EOpConvDoubleToUint64: out.debug << "Convert double to uint64"; break; case EOpConvDoubleToUint64: out.debug << "Convert double to uint64"; break;
case EOpConvUint64ToPtr: out.debug << "Convert uint64_t to pointer"; break;
case EOpConvPtrToUint64: out.debug << "Convert pointer to uint64_t"; break;
case EOpRadians: out.debug << "radians"; break; case EOpRadians: out.debug << "radians"; break;
case EOpDegrees: out.debug << "degrees"; break; case EOpDegrees: out.debug << "degrees"; break;
@ -674,6 +680,8 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
case EOpSubpassLoad: out.debug << "subpassLoad"; break; case EOpSubpassLoad: out.debug << "subpassLoad"; break;
case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break; case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
case EOpConstructReference: out.debug << "Construct reference type"; break;
default: out.debug.message(EPrefixError, "Bad unary op"); default: out.debug.message(EPrefixError, "Bad unary op");
} }
@ -808,6 +816,7 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpConstructF16Mat4x4: out.debug << "Construct f16mat4"; break; case EOpConstructF16Mat4x4: out.debug << "Construct f16mat4"; break;
case EOpConstructStruct: out.debug << "Construct structure"; break; case EOpConstructStruct: out.debug << "Construct structure"; break;
case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break; case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
case EOpConstructReference: out.debug << "Construct reference"; break;
case EOpLessThan: out.debug << "Compare Less Than"; break; case EOpLessThan: out.debug << "Compare Less Than"; break;
case EOpGreaterThan: out.debug << "Compare Greater Than"; break; case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
@ -871,6 +880,8 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpAtomicXor: out.debug << "AtomicXor"; break; case EOpAtomicXor: out.debug << "AtomicXor"; break;
case EOpAtomicExchange: out.debug << "AtomicExchange"; break; case EOpAtomicExchange: out.debug << "AtomicExchange"; break;
case EOpAtomicCompSwap: out.debug << "AtomicCompSwap"; break; case EOpAtomicCompSwap: out.debug << "AtomicCompSwap"; break;
case EOpAtomicLoad: out.debug << "AtomicLoad"; break;
case EOpAtomicStore: out.debug << "AtomicStore"; break;
case EOpAtomicCounterAdd: out.debug << "AtomicCounterAdd"; break; case EOpAtomicCounterAdd: out.debug << "AtomicCounterAdd"; break;
case EOpAtomicCounterSubtract: out.debug << "AtomicCounterSubtract"; break; case EOpAtomicCounterSubtract: out.debug << "AtomicCounterSubtract"; break;
@ -894,6 +905,8 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpImageAtomicXor: out.debug << "imageAtomicXor"; break; case EOpImageAtomicXor: out.debug << "imageAtomicXor"; break;
case EOpImageAtomicExchange: out.debug << "imageAtomicExchange"; break; case EOpImageAtomicExchange: out.debug << "imageAtomicExchange"; break;
case EOpImageAtomicCompSwap: out.debug << "imageAtomicCompSwap"; break; case EOpImageAtomicCompSwap: out.debug << "imageAtomicCompSwap"; break;
case EOpImageAtomicLoad: out.debug << "imageAtomicLoad"; break;
case EOpImageAtomicStore: out.debug << "imageAtomicStore"; break;
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
case EOpImageLoadLod: out.debug << "imageLoadLod"; break; case EOpImageLoadLod: out.debug << "imageLoadLod"; break;
case EOpImageStoreLod: out.debug << "imageStoreLod"; break; case EOpImageStoreLod: out.debug << "imageStoreLod"; break;
@ -952,7 +965,13 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpSparseTextureGatherLodOffsets: out.debug << "sparseTextureGatherLodOffsets"; break; case EOpSparseTextureGatherLodOffsets: out.debug << "sparseTextureGatherLodOffsets"; break;
case EOpSparseImageLoadLod: out.debug << "sparseImageLoadLod"; break; case EOpSparseImageLoadLod: out.debug << "sparseImageLoadLod"; break;
#endif #endif
#ifdef NV_EXTENSIONS
case EOpImageSampleFootprintNV: out.debug << "imageSampleFootprintNV"; break;
case EOpImageSampleFootprintClampNV: out.debug << "imageSampleFootprintClampNV"; break;
case EOpImageSampleFootprintLodNV: out.debug << "imageSampleFootprintLodNV"; break;
case EOpImageSampleFootprintGradNV: out.debug << "imageSampleFootprintGradNV"; break;
case EOpImageSampleFootprintGradClampNV: out.debug << "mageSampleFootprintGradClampNV"; break;
#endif
case EOpAddCarry: out.debug << "addCarry"; break; case EOpAddCarry: out.debug << "addCarry"; break;
case EOpSubBorrow: out.debug << "subBorrow"; break; case EOpSubBorrow: out.debug << "subBorrow"; break;
case EOpUMulExtended: out.debug << "uMulExtended"; break; case EOpUMulExtended: out.debug << "uMulExtended"; break;
@ -1038,6 +1057,15 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node
case EOpSubpassLoad: out.debug << "subpassLoad"; break; case EOpSubpassLoad: out.debug << "subpassLoad"; break;
case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break; case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
#ifdef NV_EXTENSIONS
case EOpTraceNV: out.debug << "traceNV"; break;
case EOpReportIntersectionNV: out.debug << "reportIntersectionNV"; break;
case EOpIgnoreIntersectionNV: out.debug << "ignoreIntersectionNV"; break;
case EOpTerminateRayNV: out.debug << "terminateRayNV"; break;
case EOpExecuteCallableNV: out.debug << "executeCallableNV"; break;
case EOpWritePackedPrimitiveIndices4x8NV: out.debug << "writePackedPrimitiveIndices4x8NV"; break;
#endif
default: out.debug.message(EPrefixError, "Bad aggregation op"); default: out.debug.message(EPrefixError, "Bad aggregation op");
} }
@ -1441,6 +1469,16 @@ void TIntermediate::output(TInfoSink& infoSink, bool tree)
} }
break; break;
#ifdef NV_EXTENSIONS
case EShLangMeshNV:
infoSink.debug << "max_vertices = " << vertices << "\n";
infoSink.debug << "max_primitives = " << primitives << "\n";
infoSink.debug << "output primitive = " << TQualifier::getGeometryString(outputPrimitive) << "\n";
// Fall through
case EShLangTaskNV:
// Fall through
#endif
case EShLangCompute: case EShLangCompute:
infoSink.debug << "local_size = (" << localSize[0] << ", " << localSize[1] << ", " << localSize[2] << ")\n"; infoSink.debug << "local_size = (" << localSize[0] << ", " << localSize[1] << ", " << localSize[2] << ")\n";
{ {

View file

@ -331,8 +331,14 @@ struct TResolverInOutAdaptor
ent.symbol->getType(), ent.symbol->getType(),
ent.live); ent.live);
} else { } else {
TString errorMsg = "Invalid shader In/Out variable semantic: "; TString errorMsg;
errorMsg += ent.symbol->getType().getQualifier().semanticName; if (ent.symbol->getType().getQualifier().semanticName != nullptr) {
errorMsg = "Invalid shader In/Out variable semantic: ";
errorMsg += ent.symbol->getType().getQualifier().semanticName;
} else {
errorMsg = "Invalid shader In/Out variable: ";
errorMsg += ent.symbol->getName();
}
infoSink.info.message(EPrefixInternalError, errorMsg.c_str()); infoSink.info.message(EPrefixInternalError, errorMsg.c_str());
error = true; error = true;
} }
@ -353,7 +359,7 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
{ {
TDefaultIoResolverBase(const TIntermediate &intermediate) : TDefaultIoResolverBase(const TIntermediate &intermediate) :
intermediate(intermediate), intermediate(intermediate),
nextUniformLocation(0), nextUniformLocation(intermediate.getUniformLocationBase()),
nextInputLocation(0), nextInputLocation(0),
nextOutputLocation(0) nextOutputLocation(0)
{ } { }
@ -428,7 +434,7 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
return 0; return 0;
} }
int resolveUniformLocation(EShLanguage /*stage*/, const char* /*name*/, const glslang::TType& type, bool /*is_live*/) override int resolveUniformLocation(EShLanguage /*stage*/, const char* name, const glslang::TType& type, bool /*is_live*/) override
{ {
// kick out of not doing this // kick out of not doing this
if (!doAutoLocationMapping()) if (!doAutoLocationMapping())
@ -449,7 +455,11 @@ struct TDefaultIoResolverBase : public glslang::TIoMapResolver
return -1; return -1;
} }
int location = nextUniformLocation; int location = intermediate.getUniformLocationOverride(name);
if (location != -1)
return location;
location = nextUniformLocation;
nextUniformLocation += TIntermediate::computeTypeUniformLocationSize(type); nextUniformLocation += TIntermediate::computeTypeUniformLocationSize(type);

View file

@ -1,6 +1,7 @@
// //
// Copyright (C) 2013 LunarG, Inc. // Copyright (C) 2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -77,12 +78,13 @@ void TIntermediate::warn(TInfoSink& infoSink, const char* message)
// //
void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
{ {
if (source == EShSourceNone) mergeCallGraphs(infoSink, unit);
source = unit.source; mergeModes(infoSink, unit);
mergeTrees(infoSink, unit);
if (source != unit.source) }
error(infoSink, "can't link compilation units from different source languages");
void TIntermediate::mergeCallGraphs(TInfoSink& infoSink, TIntermediate& unit)
{
if (unit.getNumEntryPoints() > 0) { if (unit.getNumEntryPoints() > 0) {
if (getNumEntryPoints() > 0) if (getNumEntryPoints() > 0)
error(infoSink, "can't handle multiple entry points per stage"); error(infoSink, "can't handle multiple entry points per stage");
@ -92,25 +94,75 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
} }
} }
numEntryPoints += unit.getNumEntryPoints(); numEntryPoints += unit.getNumEntryPoints();
callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end());
}
#define MERGE_MAX(member) member = std::max(member, unit.member)
#define MERGE_TRUE(member) if (unit.member) member = unit.member;
void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit)
{
if (language != unit.language)
error(infoSink, "stages must match when linking into a single stage");
if (source == EShSourceNone)
source = unit.source;
if (source != unit.source)
error(infoSink, "can't link compilation units from different source languages");
if (treeRoot == nullptr) {
profile = unit.profile;
version = unit.version;
requestedExtensions = unit.requestedExtensions;
} else {
if ((profile == EEsProfile) != (unit.profile == EEsProfile))
error(infoSink, "Cannot cross link ES and desktop profiles");
else if (unit.profile == ECompatibilityProfile)
profile = ECompatibilityProfile;
version = std::max(version, unit.version);
requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end());
}
MERGE_MAX(spvVersion.spv);
MERGE_MAX(spvVersion.vulkanGlsl);
MERGE_MAX(spvVersion.vulkan);
MERGE_MAX(spvVersion.openGl);
numErrors += unit.getNumErrors(); numErrors += unit.getNumErrors();
numPushConstants += unit.numPushConstants; numPushConstants += unit.numPushConstants;
callGraph.insert(callGraph.end(), unit.callGraph.begin(), unit.callGraph.end());
if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger) if (unit.invocations != TQualifier::layoutNotSet) {
error(infoSink, "gl_FragCoord redeclarations must match across shaders"); if (invocations == TQualifier::layoutNotSet)
invocations = unit.invocations;
else if (invocations != unit.invocations)
error(infoSink, "number of invocations must match between compilation units");
}
if (! earlyFragmentTests) if (vertices == TQualifier::layoutNotSet)
earlyFragmentTests = unit.earlyFragmentTests; vertices = unit.vertices;
else if (vertices != unit.vertices) {
if (!postDepthCoverage) if (language == EShLangGeometry
postDepthCoverage = unit.postDepthCoverage; #ifdef NV_EXTENSIONS
|| language == EShLangMeshNV
if (depthLayout == EldNone) #endif
depthLayout = unit.depthLayout; )
else if (depthLayout != unit.depthLayout) error(infoSink, "Contradictory layout max_vertices values");
error(infoSink, "Contradictory depth layouts"); else if (language == EShLangTessControl)
error(infoSink, "Contradictory layout vertices values");
blendEquations |= unit.blendEquations; else
assert(0);
}
#ifdef NV_EXTENSIONS
if (primitives == TQualifier::layoutNotSet)
primitives = unit.primitives;
else if (primitives != unit.primitives) {
if (language == EShLangMeshNV)
error(infoSink, "Contradictory layout max_primitives values");
else
assert(0);
}
#endif
if (inputPrimitive == ElgNone) if (inputPrimitive == ElgNone)
inputPrimitive = unit.inputPrimitive; inputPrimitive = unit.inputPrimitive;
@ -122,16 +174,8 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
else if (outputPrimitive != unit.outputPrimitive) else if (outputPrimitive != unit.outputPrimitive)
error(infoSink, "Contradictory output layout primitives"); error(infoSink, "Contradictory output layout primitives");
if (vertices == TQualifier::layoutNotSet) if (originUpperLeft != unit.originUpperLeft || pixelCenterInteger != unit.pixelCenterInteger)
vertices = unit.vertices; error(infoSink, "gl_FragCoord redeclarations must match across shaders");
else if (vertices != unit.vertices) {
if (language == EShLangGeometry)
error(infoSink, "Contradictory layout max_vertices values");
else if (language == EShLangTessControl)
error(infoSink, "Contradictory layout vertices values");
else
assert(0);
}
if (vertexSpacing == EvsNone) if (vertexSpacing == EvsNone)
vertexSpacing = unit.vertexSpacing; vertexSpacing = unit.vertexSpacing;
@ -143,8 +187,7 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
else if (vertexOrder != unit.vertexOrder) else if (vertexOrder != unit.vertexOrder)
error(infoSink, "Contradictory triangle ordering"); error(infoSink, "Contradictory triangle ordering");
if (unit.pointMode) MERGE_TRUE(pointMode);
pointMode = true;
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
if (localSize[i] > 1) if (localSize[i] > 1)
@ -158,48 +201,214 @@ void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit)
error(infoSink, "Contradictory local size specialization ids"); error(infoSink, "Contradictory local size specialization ids");
} }
if (unit.xfbMode) MERGE_TRUE(earlyFragmentTests);
xfbMode = true; MERGE_TRUE(postDepthCoverage);
if (depthLayout == EldNone)
depthLayout = unit.depthLayout;
else if (depthLayout != unit.depthLayout)
error(infoSink, "Contradictory depth layouts");
MERGE_TRUE(depthReplacing);
MERGE_TRUE(hlslFunctionality1);
blendEquations |= unit.blendEquations;
MERGE_TRUE(xfbMode);
for (size_t b = 0; b < xfbBuffers.size(); ++b) { for (size_t b = 0; b < xfbBuffers.size(); ++b) {
if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd) if (xfbBuffers[b].stride == TQualifier::layoutXfbStrideEnd)
xfbBuffers[b].stride = unit.xfbBuffers[b].stride; xfbBuffers[b].stride = unit.xfbBuffers[b].stride;
else if (xfbBuffers[b].stride != unit.xfbBuffers[b].stride) else if (xfbBuffers[b].stride != unit.xfbBuffers[b].stride)
error(infoSink, "Contradictory xfb_stride"); error(infoSink, "Contradictory xfb_stride");
xfbBuffers[b].implicitStride = std::max(xfbBuffers[b].implicitStride, unit.xfbBuffers[b].implicitStride); xfbBuffers[b].implicitStride = std::max(xfbBuffers[b].implicitStride, unit.xfbBuffers[b].implicitStride);
if (unit.xfbBuffers[b].containsDouble) if (unit.xfbBuffers[b].contains64BitType)
xfbBuffers[b].containsDouble = true; xfbBuffers[b].contains64BitType = true;
#ifdef AMD_EXTENSIONS
if (unit.xfbBuffers[b].contains32BitType)
xfbBuffers[b].contains32BitType = true;
if (unit.xfbBuffers[b].contains16BitType)
xfbBuffers[b].contains16BitType = true;
#endif
// TODO: 4.4 link: enhanced layouts: compare ranges // TODO: 4.4 link: enhanced layouts: compare ranges
} }
if (unit.treeRoot == 0) MERGE_TRUE(multiStream);
#ifdef NV_EXTENSIONS
MERGE_TRUE(layoutOverrideCoverage);
MERGE_TRUE(geoPassthroughEXT);
#endif
for (unsigned int i = 0; i < unit.shiftBinding.size(); ++i) {
if (unit.shiftBinding[i] > 0)
setShiftBinding((TResourceType)i, unit.shiftBinding[i]);
}
for (unsigned int i = 0; i < unit.shiftBindingForSet.size(); ++i) {
for (auto it = unit.shiftBindingForSet[i].begin(); it != unit.shiftBindingForSet[i].end(); ++it)
setShiftBindingForSet((TResourceType)i, it->second, it->first);
}
resourceSetBinding.insert(resourceSetBinding.end(), unit.resourceSetBinding.begin(), unit.resourceSetBinding.end());
MERGE_TRUE(autoMapBindings);
MERGE_TRUE(autoMapLocations);
MERGE_TRUE(invertY);
MERGE_TRUE(flattenUniformArrays);
MERGE_TRUE(useUnknownFormat);
MERGE_TRUE(hlslOffsets);
MERGE_TRUE(useStorageBuffer);
MERGE_TRUE(hlslIoMapping);
// TODO: sourceFile
// TODO: sourceText
// TODO: processes
MERGE_TRUE(needToLegalize);
MERGE_TRUE(binaryDoubleOutput);
MERGE_TRUE(usePhysicalStorageBuffer);
}
//
// Merge the 'unit' AST into 'this' AST.
// That includes rationalizing the unique IDs, which were set up independently,
// and might have overlaps that are not the same symbol, or might have different
// IDs for what should be the same shared symbol.
//
void TIntermediate::mergeTrees(TInfoSink& infoSink, TIntermediate& unit)
{
if (unit.treeRoot == nullptr)
return; return;
if (treeRoot == 0) { if (treeRoot == nullptr) {
treeRoot = unit.treeRoot; treeRoot = unit.treeRoot;
version = unit.version;
requestedExtensions = unit.requestedExtensions;
return; return;
} }
// Getting this far means we have two existing trees to merge... // Getting this far means we have two existing trees to merge...
#ifdef NV_EXTENSIONS
numShaderRecordNVBlocks += unit.numShaderRecordNVBlocks;
#endif
version = std::max(version, unit.version); #ifdef NV_EXTENSIONS
requestedExtensions.insert(unit.requestedExtensions.begin(), unit.requestedExtensions.end()); numTaskNVBlocks += unit.numTaskNVBlocks;
#endif
// Get the top-level globals of each unit // Get the top-level globals of each unit
TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence(); TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence(); TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence();
// Get the linker-object lists // Get the linker-object lists
TIntermSequence& linkerObjects = findLinkerObjects(); TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
TIntermSequence& unitLinkerObjects = unit.findLinkerObjects(); const TIntermSequence& unitLinkerObjects = unit.findLinkerObjects()->getSequence();
// Map by global name to unique ID to rationalize the same object having
// differing IDs in different trees.
TMap<TString, int> idMap;
int maxId;
seedIdMap(idMap, maxId);
remapIds(idMap, maxId + 1, unit);
mergeBodies(infoSink, globals, unitGlobals); mergeBodies(infoSink, globals, unitGlobals);
mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects); mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects);
ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end()); ioAccessed.insert(unit.ioAccessed.begin(), unit.ioAccessed.end());
} }
// Traverser that seeds an ID map with all built-ins, and tracks the
// maximum ID used.
// (It would be nice to put this in a function, but that causes warnings
// on having no bodies for the copy-constructor/operator=.)
class TBuiltInIdTraverser : public TIntermTraverser {
public:
TBuiltInIdTraverser(TMap<TString, int>& idMap) : idMap(idMap), maxId(0) { }
// If it's a built in, add it to the map.
// Track the max ID.
virtual void visitSymbol(TIntermSymbol* symbol)
{
const TQualifier& qualifier = symbol->getType().getQualifier();
if (qualifier.builtIn != EbvNone)
idMap[symbol->getName()] = symbol->getId();
maxId = std::max(maxId, symbol->getId());
}
int getMaxId() const { return maxId; }
protected:
TBuiltInIdTraverser(TBuiltInIdTraverser&);
TBuiltInIdTraverser& operator=(TBuiltInIdTraverser&);
TMap<TString, int>& idMap;
int maxId;
};
// Traverser that seeds an ID map with non-builtins.
// (It would be nice to put this in a function, but that causes warnings
// on having no bodies for the copy-constructor/operator=.)
class TUserIdTraverser : public TIntermTraverser {
public:
TUserIdTraverser(TMap<TString, int>& idMap) : idMap(idMap) { }
// If its a non-built-in global, add it to the map.
virtual void visitSymbol(TIntermSymbol* symbol)
{
const TQualifier& qualifier = symbol->getType().getQualifier();
if (qualifier.builtIn == EbvNone)
idMap[symbol->getName()] = symbol->getId();
}
protected:
TUserIdTraverser(TUserIdTraverser&);
TUserIdTraverser& operator=(TUserIdTraverser&);
TMap<TString, int>& idMap; // over biggest id
};
// Initialize the the ID map with what we know of 'this' AST.
void TIntermediate::seedIdMap(TMap<TString, int>& idMap, int& maxId)
{
// all built-ins everywhere need to align on IDs and contribute to the max ID
TBuiltInIdTraverser builtInIdTraverser(idMap);
treeRoot->traverse(&builtInIdTraverser);
maxId = builtInIdTraverser.getMaxId();
// user variables in the linker object list need to align on ids
TUserIdTraverser userIdTraverser(idMap);
findLinkerObjects()->traverse(&userIdTraverser);
}
// Traverser to map an AST ID to what was known from the seeding AST.
// (It would be nice to put this in a function, but that causes warnings
// on having no bodies for the copy-constructor/operator=.)
class TRemapIdTraverser : public TIntermTraverser {
public:
TRemapIdTraverser(const TMap<TString, int>& idMap, int idShift) : idMap(idMap), idShift(idShift) { }
// Do the mapping:
// - if the same symbol, adopt the 'this' ID
// - otherwise, ensure a unique ID by shifting to a new space
virtual void visitSymbol(TIntermSymbol* symbol)
{
const TQualifier& qualifier = symbol->getType().getQualifier();
bool remapped = false;
if (qualifier.isLinkable() || qualifier.builtIn != EbvNone) {
auto it = idMap.find(symbol->getName());
if (it != idMap.end()) {
symbol->changeId(it->second);
remapped = true;
}
}
if (!remapped)
symbol->changeId(symbol->getId() + idShift);
}
protected:
TRemapIdTraverser(TRemapIdTraverser&);
TRemapIdTraverser& operator=(TRemapIdTraverser&);
const TMap<TString, int>& idMap;
int idShift;
};
void TIntermediate::remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate& unit)
{
// Remap all IDs to either share or be unique, as dictated by the idMap and idShift.
TRemapIdTraverser idTraverser(idMap, idShift);
unit.getTreeRoot()->traverse(&idTraverser);
}
// //
// Merge the function bodies and global-level initializers from unitGlobals into globals. // Merge the function bodies and global-level initializers from unitGlobals into globals.
// Will error check duplication of function bodies for the same signature. // Will error check duplication of function bodies for the same signature.
@ -344,11 +553,16 @@ void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& sy
} }
// Memory... // Memory...
if (symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent || if (symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent ||
symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil || symbol.getQualifier().devicecoherent != unitSymbol.getQualifier().devicecoherent ||
symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict || symbol.getQualifier().queuefamilycoherent != unitSymbol.getQualifier().queuefamilycoherent ||
symbol.getQualifier().readonly != unitSymbol.getQualifier().readonly || symbol.getQualifier().workgroupcoherent != unitSymbol.getQualifier().workgroupcoherent ||
symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) { symbol.getQualifier().subgroupcoherent != unitSymbol.getQualifier().subgroupcoherent ||
symbol.getQualifier().nonprivate != unitSymbol.getQualifier().nonprivate ||
symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil ||
symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict ||
symbol.getQualifier().readonly != unitSymbol.getQualifier().readonly ||
symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) {
error(infoSink, "Memory qualifiers must match:"); error(infoSink, "Memory qualifiers must match:");
writeTypeComparison = true; writeTypeComparison = true;
} }
@ -426,8 +640,14 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
error(infoSink, "Cannot use both gl_FragColor and gl_FragData"); error(infoSink, "Cannot use both gl_FragColor and gl_FragData");
for (size_t b = 0; b < xfbBuffers.size(); ++b) { for (size_t b = 0; b < xfbBuffers.size(); ++b) {
if (xfbBuffers[b].containsDouble) if (xfbBuffers[b].contains64BitType)
RoundToPow2(xfbBuffers[b].implicitStride, 8); RoundToPow2(xfbBuffers[b].implicitStride, 8);
#ifdef AMD_EXTENSIONS
else if (xfbBuffers[b].contains32BitType)
RoundToPow2(xfbBuffers[b].implicitStride, 4);
else if (xfbBuffers[b].contains16BitType)
RoundToPow2(xfbBuffers[b].implicitStride, 2);
#endif
// "It is a compile-time or link-time error to have // "It is a compile-time or link-time error to have
// any xfb_offset that overflows xfb_stride, whether stated on declarations before or after the xfb_stride, or // any xfb_offset that overflows xfb_stride, whether stated on declarations before or after the xfb_stride, or
@ -442,18 +662,31 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
xfbBuffers[b].stride = xfbBuffers[b].implicitStride; xfbBuffers[b].stride = xfbBuffers[b].implicitStride;
// "If the buffer is capturing any // "If the buffer is capturing any
// outputs with double-precision components, the stride must be a multiple of 8, otherwise it must be a // outputs with double-precision or 64-bit integer components, the stride must be a multiple of 8, otherwise it must be a
// multiple of 4, or a compile-time or link-time error results." // multiple of 4, or a compile-time or link-time error results."
if (xfbBuffers[b].containsDouble && ! IsMultipleOfPow2(xfbBuffers[b].stride, 8)) { if (xfbBuffers[b].contains64BitType && ! IsMultipleOfPow2(xfbBuffers[b].stride, 8)) {
error(infoSink, "xfb_stride must be multiple of 8 for buffer holding a double:"); error(infoSink, "xfb_stride must be multiple of 8 for buffer holding a double or 64-bit integer:");
infoSink.info.prefix(EPrefixError); infoSink.info.prefix(EPrefixError);
infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n"; infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n";
#ifdef AMD_EXTENSIONS
} else if (xfbBuffers[b].contains32BitType && ! IsMultipleOfPow2(xfbBuffers[b].stride, 4)) {
#else
} else if (! IsMultipleOfPow2(xfbBuffers[b].stride, 4)) { } else if (! IsMultipleOfPow2(xfbBuffers[b].stride, 4)) {
#endif
error(infoSink, "xfb_stride must be multiple of 4:"); error(infoSink, "xfb_stride must be multiple of 4:");
infoSink.info.prefix(EPrefixError); infoSink.info.prefix(EPrefixError);
infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n"; infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n";
} }
#ifdef AMD_EXTENSIONS
// "If the buffer is capturing any
// outputs with half-precision or 16-bit integer components, the stride must be a multiple of 2"
else if (xfbBuffers[b].contains16BitType && ! IsMultipleOfPow2(xfbBuffers[b].stride, 2)) {
error(infoSink, "xfb_stride must be multiple of 2 for buffer holding a half float or 16-bit integer:");
infoSink.info.prefix(EPrefixError);
infoSink.info << " xfb_buffer " << (unsigned int)b << ", xfb_stride " << xfbBuffers[b].stride << "\n";
}
#endif
// "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the // "The resulting stride (implicit or explicit), when divided by 4, must be less than or equal to the
// implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents." // implementation-dependent constant gl_MaxTransformFeedbackInterleavedComponents."
if (xfbBuffers[b].stride > (unsigned int)(4 * resources.maxTransformFeedbackInterleavedComponents)) { if (xfbBuffers[b].stride > (unsigned int)(4 * resources.maxTransformFeedbackInterleavedComponents)) {
@ -483,17 +716,9 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
case EShLangGeometry: case EShLangGeometry:
if (inputPrimitive == ElgNone) if (inputPrimitive == ElgNone)
error(infoSink, "At least one shader must specify an input layout primitive"); error(infoSink, "At least one shader must specify an input layout primitive");
if (outputPrimitive == ElgNone if (outputPrimitive == ElgNone)
#ifdef NV_EXTENSIONS
&& !getGeoPassthroughEXT()
#endif
)
error(infoSink, "At least one shader must specify an output layout primitive"); error(infoSink, "At least one shader must specify an output layout primitive");
if (vertices == TQualifier::layoutNotSet if (vertices == TQualifier::layoutNotSet)
#ifdef NV_EXTENSIONS
&& !getGeoPassthroughEXT()
#endif
)
error(infoSink, "At least one shader must specify a layout(max_vertices = value)"); error(infoSink, "At least one shader must specify a layout(max_vertices = value)");
break; break;
case EShLangFragment: case EShLangFragment:
@ -505,6 +730,42 @@ void TIntermediate::finalCheck(TInfoSink& infoSink, bool keepUncalled)
break; break;
case EShLangCompute: case EShLangCompute:
break; break;
#ifdef NV_EXTENSIONS
case EShLangRayGenNV:
case EShLangIntersectNV:
case EShLangAnyHitNV:
case EShLangClosestHitNV:
case EShLangMissNV:
case EShLangCallableNV:
if (numShaderRecordNVBlocks > 1)
error(infoSink, "Only one shaderRecordNV buffer block is allowed per stage");
break;
case EShLangMeshNV:
// NV_mesh_shader doesn't allow use of both single-view and per-view builtins.
if (inIoAccessed("gl_Position") && inIoAccessed("gl_PositionPerViewNV"))
error(infoSink, "Can only use one of gl_Position or gl_PositionPerViewNV");
if (inIoAccessed("gl_ClipDistance") && inIoAccessed("gl_ClipDistancePerViewNV"))
error(infoSink, "Can only use one of gl_ClipDistance or gl_ClipDistancePerViewNV");
if (inIoAccessed("gl_CullDistance") && inIoAccessed("gl_CullDistancePerViewNV"))
error(infoSink, "Can only use one of gl_CullDistance or gl_CullDistancePerViewNV");
if (inIoAccessed("gl_Layer") && inIoAccessed("gl_LayerPerViewNV"))
error(infoSink, "Can only use one of gl_Layer or gl_LayerPerViewNV");
if (inIoAccessed("gl_ViewportMask") && inIoAccessed("gl_ViewportMaskPerViewNV"))
error(infoSink, "Can only use one of gl_ViewportMask or gl_ViewportMaskPerViewNV");
if (outputPrimitive == ElgNone)
error(infoSink, "At least one shader must specify an output layout primitive");
if (vertices == TQualifier::layoutNotSet)
error(infoSink, "At least one shader must specify a layout(max_vertices = value)");
if (primitives == TQualifier::layoutNotSet)
error(infoSink, "At least one shader must specify a layout(max_primitives = value)");
// fall through
case EShLangTaskNV:
if (numTaskNVBlocks > 1)
error(infoSink, "Only one taskNV interface block is allowed per shader");
break;
#endif
default: default:
error(infoSink, "Unknown Stage."); error(infoSink, "Unknown Stage.");
break; break;
@ -699,7 +960,7 @@ void TIntermediate::inOutLocationCheck(TInfoSink& infoSink)
// TODO: linker functionality: location collision checking // TODO: linker functionality: location collision checking
TIntermSequence& linkObjects = findLinkerObjects(); TIntermSequence& linkObjects = findLinkerObjects()->getSequence();
for (size_t i = 0; i < linkObjects.size(); ++i) { for (size_t i = 0; i < linkObjects.size(); ++i) {
const TType& type = linkObjects[i]->getAsTyped()->getType(); const TType& type = linkObjects[i]->getAsTyped()->getType();
const TQualifier& qualifier = type.getQualifier(); const TQualifier& qualifier = type.getQualifier();
@ -718,7 +979,7 @@ void TIntermediate::inOutLocationCheck(TInfoSink& infoSink)
} }
} }
TIntermSequence& TIntermediate::findLinkerObjects() const TIntermAggregate* TIntermediate::findLinkerObjects() const
{ {
// Get the top-level globals // Get the top-level globals
TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence(); TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence();
@ -726,7 +987,7 @@ TIntermSequence& TIntermediate::findLinkerObjects() const
// Get the last member of the sequences, expected to be the linker-object lists // Get the last member of the sequences, expected to be the linker-object lists
assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects); assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects);
return globals.back()->getAsAggregate()->getSequence(); return globals.back()->getAsAggregate();
} }
// See if a variable was both a user-declared output and used. // See if a variable was both a user-declared output and used.
@ -734,7 +995,7 @@ TIntermSequence& TIntermediate::findLinkerObjects() const
// is more useful, and perhaps the spec should be changed to reflect that. // is more useful, and perhaps the spec should be changed to reflect that.
bool TIntermediate::userOutputUsed() const bool TIntermediate::userOutputUsed() const
{ {
const TIntermSequence& linkerObjects = findLinkerObjects(); const TIntermSequence& linkerObjects = findLinkerObjects()->getSequence();
bool found = false; bool found = false;
for (size_t i = 0; i < linkerObjects.size(); ++i) { for (size_t i = 0; i < linkerObjects.size(); ++i) {
@ -775,7 +1036,7 @@ int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& typ
return -1; return -1;
int size; int size;
if (qualifier.isUniformOrBuffer()) { if (qualifier.isUniformOrBuffer() || qualifier.isTaskMemory()) {
if (type.isSizedArray()) if (type.isSizedArray())
size = type.getCumulativeArraySize(); size = type.getCumulativeArraySize();
else else
@ -926,10 +1187,19 @@ int TIntermediate::computeTypeLocationSize(const TType& type, EShLanguage stage)
// TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
// TODO: are there valid cases of having an unsized array with a location? If so, running this code too early. // TODO: are there valid cases of having an unsized array with a location? If so, running this code too early.
TType elementType(type, 0); TType elementType(type, 0);
if (type.isSizedArray()) if (type.isSizedArray()
#ifdef NV_EXTENSIONS
&& !type.getQualifier().isPerView()
#endif
)
return type.getOuterArraySize() * computeTypeLocationSize(elementType, stage); return type.getOuterArraySize() * computeTypeLocationSize(elementType, stage);
else else {
#ifdef NV_EXTENSIONS
// unset perViewNV attributes for arrayed per-view outputs: "perviewNV vec4 v[MAX_VIEWS][3];"
elementType.getQualifier().perViewNV = false;
#endif
return computeTypeLocationSize(elementType, stage); return computeTypeLocationSize(elementType, stage);
}
} }
// "The locations consumed by block and structure members are determined by applying the rules above // "The locations consumed by block and structure members are determined by applying the rules above
@ -1015,7 +1285,11 @@ int TIntermediate::addXfbBufferOffset(const TType& type)
TXfbBuffer& buffer = xfbBuffers[qualifier.layoutXfbBuffer]; TXfbBuffer& buffer = xfbBuffers[qualifier.layoutXfbBuffer];
// compute the range // compute the range
unsigned int size = computeTypeXfbSize(type, buffer.containsDouble); #ifdef AMD_EXTENSIONS
unsigned int size = computeTypeXfbSize(type, buffer.contains64BitType, buffer.contains32BitType, buffer.contains16BitType);
#else
unsigned int size = computeTypeXfbSize(type, buffer.contains64BitType);
#endif
buffer.implicitStride = std::max(buffer.implicitStride, qualifier.layoutXfbOffset + size); buffer.implicitStride = std::max(buffer.implicitStride, qualifier.layoutXfbOffset + size);
TRange range(qualifier.layoutXfbOffset, qualifier.layoutXfbOffset + size - 1); TRange range(qualifier.layoutXfbOffset, qualifier.layoutXfbOffset + size - 1);
@ -1034,11 +1308,18 @@ int TIntermediate::addXfbBufferOffset(const TType& type)
// Recursively figure out how many bytes of xfb buffer are used by the given type. // Recursively figure out how many bytes of xfb buffer are used by the given type.
// Return the size of type, in bytes. // Return the size of type, in bytes.
// Sets containsDouble to true if the type contains a double. // Sets contains64BitType to true if the type contains a 64-bit data type.
// N.B. Caller must set containsDouble to false before calling. #ifdef AMD_EXTENSIONS
unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& containsDouble) const // Sets contains32BitType to true if the type contains a 32-bit data type.
// Sets contains16BitType to true if the type contains a 16-bit data type.
// N.B. Caller must set contains64BitType, contains32BitType, and contains16BitType to false before calling.
unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const
#else
// N.B. Caller must set contains64BitType to false before calling.
unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains64BitType) const
#endif
{ {
// "...if applied to an aggregate containing a double, the offset must also be a multiple of 8, // "...if applied to an aggregate containing a double or 64-bit integer, the offset must also be a multiple of 8,
// and the space taken in the buffer will be a multiple of 8. // and the space taken in the buffer will be a multiple of 8.
// ...within the qualified entity, subsequent components are each // ...within the qualified entity, subsequent components are each
// assigned, in order, to the next available offset aligned to a multiple of // assigned, in order, to the next available offset aligned to a multiple of
@ -1049,29 +1330,59 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains
// TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness // TODO: perf: this can be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
assert(type.isSizedArray()); assert(type.isSizedArray());
TType elementType(type, 0); TType elementType(type, 0);
return type.getOuterArraySize() * computeTypeXfbSize(elementType, containsDouble); #ifdef AMD_EXTENSIONS
return type.getOuterArraySize() * computeTypeXfbSize(elementType, contains64BitType, contains16BitType, contains16BitType);
#else
return type.getOuterArraySize() * computeTypeXfbSize(elementType, contains64BitType);
#endif
} }
if (type.isStruct()) { if (type.isStruct()) {
unsigned int size = 0; unsigned int size = 0;
bool structContainsDouble = false; bool structContains64BitType = false;
#ifdef AMD_EXTENSIONS
bool structContains32BitType = false;
bool structContains16BitType = false;
#endif
for (int member = 0; member < (int)type.getStruct()->size(); ++member) { for (int member = 0; member < (int)type.getStruct()->size(); ++member) {
TType memberType(type, member); TType memberType(type, member);
// "... if applied to // "... if applied to
// an aggregate containing a double, the offset must also be a multiple of 8, // an aggregate containing a double or 64-bit integer, the offset must also be a multiple of 8,
// and the space taken in the buffer will be a multiple of 8." // and the space taken in the buffer will be a multiple of 8."
bool memberContainsDouble = false; bool memberContains64BitType = false;
int memberSize = computeTypeXfbSize(memberType, memberContainsDouble); #ifdef AMD_EXTENSIONS
if (memberContainsDouble) { bool memberContains32BitType = false;
structContainsDouble = true; bool memberContains16BitType = false;
int memberSize = computeTypeXfbSize(memberType, memberContains64BitType, memberContains32BitType, memberContains16BitType);
#else
int memberSize = computeTypeXfbSize(memberType, memberContains64BitType);
#endif
if (memberContains64BitType) {
structContains64BitType = true;
RoundToPow2(size, 8); RoundToPow2(size, 8);
#ifdef AMD_EXTENSIONS
} else if (memberContains32BitType) {
structContains32BitType = true;
RoundToPow2(size, 4);
} else if (memberContains16BitType) {
structContains16BitType = true;
RoundToPow2(size, 2);
#endif
} }
size += memberSize; size += memberSize;
} }
if (structContainsDouble) { if (structContains64BitType) {
containsDouble = true; contains64BitType = true;
RoundToPow2(size, 8); RoundToPow2(size, 8);
#ifdef AMD_EXTENSIONS
} else if (structContains32BitType) {
contains32BitType = true;
RoundToPow2(size, 4);
} else if (structContains16BitType) {
contains16BitType = true;
RoundToPow2(size, 2);
#endif
} }
return size; return size;
} }
@ -1088,11 +1399,23 @@ unsigned int TIntermediate::computeTypeXfbSize(const TType& type, bool& contains
numComponents = 1; numComponents = 1;
} }
if (type.getBasicType() == EbtDouble) { if (type.getBasicType() == EbtDouble || type.getBasicType() == EbtInt64 || type.getBasicType() == EbtUint64) {
containsDouble = true; contains64BitType = true;
return 8 * numComponents; return 8 * numComponents;
#ifdef AMD_EXTENSIONS
} else if (type.getBasicType() == EbtFloat16 || type.getBasicType() == EbtInt16 || type.getBasicType() == EbtUint16) {
contains16BitType = true;
return 2 * numComponents;
} else if (type.getBasicType() == EbtInt8 || type.getBasicType() == EbtUint8)
return numComponents;
else {
contains32BitType = true;
return 4 * numComponents;
}
#else
} else } else
return 4 * numComponents; return 4 * numComponents;
#endif
} }
const int baseAlignmentVec4Std140 = 16; const int baseAlignmentVec4Std140 = 16;
@ -1111,6 +1434,7 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
case EbtUint8: size = 1; return 1; case EbtUint8: size = 1; return 1;
case EbtInt16: case EbtInt16:
case EbtUint16: size = 2; return 2; case EbtUint16: size = 2; return 2;
case EbtReference: size = 8; return 8;
default: size = 4; return 4; default: size = 4; return 4;
} }
} }
@ -1129,10 +1453,11 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size)
// stride comes from the flattening down to vectors. // stride comes from the flattening down to vectors.
// //
// Return value is the alignment of the type. // Return value is the alignment of the type.
int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, bool std140, bool rowMajor) int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor)
{ {
int alignment; int alignment;
bool std140 = layoutPacking == glslang::ElpStd140;
// When using the std140 storage layout, structures will be laid out in buffer // When using the std140 storage layout, structures will be laid out in buffer
// storage with its members stored in monotonically increasing order based on their // storage with its members stored in monotonically increasing order based on their
// location in the declaration. A structure and each structure member have a base // location in the declaration. A structure and each structure member have a base
@ -1196,7 +1521,7 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b
if (type.isArray()) { if (type.isArray()) {
// TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness // TODO: perf: this might be flattened by using getCumulativeArraySize(), and a deref that discards all arrayness
TType derefType(type, 0); TType derefType(type, 0);
alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor); alignment = getBaseAlignment(derefType, size, dummyStride, layoutPacking, rowMajor);
if (std140) if (std140)
alignment = std::max(baseAlignmentVec4Std140, alignment); alignment = std::max(baseAlignmentVec4Std140, alignment);
RoundToPow2(size, alignment); RoundToPow2(size, alignment);
@ -1216,7 +1541,7 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b
int memberSize; int memberSize;
// modify just the children's view of matrix layout, if there is one for this member // modify just the children's view of matrix layout, if there is one for this member
TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix; TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, std140, int memberAlignment = getBaseAlignment(*memberList[m].type, memberSize, dummyStride, layoutPacking,
(subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor); (subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
maxAlignment = std::max(maxAlignment, memberAlignment); maxAlignment = std::max(maxAlignment, memberAlignment);
RoundToPow2(size, memberAlignment); RoundToPow2(size, memberAlignment);
@ -1255,7 +1580,7 @@ int TIntermediate::getBaseAlignment(const TType& type, int& size, int& stride, b
// rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows // rule 5: deref to row, not to column, meaning the size of vector is num columns instead of num rows
TType derefType(type, 0, rowMajor); TType derefType(type, 0, rowMajor);
alignment = getBaseAlignment(derefType, size, dummyStride, std140, rowMajor); alignment = getBaseAlignment(derefType, size, dummyStride, layoutPacking, rowMajor);
if (std140) if (std140)
alignment = std::max(baseAlignmentVec4Std140, alignment); alignment = std::max(baseAlignmentVec4Std140, alignment);
RoundToPow2(size, alignment); RoundToPow2(size, alignment);
@ -1283,4 +1608,79 @@ bool TIntermediate::improperStraddle(const TType& type, int size, int offset)
: offset % 16 != 0; : offset % 16 != 0;
} }
int TIntermediate::getScalarAlignment(const TType& type, int& size, int& stride, bool rowMajor)
{
int alignment;
stride = 0;
int dummyStride;
if (type.isArray()) {
TType derefType(type, 0);
alignment = getScalarAlignment(derefType, size, dummyStride, rowMajor);
stride = size;
RoundToPow2(stride, alignment);
size = stride * (type.getOuterArraySize() - 1) + size;
return alignment;
}
if (type.getBasicType() == EbtStruct) {
const TTypeList& memberList = *type.getStruct();
size = 0;
int maxAlignment = 0;
for (size_t m = 0; m < memberList.size(); ++m) {
int memberSize;
// modify just the children's view of matrix layout, if there is one for this member
TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
int memberAlignment = getScalarAlignment(*memberList[m].type, memberSize, dummyStride,
(subMatrixLayout != ElmNone) ? (subMatrixLayout == ElmRowMajor) : rowMajor);
maxAlignment = std::max(maxAlignment, memberAlignment);
RoundToPow2(size, memberAlignment);
size += memberSize;
}
return maxAlignment;
}
if (type.isScalar())
return getBaseAlignmentScalar(type, size);
if (type.isVector()) {
int scalarAlign = getBaseAlignmentScalar(type, size);
size *= type.getVectorSize();
return scalarAlign;
}
if (type.isMatrix()) {
TType derefType(type, 0, rowMajor);
alignment = getScalarAlignment(derefType, size, dummyStride, rowMajor);
stride = size; // use intra-matrix stride for stride of a just a matrix
if (rowMajor)
size = stride * type.getMatrixRows();
else
size = stride * type.getMatrixCols();
return alignment;
}
assert(0); // all cases should be covered above
size = 1;
return 1;
}
int TIntermediate::getMemberAlignment(const TType& type, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor)
{
if (layoutPacking == glslang::ElpScalar) {
return getScalarAlignment(type, size, stride, rowMajor);
} else {
return getBaseAlignment(type, size, stride, layoutPacking, rowMajor);
}
}
} // end namespace glslang } // end namespace glslang

View file

@ -2,6 +2,8 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2016 LunarG, Inc. // Copyright (C) 2016 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
//
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
@ -41,6 +43,8 @@
#include "../Public/ShaderLang.h" #include "../Public/ShaderLang.h"
#include "Versions.h" #include "Versions.h"
#include <string>
#include <vector>
#include <algorithm> #include <algorithm>
#include <set> #include <set>
#include <array> #include <array>
@ -145,11 +149,20 @@ struct TOffsetRange {
// Things that need to be tracked per xfb buffer. // Things that need to be tracked per xfb buffer.
struct TXfbBuffer { struct TXfbBuffer {
TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), containsDouble(false) { } #ifdef AMD_EXTENSIONS
TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false),
contains32BitType(false), contains16BitType(false) { }
#else
TXfbBuffer() : stride(TQualifier::layoutXfbStrideEnd), implicitStride(0), contains64BitType(false) { }
#endif
std::vector<TRange> ranges; // byte offsets that have already been assigned std::vector<TRange> ranges; // byte offsets that have already been assigned
unsigned int stride; unsigned int stride;
unsigned int implicitStride; unsigned int implicitStride;
bool containsDouble; bool contains64BitType;
#ifdef AMD_EXTENSIONS
bool contains32BitType;
bool contains16BitType;
#endif
}; };
// Track a set of strings describing how the module was processed. // Track a set of strings describing how the module was processed.
@ -204,6 +217,17 @@ class TSymbolTable;
class TSymbol; class TSymbol;
class TVariable; class TVariable;
#ifdef NV_EXTENSIONS
//
// Texture and Sampler transformation mode.
//
enum ComputeDerivativeMode {
LayoutDerivativeNone, // default layout as SPV_NV_compute_shader_derivatives not enabled
LayoutDerivativeGroupQuads, // derivative_group_quadsNV
LayoutDerivativeGroupLinear, // derivative_group_linearNV
};
#endif
// //
// Set of helper functions to help parse and build the tree. // Set of helper functions to help parse and build the tree.
// //
@ -223,6 +247,10 @@ public:
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
layoutOverrideCoverage(false), layoutOverrideCoverage(false),
geoPassthroughEXT(false), geoPassthroughEXT(false),
numShaderRecordNVBlocks(0),
computeDerivativeMode(LayoutDerivativeNone),
primitives(TQualifier::layoutNotSet),
numTaskNVBlocks(0),
#endif #endif
autoMapBindings(false), autoMapBindings(false),
autoMapLocations(false), autoMapLocations(false),
@ -231,10 +259,13 @@ public:
useUnknownFormat(false), useUnknownFormat(false),
hlslOffsets(false), hlslOffsets(false),
useStorageBuffer(false), useStorageBuffer(false),
useVulkanMemoryModel(false),
hlslIoMapping(false), hlslIoMapping(false),
textureSamplerTransformMode(EShTexSampTransKeep), textureSamplerTransformMode(EShTexSampTransKeep),
needToLegalize(false), needToLegalize(false),
binaryDoubleOutput(false) binaryDoubleOutput(false),
usePhysicalStorageBuffer(false),
uniformLocationBase(0)
{ {
localSize[0] = 1; localSize[0] = 1;
localSize[1] = 1; localSize[1] = 1;
@ -349,7 +380,7 @@ public:
if (hlslOffsets) if (hlslOffsets)
processes.addProcess("hlsl-offsets"); processes.addProcess("hlsl-offsets");
} }
bool usingHlslOFfsets() const { return hlslOffsets; } bool usingHlslOffsets() const { return hlslOffsets; }
void setUseStorageBuffer() void setUseStorageBuffer()
{ {
useStorageBuffer = true; useStorageBuffer = true;
@ -363,6 +394,17 @@ public:
processes.addProcess("hlsl-iomap"); processes.addProcess("hlsl-iomap");
} }
bool usingHlslIoMapping() { return hlslIoMapping; } bool usingHlslIoMapping() { return hlslIoMapping; }
void setUseVulkanMemoryModel()
{
useVulkanMemoryModel = true;
processes.addProcess("use-vulkan-memory-model");
}
bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; }
void setUsePhysicalStorageBuffer()
{
usePhysicalStorageBuffer = true;
}
bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; }
template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; } template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; }
bool hasCounterBufferName(const TString& name) const { bool hasCounterBufferName(const TString& name) const {
@ -387,11 +429,40 @@ public:
if (spvVersion.openGl > 0) if (spvVersion.openGl > 0)
processes.addProcess("client opengl100"); processes.addProcess("client opengl100");
// target SPV
switch (spvVersion.spv) {
case 0:
break;
case EShTargetSpv_1_0:
break;
case EShTargetSpv_1_1:
processes.addProcess("target-env spirv1.1");
break;
case EShTargetSpv_1_2:
processes.addProcess("target-env spirv1.2");
break;
case EShTargetSpv_1_3:
processes.addProcess("target-env spirv1.3");
break;
default:
processes.addProcess("target-env spirvUnknown");
break;
}
// target-environment processes // target-environment processes
if (spvVersion.vulkan > 0) switch (spvVersion.vulkan) {
case 0:
break;
case EShTargetVulkan_1_0:
processes.addProcess("target-env vulkan1.0"); processes.addProcess("target-env vulkan1.0");
else if (spvVersion.vulkan > 0) break;
case EShTargetVulkan_1_1:
processes.addProcess("target-env vulkan1.1");
break;
default:
processes.addProcess("target-env vulkanUnknown"); processes.addProcess("target-env vulkanUnknown");
break;
}
if (spvVersion.openGl > 0) if (spvVersion.openGl > 0)
processes.addProcess("target-env opengl"); processes.addProcess("target-env opengl");
} }
@ -406,6 +477,11 @@ public:
int getNumEntryPoints() const { return numEntryPoints; } int getNumEntryPoints() const { return numEntryPoints; }
int getNumErrors() const { return numErrors; } int getNumErrors() const { return numErrors; }
void addPushConstantCount() { ++numPushConstants; } void addPushConstantCount() { ++numPushConstants; }
#ifdef NV_EXTENSIONS
void addShaderRecordNVCount() { ++numShaderRecordNVBlocks; }
void addTaskNVCount() { ++numTaskNVBlocks; }
#endif
bool isRecursive() const { return recursive; } bool isRecursive() const { return recursive; }
TIntermSymbol* addSymbol(const TVariable&); TIntermSymbol* addSymbol(const TVariable&);
@ -602,9 +678,15 @@ public:
} }
unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; } unsigned getXfbStride(int buffer) const { return xfbBuffers[buffer].stride; }
int addXfbBufferOffset(const TType&); int addXfbBufferOffset(const TType&);
unsigned int computeTypeXfbSize(const TType&, bool& containsDouble) const; #ifdef AMD_EXTENSIONS
unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType, bool& contains32BitType, bool& contains16BitType) const;
#else
unsigned int computeTypeXfbSize(const TType&, bool& contains64BitType) const;
#endif
static int getBaseAlignmentScalar(const TType&, int& size); static int getBaseAlignmentScalar(const TType&, int& size);
static int getBaseAlignment(const TType&, int& size, int& stride, bool std140, bool rowMajor); static int getBaseAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
static int getScalarAlignment(const TType&, int& size, int& stride, bool rowMajor);
static int getMemberAlignment(const TType&, int& size, int& stride, TLayoutPacking layoutPacking, bool rowMajor);
static bool improperStraddle(const TType& type, int size, int offset); static bool improperStraddle(const TType& type, int size, int offset);
bool promote(TIntermOperator*); bool promote(TIntermOperator*);
@ -613,6 +695,16 @@ public:
bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; } bool getLayoutOverrideCoverage() const { return layoutOverrideCoverage; }
void setGeoPassthroughEXT() { geoPassthroughEXT = true; } void setGeoPassthroughEXT() { geoPassthroughEXT = true; }
bool getGeoPassthroughEXT() const { return geoPassthroughEXT; } bool getGeoPassthroughEXT() const { return geoPassthroughEXT; }
void setLayoutDerivativeMode(ComputeDerivativeMode mode) { computeDerivativeMode = mode; }
ComputeDerivativeMode getLayoutDerivativeModeNone() const { return computeDerivativeMode; }
bool setPrimitives(int m)
{
if (primitives != TQualifier::layoutNotSet)
return primitives == m;
primitives = m;
return true;
}
int getPrimitives() const { return primitives; }
#endif #endif
const char* addSemanticName(const TString& name) const char* addSemanticName(const TString& name)
@ -622,9 +714,12 @@ public:
void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; } void setSourceFile(const char* file) { if (file != nullptr) sourceFile = file; }
const std::string& getSourceFile() const { return sourceFile; } const std::string& getSourceFile() const { return sourceFile; }
void addSourceText(const char* text) { sourceText = sourceText + text; } void addSourceText(const char* text, size_t len) { sourceText.append(text, len); }
const std::string& getSourceText() const { return sourceText; } const std::string& getSourceText() const { return sourceText; }
void addProcesses(const std::vector<std::string>& p) { const std::map<std::string, std::string>& getIncludeText() const { return includeText; }
void addIncludeText(const char* name, const char* text, size_t len) { includeText[name].assign(text,len); }
void addProcesses(const std::vector<std::string>& p)
{
for (int i = 0; i < (int)p.size(); ++i) for (int i = 0; i < (int)p.size(); ++i)
processes.addProcess(p[i]); processes.addProcess(p[i]);
} }
@ -632,6 +727,25 @@ public:
void addProcessArgument(const std::string& arg) { processes.addArgument(arg); } void addProcessArgument(const std::string& arg) { processes.addArgument(arg); }
const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); } const std::vector<std::string>& getProcesses() const { return processes.getProcesses(); }
void addUniformLocationOverride(const char* nameStr, int location)
{
std::string name = nameStr;
uniformLocationOverrides[name] = location;
}
int getUniformLocationOverride(const char* nameStr) const
{
std::string name = nameStr;
auto pos = uniformLocationOverrides.find(name);
if (pos == uniformLocationOverrides.end())
return -1;
else
return pos->second;
}
void setUniformLocationBase(int base) { uniformLocationBase = base; }
int getUniformLocationBase() const { return uniformLocationBase; }
void setNeedsLegalization() { needToLegalize = true; } void setNeedsLegalization() { needToLegalize = true; }
bool needsLegalization() const { return needToLegalize; } bool needsLegalization() const { return needToLegalize; }
@ -645,6 +759,11 @@ protected:
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&); TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TConstUnionArray&, TIntermTyped* subtree, const TSourceLoc&);
void error(TInfoSink& infoSink, const char*); void error(TInfoSink& infoSink, const char*);
void warn(TInfoSink& infoSink, const char*); void warn(TInfoSink& infoSink, const char*);
void mergeCallGraphs(TInfoSink&, TIntermediate&);
void mergeModes(TInfoSink&, TIntermediate&);
void mergeTrees(TInfoSink&, TIntermediate&);
void seedIdMap(TMap<TString, int>& idMap, int& maxId);
void remapIds(const TMap<TString, int>& idMap, int idShift, TIntermediate&);
void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals);
void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects);
void mergeImplicitArraySizes(TType&, const TType&); void mergeImplicitArraySizes(TType&, const TType&);
@ -652,7 +771,7 @@ protected:
void checkCallGraphCycles(TInfoSink&); void checkCallGraphCycles(TInfoSink&);
void checkCallGraphBodies(TInfoSink&, bool keepUncalled); void checkCallGraphBodies(TInfoSink&, bool keepUncalled);
void inOutLocationCheck(TInfoSink&); void inOutLocationCheck(TInfoSink&);
TIntermSequence& findLinkerObjects() const; TIntermAggregate* findLinkerObjects() const;
bool userOutputUsed() const; bool userOutputUsed() const;
bool isSpecializationOperation(const TIntermOperator&) const; bool isSpecializationOperation(const TIntermOperator&) const;
bool isNonuniformPropagating(TOperator) const; bool isNonuniformPropagating(TOperator) const;
@ -665,7 +784,7 @@ protected:
bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&); bool specConstantPropagates(const TIntermTyped&, const TIntermTyped&);
void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root); void performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root);
bool isConversionAllowed(TOperator op, TIntermTyped* node) const; bool isConversionAllowed(TOperator op, TIntermTyped* node) const;
TIntermUnary* createConversion(TBasicType convertTo, TIntermTyped* node) const; TIntermTyped* createConversion(TBasicType convertTo, TIntermTyped* node) const;
std::tuple<TBasicType, TBasicType> getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const; std::tuple<TBasicType, TBasicType> getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const;
bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();} bool extensionRequested(const char *extension) const {return requestedExtensions.find(extension) != requestedExtensions.end();}
static const char* getResourceName(TResourceType); static const char* getResourceName(TResourceType);
@ -674,6 +793,8 @@ protected:
EShSource source; // source language, known a bit later EShSource source; // source language, known a bit later
std::string entryPointName; std::string entryPointName;
std::string entryPointMangledName; std::string entryPointMangledName;
typedef std::list<TCall> TGraph;
TGraph callGraph;
EProfile profile; // source profile EProfile profile; // source profile
int version; // source version int version; // source version
@ -703,18 +824,23 @@ protected:
bool hlslFunctionality1; bool hlslFunctionality1;
int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift int blendEquations; // an 'or'ing of masks of shifts of TBlendEquationShift
bool xfbMode; bool xfbMode;
std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
bool multiStream; bool multiStream;
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
bool layoutOverrideCoverage; bool layoutOverrideCoverage;
bool geoPassthroughEXT; bool geoPassthroughEXT;
int numShaderRecordNVBlocks;
ComputeDerivativeMode computeDerivativeMode;
int primitives;
int numTaskNVBlocks;
#endif #endif
// Base shift values // Base shift values
std::array<unsigned int, EResCount> shiftBinding; std::array<unsigned int, EResCount> shiftBinding;
// Per-descriptor-set shift values // Per-descriptor-set shift values
std::array<std::map<int, int>, EResCount> shiftBindingForSet; std::array<std::map<int, int>, EResCount> shiftBindingForSet;
std::vector<std::string> resourceSetBinding; std::vector<std::string> resourceSetBinding;
bool autoMapBindings; bool autoMapBindings;
@ -724,15 +850,12 @@ protected:
bool useUnknownFormat; bool useUnknownFormat;
bool hlslOffsets; bool hlslOffsets;
bool useStorageBuffer; bool useStorageBuffer;
bool useVulkanMemoryModel;
bool hlslIoMapping; bool hlslIoMapping;
typedef std::list<TCall> TGraph;
TGraph callGraph;
std::set<TString> ioAccessed; // set of names of statically read/written I/O that might need extra checking std::set<TString> ioAccessed; // set of names of statically read/written I/O that might need extra checking
std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers std::vector<TIoRange> usedIo[4]; // sets of used locations, one for each of in, out, uniform, and buffers
std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters std::vector<TOffsetRange> usedAtomics; // sets of bindings used by atomic counters
std::vector<TXfbBuffer> xfbBuffers; // all the data we need to track per xfb buffer
std::unordered_set<int> usedConstantId; // specialization constant ids used std::unordered_set<int> usedConstantId; // specialization constant ids used
std::set<TString> semanticNameSet; std::set<TString> semanticNameSet;
@ -742,11 +865,18 @@ protected:
std::string sourceFile; std::string sourceFile;
std::string sourceText; std::string sourceText;
// Included text. First string is a name, second is the included text
std::map<std::string, std::string> includeText;
// for OpModuleProcessed, or equivalent // for OpModuleProcessed, or equivalent
TProcesses processes; TProcesses processes;
bool needToLegalize; bool needToLegalize;
bool binaryDoubleOutput; bool binaryDoubleOutput;
bool usePhysicalStorageBuffer;
std::unordered_map<std::string, int> uniformLocationOverrides;
int uniformLocationBase;
private: private:
void operator=(TIntermediate&); // prevent assignments void operator=(TIntermediate&); // prevent assignments

View file

@ -1,5 +1,5 @@
// //
// Copyright (C) 2016 Google, Inc. // Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// //
// All rights reserved. // All rights reserved.
@ -103,6 +103,7 @@ public:
virtual void requireSpv(const TSourceLoc&, const char* op); virtual void requireSpv(const TSourceLoc&, const char* op);
virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc); virtual bool checkExtensionsRequested(const TSourceLoc&, int numExtensions, const char* const extensions[], const char* featureDesc);
virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior); virtual void updateExtensionBehavior(const char* const extension, TExtensionBehavior);
virtual void checkExtensionStage(const TSourceLoc&, const char* const extension);
virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken,
const char* szExtraInfoFormat, ...) = 0; const char* szExtraInfoFormat, ...) = 0;
@ -129,6 +130,7 @@ public:
bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; } bool suppressWarnings() const { return (messages & EShMsgSuppressWarnings) != 0; }
bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; } bool isReadingHLSL() const { return (messages & EShMsgReadHlsl) == EShMsgReadHlsl; }
bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; } bool hlslEnable16BitTypes() const { return (messages & EShMsgHlslEnable16BitTypes) != 0; }
bool hlslDX9Compatible() const { return (messages & EShMsgHlslDX9Compatible) != 0; }
TInfoSink& infoSink; TInfoSink& infoSink;

View file

@ -0,0 +1,35 @@
//
// Copyright (C) 2018 The Khronos Group 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 3Dlabs Inc. Ltd. 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.
//
#include "pch.h"

View file

@ -0,0 +1,49 @@
#ifndef _PCH_H
#define _PCH_H
//
// Copyright (C) 2018 The Khronos Group 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 3Dlabs Inc. Ltd. 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.
//
#include <sstream>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <climits>
#include <iostream>
#include <sstream>
#include <memory>
#include "SymbolTable.h"
#include "ParseHelper.h"
#include "Scan.h"
#include "ScanContext.h"
#endif /* _PCH_H */

View file

@ -1,6 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013 LunarG, Inc. // Copyright (C) 2013 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
@ -109,11 +110,12 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
// save the macro name // save the macro name
const int defAtom = atomStrings.getAddAtom(ppToken->name); const int defAtom = atomStrings.getAddAtom(ppToken->name);
TSourceLoc defineLoc = ppToken->loc; // because ppToken might go to the next line before we report errors
// gather parameters to the macro, between (...) // gather parameters to the macro, between (...)
token = scanToken(ppToken); token = scanToken(ppToken);
if (token == '(' && ! ppToken->space) { if (token == '(' && !ppToken->space) {
mac.emptyArgs = 1; mac.functionLike = 1;
do { do {
token = scanToken(ppToken); token = scanToken(ppToken);
if (mac.args.size() == 0 && token == ')') if (mac.args.size() == 0 && token == ')')
@ -123,7 +125,6 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
return token; return token;
} }
mac.emptyArgs = 0;
const int argAtom = atomStrings.getAddAtom(ppToken->name); const int argAtom = atomStrings.getAddAtom(ppToken->name);
// check for duplication of parameter name // check for duplication of parameter name
@ -149,7 +150,6 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
} }
// record the definition of the macro // record the definition of the macro
TSourceLoc defineLoc = ppToken->loc; // because ppToken is going to go to the next line before we report errors
while (token != '\n' && token != EndOfInput) { while (token != '\n' && token != EndOfInput) {
mac.body.putToken(token, ppToken); mac.body.putToken(token, ppToken);
token = scanToken(ppToken); token = scanToken(ppToken);
@ -164,7 +164,9 @@ int TPpContext::CPPdefine(TPpToken* ppToken)
// Already defined -- need to make sure they are identical: // Already defined -- need to make sure they are identical:
// "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number, // "Two replacement lists are identical if and only if the preprocessing tokens in both have the same number,
// ordering, spelling, and white-space separation, where all white-space separations are considered identical." // ordering, spelling, and white-space separation, where all white-space separations are considered identical."
if (existing->args.size() != mac.args.size() || existing->emptyArgs != mac.emptyArgs) if (existing->functionLike != mac.functionLike)
parseContext.ppError(defineLoc, "Macro redefined; function-like versus object-like:", "#define", atomStrings.getString(defAtom));
else if (existing->args.size() != mac.args.size())
parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", atomStrings.getString(defAtom)); parseContext.ppError(defineLoc, "Macro redefined; different number of arguments:", "#define", atomStrings.getString(defAtom));
else { else {
if (existing->args != mac.args) if (existing->args != mac.args)
@ -651,6 +653,7 @@ int TPpContext::CPPinclude(TPpToken* ppToken)
epilogue << (res->headerData[res->headerLength - 1] == '\n'? "" : "\n") << epilogue << (res->headerData[res->headerLength - 1] == '\n'? "" : "\n") <<
"#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n"; "#line " << directiveLoc.line + forNextLine << " " << directiveLoc.getStringNameOrNum() << "\n";
pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), this)); pushInput(new TokenizableIncludeFile(directiveLoc, prologue.str(), res, epilogue.str(), this));
parseContext.intermediate.addIncludeText(res->headerName.c_str(), res->headerData, res->headerLength);
// There's no "current" location anymore. // There's no "current" location anymore.
parseContext.setCurrentColumn(0); parseContext.setCurrentColumn(0);
} else { } else {
@ -1120,7 +1123,8 @@ int TPpContext::tZeroInput::scan(TPpToken* ppToken)
if (done) if (done)
return EndOfInput; return EndOfInput;
strcpy(ppToken->name, "0"); ppToken->name[0] = '0';
ppToken->name[1] = 0;
ppToken->ival = 0; ppToken->ival = 0;
ppToken->space = false; ppToken->space = false;
done = true; done = true;
@ -1190,14 +1194,20 @@ MacroExpandResult TPpContext::MacroExpand(TPpToken* ppToken, bool expandUndef, b
TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error TSourceLoc loc = ppToken->loc; // in case we go to the next line before discovering the error
in->mac = macro; in->mac = macro;
if (macro->args.size() > 0 || macro->emptyArgs) { if (macro->functionLike) {
int token = scanToken(ppToken); // We don't know yet if this will be a successful call of a
// function-like macro; need to look for a '(', but without trashing
// the passed in ppToken, until we know we are no longer speculative.
TPpToken parenToken;
int token = scanToken(&parenToken);
if (newLineOkay) { if (newLineOkay) {
while (token == '\n') while (token == '\n')
token = scanToken(ppToken); token = scanToken(&parenToken);
} }
if (token != '(') { if (token != '(') {
UngetToken(token, ppToken); // Function-like macro called with object-like syntax: okay, don't expand.
// (We ate exactly one token that might not be white space; put it back.
UngetToken(token, &parenToken);
delete in; delete in;
return MacroExpandNotStarted; return MacroExpandNotStarted;
} }

View file

@ -1,6 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013 LunarG, Inc. // Copyright (C) 2013 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without

View file

@ -1,5 +1,6 @@
// //
// Copyright (C) 2013 LunarG, Inc. // Copyright (C) 2013 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
@ -267,12 +268,12 @@ public:
// //
struct MacroSymbol { struct MacroSymbol {
MacroSymbol() : emptyArgs(0), busy(0), undef(0) { } MacroSymbol() : functionLike(0), busy(0), undef(0) { }
TVector<int> args; TVector<int> args;
TokenStream body; TokenStream body;
unsigned emptyArgs : 1; unsigned functionLike : 1; // 0 means object-like, 1 means function-like
unsigned busy : 1; unsigned busy : 1;
unsigned undef : 1; unsigned undef : 1;
}; };
typedef TMap<int, MacroSymbol> TSymbolMap; typedef TMap<int, MacroSymbol> TSymbolMap;
@ -533,7 +534,7 @@ protected:
prologue_(prologue), prologue_(prologue),
epilogue_(epilogue), epilogue_(epilogue),
includedFile_(includedFile), includedFile_(includedFile),
scanner(3, strings, lengths, names, 0, 0, true), scanner(3, strings, lengths, nullptr, 0, 0, true),
prevScanner(nullptr), prevScanner(nullptr),
stringInput(pp, scanner) stringInput(pp, scanner)
{ {
@ -548,9 +549,9 @@ protected:
scanner.setLine(startLoc.line); scanner.setLine(startLoc.line);
scanner.setString(startLoc.string); scanner.setString(startLoc.string);
scanner.setFile(startLoc.name, 0); scanner.setFile(startLoc.getFilenameStr(), 0);
scanner.setFile(startLoc.name, 1); scanner.setFile(startLoc.getFilenameStr(), 1);
scanner.setFile(startLoc.name, 2); scanner.setFile(startLoc.getFilenameStr(), 2);
} }
// tInput methods: // tInput methods:
@ -590,8 +591,6 @@ protected:
const char* strings[3]; const char* strings[3];
// Length of str_, passed to scanner constructor. // Length of str_, passed to scanner constructor.
size_t lengths[3]; size_t lengths[3];
// String names
const char* names[3];
// Scans over str_. // Scans over str_.
TInputScanner scanner; TInputScanner scanner;
// The previous effective scanner before the scanner in this instance // The previous effective scanner before the scanner in this instance

View file

@ -2,6 +2,8 @@
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013 LunarG, Inc. // Copyright (C) 2013 LunarG, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// Copyright (C) 2015-2018 Google, Inc.
//
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
@ -316,16 +318,32 @@ int TPpContext::lFloatConst(int len, int ch, TPpToken* ppToken)
ppToken->dval = (double)wholeNumber * exponentValue; ppToken->dval = (double)wholeNumber * exponentValue;
} else { } else {
// slow path // slow path
ppToken->dval = 0.0;
// remove suffix
TString numstr(ppToken->name);
if (numstr.back() == 'f' || numstr.back() == 'F')
numstr.pop_back();
if (numstr.back() == 'h' || numstr.back() == 'H')
numstr.pop_back();
if (numstr.back() == 'l' || numstr.back() == 'L')
numstr.pop_back();
// use platform library
strtodStream.clear(); strtodStream.clear();
strtodStream.str(ppToken->name); strtodStream.str(numstr.c_str());
strtodStream >> ppToken->dval; strtodStream >> ppToken->dval;
// Assume failure combined with a large exponent was overflow, in
// an attempt to set INF. Otherwise, assume underflow, and set 0.0.
if (strtodStream.fail()) { if (strtodStream.fail()) {
// Assume failure combined with a large exponent was overflow, in
// an attempt to set INF.
if (!negativeExponent && exponent + numWholeNumberDigits > 300) if (!negativeExponent && exponent + numWholeNumberDigits > 300)
ppToken->i64val = 0x7ff0000000000000; // +Infinity ppToken->i64val = 0x7ff0000000000000; // +Infinity
else // Assume failure combined with a small exponent was overflow.
if (negativeExponent && exponent + numWholeNumberDigits > 300)
ppToken->dval = 0.0; ppToken->dval = 0.0;
// Unknown reason for failure. Theory is that either
// - the 0.0 is still there, or
// - something reasonable was written that is better than 0.0
} }
} }
@ -430,16 +448,16 @@ int TPpContext::tStringInput::scan(TPpToken* ppToken)
static const char* const Int64_Extensions[] = { static const char* const Int64_Extensions[] = {
E_GL_ARB_gpu_shader_int64, E_GL_ARB_gpu_shader_int64,
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int64 }; E_GL_EXT_shader_explicit_arithmetic_types_int64 };
static const int Num_Int64_Extensions = sizeof(Int64_Extensions) / sizeof(Int64_Extensions[0]); static const int Num_Int64_Extensions = sizeof(Int64_Extensions) / sizeof(Int64_Extensions[0]);
static const char* const Int16_Extensions[] = { static const char* const Int16_Extensions[] = {
#ifdef AMD_EXTENSIONS #ifdef AMD_EXTENSIONS
E_GL_AMD_gpu_shader_int16, E_GL_AMD_gpu_shader_int16,
#endif #endif
E_GL_KHX_shader_explicit_arithmetic_types, E_GL_EXT_shader_explicit_arithmetic_types,
E_GL_KHX_shader_explicit_arithmetic_types_int16 }; E_GL_EXT_shader_explicit_arithmetic_types_int16 };
static const int Num_Int16_Extensions = sizeof(Int16_Extensions) / sizeof(Int16_Extensions[0]); static const int Num_Int16_Extensions = sizeof(Int16_Extensions) / sizeof(Int16_Extensions[0]);
ppToken->ival = 0; ppToken->ival = 0;

View file

@ -1,6 +1,8 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013 LunarG, Inc. // Copyright (C) 2013 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
//
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without

View file

@ -105,14 +105,29 @@ public:
const TString &name = base.getName(); const TString &name = base.getName();
const TType &type = base.getType(); const TType &type = base.getType();
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name); TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
if (it == reflection.nameToIndex.end()) { if (it == reflection.nameToIndex.end()) {
reflection.nameToIndex[name] = (int)reflection.indexToAttribute.size(); reflection.nameToIndex[name.c_str()] = (int)reflection.indexToAttribute.size();
reflection.indexToAttribute.push_back(TObjectReflection(name, type, 0, mapToGlType(type), 0, 0)); reflection.indexToAttribute.push_back(TObjectReflection(name.c_str(), type, 0, mapToGlType(type), 0, 0));
} }
} }
} }
// shared calculation by getOffset and getOffsets
void updateOffset(const TType& parentType, const TType& memberType, int& offset, int& memberSize)
{
int dummyStride;
// modify just the children's view of matrix layout, if there is one for this member
TLayoutMatrix subMatrixLayout = memberType.getQualifier().layoutMatrix;
int memberAlignment = intermediate.getMemberAlignment(memberType, memberSize, dummyStride,
parentType.getQualifier().layoutPacking,
subMatrixLayout != ElmNone
? subMatrixLayout == ElmRowMajor
: parentType.getQualifier().layoutMatrix == ElmRowMajor);
RoundToPow2(offset, memberAlignment);
}
// Lookup or calculate the offset of a block member, using the recursively // Lookup or calculate the offset of a block member, using the recursively
// defined block offset rules. // defined block offset rules.
int getOffset(const TType& type, int index) int getOffset(const TType& type, int index)
@ -125,18 +140,11 @@ public:
if (memberList[index].type->getQualifier().hasOffset()) if (memberList[index].type->getQualifier().hasOffset())
return memberList[index].type->getQualifier().layoutOffset; return memberList[index].type->getQualifier().layoutOffset;
int memberSize; int memberSize = 0;
int dummyStride;
int offset = 0; int offset = 0;
for (int m = 0; m <= index; ++m) { for (int m = 0; m <= index; ++m) {
// modify just the children's view of matrix layout, if there is one for this member updateOffset(type, *memberList[m].type, offset, memberSize);
TLayoutMatrix subMatrixLayout = memberList[m].type->getQualifier().layoutMatrix;
int memberAlignment = intermediate.getBaseAlignment(*memberList[m].type, memberSize, dummyStride,
type.getQualifier().layoutPacking == ElpStd140,
subMatrixLayout != ElmNone
? subMatrixLayout == ElmRowMajor
: type.getQualifier().layoutMatrix == ElmRowMajor);
RoundToPow2(offset, memberAlignment);
if (m < index) if (m < index)
offset += memberSize; offset += memberSize;
} }
@ -144,6 +152,50 @@ public:
return offset; return offset;
} }
// Lookup or calculate the offset of all block members at once, using the recursively
// defined block offset rules.
void getOffsets(const TType& type, TVector<int>& offsets)
{
const TTypeList& memberList = *type.getStruct();
int memberSize = 0;
int offset = 0;
for (size_t m = 0; m < offsets.size(); ++m) {
// if the user supplied an offset, snap to it now
if (memberList[m].type->getQualifier().hasOffset())
offset = memberList[m].type->getQualifier().layoutOffset;
// calculate the offset of the next member and align the current offset to this member
updateOffset(type, *memberList[m].type, offset, memberSize);
// save the offset of this member
offsets[m] = offset;
// update for the next member
offset += memberSize;
}
}
// Calculate the stride of an array type
int getArrayStride(const TType& baseType, const TType& type)
{
int dummySize;
int stride;
// consider blocks to have 0 stride, so that all offsets are relative to the start of their block
if (type.getBasicType() == EbtBlock)
return 0;
TLayoutMatrix subMatrixLayout = type.getQualifier().layoutMatrix;
intermediate.getMemberAlignment(type, dummySize, stride,
baseType.getQualifier().layoutPacking,
subMatrixLayout != ElmNone
? subMatrixLayout == ElmRowMajor
: baseType.getQualifier().layoutMatrix == ElmRowMajor);
return stride;
}
// Calculate the block data size. // Calculate the block data size.
// Block arrayness is not taken into account, each element is backed by a separate buffer. // Block arrayness is not taken into account, each element is backed by a separate buffer.
int getBlockSize(const TType& blockType) int getBlockSize(const TType& blockType)
@ -154,9 +206,9 @@ public:
int lastMemberSize; int lastMemberSize;
int dummyStride; int dummyStride;
intermediate.getBaseAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride, intermediate.getMemberAlignment(*memberList[lastIndex].type, lastMemberSize, dummyStride,
blockType.getQualifier().layoutPacking == ElpStd140, blockType.getQualifier().layoutPacking,
blockType.getQualifier().layoutMatrix == ElmRowMajor); blockType.getQualifier().layoutMatrix == ElmRowMajor);
return lastOffset + lastMemberSize; return lastOffset + lastMemberSize;
} }
@ -179,7 +231,9 @@ public:
terminalType = &visitNode->getType(); terminalType = &visitNode->getType();
int index; int index;
switch (visitNode->getOp()) { switch (visitNode->getOp()) {
case EOpIndexIndirect: case EOpIndexIndirect: {
int stride = getArrayStride(baseType, visitNode->getLeft()->getType());
// Visit all the indices of this array, and for each one add on the remaining dereferencing // Visit all the indices of this array, and for each one add on the remaining dereferencing
for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) { for (int i = 0; i < std::max(visitNode->getLeft()->getType().getOuterArraySize(), 1); ++i) {
TString newBaseName = name; TString newBaseName = name;
@ -189,14 +243,22 @@ public:
++nextDeref; ++nextDeref;
TType derefType(*terminalType, 0); TType derefType(*terminalType, 0);
blowUpActiveAggregate(derefType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize); blowUpActiveAggregate(derefType, newBaseName, derefs, nextDeref, offset, blockIndex, arraySize);
if (offset >= 0)
offset += stride;
} }
// it was all completed in the recursive calls above // it was all completed in the recursive calls above
return; return;
}
case EOpIndexDirect: case EOpIndexDirect:
index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
if (baseType.getBasicType() != EbtBlock) if (baseType.getBasicType() != EbtBlock) {
name.append(TString("[") + String(index) + "]"); name.append(TString("[") + String(index) + "]");
if (offset >= 0)
offset += getArrayStride(baseType, visitNode->getLeft()->getType()) * index;
}
break; break;
case EOpIndexDirectStruct: case EOpIndexDirectStruct:
index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst(); index = visitNode->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
@ -213,23 +275,43 @@ public:
// if the terminalType is still too coarse a granularity, this is still an aggregate to expand, expand it... // if the terminalType is still too coarse a granularity, this is still an aggregate to expand, expand it...
if (! isReflectionGranularity(*terminalType)) { if (! isReflectionGranularity(*terminalType)) {
// the base offset of this node, that children are relative to
int baseOffset = offset;
if (terminalType->isArray()) { if (terminalType->isArray()) {
// Visit all the indices of this array, and for each one, // Visit all the indices of this array, and for each one,
// fully explode the remaining aggregate to dereference // fully explode the remaining aggregate to dereference
int stride = 0;
if (offset >= 0)
stride = getArrayStride(baseType, *terminalType);
for (int i = 0; i < std::max(terminalType->getOuterArraySize(), 1); ++i) { for (int i = 0; i < std::max(terminalType->getOuterArraySize(), 1); ++i) {
TString newBaseName = name; TString newBaseName = name;
newBaseName.append(TString("[") + String(i) + "]"); newBaseName.append(TString("[") + String(i) + "]");
TType derefType(*terminalType, 0); TType derefType(*terminalType, 0);
if (offset >= 0)
offset = baseOffset + stride * i;
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0); blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0);
} }
} else { } else {
// Visit all members of this aggregate, and for each one, // Visit all members of this aggregate, and for each one,
// fully explode the remaining aggregate to dereference // fully explode the remaining aggregate to dereference
const TTypeList& typeList = *terminalType->getStruct(); const TTypeList& typeList = *terminalType->getStruct();
TVector<int> memberOffsets;
if (baseOffset >= 0) {
memberOffsets.resize(typeList.size());
getOffsets(*terminalType, memberOffsets);
}
for (int i = 0; i < (int)typeList.size(); ++i) { for (int i = 0; i < (int)typeList.size(); ++i) {
TString newBaseName = name; TString newBaseName = name;
newBaseName.append(TString(".") + typeList[i].type->getFieldName()); newBaseName.append(TString(".") + typeList[i].type->getFieldName());
TType derefType(*terminalType, i); TType derefType(*terminalType, i);
if (offset >= 0)
offset = baseOffset + memberOffsets[i];
blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0); blowUpActiveAggregate(derefType, newBaseName, derefs, derefs.end(), offset, blockIndex, 0);
} }
} }
@ -245,10 +327,10 @@ public:
if (arraySize == 0) if (arraySize == 0)
arraySize = mapToGlArraySize(*terminalType); arraySize = mapToGlArraySize(*terminalType);
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name); TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
if (it == reflection.nameToIndex.end()) { if (it == reflection.nameToIndex.end()) {
reflection.nameToIndex[name] = (int)reflection.indexToUniform.size(); reflection.nameToIndex[name.c_str()] = (int)reflection.indexToUniform.size();
reflection.indexToUniform.push_back(TObjectReflection(name, *terminalType, offset, reflection.indexToUniform.push_back(TObjectReflection(name.c_str(), *terminalType, offset,
mapToGlType(*terminalType), mapToGlType(*terminalType),
arraySize, blockIndex)); arraySize, blockIndex));
} else if (arraySize > 1) { } else if (arraySize > 1) {
@ -348,11 +430,11 @@ public:
int addBlockName(const TString& name, const TType& type, int size) int addBlockName(const TString& name, const TType& type, int size)
{ {
int blockIndex; int blockIndex;
TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name); TReflection::TNameToIndex::const_iterator it = reflection.nameToIndex.find(name.c_str());
if (reflection.nameToIndex.find(name) == reflection.nameToIndex.end()) { if (reflection.nameToIndex.find(name.c_str()) == reflection.nameToIndex.end()) {
blockIndex = (int)reflection.indexToUniformBlock.size(); blockIndex = (int)reflection.indexToUniformBlock.size();
reflection.nameToIndex[name] = blockIndex; reflection.nameToIndex[name.c_str()] = blockIndex;
reflection.indexToUniformBlock.push_back(TObjectReflection(name, type, -1, -1, size, -1)); reflection.indexToUniformBlock.push_back(TObjectReflection(name.c_str(), type, -1, -1, size, -1));
} else } else
blockIndex = it->second; blockIndex = it->second;
@ -770,7 +852,7 @@ void TReflection::buildCounterIndices(const TIntermediate& intermediate)
{ {
// search for ones that have counters // search for ones that have counters
for (int i = 0; i < int(indexToUniformBlock.size()); ++i) { for (int i = 0; i < int(indexToUniformBlock.size()); ++i) {
const TString counterName(intermediate.addCounterBufferName(indexToUniformBlock[i].name)); const TString counterName(intermediate.addCounterBufferName(indexToUniformBlock[i].name).c_str());
const int index = getIndex(counterName); const int index = getIndex(counterName);
if (index >= 0) if (index >= 0)

View file

@ -55,11 +55,11 @@ class TReflectionTraverser;
// Data needed for just a single object at the granularity exchanged by the reflection API // Data needed for just a single object at the granularity exchanged by the reflection API
class TObjectReflection { class TObjectReflection {
public: public:
TObjectReflection(const TString& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex) : TObjectReflection(const std::string& pName, const TType& pType, int pOffset, int pGLDefineType, int pSize, int pIndex) :
name(pName), offset(pOffset), name(pName), offset(pOffset),
glDefineType(pGLDefineType), size(pSize), index(pIndex), counterIndex(-1), type(pType.clone()), stages(EShLanguageMask(0)) { } glDefineType(pGLDefineType), size(pSize), index(pIndex), counterIndex(-1), stages(EShLanguageMask(0)), type(pType.clone()) { }
const TType* const getType() const { return type; } const TType* getType() const { return type; }
int getBinding() const int getBinding() const
{ {
if (type == nullptr || !type->getQualifier().hasBinding()) if (type == nullptr || !type->getQualifier().hasBinding())
@ -78,7 +78,7 @@ public:
} }
static TObjectReflection badReflection() { return TObjectReflection(); } static TObjectReflection badReflection() { return TObjectReflection(); }
TString name; std::string name;
int offset; int offset;
int glDefineType; int glDefineType;
int size; // data size in bytes for a block, array size for a (non-block) object that's an array int size; // data size in bytes for a block, array size for a (non-block) object that's an array
@ -87,7 +87,8 @@ public:
EShLanguageMask stages; EShLanguageMask stages;
protected: protected:
TObjectReflection() : offset(-1), glDefineType(-1), size(-1), index(-1), type(nullptr) { } TObjectReflection() :
offset(-1), glDefineType(-1), size(-1), index(-1), counterIndex(-1), stages(EShLanguageMask(0)), type(nullptr) { }
const TType* type; const TType* type;
}; };
@ -162,7 +163,7 @@ protected:
void buildAttributeReflection(EShLanguage, const TIntermediate&); void buildAttributeReflection(EShLanguage, const TIntermediate&);
// Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex; // Need a TString hash: typedef std::unordered_map<TString, int> TNameToIndex;
typedef std::map<TString, int> TNameToIndex; typedef std::map<std::string, int> TNameToIndex;
typedef std::vector<TObjectReflection> TMapIndexToReflection; typedef std::vector<TObjectReflection> TMapIndexToReflection;
TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this TObjectReflection badReflection; // return for queries of -1 or generally out of range; has expected descriptions with in it for this

View file

@ -2,6 +2,23 @@ add_library(OSDependent STATIC ossource.cpp ../osinclude.h)
set_property(TARGET OSDependent PROPERTY FOLDER glslang) set_property(TARGET OSDependent PROPERTY FOLDER glslang)
set_property(TARGET OSDependent PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET OSDependent PROPERTY POSITION_INDEPENDENT_CODE ON)
# Link pthread
set(CMAKE_THREAD_PREFER_PTHREAD ON)
if(${CMAKE_VERSION} VERSION_LESS "3.1.0" OR CMAKE_CROSSCOMPILING)
# Needed as long as we support CMake 2.8 for Ubuntu 14.04,
# which does not support the recommended Threads::Threads target.
# https://cmake.org/cmake/help/v2.8.12/cmake.html#module:FindThreads
# Also needed when cross-compiling to work around
# https://gitlab.kitware.com/cmake/cmake/issues/16920
find_package(Threads)
target_link_libraries(OSDependent ${CMAKE_THREAD_LIBS_INIT})
else()
# This is the recommended way, so we use it for 3.1+.
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
target_link_libraries(OSDependent Threads::Threads)
endif()
if(ENABLE_GLSLANG_INSTALL) if(ENABLE_GLSLANG_INSTALL)
install(TARGETS OSDependent install(TARGETS OSDependent
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})

View file

@ -45,7 +45,10 @@
#include <stdint.h> #include <stdint.h>
#include <cstdio> #include <cstdio>
#include <sys/time.h> #include <sys/time.h>
#if !defined(__Fuchsia__)
#include <sys/resource.h> #include <sys/resource.h>
#endif
namespace glslang { namespace glslang {
@ -70,7 +73,7 @@ static void DetachThreadLinux(void *)
// //
void OS_CleanupThreadData(void) void OS_CleanupThreadData(void)
{ {
#ifdef __ANDROID__ #if defined(__ANDROID__) || defined(__Fuchsia__)
DetachThreadLinux(NULL); DetachThreadLinux(NULL);
#else #else
int old_cancel_state, old_cancel_type; int old_cancel_state, old_cancel_type;

View file

@ -1,6 +1,7 @@
// //
// Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
// Copyright (C) 2013-2016 LunarG, Inc. // Copyright (C) 2013-2016 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -52,9 +53,6 @@
#define SH_IMPORT_EXPORT #define SH_IMPORT_EXPORT
#else #else
#define SH_IMPORT_EXPORT #define SH_IMPORT_EXPORT
#ifndef __fastcall
#define __fastcall
#endif
#define C_DECL #define C_DECL
#endif #endif
@ -70,7 +68,7 @@
// This should always increase, as some paths to do not consume // This should always increase, as some paths to do not consume
// a more major number. // a more major number.
// It should increment by one when new functionality is added. // It should increment by one when new functionality is added.
#define GLSLANG_MINOR_VERSION 8 #define GLSLANG_MINOR_VERSION 11
// //
// Call before doing any other compiler/linker operations. // Call before doing any other compiler/linker operations.
@ -82,7 +80,7 @@ SH_IMPORT_EXPORT int ShInitialize();
// //
// Call this at process shutdown to clean up memory. // Call this at process shutdown to clean up memory.
// //
SH_IMPORT_EXPORT int __fastcall ShFinalize(); SH_IMPORT_EXPORT int ShFinalize();
// //
// Types of languages the compiler can consume. // Types of languages the compiler can consume.
@ -94,6 +92,14 @@ typedef enum {
EShLangGeometry, EShLangGeometry,
EShLangFragment, EShLangFragment,
EShLangCompute, EShLangCompute,
EShLangRayGenNV,
EShLangIntersectNV,
EShLangAnyHitNV,
EShLangClosestHitNV,
EShLangMissNV,
EShLangCallableNV,
EShLangTaskNV,
EShLangMeshNV,
EShLangCount, EShLangCount,
} EShLanguage; // would be better as stage, but this is ancient now } EShLanguage; // would be better as stage, but this is ancient now
@ -104,6 +110,14 @@ typedef enum {
EShLangGeometryMask = (1 << EShLangGeometry), EShLangGeometryMask = (1 << EShLangGeometry),
EShLangFragmentMask = (1 << EShLangFragment), EShLangFragmentMask = (1 << EShLangFragment),
EShLangComputeMask = (1 << EShLangCompute), EShLangComputeMask = (1 << EShLangCompute),
EShLangRayGenNVMask = (1 << EShLangRayGenNV),
EShLangIntersectNVMask = (1 << EShLangIntersectNV),
EShLangAnyHitNVMask = (1 << EShLangAnyHitNV),
EShLangClosestHitNVMask = (1 << EShLangClosestHitNV),
EShLangMissNVMask = (1 << EShLangMissNV),
EShLangCallableNVMask = (1 << EShLangCallableNV),
EShLangTaskNVMask = (1 << EShLangTaskNV),
EShLangMeshNVMask = (1 << EShLangMeshNV),
} EShLanguageMask; } EShLanguageMask;
namespace glslang { namespace glslang {
@ -138,7 +152,10 @@ typedef EShTargetClientVersion EshTargetClientVersion;
typedef enum { typedef enum {
EShTargetSpv_1_0 = (1 << 16), EShTargetSpv_1_0 = (1 << 16),
EShTargetSpv_1_1 = (1 << 16) | (1 << 8),
EShTargetSpv_1_2 = (1 << 16) | (2 << 8),
EShTargetSpv_1_3 = (1 << 16) | (3 << 8), EShTargetSpv_1_3 = (1 << 16) | (3 << 8),
EShTargetSpv_1_4 = (1 << 16) | (4 << 8),
} EShTargetLanguageVersion; } EShTargetLanguageVersion;
struct TInputLanguage { struct TInputLanguage {
@ -216,6 +233,7 @@ enum EShMessages {
EShMsgDebugInfo = (1 << 10), // save debug information EShMsgDebugInfo = (1 << 10), // save debug information
EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL EShMsgHlslEnable16BitTypes = (1 << 11), // enable use of 16-bit types in SPIR-V for HLSL
EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages EShMsgHlslLegalization = (1 << 12), // enable HLSL Legalization messages
EShMsgHlslDX9Compatible = (1 << 13), // enable HLSL DX9 compatible mode (right now only for samplers)
}; };
// //
@ -397,6 +415,8 @@ public:
void setResourceSetBinding(const std::vector<std::string>& base); void setResourceSetBinding(const std::vector<std::string>& base);
void setAutoMapBindings(bool map); void setAutoMapBindings(bool map);
void setAutoMapLocations(bool map); void setAutoMapLocations(bool map);
void addUniformLocationOverride(const char* name, int loc);
void setUniformLocationBase(int base);
void setInvertY(bool invert); void setInvertY(bool invert);
void setHlslIoMapping(bool hlslIoMap); void setHlslIoMapping(bool hlslIoMap);
void setFlattenUniformArrays(bool flatten); void setFlattenUniformArrays(bool flatten);
@ -532,6 +552,8 @@ public:
return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer); return parse(builtInResources, defaultVersion, ENoProfile, false, forwardCompatible, messages, includer);
} }
// NOTE: Doing just preprocessing to obtain a correct preprocessed shader string
// is not an officially supported or fully working path.
bool preprocess(const TBuiltInResource* builtInResources, bool preprocess(const TBuiltInResource* builtInResources,
int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile,
bool forwardCompatible, EShMessages message, std::string* outputString, bool forwardCompatible, EShMessages message, std::string* outputString,

View file

@ -19,7 +19,9 @@ set(SOURCES
InReadableOrder.cpp InReadableOrder.cpp
Logger.cpp Logger.cpp
SpvBuilder.cpp SpvBuilder.cpp
SpvPostProcess.cpp
doc.cpp doc.cpp
SpvTools.cpp
disassemble.cpp) disassemble.cpp)
set(SPVREMAP_SOURCES set(SPVREMAP_SOURCES
@ -38,6 +40,7 @@ set(HEADERS
SpvBuilder.h SpvBuilder.h
spvIR.h spvIR.h
doc.h doc.h
SpvTools.h
disassemble.h) disassemble.h)
set(SPVREMAP_HEADERS set(SPVREMAP_HEADERS
@ -61,13 +64,17 @@ set_property(TARGET SPIRV PROPERTY FOLDER glslang)
set_property(TARGET SPIRV PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET SPIRV PROPERTY POSITION_INDEPENDENT_CODE ON)
target_include_directories(SPIRV PUBLIC ..) target_include_directories(SPIRV PUBLIC ..)
add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) if (ENABLE_SPVREMAPPER)
set_property(TARGET SPVRemapper PROPERTY FOLDER glslang) add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS})
set_property(TARGET SPVRemapper PROPERTY POSITION_INDEPENDENT_CODE ON) set_property(TARGET SPVRemapper PROPERTY FOLDER glslang)
set_property(TARGET SPVRemapper PROPERTY POSITION_INDEPENDENT_CODE ON)
endif()
if(WIN32 AND BUILD_SHARED_LIBS) if(WIN32 AND BUILD_SHARED_LIBS)
set_target_properties(SPIRV PROPERTIES PREFIX "") set_target_properties(SPIRV PROPERTIES PREFIX "")
set_target_properties(SPVRemapper PROPERTIES PREFIX "") if (ENABLE_SPVREMAPPER)
set_target_properties(SPVRemapper PROPERTIES PREFIX "")
endif()
endif() endif()
if(ENABLE_OPT) if(ENABLE_OPT)
@ -88,11 +95,20 @@ endif(WIN32)
if(ENABLE_GLSLANG_INSTALL) if(ENABLE_GLSLANG_INSTALL)
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)
install(TARGETS SPIRV SPVRemapper if (ENABLE_SPVREMAPPER)
install(TARGETS SPVRemapper
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
install(TARGETS SPIRV
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
else() else()
install(TARGETS SPIRV SPVRemapper if (ENABLE_SPVREMAPPER)
install(TARGETS SPVRemapper
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
install(TARGETS SPIRV
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif() endif()

View file

@ -28,10 +28,11 @@
#define GLSLextEXT_H #define GLSLextEXT_H
static const int GLSLextEXTVersion = 100; static const int GLSLextEXTVersion = 100;
static const int GLSLextEXTRevision = 1; static const int GLSLextEXTRevision = 2;
static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export"; static const char* const E_SPV_EXT_shader_stencil_export = "SPV_EXT_shader_stencil_export";
static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer"; static const char* const E_SPV_EXT_shader_viewport_index_layer = "SPV_EXT_shader_viewport_index_layer";
static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered"; static const char* const E_SPV_EXT_fragment_fully_covered = "SPV_EXT_fragment_fully_covered";
static const char* const E_SPV_EXT_fragment_invocation_density = "SPV_EXT_fragment_invocation_density";
#endif // #ifndef GLSLextEXT_H #endif // #ifndef GLSLextEXT_H

View file

@ -39,5 +39,7 @@ static const char* const E_SPV_KHR_16bit_storage = "SPV_KHR_16bit
static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage"; static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_storage";
static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class"; static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class";
static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage"; static const char* const E_SPV_KHR_post_depth_coverage = "SPV_KHR_post_depth_coverage";
static const char* const E_SPV_KHR_vulkan_memory_model = "SPV_KHR_vulkan_memory_model";
static const char* const E_SPV_EXT_physical_storage_buffer = "SPV_EXT_physical_storage_buffer";
#endif // #ifndef GLSLextKHR_H #endif // #ifndef GLSLextKHR_H

View file

@ -33,7 +33,7 @@ enum Op;
enum Capability; enum Capability;
static const int GLSLextNVVersion = 100; static const int GLSLextNVVersion = 100;
static const int GLSLextNVRevision = 5; static const int GLSLextNVRevision = 11;
//SPV_NV_sample_mask_override_coverage //SPV_NV_sample_mask_override_coverage
const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage"; const char* const E_SPV_NV_sample_mask_override_coverage = "SPV_NV_sample_mask_override_coverage";
@ -54,4 +54,22 @@ const char* const E_SPV_NVX_multiview_per_view_attributes = "SPV_NVX_multiview_p
//SPV_NV_shader_subgroup_partitioned //SPV_NV_shader_subgroup_partitioned
const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned"; const char* const E_SPV_NV_shader_subgroup_partitioned = "SPV_NV_shader_subgroup_partitioned";
#endif // #ifndef GLSLextNV_H //SPV_NV_fragment_shader_barycentric
const char* const E_SPV_NV_fragment_shader_barycentric = "SPV_NV_fragment_shader_barycentric";
//SPV_NV_compute_shader_derivatives
const char* const E_SPV_NV_compute_shader_derivatives = "SPV_NV_compute_shader_derivatives";
//SPV_NV_shader_image_footprint
const char* const E_SPV_NV_shader_image_footprint = "SPV_NV_shader_image_footprint";
//SPV_NV_mesh_shader
const char* const E_SPV_NV_mesh_shader = "SPV_NV_mesh_shader";
//SPV_NV_raytracing
const char* const E_SPV_NV_ray_tracing = "SPV_NV_ray_tracing";
//SPV_NV_shading_rate
const char* const E_SPV_NV_shading_rate = "SPV_NV_shading_rate";
#endif // #ifndef GLSLextNV_H

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
// //
// Copyright (C) 2014 LunarG, Inc. // Copyright (C) 2014 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -38,6 +39,7 @@
#pragma warning(disable : 4464) // relative include path contains '..' #pragma warning(disable : 4464) // relative include path contains '..'
#endif #endif
#include "SpvTools.h"
#include "../glslang/Include/intermediate.h" #include "../glslang/Include/intermediate.h"
#include <string> #include <string>
@ -47,14 +49,6 @@
namespace glslang { namespace glslang {
struct SpvOptions {
SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
optimizeSize(false) { }
bool generateDebugInfo;
bool disableOptimizer;
bool optimizeSize;
};
void GetSpirvVersion(std::string&); void GetSpirvVersion(std::string&);
int GetSpirvGeneratorVersion(); int GetSpirvGeneratorVersion();
void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv, void GlslangToSpv(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,

View file

@ -1,6 +1,6 @@
// //
// Copyright (C) 2014-2015 LunarG, Inc. // Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2016 Google, Inc. // Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -60,6 +60,7 @@ Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogg
sourceVersion(0), sourceVersion(0),
sourceFileStringId(NoResult), sourceFileStringId(NoResult),
currentLine(0), currentLine(0),
currentFile(nullptr),
emitOpLines(false), emitOpLines(false),
addressModel(AddressingModelLogical), addressModel(AddressingModelLogical),
memoryModel(MemoryModelGLSL450), memoryModel(MemoryModelGLSL450),
@ -81,13 +82,15 @@ Id Builder::import(const char* name)
{ {
Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport); Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport);
import->addStringOperand(name); import->addStringOperand(name);
module.mapInstruction(import);
imports.push_back(std::unique_ptr<Instruction>(import)); imports.push_back(std::unique_ptr<Instruction>(import));
return import->getResultId(); return import->getResultId();
} }
// Emit an OpLine if we've been asked to emit OpLines and the line number // Emit instruction for non-filename-based #line directives (ie. no filename
// has changed since the last time, and is a valid line number. // seen yet): emit an OpLine if we've been asked to emit OpLines and the line
// number has changed since the last time, and is a valid line number.
void Builder::setLine(int lineNum) void Builder::setLine(int lineNum)
{ {
if (lineNum != 0 && lineNum != currentLine) { if (lineNum != 0 && lineNum != currentLine) {
@ -97,6 +100,26 @@ void Builder::setLine(int lineNum)
} }
} }
// If no filename, do non-filename-based #line emit. Else do filename-based emit.
// Emit OpLine if we've been asked to emit OpLines and the line number or filename
// has changed since the last time, and line number is valid.
void Builder::setLine(int lineNum, const char* filename)
{
if (filename == nullptr) {
setLine(lineNum);
return;
}
if ((lineNum != 0 && lineNum != currentLine) || currentFile == nullptr ||
strncmp(filename, currentFile, strlen(currentFile) + 1) != 0) {
currentLine = lineNum;
currentFile = filename;
if (emitOpLines) {
spv::Id strId = getStringId(filename);
addLine(strId, currentLine, 0);
}
}
}
void Builder::addLine(Id fileName, int lineNum, int column) void Builder::addLine(Id fileName, int lineNum, int column)
{ {
Instruction* line = new Instruction(OpLine); Instruction* line = new Instruction(OpLine);
@ -171,6 +194,40 @@ Id Builder::makePointer(StorageClass storageClass, Id pointee)
return type->getResultId(); return type->getResultId();
} }
Id Builder::makeForwardPointer(StorageClass storageClass)
{
// Caching/uniquifying doesn't work here, because we don't know the
// pointee type and there can be multiple forward pointers of the same
// storage type. Somebody higher up in the stack must keep track.
Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeForwardPointer);
type->addImmediateOperand(storageClass);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
return type->getResultId();
}
Id Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardPointerType, Id pointee)
{
// try to find it
Instruction* type;
for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
type = groupedTypes[OpTypePointer][t];
if (type->getImmediateOperand(0) == (unsigned)storageClass &&
type->getIdOperand(1) == pointee)
return type->getResultId();
}
type = new Instruction(forwardPointerType, NoType, OpTypePointer);
type->addImmediateOperand(storageClass);
type->addIdOperand(pointee);
groupedTypes[OpTypePointer].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
return type->getResultId();
}
Id Builder::makeIntegerType(int width, bool hasSign) Id Builder::makeIntegerType(int width, bool hasSign)
{ {
// try to find it // try to find it
@ -193,10 +250,8 @@ Id Builder::makeIntegerType(int width, bool hasSign)
// deal with capabilities // deal with capabilities
switch (width) { switch (width) {
case 8: case 8:
addCapability(CapabilityInt8);
break;
case 16: case 16:
addCapability(CapabilityInt16); // these are currently handled by storage-type declarations and post processing
break; break;
case 64: case 64:
addCapability(CapabilityInt64); addCapability(CapabilityInt64);
@ -228,7 +283,7 @@ Id Builder::makeFloatType(int width)
// deal with capabilities // deal with capabilities
switch (width) { switch (width) {
case 16: case 16:
addCapability(CapabilityFloat16); // currently handled by storage-type declarations and post processing
break; break;
case 64: case 64:
addCapability(CapabilityFloat64); addCapability(CapabilityFloat64);
@ -504,12 +559,28 @@ Id Builder::makeSampledImageType(Id imageType)
return type->getResultId(); return type->getResultId();
} }
#ifdef NV_EXTENSIONS
Id Builder::makeAccelerationStructureNVType()
{
Instruction *type;
if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) {
type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV);
groupedTypes[OpTypeAccelerationStructureNV].push_back(type);
constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
module.mapInstruction(type);
} else {
type = groupedTypes[OpTypeAccelerationStructureNV].back();
}
return type->getResultId();
}
#endif
Id Builder::getDerefTypeId(Id resultId) const Id Builder::getDerefTypeId(Id resultId) const
{ {
Id typeId = getTypeId(resultId); Id typeId = getTypeId(resultId);
assert(isPointerType(typeId)); assert(isPointerType(typeId));
return module.getInstruction(typeId)->getImmediateOperand(1); return module.getInstruction(typeId)->getIdOperand(1);
} }
Op Builder::getMostBasicTypeClass(Id typeId) const Op Builder::getMostBasicTypeClass(Id typeId) const
@ -519,12 +590,6 @@ Op Builder::getMostBasicTypeClass(Id typeId) const
Op typeClass = instr->getOpCode(); Op typeClass = instr->getOpCode();
switch (typeClass) switch (typeClass)
{ {
case OpTypeVoid:
case OpTypeBool:
case OpTypeInt:
case OpTypeFloat:
case OpTypeStruct:
return typeClass;
case OpTypeVector: case OpTypeVector:
case OpTypeMatrix: case OpTypeMatrix:
case OpTypeArray: case OpTypeArray:
@ -533,8 +598,7 @@ Op Builder::getMostBasicTypeClass(Id typeId) const
case OpTypePointer: case OpTypePointer:
return getMostBasicTypeClass(instr->getIdOperand(1)); return getMostBasicTypeClass(instr->getIdOperand(1));
default: default:
assert(0); return typeClass;
return OpTypeFloat;
} }
} }
@ -547,13 +611,14 @@ int Builder::getNumTypeConstituents(Id typeId) const
case OpTypeBool: case OpTypeBool:
case OpTypeInt: case OpTypeInt:
case OpTypeFloat: case OpTypeFloat:
case OpTypePointer:
return 1; return 1;
case OpTypeVector: case OpTypeVector:
case OpTypeMatrix: case OpTypeMatrix:
return instr->getImmediateOperand(1); return instr->getImmediateOperand(1);
case OpTypeArray: case OpTypeArray:
{ {
Id lengthId = instr->getImmediateOperand(1); Id lengthId = instr->getIdOperand(1);
return module.getInstruction(lengthId)->getImmediateOperand(0); return module.getInstruction(lengthId)->getImmediateOperand(0);
} }
case OpTypeStruct: case OpTypeStruct:
@ -621,6 +686,55 @@ Id Builder::getContainedTypeId(Id typeId) const
return getContainedTypeId(typeId, 0); return getContainedTypeId(typeId, 0);
} }
// Returns true if 'typeId' is or contains a scalar type declared with 'typeOp'
// of width 'width'. The 'width' is only consumed for int and float types.
// Returns false otherwise.
bool Builder::containsType(Id typeId, spv::Op typeOp, unsigned int width) const
{
const Instruction& instr = *module.getInstruction(typeId);
Op typeClass = instr.getOpCode();
switch (typeClass)
{
case OpTypeInt:
case OpTypeFloat:
return typeClass == typeOp && instr.getImmediateOperand(0) == width;
case OpTypeStruct:
for (int m = 0; m < instr.getNumOperands(); ++m) {
if (containsType(instr.getIdOperand(m), typeOp, width))
return true;
}
return false;
case OpTypePointer:
return false;
case OpTypeVector:
case OpTypeMatrix:
case OpTypeArray:
case OpTypeRuntimeArray:
return containsType(getContainedTypeId(typeId), typeOp, width);
default:
return typeClass == typeOp;
}
}
// return true if the type is a pointer to PhysicalStorageBufferEXT or an
// array of such pointers. These require restrict/aliased decorations.
bool Builder::containsPhysicalStorageBufferOrArray(Id typeId) const
{
const Instruction& instr = *module.getInstruction(typeId);
Op typeClass = instr.getOpCode();
switch (typeClass)
{
case OpTypePointer:
return getTypeStorageClass(typeId) == StorageClassPhysicalStorageBufferEXT;
case OpTypeArray:
return containsPhysicalStorageBufferOrArray(getContainedTypeId(typeId));
default:
return false;
}
}
// See if a scalar constant of this type has already been created, so it // See if a scalar constant of this type has already been created, so it
// can be reused rather than duplicated. (Required by the specification). // can be reused rather than duplicated. (Required by the specification).
Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value)
@ -1193,20 +1307,65 @@ Id Builder::createUndefined(Id type)
return inst->getResultId(); return inst->getResultId();
} }
// av/vis/nonprivate are unnecessary and illegal for some storage classes.
spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const
{
switch (sc) {
case spv::StorageClassUniform:
case spv::StorageClassWorkgroup:
case spv::StorageClassStorageBuffer:
case spv::StorageClassPhysicalStorageBufferEXT:
break;
default:
memoryAccess = spv::MemoryAccessMask(memoryAccess &
~(spv::MemoryAccessMakePointerAvailableKHRMask |
spv::MemoryAccessMakePointerVisibleKHRMask |
spv::MemoryAccessNonPrivatePointerKHRMask));
break;
}
return memoryAccess;
}
// Comments in header // Comments in header
void Builder::createStore(Id rValue, Id lValue) void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{ {
Instruction* store = new Instruction(OpStore); Instruction* store = new Instruction(OpStore);
store->addIdOperand(lValue); store->addIdOperand(lValue);
store->addIdOperand(rValue); store->addIdOperand(rValue);
memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
if (memoryAccess != MemoryAccessMaskNone) {
store->addImmediateOperand(memoryAccess);
if (memoryAccess & spv::MemoryAccessAlignedMask) {
store->addImmediateOperand(alignment);
}
if (memoryAccess & spv::MemoryAccessMakePointerAvailableKHRMask) {
store->addIdOperand(makeUintConstant(scope));
}
}
buildPoint->addInstruction(std::unique_ptr<Instruction>(store)); buildPoint->addInstruction(std::unique_ptr<Instruction>(store));
} }
// Comments in header // Comments in header
Id Builder::createLoad(Id lValue) Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{ {
Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad); Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
load->addIdOperand(lValue); load->addIdOperand(lValue);
memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
if (memoryAccess != MemoryAccessMaskNone) {
load->addImmediateOperand(memoryAccess);
if (memoryAccess & spv::MemoryAccessAlignedMask) {
load->addImmediateOperand(alignment);
}
if (memoryAccess & spv::MemoryAccessMakePointerVisibleKHRMask) {
load->addIdOperand(makeUintConstant(scope));
}
}
buildPoint->addInstruction(std::unique_ptr<Instruction>(load)); buildPoint->addInstruction(std::unique_ptr<Instruction>(load));
return load->getResultId(); return load->getResultId();
@ -1240,7 +1399,7 @@ Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vec
Id Builder::createArrayLength(Id base, unsigned int member) Id Builder::createArrayLength(Id base, unsigned int member)
{ {
spv::Id intType = makeIntType(32); spv::Id intType = makeUintType(32);
Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength); Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength);
length->addIdOperand(base); length->addIdOperand(base);
length->addImmediateOperand(member); length->addImmediateOperand(member);
@ -1331,7 +1490,7 @@ void Builder::createNoResultOp(Op opCode)
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
} }
// An opcode that has one operand, no result id, and no type // An opcode that has one id operand, no result id, and no type
void Builder::createNoResultOp(Op opCode, Id operand) void Builder::createNoResultOp(Op opCode, Id operand)
{ {
Instruction* op = new Instruction(opCode); Instruction* op = new Instruction(opCode);
@ -1339,29 +1498,43 @@ void Builder::createNoResultOp(Op opCode, Id operand)
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
} }
// An opcode that has one operand, no result id, and no type // An opcode that has one or more operands, no result id, and no type
void Builder::createNoResultOp(Op opCode, const std::vector<Id>& operands) void Builder::createNoResultOp(Op opCode, const std::vector<Id>& operands)
{ {
Instruction* op = new Instruction(opCode); Instruction* op = new Instruction(opCode);
for (auto it = operands.cbegin(); it != operands.cend(); ++it) for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
op->addIdOperand(*it); op->addIdOperand(*it);
}
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
}
// An opcode that has multiple operands, no result id, and no type
void Builder::createNoResultOp(Op opCode, const std::vector<IdImmediate>& operands)
{
Instruction* op = new Instruction(opCode);
for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
if (it->isId)
op->addIdOperand(it->word);
else
op->addImmediateOperand(it->word);
}
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
} }
void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics) void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics)
{ {
Instruction* op = new Instruction(OpControlBarrier); Instruction* op = new Instruction(OpControlBarrier);
op->addImmediateOperand(makeUintConstant(execution)); op->addIdOperand(makeUintConstant(execution));
op->addImmediateOperand(makeUintConstant(memory)); op->addIdOperand(makeUintConstant(memory));
op->addImmediateOperand(makeUintConstant(semantics)); op->addIdOperand(makeUintConstant(semantics));
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
} }
void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics) void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics)
{ {
Instruction* op = new Instruction(OpMemoryBarrier); Instruction* op = new Instruction(OpMemoryBarrier);
op->addImmediateOperand(makeUintConstant(executionScope)); op->addIdOperand(makeUintConstant(executionScope));
op->addImmediateOperand(makeUintConstant(memorySemantics)); op->addIdOperand(makeUintConstant(memorySemantics));
buildPoint->addInstruction(std::unique_ptr<Instruction>(op)); buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
} }
@ -1428,6 +1601,20 @@ Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
return op->getResultId(); return op->getResultId();
} }
Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& operands)
{
Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
if (it->isId)
op->addIdOperand(it->word);
else
op->addImmediateOperand(it->word);
}
buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
return op->getResultId();
}
Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals) Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals)
{ {
Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp); Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
@ -1588,6 +1775,13 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
if (parameters.component != NoResult) if (parameters.component != NoResult)
texArgs[numArgs++] = parameters.component; texArgs[numArgs++] = parameters.component;
#ifdef NV_EXTENSIONS
if (parameters.granularity != NoResult)
texArgs[numArgs++] = parameters.granularity;
if (parameters.coarse != NoResult)
texArgs[numArgs++] = parameters.coarse;
#endif
// //
// Set up the optional arguments // Set up the optional arguments
// //
@ -1639,6 +1833,12 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask); mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask);
texArgs[numArgs++] = parameters.lodClamp; texArgs[numArgs++] = parameters.lodClamp;
} }
if (parameters.nonprivate) {
mask = mask | ImageOperandsNonPrivateTexelKHRMask;
}
if (parameters.volatil) {
mask = mask | ImageOperandsVolatileTexelKHRMask;
}
if (mask == ImageOperandsMaskNone) if (mask == ImageOperandsMaskNone)
--numArgs; // undo speculative reservation for the mask argument --numArgs; // undo speculative reservation for the mask argument
else else
@ -1653,6 +1853,10 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
opCode = OpImageSparseFetch; opCode = OpImageSparseFetch;
else else
opCode = OpImageFetch; opCode = OpImageFetch;
#ifdef NV_EXTENSIONS
} else if (parameters.granularity && parameters.coarse) {
opCode = OpImageSampleFootprintNV;
#endif
} else if (gather) { } else if (gather) {
if (parameters.Dref) if (parameters.Dref)
if (sparse) if (sparse)
@ -1774,9 +1978,6 @@ Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse,
// Comments in header // Comments in header
Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters, bool isUnsignedResult) Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters, bool isUnsignedResult)
{ {
// All these need a capability
addCapability(CapabilityImageQuery);
// Figure out the result type // Figure out the result type
Id resultType = 0; Id resultType = 0;
switch (opCode) { switch (opCode) {
@ -2001,7 +2202,8 @@ Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sourc
// Go through the source arguments, each one could have either // Go through the source arguments, each one could have either
// a single or multiple components to contribute. // a single or multiple components to contribute.
for (unsigned int i = 0; i < sources.size(); ++i) { for (unsigned int i = 0; i < sources.size(); ++i) {
if (isScalar(sources[i]))
if (isScalar(sources[i]) || isPointer(sources[i]))
latchResult(sources[i]); latchResult(sources[i]);
else if (isVector(sources[i])) else if (isVector(sources[i]))
accumulateVectorConstituents(sources[i]); accumulateVectorConstituents(sources[i]);
@ -2029,9 +2231,39 @@ Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>&
int numRows = getTypeNumRows(resultTypeId); int numRows = getTypeNumRows(resultTypeId);
Instruction* instr = module.getInstruction(componentTypeId); Instruction* instr = module.getInstruction(componentTypeId);
Id bitCount = instr->getIdOperand(0); unsigned bitCount = instr->getImmediateOperand(0);
// Will use a two step process // Optimize matrix constructed from a bigger matrix
if (isMatrix(sources[0]) && getNumColumns(sources[0]) >= numCols && getNumRows(sources[0]) >= numRows) {
// To truncate the matrix to a smaller number of rows/columns, we need to:
// 1. For each column, extract the column and truncate it to the required size using shuffle
// 2. Assemble the resulting matrix from all columns
Id matrix = sources[0];
Id columnTypeId = getContainedTypeId(resultTypeId);
Id sourceColumnTypeId = getContainedTypeId(getTypeId(matrix));
std::vector<unsigned> channels;
for (int row = 0; row < numRows; ++row)
channels.push_back(row);
std::vector<Id> matrixColumns;
for (int col = 0; col < numCols; ++col) {
std::vector<unsigned> indexes;
indexes.push_back(col);
Id colv = createCompositeExtract(matrix, sourceColumnTypeId, indexes);
setPrecision(colv, precision);
if (numRows != getNumRows(matrix)) {
matrixColumns.push_back(createRvalueSwizzle(precision, columnTypeId, colv, channels));
} else {
matrixColumns.push_back(colv);
}
}
return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision);
}
// Otherwise, will use a two step process
// 1. make a compile-time 2D array of values // 1. make a compile-time 2D array of values
// 2. construct a matrix from that array // 2. construct a matrix from that array
@ -2285,11 +2517,16 @@ void Builder::clearAccessChain()
accessChain.component = NoResult; accessChain.component = NoResult;
accessChain.preSwizzleBaseType = NoType; accessChain.preSwizzleBaseType = NoType;
accessChain.isRValue = false; accessChain.isRValue = false;
accessChain.coherentFlags.clear();
accessChain.alignment = 0;
} }
// Comments in header // Comments in header
void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType) void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
{ {
accessChain.coherentFlags |= coherentFlags;
accessChain.alignment |= alignment;
// swizzles can be stacked in GLSL, but simplified to a single // swizzles can be stacked in GLSL, but simplified to a single
// one here; the base type doesn't change // one here; the base type doesn't change
if (accessChain.preSwizzleBaseType == NoType) if (accessChain.preSwizzleBaseType == NoType)
@ -2311,7 +2548,7 @@ void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizz
} }
// Comments in header // Comments in header
void Builder::accessChainStore(Id rvalue) void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{ {
assert(accessChain.isRValue == false); assert(accessChain.isRValue == false);
@ -2329,11 +2566,17 @@ void Builder::accessChainStore(Id rvalue)
source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle); source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
} }
createStore(source, base); // take LSB of alignment
alignment = alignment & ~(alignment & (alignment-1));
if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
}
createStore(source, base, memoryAccess, scope, alignment);
} }
// Comments in header // Comments in header
Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType) Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
{ {
Id id; Id id;
@ -2376,8 +2619,15 @@ Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu
id = accessChain.base; // no precision, it was set when this was defined id = accessChain.base; // no precision, it was set when this was defined
} else { } else {
transferAccessChainSwizzle(true); transferAccessChainSwizzle(true);
// take LSB of alignment
alignment = alignment & ~(alignment & (alignment-1));
if (getStorageClass(accessChain.base) == StorageClassPhysicalStorageBufferEXT) {
memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
}
// load through the access chain // load through the access chain
id = createLoad(collapseAccessChain()); id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment);
setPrecision(id, precision); setPrecision(id, precision);
addDecoration(id, nonUniform); addDecoration(id, nonUniform);
} }
@ -2453,42 +2703,6 @@ Id Builder::accessChainGetInferredType()
return type; return type;
} }
// comment in header
void Builder::eliminateDeadDecorations() {
std::unordered_set<const Block*> reachable_blocks;
std::unordered_set<Id> unreachable_definitions;
// Collect IDs defined in unreachable blocks. For each function, label the
// reachable blocks first. Then for each unreachable block, collect the
// result IDs of the instructions in it.
for (std::vector<Function*>::const_iterator fi = module.getFunctions().cbegin();
fi != module.getFunctions().cend(); fi++) {
Function* f = *fi;
Block* entry = f->getEntryBlock();
inReadableOrder(entry, [&reachable_blocks](const Block* b) {
reachable_blocks.insert(b);
});
for (std::vector<Block*>::const_iterator bi = f->getBlocks().cbegin();
bi != f->getBlocks().cend(); bi++) {
Block* b = *bi;
if (!reachable_blocks.count(b)) {
for (std::vector<std::unique_ptr<Instruction> >::const_iterator
ii = b->getInstructions().cbegin();
ii != b->getInstructions().cend(); ii++) {
Instruction* i = ii->get();
unreachable_definitions.insert(i->getResultId());
}
}
}
}
decorations.erase(std::remove_if(decorations.begin(), decorations.end(),
[&unreachable_definitions](std::unique_ptr<Instruction>& I) -> bool {
Instruction* inst = I.get();
Id decoration_id = inst->getIdOperand(0);
return unreachable_definitions.count(decoration_id) != 0;
}),
decorations.end());
}
void Builder::dump(std::vector<unsigned int>& out) const void Builder::dump(std::vector<unsigned int>& out) const
{ {
// Header, before first instructions: // Header, before first instructions:
@ -2719,7 +2933,8 @@ void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* els
// OpSource // OpSource
// [OpSourceContinued] // [OpSourceContinued]
// ... // ...
void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const void Builder::dumpSourceInstructions(const spv::Id fileId, const std::string& text,
std::vector<unsigned int>& out) const
{ {
const int maxWordCount = 0xFFFF; const int maxWordCount = 0xFFFF;
const int opSourceWordCount = 4; const int opSourceWordCount = 4;
@ -2731,14 +2946,14 @@ void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
sourceInst.addImmediateOperand(source); sourceInst.addImmediateOperand(source);
sourceInst.addImmediateOperand(sourceVersion); sourceInst.addImmediateOperand(sourceVersion);
// File operand // File operand
if (sourceFileStringId != NoResult) { if (fileId != NoResult) {
sourceInst.addIdOperand(sourceFileStringId); sourceInst.addIdOperand(fileId);
// Source operand // Source operand
if (sourceText.size() > 0) { if (text.size() > 0) {
int nextByte = 0; int nextByte = 0;
std::string subString; std::string subString;
while ((int)sourceText.size() - nextByte > 0) { while ((int)text.size() - nextByte > 0) {
subString = sourceText.substr(nextByte, nonNullBytesPerInstruction); subString = text.substr(nextByte, nonNullBytesPerInstruction);
if (nextByte == 0) { if (nextByte == 0) {
// OpSource // OpSource
sourceInst.addStringOperand(subString.c_str()); sourceInst.addStringOperand(subString.c_str());
@ -2758,6 +2973,14 @@ void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
} }
} }
// Dump an OpSource[Continued] sequence for the source and every include file
void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
{
dumpSourceInstructions(sourceFileStringId, sourceText, out);
for (auto iItr = includeFiles.begin(); iItr != includeFiles.end(); ++iItr)
dumpSourceInstructions(iItr->first, *iItr->second, out);
}
void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
{ {
for (int i = 0; i < (int)instructions.size(); ++i) { for (int i = 0; i < (int)instructions.size(); ++i) {

View file

@ -1,6 +1,6 @@
// //
// Copyright (C) 2014-2015 LunarG, Inc. // Copyright (C) 2014-2015 LunarG, Inc.
// Copyright (C) 2015-2016 Google, Inc. // Copyright (C) 2015-2018 Google, Inc.
// Copyright (C) 2017 ARM Limited. // Copyright (C) 2017 ARM Limited.
// //
// All rights reserved. // All rights reserved.
@ -57,6 +57,7 @@
#include <sstream> #include <sstream>
#include <stack> #include <stack>
#include <unordered_map> #include <unordered_map>
#include <map>
namespace spv { namespace spv {
@ -74,18 +75,33 @@ public:
source = lang; source = lang;
sourceVersion = version; sourceVersion = version;
} }
spv::Id getStringId(const std::string& str)
{
auto sItr = stringIds.find(str);
if (sItr != stringIds.end())
return sItr->second;
spv::Id strId = getUniqueId();
Instruction* fileString = new Instruction(strId, NoType, OpString);
const char* file_c_str = str.c_str();
fileString->addStringOperand(file_c_str);
strings.push_back(std::unique_ptr<Instruction>(fileString));
stringIds[file_c_str] = strId;
return strId;
}
void setSourceFile(const std::string& file) void setSourceFile(const std::string& file)
{ {
Instruction* fileString = new Instruction(getUniqueId(), NoType, OpString); sourceFileStringId = getStringId(file);
fileString->addStringOperand(file.c_str());
sourceFileStringId = fileString->getResultId();
strings.push_back(std::unique_ptr<Instruction>(fileString));
} }
void setSourceText(const std::string& text) { sourceText = text; } void setSourceText(const std::string& text) { sourceText = text; }
void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); } void addSourceExtension(const char* ext) { sourceExtensions.push_back(ext); }
void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); } void addModuleProcessed(const std::string& p) { moduleProcesses.push_back(p.c_str()); }
void setEmitOpLines() { emitOpLines = true; } void setEmitOpLines() { emitOpLines = true; }
void addExtension(const char* ext) { extensions.insert(ext); } void addExtension(const char* ext) { extensions.insert(ext); }
void addInclude(const std::string& name, const std::string& text)
{
spv::Id incId = getStringId(name);
includeFiles[incId] = &text;
}
Id import(const char*); Id import(const char*);
void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem) void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
{ {
@ -106,16 +122,25 @@ public:
return id; return id;
} }
// Log the current line, and if different than the last one, // Generate OpLine for non-filename-based #line directives (ie no filename
// issue a new OpLine, using the current file name. // seen yet): Log the current line, and if different than the last one,
// issue a new OpLine using the new line and current source file name.
void setLine(int line); void setLine(int line);
// If filename null, generate OpLine for non-filename-based line directives,
// else do filename-based: Log the current line and file, and if different
// than the last one, issue a new OpLine using the new line and file
// name.
void setLine(int line, const char* filename);
// Low-level OpLine. See setLine() for a layered helper. // Low-level OpLine. See setLine() for a layered helper.
void addLine(Id fileName, int line, int column); void addLine(Id fileName, int line, int column);
// For creating new types (will return old type if the requested one was already made). // For creating new types (will return old type if the requested one was already made).
Id makeVoidType(); Id makeVoidType();
Id makeBoolType(); Id makeBoolType();
Id makePointer(StorageClass, Id type); Id makePointer(StorageClass, Id pointee);
Id makeForwardPointer(StorageClass);
Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee);
Id makeIntegerType(int width, bool hasSign); // generic Id makeIntegerType(int width, bool hasSign); // generic
Id makeIntType(int width) { return makeIntegerType(width, true); } Id makeIntType(int width) { return makeIntegerType(width, true); }
Id makeUintType(int width) { return makeIntegerType(width, false); } Id makeUintType(int width) { return makeIntegerType(width, false); }
@ -131,6 +156,9 @@ public:
Id makeSamplerType(); Id makeSamplerType();
Id makeSampledImageType(Id imageType); Id makeSampledImageType(Id imageType);
// accelerationStructureNV type
Id makeAccelerationStructureNVType();
// For querying about types. // For querying about types.
Id getTypeId(Id resultId) const { return module.getTypeId(resultId); } Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
Id getDerefTypeId(Id resultId) const; Id getDerefTypeId(Id resultId) const;
@ -167,6 +195,8 @@ public:
bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; } bool isImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeImage; }
bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; } bool isSamplerType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampler; }
bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; } bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
bool containsType(Id typeId, Op typeOp, unsigned int width) const;
bool containsPhysicalStorageBufferOrArray(Id typeId) const;
bool isConstantOpCode(Op opcode) const; bool isConstantOpCode(Op opcode) const;
bool isSpecConstantOpCode(Op opcode) const; bool isSpecConstantOpCode(Op opcode) const;
@ -273,10 +303,10 @@ public:
Id createUndefined(Id type); Id createUndefined(Id type);
// Store into an Id and return the l-value // Store into an Id and return the l-value
void createStore(Id rValue, Id lValue); void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// Load from an Id and return it // Load from an Id and return it
Id createLoad(Id lValue); Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// Create an OpAccessChain instruction // Create an OpAccessChain instruction
Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets); Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
@ -296,12 +326,14 @@ public:
void createNoResultOp(Op); void createNoResultOp(Op);
void createNoResultOp(Op, Id operand); void createNoResultOp(Op, Id operand);
void createNoResultOp(Op, const std::vector<Id>& operands); void createNoResultOp(Op, const std::vector<Id>& operands);
void createNoResultOp(Op, const std::vector<IdImmediate>& operands);
void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask); void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask);
void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics); void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics);
Id createUnaryOp(Op, Id typeId, Id operand); Id createUnaryOp(Op, Id typeId, Id operand);
Id createBinOp(Op, Id typeId, Id operand1, Id operand2); Id createBinOp(Op, Id typeId, Id operand1, Id operand2);
Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3); Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
Id createOp(Op, Id typeId, const std::vector<Id>& operands); Id createOp(Op, Id typeId, const std::vector<Id>& operands);
Id createOp(Op, Id typeId, const std::vector<IdImmediate>& operands);
Id createFunctionCall(spv::Function*, const std::vector<spv::Id>&); Id createFunctionCall(spv::Function*, const std::vector<spv::Id>&);
Id createSpecConstantOp(Op, Id typeId, const std::vector<spv::Id>& operands, const std::vector<unsigned>& literals); Id createSpecConstantOp(Op, Id typeId, const std::vector<spv::Id>& operands, const std::vector<unsigned>& literals);
@ -363,6 +395,10 @@ public:
Id component; Id component;
Id texelOut; Id texelOut;
Id lodClamp; Id lodClamp;
Id granularity;
Id coarse;
bool nonprivate;
bool volatil;
}; };
// Select the correct texture operation based on all inputs, and emit the correct instruction // Select the correct texture operation based on all inputs, and emit the correct instruction
@ -502,6 +538,44 @@ public:
Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present Id component; // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present
Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present Id preSwizzleBaseType; // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value bool isRValue; // true if 'base' is an r-value, otherwise, base is an l-value
unsigned int alignment; // bitwise OR of alignment values passed in. Accumulates worst alignment. Only tracks base and (optional) component selection alignment.
// Accumulate whether anything in the chain of structures has coherent decorations.
struct CoherentFlags {
unsigned coherent : 1;
unsigned devicecoherent : 1;
unsigned queuefamilycoherent : 1;
unsigned workgroupcoherent : 1;
unsigned subgroupcoherent : 1;
unsigned nonprivate : 1;
unsigned volatil : 1;
unsigned isImage : 1;
void clear() {
coherent = 0;
devicecoherent = 0;
queuefamilycoherent = 0;
workgroupcoherent = 0;
subgroupcoherent = 0;
nonprivate = 0;
volatil = 0;
isImage = 0;
}
CoherentFlags() { clear(); }
CoherentFlags operator |=(const CoherentFlags &other) {
coherent |= other.coherent;
devicecoherent |= other.devicecoherent;
queuefamilycoherent |= other.queuefamilycoherent;
workgroupcoherent |= other.workgroupcoherent;
subgroupcoherent |= other.subgroupcoherent;
nonprivate |= other.nonprivate;
volatil |= other.volatil;
isImage |= other.isImage;
return *this;
}
};
CoherentFlags coherentFlags;
}; };
// //
@ -531,30 +605,34 @@ public:
} }
// push offset onto the end of the chain // push offset onto the end of the chain
void accessChainPush(Id offset) void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
{ {
accessChain.indexChain.push_back(offset); accessChain.indexChain.push_back(offset);
accessChain.coherentFlags |= coherentFlags;
accessChain.alignment |= alignment;
} }
// push new swizzle onto the end of any existing swizzle, merging into a single swizzle // push new swizzle onto the end of any existing swizzle, merging into a single swizzle
void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType); void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
// push a dynamic component selection onto the access chain, only applicable with a // push a dynamic component selection onto the access chain, only applicable with a
// non-trivial swizzle or no swizzle // non-trivial swizzle or no swizzle
void accessChainPushComponent(Id component, Id preSwizzleBaseType) void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
{ {
if (accessChain.swizzle.size() != 1) { if (accessChain.swizzle.size() != 1) {
accessChain.component = component; accessChain.component = component;
if (accessChain.preSwizzleBaseType == NoType) if (accessChain.preSwizzleBaseType == NoType)
accessChain.preSwizzleBaseType = preSwizzleBaseType; accessChain.preSwizzleBaseType = preSwizzleBaseType;
} }
accessChain.coherentFlags |= coherentFlags;
accessChain.alignment |= alignment;
} }
// use accessChain and swizzle to store value // use accessChain and swizzle to store value
void accessChainStore(Id rvalue); void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// use accessChain and swizzle to load an r-value // use accessChain and swizzle to load an r-value
Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType); Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
// get the direct pointer for an l-value // get the direct pointer for an l-value
Id accessChainGetLValue(); Id accessChainGetLValue();
@ -563,9 +641,17 @@ public:
// based on the type of the base and the chain of dereferences. // based on the type of the base and the chain of dereferences.
Id accessChainGetInferredType(); Id accessChainGetInferredType();
// Remove OpDecorate instructions whose operands are defined in unreachable // Add capabilities, extensions, remove unneeded decorations, etc.,
// blocks. // based on the resulting SPIR-V.
void eliminateDeadDecorations(); void postProcess();
// Hook to visit each instruction in a block in a function
void postProcess(Instruction&);
// Hook to visit each instruction in a reachable block in a function.
void postProcessReachable(const Instruction&);
// Hook to visit each non-32-bit sized float/int operation in a block.
void postProcessType(const Instruction&, spv::Id typeId);
void dump(std::vector<unsigned int>&) const; void dump(std::vector<unsigned int>&) const;
void createBranch(Block* block); void createBranch(Block* block);
@ -593,8 +679,10 @@ public:
void createAndSetNoPredecessorBlock(const char*); void createAndSetNoPredecessorBlock(const char*);
void createSelectionMerge(Block* mergeBlock, unsigned int control); void createSelectionMerge(Block* mergeBlock, unsigned int control);
void dumpSourceInstructions(std::vector<unsigned int>&) const; void dumpSourceInstructions(std::vector<unsigned int>&) const;
void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const;
void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const; void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
void dumpModuleProcesses(std::vector<unsigned int>&) const; void dumpModuleProcesses(std::vector<unsigned int>&) const;
spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const;
unsigned int spvVersion; // the version of SPIR-V to emit in the header unsigned int spvVersion; // the version of SPIR-V to emit in the header
SourceLanguage source; SourceLanguage source;
@ -602,6 +690,7 @@ public:
spv::Id sourceFileStringId; spv::Id sourceFileStringId;
std::string sourceText; std::string sourceText;
int currentLine; int currentLine;
const char* currentFile;
bool emitOpLines; bool emitOpLines;
std::set<std::string> extensions; std::set<std::string> extensions;
std::vector<const char*> sourceExtensions; std::vector<const char*> sourceExtensions;
@ -639,6 +728,12 @@ public:
// Our loop stack. // Our loop stack.
std::stack<LoopBlocks> loops; std::stack<LoopBlocks> loops;
// map from strings to their string ids
std::unordered_map<std::string, spv::Id> stringIds;
// map from include file name ids to their contents
std::map<spv::Id, const std::string*> includeFiles;
// The stream for outputting warnings and errors. // The stream for outputting warnings and errors.
SpvBuildLogger* logger; SpvBuildLogger* logger;
}; // end Builder class }; // end Builder class

View file

@ -0,0 +1,390 @@
//
// Copyright (C) 2018 Google, 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 3Dlabs Inc. Ltd. 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.
//
// Post-processing for SPIR-V IR, in internal form, not standard binary form.
//
#include <cassert>
#include <cstdlib>
#include <unordered_set>
#include <algorithm>
#include "SpvBuilder.h"
#include "spirv.hpp"
#include "GlslangToSpv.h"
#include "SpvBuilder.h"
namespace spv {
#include "GLSL.std.450.h"
#include "GLSL.ext.KHR.h"
#include "GLSL.ext.EXT.h"
#ifdef AMD_EXTENSIONS
#include "GLSL.ext.AMD.h"
#endif
#ifdef NV_EXTENSIONS
#include "GLSL.ext.NV.h"
#endif
}
namespace spv {
// Hook to visit each operand type and result type of an instruction.
// Will be called multiple times for one instruction, once for each typed
// operand and the result.
void Builder::postProcessType(const Instruction& inst, Id typeId)
{
// Characterize the type being questioned
Id basicTypeOp = getMostBasicTypeClass(typeId);
int width = 0;
if (basicTypeOp == OpTypeFloat || basicTypeOp == OpTypeInt)
width = getScalarTypeWidth(typeId);
// Do opcode-specific checks
switch (inst.getOpCode()) {
case OpLoad:
case OpStore:
if (basicTypeOp == OpTypeStruct) {
if (containsType(typeId, OpTypeInt, 8))
addCapability(CapabilityInt8);
if (containsType(typeId, OpTypeInt, 16))
addCapability(CapabilityInt16);
if (containsType(typeId, OpTypeFloat, 16))
addCapability(CapabilityFloat16);
} else {
StorageClass storageClass = getStorageClass(inst.getIdOperand(0));
if (width == 8) {
switch (storageClass) {
case StorageClassPhysicalStorageBufferEXT:
case StorageClassUniform:
case StorageClassStorageBuffer:
case StorageClassPushConstant:
break;
default:
addCapability(CapabilityInt8);
break;
}
} else if (width == 16) {
switch (storageClass) {
case StorageClassPhysicalStorageBufferEXT:
case StorageClassUniform:
case StorageClassStorageBuffer:
case StorageClassPushConstant:
case StorageClassInput:
case StorageClassOutput:
break;
default:
if (basicTypeOp == OpTypeInt)
addCapability(CapabilityInt16);
if (basicTypeOp == OpTypeFloat)
addCapability(CapabilityFloat16);
break;
}
}
}
break;
case OpAccessChain:
case OpPtrAccessChain:
case OpCopyObject:
case OpFConvert:
case OpSConvert:
case OpUConvert:
break;
case OpExtInst:
#if AMD_EXTENSIONS
switch (inst.getImmediateOperand(1)) {
case GLSLstd450Frexp:
case GLSLstd450FrexpStruct:
if (getSpvVersion() < glslang::EShTargetSpv_1_3 && containsType(typeId, OpTypeInt, 16))
addExtension(spv::E_SPV_AMD_gpu_shader_int16);
break;
case GLSLstd450InterpolateAtCentroid:
case GLSLstd450InterpolateAtSample:
case GLSLstd450InterpolateAtOffset:
if (getSpvVersion() < glslang::EShTargetSpv_1_3 && containsType(typeId, OpTypeFloat, 16))
addExtension(spv::E_SPV_AMD_gpu_shader_half_float);
break;
default:
break;
}
#endif
break;
default:
if (basicTypeOp == OpTypeFloat && width == 16)
addCapability(CapabilityFloat16);
if (basicTypeOp == OpTypeInt && width == 16)
addCapability(CapabilityInt16);
if (basicTypeOp == OpTypeInt && width == 8)
addCapability(CapabilityInt8);
break;
}
}
// Called for each instruction that resides in a block.
void Builder::postProcess(Instruction& inst)
{
// Add capabilities based simply on the opcode.
switch (inst.getOpCode()) {
case OpExtInst:
switch (inst.getImmediateOperand(1)) {
case GLSLstd450InterpolateAtCentroid:
case GLSLstd450InterpolateAtSample:
case GLSLstd450InterpolateAtOffset:
addCapability(CapabilityInterpolationFunction);
break;
default:
break;
}
break;
case OpDPdxFine:
case OpDPdyFine:
case OpFwidthFine:
case OpDPdxCoarse:
case OpDPdyCoarse:
case OpFwidthCoarse:
addCapability(CapabilityDerivativeControl);
break;
case OpImageQueryLod:
case OpImageQuerySize:
case OpImageQuerySizeLod:
case OpImageQuerySamples:
case OpImageQueryLevels:
addCapability(CapabilityImageQuery);
break;
#ifdef NV_EXTENSIONS
case OpGroupNonUniformPartitionNV:
addExtension(E_SPV_NV_shader_subgroup_partitioned);
addCapability(CapabilityGroupNonUniformPartitionedNV);
break;
#endif
case OpLoad:
case OpStore:
{
// For any load/store to a PhysicalStorageBufferEXT, walk the accesschain
// index list to compute the misalignment. The pre-existing alignment value
// (set via Builder::AccessChain::alignment) only accounts for the base of
// the reference type and any scalar component selection in the accesschain,
// and this function computes the rest from the SPIR-V Offset decorations.
Instruction *accessChain = module.getInstruction(inst.getIdOperand(0));
if (accessChain->getOpCode() == OpAccessChain) {
Instruction *base = module.getInstruction(accessChain->getIdOperand(0));
// Get the type of the base of the access chain. It must be a pointer type.
Id typeId = base->getTypeId();
Instruction *type = module.getInstruction(typeId);
assert(type->getOpCode() == OpTypePointer);
if (type->getImmediateOperand(0) != StorageClassPhysicalStorageBufferEXT) {
break;
}
// Get the pointee type.
typeId = type->getIdOperand(1);
type = module.getInstruction(typeId);
// Walk the index list for the access chain. For each index, find any
// misalignment that can apply when accessing the member/element via
// Offset/ArrayStride/MatrixStride decorations, and bitwise OR them all
// together.
int alignment = 0;
for (int i = 1; i < accessChain->getNumOperands(); ++i) {
Instruction *idx = module.getInstruction(accessChain->getIdOperand(i));
if (type->getOpCode() == OpTypeStruct) {
assert(idx->getOpCode() == OpConstant);
unsigned int c = idx->getImmediateOperand(0);
const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
if (decoration.get()->getOpCode() == OpMemberDecorate &&
decoration.get()->getIdOperand(0) == typeId &&
decoration.get()->getImmediateOperand(1) == c &&
(decoration.get()->getImmediateOperand(2) == DecorationOffset ||
decoration.get()->getImmediateOperand(2) == DecorationMatrixStride)) {
alignment |= decoration.get()->getImmediateOperand(3);
}
};
std::for_each(decorations.begin(), decorations.end(), function);
// get the next member type
typeId = type->getIdOperand(c);
type = module.getInstruction(typeId);
} else if (type->getOpCode() == OpTypeArray ||
type->getOpCode() == OpTypeRuntimeArray) {
const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
if (decoration.get()->getOpCode() == OpDecorate &&
decoration.get()->getIdOperand(0) == typeId &&
decoration.get()->getImmediateOperand(1) == DecorationArrayStride) {
alignment |= decoration.get()->getImmediateOperand(2);
}
};
std::for_each(decorations.begin(), decorations.end(), function);
// Get the element type
typeId = type->getIdOperand(0);
type = module.getInstruction(typeId);
} else {
// Once we get to any non-aggregate type, we're done.
break;
}
}
assert(inst.getNumOperands() >= 3);
unsigned int memoryAccess = inst.getImmediateOperand((inst.getOpCode() == OpStore) ? 2 : 1);
assert(memoryAccess & MemoryAccessAlignedMask);
// Compute the index of the alignment operand.
int alignmentIdx = 2;
if (memoryAccess & MemoryAccessVolatileMask)
alignmentIdx++;
if (inst.getOpCode() == OpStore)
alignmentIdx++;
// Merge new and old (mis)alignment
alignment |= inst.getImmediateOperand(alignmentIdx);
// Pick the LSB
alignment = alignment & ~(alignment & (alignment-1));
// update the Aligned operand
inst.setImmediateOperand(alignmentIdx, alignment);
}
break;
}
default:
break;
}
// Checks based on type
if (inst.getTypeId() != NoType)
postProcessType(inst, inst.getTypeId());
for (int op = 0; op < inst.getNumOperands(); ++op) {
if (inst.isIdOperand(op)) {
// In blocks, these are always result ids, but we are relying on
// getTypeId() to return NoType for things like OpLabel.
if (getTypeId(inst.getIdOperand(op)) != NoType)
postProcessType(inst, getTypeId(inst.getIdOperand(op)));
}
}
}
// Called for each instruction in a reachable block.
void Builder::postProcessReachable(const Instruction&)
{
// did have code here, but questionable to do so without deleting the instructions
}
// comment in header
void Builder::postProcess()
{
std::unordered_set<const Block*> reachableBlocks;
std::unordered_set<Id> unreachableDefinitions;
// Collect IDs defined in unreachable blocks. For each function, label the
// reachable blocks first. Then for each unreachable block, collect the
// result IDs of the instructions in it.
for (auto fi = module.getFunctions().cbegin(); fi != module.getFunctions().cend(); fi++) {
Function* f = *fi;
Block* entry = f->getEntryBlock();
inReadableOrder(entry, [&reachableBlocks](const Block* b) { reachableBlocks.insert(b); });
for (auto bi = f->getBlocks().cbegin(); bi != f->getBlocks().cend(); bi++) {
Block* b = *bi;
if (reachableBlocks.count(b) == 0) {
for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ii++)
unreachableDefinitions.insert(ii->get()->getResultId());
}
}
}
// Remove unneeded decorations, for unreachable instructions
decorations.erase(std::remove_if(decorations.begin(), decorations.end(),
[&unreachableDefinitions](std::unique_ptr<Instruction>& I) -> bool {
Id decoration_id = I.get()->getIdOperand(0);
return unreachableDefinitions.count(decoration_id) != 0;
}),
decorations.end());
// Add per-instruction capabilities, extensions, etc.,
// process all reachable instructions...
for (auto bi = reachableBlocks.cbegin(); bi != reachableBlocks.cend(); ++bi) {
const Block* block = *bi;
const auto function = [this](const std::unique_ptr<Instruction>& inst) { postProcessReachable(*inst.get()); };
std::for_each(block->getInstructions().begin(), block->getInstructions().end(), function);
}
// process all block-contained instructions
for (auto fi = module.getFunctions().cbegin(); fi != module.getFunctions().cend(); fi++) {
Function* f = *fi;
for (auto bi = f->getBlocks().cbegin(); bi != f->getBlocks().cend(); bi++) {
Block* b = *bi;
for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ii++)
postProcess(*ii->get());
// For all local variables that contain pointers to PhysicalStorageBufferEXT, check whether
// there is an existing restrict/aliased decoration. If we don't find one, add Aliased as the
// default.
for (auto vi = b->getLocalVariables().cbegin(); vi != b->getLocalVariables().cend(); vi++) {
const Instruction& inst = *vi->get();
Id resultId = inst.getResultId();
if (containsPhysicalStorageBufferOrArray(getDerefTypeId(resultId))) {
bool foundDecoration = false;
const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
if (decoration.get()->getIdOperand(0) == resultId &&
decoration.get()->getOpCode() == OpDecorate &&
(decoration.get()->getImmediateOperand(1) == spv::DecorationAliasedPointerEXT ||
decoration.get()->getImmediateOperand(1) == spv::DecorationRestrictPointerEXT)) {
foundDecoration = true;
}
};
std::for_each(decorations.begin(), decorations.end(), function);
if (!foundDecoration) {
addDecoration(resultId, spv::DecorationAliasedPointerEXT);
}
}
}
}
}
// Look for any 8/16 bit type in physical storage buffer class, and set the
// appropriate capability. This happens in createSpvVariable for other storage
// classes, but there isn't always a variable for physical storage buffer.
for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
Instruction* type = groupedTypes[OpTypePointer][t];
if (type->getImmediateOperand(0) == (unsigned)StorageClassPhysicalStorageBufferEXT) {
if (containsType(type->getIdOperand(1), OpTypeInt, 8)) {
addExtension(spv::E_SPV_KHR_8bit_storage);
addCapability(spv::CapabilityStorageBuffer8BitAccess);
}
if (containsType(type->getIdOperand(1), OpTypeInt, 16) ||
containsType(type->getIdOperand(1), OpTypeFloat, 16)) {
addExtension(spv::E_SPV_KHR_16bit_storage);
addCapability(spv::CapabilityStorageBuffer16BitAccess);
}
}
}
}
}; // end spv namespace

199
glslang/spirv/SpvTools.cpp Normal file
View file

@ -0,0 +1,199 @@
//
// Copyright (C) 2014-2016 LunarG, Inc.
// Copyright (C) 2018 Google, 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 3Dlabs Inc. Ltd. 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.
//
// Call into SPIRV-Tools to disassemble, validate, and optimize.
//
#if ENABLE_OPT
#include <cstdio>
#include <iostream>
#include "SpvTools.h"
#include "spirv-tools/optimizer.hpp"
#include "spirv-tools/libspirv.h"
namespace glslang {
// Translate glslang's view of target versioning to what SPIRV-Tools uses.
spv_target_env MapToSpirvToolsEnv(const SpvVersion& spvVersion, spv::SpvBuildLogger* logger)
{
switch (spvVersion.vulkan) {
case glslang::EShTargetVulkan_1_0: return spv_target_env::SPV_ENV_VULKAN_1_0;
case glslang::EShTargetVulkan_1_1: return spv_target_env::SPV_ENV_VULKAN_1_1;
default:
break;
}
if (spvVersion.openGl > 0)
return spv_target_env::SPV_ENV_OPENGL_4_5;
logger->missingFunctionality("Target version for SPIRV-Tools validator");
return spv_target_env::SPV_ENV_UNIVERSAL_1_0;
}
// Use the SPIRV-Tools disassembler to print SPIR-V.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
{
// disassemble
spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3);
spv_text text;
spv_diagnostic diagnostic = nullptr;
spvBinaryToText(context, spirv.data(), spirv.size(),
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT,
&text, &diagnostic);
// dump
if (diagnostic == nullptr)
out << text->str;
else
spvDiagnosticPrint(diagnostic);
// teardown
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
}
// Apply the SPIRV-Tools validator to generated SPIR-V.
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger* logger)
{
// validate
spv_context context = spvContextCreate(MapToSpirvToolsEnv(intermediate.getSpv(), logger));
spv_const_binary_t binary = { spirv.data(), spirv.size() };
spv_diagnostic diagnostic = nullptr;
spv_validator_options options = spvValidatorOptionsCreate();
spvValidatorOptionsSetRelaxBlockLayout(options, intermediate.usingHlslOffsets());
spvValidateWithOptions(context, options, &binary, &diagnostic);
// report
if (diagnostic != nullptr) {
logger->error("SPIRV-Tools Validation Errors");
logger->error(diagnostic->error);
}
// tear down
spvValidatorOptionsDestroy(options);
spvDiagnosticDestroy(diagnostic);
spvContextDestroy(context);
}
// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
// legalizing HLSL SPIR-V.
void SpirvToolsLegalize(const glslang::TIntermediate&, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, const SpvOptions* options)
{
spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
spvtools::Optimizer optimizer(target_env);
optimizer.SetMessageConsumer(
[](spv_message_level_t level, const char *source, const spv_position_t &position, const char *message) {
auto &out = std::cerr;
switch (level)
{
case SPV_MSG_FATAL:
case SPV_MSG_INTERNAL_ERROR:
case SPV_MSG_ERROR:
out << "error: ";
break;
case SPV_MSG_WARNING:
out << "warning: ";
break;
case SPV_MSG_INFO:
case SPV_MSG_DEBUG:
out << "info: ";
break;
default:
break;
}
if (source)
{
out << source << ":";
}
out << position.line << ":" << position.column << ":" << position.index << ":";
if (message)
{
out << " " << message;
}
out << std::endl;
});
// If debug (specifically source line info) is being generated, propagate
// line information into all SPIR-V instructions. This avoids loss of
// information when instructions are deleted or moved. Later, remove
// redundant information to minimize final SPRIR-V size.
if (options->generateDebugInfo) {
optimizer.RegisterPass(spvtools::CreatePropagateLineInfoPass());
}
optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
optimizer.RegisterPass(spvtools::CreateMergeReturnPass());
optimizer.RegisterPass(spvtools::CreateInlineExhaustivePass());
optimizer.RegisterPass(spvtools::CreateEliminateDeadFunctionsPass());
optimizer.RegisterPass(spvtools::CreateScalarReplacementPass());
optimizer.RegisterPass(spvtools::CreateLocalAccessChainConvertPass());
optimizer.RegisterPass(spvtools::CreateLocalSingleBlockLoadStoreElimPass());
optimizer.RegisterPass(spvtools::CreateLocalSingleStoreElimPass());
optimizer.RegisterPass(spvtools::CreateSimplificationPass());
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateVectorDCEPass());
optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass());
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateDeadBranchElimPass());
optimizer.RegisterPass(spvtools::CreateBlockMergePass());
optimizer.RegisterPass(spvtools::CreateLocalMultiStoreElimPass());
optimizer.RegisterPass(spvtools::CreateIfConversionPass());
optimizer.RegisterPass(spvtools::CreateSimplificationPass());
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateVectorDCEPass());
optimizer.RegisterPass(spvtools::CreateDeadInsertElimPass());
if (options->optimizeSize) {
optimizer.RegisterPass(spvtools::CreateRedundancyEliminationPass());
// TODO(greg-lunarg): Add this when AMD driver issues are resolved
// optimizer.RegisterPass(CreateCommonUniformElimPass());
}
optimizer.RegisterPass(spvtools::CreateAggressiveDCEPass());
optimizer.RegisterPass(spvtools::CreateCFGCleanupPass());
if (options->generateDebugInfo) {
optimizer.RegisterPass(spvtools::CreateRedundantLineInfoElimPass());
}
optimizer.Run(spirv.data(), spirv.size(), &spirv);
}
}; // end namespace glslang
#endif

80
glslang/spirv/SpvTools.h Normal file
View file

@ -0,0 +1,80 @@
//
// Copyright (C) 2014-2016 LunarG, Inc.
// Copyright (C) 2018 Google, 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 3Dlabs Inc. Ltd. 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.
//
// Call into SPIRV-Tools to disassemble, validate, and optimize.
//
#pragma once
#ifndef GLSLANG_SPV_TOOLS_H
#define GLSLANG_SPV_TOOLS_H
#include <vector>
#include <ostream>
#include "../glslang/MachineIndependent/localintermediate.h"
#include "Logger.h"
namespace glslang {
struct SpvOptions {
SpvOptions() : generateDebugInfo(false), disableOptimizer(true),
optimizeSize(false), disassemble(false), validate(false) { }
bool generateDebugInfo;
bool disableOptimizer;
bool optimizeSize;
bool disassemble;
bool validate;
};
#if ENABLE_OPT
// Use the SPIRV-Tools disassembler to print SPIR-V.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv);
// Apply the SPIRV-Tools validator to generated SPIR-V.
void SpirvToolsValidate(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*);
// Apply the SPIRV-Tools optimizer to generated SPIR-V, for the purpose of
// legalizing HLSL SPIR-V.
void SpirvToolsLegalize(const glslang::TIntermediate& intermediate, std::vector<unsigned int>& spirv,
spv::SpvBuildLogger*, const SpvOptions*);
#endif
}; // end namespace glslang
#endif // GLSLANG_SPV_TOOLS_H

View file

@ -26,7 +26,7 @@ Dest BitwiseCast(Src source) {
Dest dest; Dest dest;
static_assert(sizeof(source) == sizeof(dest), static_assert(sizeof(source) == sizeof(dest),
"BitwiseCast: Source and destination must have the same size"); "BitwiseCast: Source and destination must have the same size");
std::memcpy(&dest, &source, sizeof(dest)); std::memcpy(static_cast<void*>(&dest), &source, sizeof(dest));
return dest; return dest;
} }

View file

@ -46,6 +46,7 @@
#include "disassemble.h" #include "disassemble.h"
#include "doc.h" #include "doc.h"
#include "SpvTools.h"
namespace spv { namespace spv {
extern "C" { extern "C" {
@ -509,7 +510,9 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
}else if (strcmp(spv::E_SPV_NV_sample_mask_override_coverage, name) == 0 || }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_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) { strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 ||
strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 ||
strcmp(spv::E_SPV_NV_mesh_shader, name) == 0) {
extInstSet = GLSLextNVInst; extInstSet = GLSLextNVInst;
#endif #endif
} }
@ -534,6 +537,19 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode,
case OperandLiteralString: case OperandLiteralString:
numOperands -= disassembleString(); numOperands -= disassembleString();
break; break;
case OperandMemoryAccess:
outputMask(OperandMemoryAccess, stream[word++]);
--numOperands;
// Aligned is the only memory access operand that uses an immediate
// value, and it is also the first operand that uses a value at all.
if (stream[word-1] & MemoryAccessAlignedMask) {
disassembleImmediates(1);
numOperands--;
if (numOperands)
out << " ";
}
disassembleIds(numOperands);
return;
default: default:
assert(operandClass >= OperandSource && operandClass < OperandOpcode); assert(operandClass >= OperandSource && operandClass < OperandOpcode);
@ -685,21 +701,45 @@ static const char* GLSLextNVGetDebugNames(const char* name, unsigned entrypoint)
strcmp(name, spv::E_SPV_NV_geometry_shader_passthrough) == 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_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) { strcmp(spv::E_SPV_NVX_multiview_per_view_attributes, name) == 0 ||
strcmp(spv::E_SPV_NV_fragment_shader_barycentric, name) == 0 ||
strcmp(name, spv::E_SPV_NV_mesh_shader) == 0) {
switch (entrypoint) { switch (entrypoint) {
case DecorationOverrideCoverageNV: return "OverrideCoverageNV"; // NV builtins
case DecorationPassthroughNV: return "PassthroughNV";
case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";
case DecorationViewportRelativeNV: return "ViewportRelativeNV";
case BuiltInViewportMaskNV: return "ViewportMaskNV"; case BuiltInViewportMaskNV: return "ViewportMaskNV";
case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV";
case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";
case BuiltInSecondaryPositionNV: return "SecondaryPositionNV"; case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV"; case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV";
case BuiltInPositionPerViewNV: return "PositionPerViewNV"; case BuiltInPositionPerViewNV: return "PositionPerViewNV";
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV"; case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
case BuiltInBaryCoordNV: return "BaryCoordNV";
case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
case BuiltInTaskCountNV: return "TaskCountNV";
case BuiltInPrimitiveCountNV: return "PrimitiveCountNV";
case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV";
case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV";
case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV";
case BuiltInLayerPerViewNV: return "LayerPerViewNV";
case BuiltInMeshViewCountNV: return "MeshViewCountNV";
case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV";
// NV Capabilities
case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";
case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV";
case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV";
case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
case CapabilityMeshShadingNV: return "MeshShadingNV";
// NV Decorations
case DecorationOverrideCoverageNV: return "OverrideCoverageNV";
case DecorationPassthroughNV: return "PassthroughNV";
case DecorationViewportRelativeNV: return "ViewportRelativeNV";
case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";
case DecorationPerVertexNV: return "PerVertexNV";
case DecorationPerPrimitiveNV: return "PerPrimitiveNV";
case DecorationPerViewNV: return "PerViewNV";
case DecorationPerTaskNV: return "PerTaskNV";
default: return "Bad"; default: return "Bad";
} }
} }
@ -716,25 +756,4 @@ void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
SpirvStream.processInstructions(); SpirvStream.processInstructions();
} }
#if ENABLE_OPT
#include "spirv-tools/libspirv.h"
// Use the SPIRV-Tools disassembler to print SPIR-V.
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& spirv)
{
spv_context context = spvContextCreate(SPV_ENV_UNIVERSAL_1_3);
spv_text text;
spv_diagnostic diagnostic = nullptr;
spvBinaryToText(context, &spirv.front(), spirv.size(),
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT,
&text, &diagnostic);
if (diagnostic == nullptr)
out << text->str;
else
spvDiagnosticPrint(diagnostic);
}
#endif
}; // end namespace spv }; // end namespace spv

View file

@ -48,9 +48,6 @@ namespace spv {
// disassemble with glslang custom disassembler // disassemble with glslang custom disassembler
void Disassemble(std::ostream& out, const std::vector<unsigned int>&); void Disassemble(std::ostream& out, const std::vector<unsigned int>&);
// disassemble with SPIRV-Tools disassembler
void SpirvToolsDisassemble(std::ostream& out, const std::vector<unsigned int>& stream);
}; // end namespace spv }; // end namespace spv
#endif // disassembler_H #endif // disassembler_H

View file

@ -98,8 +98,22 @@ const char* ExecutionModelString(int model)
case 4: return "Fragment"; case 4: return "Fragment";
case 5: return "GLCompute"; case 5: return "GLCompute";
case 6: return "Kernel"; case 6: return "Kernel";
#ifdef NV_EXTENSIONS
case ExecutionModelTaskNV: return "TaskNV";
case ExecutionModelMeshNV: return "MeshNV";
#endif
default: return "Bad"; default: return "Bad";
#ifdef NV_EXTENSIONS
case ExecutionModelRayGenerationNV: return "RayGenerationNV";
case ExecutionModelIntersectionNV: return "IntersectionNV";
case ExecutionModelAnyHitNV: return "AnyHitNV";
case ExecutionModelClosestHitNV: return "ClosestHitNV";
case ExecutionModelMissNV: return "MissNV";
case ExecutionModelCallableNV: return "CallableNV";
#endif
} }
} }
@ -110,6 +124,8 @@ const char* AddressingString(int addr)
case 1: return "Physical32"; case 1: return "Physical32";
case 2: return "Physical64"; case 2: return "Physical64";
case AddressingModelPhysicalStorageBuffer64EXT: return "PhysicalStorageBuffer64EXT";
default: return "Bad"; default: return "Bad";
} }
} }
@ -117,9 +133,10 @@ const char* AddressingString(int addr)
const char* MemoryString(int mem) const char* MemoryString(int mem)
{ {
switch (mem) { switch (mem) {
case 0: return "Simple"; case MemoryModelSimple: return "Simple";
case 1: return "GLSL450"; case MemoryModelGLSL450: return "GLSL450";
case 2: return "OpenCL"; case MemoryModelOpenCL: return "OpenCL";
case MemoryModelVulkanKHR: return "VulkanKHR";
default: return "Bad"; default: return "Bad";
} }
@ -165,6 +182,15 @@ const char* ExecutionModeString(int mode)
case 32: return "Bad"; case 32: return "Bad";
case 4446: return "PostDepthCoverage"; case 4446: return "PostDepthCoverage";
#ifdef NV_EXTENSIONS
case ExecutionModeOutputLinesNV: return "OutputLinesNV";
case ExecutionModeOutputPrimitivesNV: return "OutputPrimitivesNV";
case ExecutionModeOutputTrianglesNV: return "OutputTrianglesNV";
case ExecutionModeDerivativeGroupQuadsNV: return "DerivativeGroupQuadsNV";
case ExecutionModeDerivativeGroupLinearNV: return "DerivativeGroupLinearNV";
#endif
case ExecutionModeCeiling: case ExecutionModeCeiling:
default: return "Bad"; default: return "Bad";
} }
@ -187,6 +213,17 @@ const char* StorageClassString(int StorageClass)
case 11: return "Image"; case 11: return "Image";
case 12: return "StorageBuffer"; case 12: return "StorageBuffer";
#ifdef NV_EXTENSIONS
case StorageClassRayPayloadNV: return "RayPayloadNV";
case StorageClassHitAttributeNV: return "HitAttributeNV";
case StorageClassIncomingRayPayloadNV: return "IncomingRayPayloadNV";
case StorageClassShaderRecordBufferNV: return "ShaderRecordBufferNV";
case StorageClassCallableDataNV: return "CallableDataNV";
case StorageClassIncomingCallableDataNV: return "IncomingCallableDataNV";
#endif
case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT";
default: return "Bad"; default: return "Bad";
} }
} }
@ -253,11 +290,17 @@ const char* DecorationString(int decoration)
case DecorationPassthroughNV: return "PassthroughNV"; case DecorationPassthroughNV: return "PassthroughNV";
case DecorationViewportRelativeNV: return "ViewportRelativeNV"; case DecorationViewportRelativeNV: return "ViewportRelativeNV";
case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV"; case DecorationSecondaryViewportRelativeNV: return "SecondaryViewportRelativeNV";
case DecorationPerPrimitiveNV: return "PerPrimitiveNV";
case DecorationPerViewNV: return "PerViewNV";
case DecorationPerTaskNV: return "PerTaskNV";
case DecorationPerVertexNV: return "PerVertexNV";
#endif #endif
case DecorationNonUniformEXT: return "DecorationNonUniformEXT"; case DecorationNonUniformEXT: return "DecorationNonUniformEXT";
case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE"; case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE";
case DecorationHlslSemanticGOOGLE: return "DecorationHlslSemanticGOOGLE"; case DecorationHlslSemanticGOOGLE: return "DecorationHlslSemanticGOOGLE";
case DecorationRestrictPointerEXT: return "DecorationRestrictPointerEXT";
case DecorationAliasedPointerEXT: return "DecorationAliasedPointerEXT";
} }
} }
@ -332,15 +375,48 @@ const char* BuiltInString(int builtIn)
#endif #endif
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
case 5253: return "ViewportMaskNV"; case BuiltInLaunchIdNV: return "LaunchIdNV";
case 5257: return "SecondaryPositionNV"; case BuiltInLaunchSizeNV: return "LaunchSizeNV";
case 5258: return "SecondaryViewportMaskNV"; case BuiltInWorldRayOriginNV: return "WorldRayOriginNV";
case 5261: return "PositionPerViewNV"; case BuiltInWorldRayDirectionNV: return "WorldRayDirectionNV";
case 5262: return "ViewportMaskPerViewNV"; case BuiltInObjectRayOriginNV: return "ObjectRayOriginNV";
case BuiltInObjectRayDirectionNV: return "ObjectRayDirectionNV";
case BuiltInRayTminNV: return "RayTminNV";
case BuiltInRayTmaxNV: return "RayTmaxNV";
case BuiltInInstanceCustomIndexNV: return "InstanceCustomIndexNV";
case BuiltInObjectToWorldNV: return "ObjectToWorldNV";
case BuiltInWorldToObjectNV: return "WorldToObjectNV";
case BuiltInHitTNV: return "HitTNV";
case BuiltInHitKindNV: return "HitKindNV";
case BuiltInIncomingRayFlagsNV: return "IncomingRayFlagsNV";
case BuiltInViewportMaskNV: return "ViewportMaskNV";
case BuiltInSecondaryPositionNV: return "SecondaryPositionNV";
case BuiltInSecondaryViewportMaskNV: return "SecondaryViewportMaskNV";
case BuiltInPositionPerViewNV: return "PositionPerViewNV";
case BuiltInViewportMaskPerViewNV: return "ViewportMaskPerViewNV";
// case BuiltInFragmentSizeNV: return "FragmentSizeNV"; // superseded by BuiltInFragSizeEXT
// case BuiltInInvocationsPerPixelNV: return "InvocationsPerPixelNV"; // superseded by BuiltInFragInvocationCountEXT
case BuiltInBaryCoordNV: return "BaryCoordNV";
case BuiltInBaryCoordNoPerspNV: return "BaryCoordNoPerspNV";
#endif #endif
case BuiltInFragSizeEXT: return "FragSizeEXT";
case BuiltInFragInvocationCountEXT: return "FragInvocationCountEXT";
case 5264: return "FullyCoveredEXT"; case 5264: return "FullyCoveredEXT";
#ifdef NV_EXTENSIONS
case BuiltInTaskCountNV: return "TaskCountNV";
case BuiltInPrimitiveCountNV: return "PrimitiveCountNV";
case BuiltInPrimitiveIndicesNV: return "PrimitiveIndicesNV";
case BuiltInClipDistancePerViewNV: return "ClipDistancePerViewNV";
case BuiltInCullDistancePerViewNV: return "CullDistancePerViewNV";
case BuiltInLayerPerViewNV: return "LayerPerViewNV";
case BuiltInMeshViewCountNV: return "MeshViewCountNV";
case BuiltInMeshViewIndicesNV: return "MeshViewIndicesNV";
#endif
default: return "Bad"; default: return "Bad";
} }
} }
@ -499,19 +575,23 @@ const char* ImageChannelDataTypeString(int type)
} }
} }
const int ImageOperandsCeiling = 8; const int ImageOperandsCeiling = 12;
const char* ImageOperandsString(int format) const char* ImageOperandsString(int format)
{ {
switch (format) { switch (format) {
case 0: return "Bias"; case ImageOperandsBiasShift: return "Bias";
case 1: return "Lod"; case ImageOperandsLodShift: return "Lod";
case 2: return "Grad"; case ImageOperandsGradShift: return "Grad";
case 3: return "ConstOffset"; case ImageOperandsConstOffsetShift: return "ConstOffset";
case 4: return "Offset"; case ImageOperandsOffsetShift: return "Offset";
case 5: return "ConstOffsets"; case ImageOperandsConstOffsetsShift: return "ConstOffsets";
case 6: return "Sample"; case ImageOperandsSampleShift: return "Sample";
case 7: return "MinLod"; case ImageOperandsMinLodShift: return "MinLod";
case ImageOperandsMakeTexelAvailableKHRShift: return "MakeTexelAvailableKHR";
case ImageOperandsMakeTexelVisibleKHRShift: return "MakeTexelVisibleKHR";
case ImageOperandsNonPrivateTexelKHRShift: return "NonPrivateTexelKHR";
case ImageOperandsVolatileTexelKHRShift: return "VolatileTexelKHR";
case ImageOperandsCeiling: case ImageOperandsCeiling:
default: default:
@ -645,12 +725,17 @@ const char* MemorySemanticsString(int mem)
} }
} }
const int MemoryAccessCeiling = 6;
const char* MemoryAccessString(int mem) const char* MemoryAccessString(int mem)
{ {
switch (mem) { switch (mem) {
case 0: return "Volatile"; case MemoryAccessVolatileShift: return "Volatile";
case 1: return "Aligned"; case MemoryAccessAlignedShift: return "Aligned";
case 2: return "Nontemporal"; case MemoryAccessNontemporalShift: return "Nontemporal";
case MemoryAccessMakePointerAvailableKHRShift: return "MakePointerAvailableKHR";
case MemoryAccessMakePointerVisibleKHRShift: return "MakePointerVisibleKHR";
case MemoryAccessNonPrivatePointerKHRShift: return "NonPrivatePointerKHR";
default: return "Bad"; default: return "Bad";
} }
@ -810,13 +895,20 @@ const char* CapabilityString(int info)
case CapabilitySampleMaskPostDepthCoverage: return "SampleMaskPostDepthCoverage"; case CapabilitySampleMaskPostDepthCoverage: return "SampleMaskPostDepthCoverage";
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV"; case CapabilityGeometryShaderPassthroughNV: return "GeometryShaderPassthroughNV";
case CapabilityShaderViewportIndexLayerNV: return "ShaderViewportIndexLayerNV"; case CapabilityShaderViewportIndexLayerNV: return "ShaderViewportIndexLayerNV";
case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV"; case CapabilityShaderViewportMaskNV: return "ShaderViewportMaskNV";
case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV"; case CapabilityShaderStereoViewNV: return "ShaderStereoViewNV";
case CapabilityPerViewAttributesNV: return "PerViewAttributesNV"; case CapabilityPerViewAttributesNV: return "PerViewAttributesNV";
case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV"; case CapabilityGroupNonUniformPartitionedNV: return "GroupNonUniformPartitionedNV";
case CapabilityRayTracingNV: return "RayTracingNV";
case CapabilityComputeDerivativeGroupQuadsNV: return "ComputeDerivativeGroupQuadsNV";
case CapabilityComputeDerivativeGroupLinearNV: return "ComputeDerivativeGroupLinearNV";
case CapabilityFragmentBarycentricNV: return "FragmentBarycentricNV";
case CapabilityMeshShadingNV: return "MeshShadingNV";
// case CapabilityShadingRateNV: return "ShadingRateNV"; // superseded by CapabilityFragmentDensityEXT
#endif #endif
case CapabilityFragmentDensityEXT: return "FragmentDensityEXT";
case CapabilityFragmentFullyCoveredEXT: return "FragmentFullyCoveredEXT"; case CapabilityFragmentFullyCoveredEXT: return "FragmentFullyCoveredEXT";
@ -833,6 +925,11 @@ const char* CapabilityString(int info)
case CapabilityUniformTexelBufferArrayNonUniformIndexingEXT: return "CapabilityUniformTexelBufferArrayNonUniformIndexingEXT"; case CapabilityUniformTexelBufferArrayNonUniformIndexingEXT: return "CapabilityUniformTexelBufferArrayNonUniformIndexingEXT";
case CapabilityStorageTexelBufferArrayNonUniformIndexingEXT: return "CapabilityStorageTexelBufferArrayNonUniformIndexingEXT"; case CapabilityStorageTexelBufferArrayNonUniformIndexingEXT: return "CapabilityStorageTexelBufferArrayNonUniformIndexingEXT";
case CapabilityVulkanMemoryModelKHR: return "CapabilityVulkanMemoryModelKHR";
case CapabilityVulkanMemoryModelDeviceScopeKHR: return "CapabilityVulkanMemoryModelDeviceScopeKHR";
case CapabilityPhysicalStorageBufferAddressesEXT: return "CapabilityPhysicalStorageBufferAddressesEXT";
default: return "Bad"; default: return "Bad";
} }
} }
@ -1225,8 +1322,17 @@ const char* OpcodeString(int op)
case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE"; case OpMemberDecorateStringGOOGLE: return "OpMemberDecorateStringGOOGLE";
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV"; case OpGroupNonUniformPartitionNV: return "OpGroupNonUniformPartitionNV";
case OpReportIntersectionNV: return "OpReportIntersectionNV";
case OpIgnoreIntersectionNV: return "OpIgnoreIntersectionNV";
case OpTerminateRayNV: return "OpTerminateRayNV";
case OpTraceNV: return "OpTraceNV";
case OpTypeAccelerationStructureNV: return "OpTypeAccelerationStructureNV";
case OpExecuteCallableNV: return "OpExecuteCallableNV";
case OpImageSampleFootprintNV: return "OpImageSampleFootprintNV";
case OpWritePackedPrimitiveIndices4x8NV: return "OpWritePackedPrimitiveIndices4x8NV";
#endif #endif
default: default:
return "Bad"; return "Bad";
} }
@ -1245,6 +1351,7 @@ EnumParameters DecorationParams[DecorationCeiling];
EnumParameters LoopControlParams[FunctionControlCeiling]; EnumParameters LoopControlParams[FunctionControlCeiling];
EnumParameters SelectionControlParams[SelectControlCeiling]; EnumParameters SelectionControlParams[SelectControlCeiling];
EnumParameters FunctionControlParams[FunctionControlCeiling]; EnumParameters FunctionControlParams[FunctionControlCeiling];
EnumParameters MemoryAccessParams[MemoryAccessCeiling];
// Set up all the parameterizing descriptions of the opcodes, operands, etc. // Set up all the parameterizing descriptions of the opcodes, operands, etc.
void Parameterize() void Parameterize()
@ -1400,7 +1507,7 @@ void Parameterize()
OperandClassParams[OperandLoop].set(LoopControlCeiling, LoopControlString, LoopControlParams, true); OperandClassParams[OperandLoop].set(LoopControlCeiling, LoopControlString, LoopControlParams, true);
OperandClassParams[OperandFunction].set(FunctionControlCeiling, FunctionControlString, FunctionControlParams, true); OperandClassParams[OperandFunction].set(FunctionControlCeiling, FunctionControlString, FunctionControlParams, true);
OperandClassParams[OperandMemorySemantics].set(0, MemorySemanticsString, nullptr, true); OperandClassParams[OperandMemorySemantics].set(0, MemorySemanticsString, nullptr, true);
OperandClassParams[OperandMemoryAccess].set(0, MemoryAccessString, nullptr, true); OperandClassParams[OperandMemoryAccess].set(MemoryAccessCeiling, MemoryAccessString, MemoryAccessParams, true);
OperandClassParams[OperandScope].set(0, ScopeString, nullptr); OperandClassParams[OperandScope].set(0, ScopeString, nullptr);
OperandClassParams[OperandGroupOperation].set(0, GroupOperationString, nullptr); OperandClassParams[OperandGroupOperation].set(0, GroupOperationString, nullptr);
OperandClassParams[OperandKernelEnqueueFlags].set(0, KernelEnqueueFlagsString, nullptr); OperandClassParams[OperandKernelEnqueueFlags].set(0, KernelEnqueueFlagsString, nullptr);
@ -1522,10 +1629,14 @@ void Parameterize()
InstructionDesc[OpLoad].operands.push(OperandId, "'Pointer'"); InstructionDesc[OpLoad].operands.push(OperandId, "'Pointer'");
InstructionDesc[OpLoad].operands.push(OperandMemoryAccess, "", true); InstructionDesc[OpLoad].operands.push(OperandMemoryAccess, "", true);
InstructionDesc[OpLoad].operands.push(OperandLiteralNumber, "", true);
InstructionDesc[OpLoad].operands.push(OperandId, "", true);
InstructionDesc[OpStore].operands.push(OperandId, "'Pointer'"); InstructionDesc[OpStore].operands.push(OperandId, "'Pointer'");
InstructionDesc[OpStore].operands.push(OperandId, "'Object'"); InstructionDesc[OpStore].operands.push(OperandId, "'Object'");
InstructionDesc[OpStore].operands.push(OperandMemoryAccess, "", true); InstructionDesc[OpStore].operands.push(OperandMemoryAccess, "", true);
InstructionDesc[OpStore].operands.push(OperandLiteralNumber, "", true);
InstructionDesc[OpStore].operands.push(OperandId, "", true);
InstructionDesc[OpPhi].operands.push(OperandVariableIds, "'Variable, Parent, ...'"); InstructionDesc[OpPhi].operands.push(OperandVariableIds, "'Variable, Parent, ...'");
@ -2566,6 +2677,42 @@ void Parameterize()
#ifdef NV_EXTENSIONS #ifdef NV_EXTENSIONS
InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X"); InstructionDesc[OpGroupNonUniformPartitionNV].operands.push(OperandId, "X");
InstructionDesc[OpTypeAccelerationStructureNV].setResultAndType(true, false);
InstructionDesc[OpTraceNV].operands.push(OperandId, "'NV Acceleration Structure'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Flags'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Cull Mask'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Offset'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'SBT Record Stride'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Miss Index'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Origin'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMin'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Ray Direction'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'TMax'");
InstructionDesc[OpTraceNV].operands.push(OperandId, "'Payload'");
InstructionDesc[OpTraceNV].setResultAndType(false, false);
InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Parameter'");
InstructionDesc[OpReportIntersectionNV].operands.push(OperandId, "'Hit Kind'");
InstructionDesc[OpIgnoreIntersectionNV].setResultAndType(false, false);
InstructionDesc[OpTerminateRayNV].setResultAndType(false, false);
InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "SBT Record Index");
InstructionDesc[OpExecuteCallableNV].operands.push(OperandId, "CallableData ID");
InstructionDesc[OpExecuteCallableNV].setResultAndType(false, false);
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Sampled Image'");
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coordinate'");
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Granularity'");
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandId, "'Coarse'");
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandImageOperands, "", true);
InstructionDesc[OpImageSampleFootprintNV].operands.push(OperandVariableIds, "", true);
InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Index Offset'");
InstructionDesc[OpWritePackedPrimitiveIndices4x8NV].operands.push(OperandId, "'Packed Indices'");
#endif #endif
} }

View file

@ -1,4 +1,4 @@
// Copyright (c) 2014-2018 The Khronos Group Inc. // Copyright (c) 2014-2019 The Khronos Group Inc.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and/or associated documentation files (the "Materials"), // of this software and/or associated documentation files (the "Materials"),
@ -26,13 +26,16 @@
// the Binary Section of the SPIR-V specification. // the Binary Section of the SPIR-V specification.
// Enumeration tokens for SPIR-V, in various styles: // Enumeration tokens for SPIR-V, in various styles:
// C, C++, C++11, JSON, Lua, Python // C, C++, C++11, JSON, Lua, Python, C#, D
// //
// - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL // - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL
// - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL // - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL
// - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL // - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL
// - Lua will use tables, e.g.: spv.SourceLanguage.GLSL // - Lua will use tables, e.g.: spv.SourceLanguage.GLSL
// - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] // - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL']
// - C# will use enum classes in the Specification class located in the "Spv" namespace,
// e.g.: Spv.Specification.SourceLanguage.GLSL
// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL
// //
// Some tokens act like mask values, which can be OR'd together, // Some tokens act like mask values, which can be OR'd together,
// while others are mutually exclusive. The mask-like ones have // while others are mutually exclusive. The mask-like ones have
@ -47,11 +50,11 @@ namespace spv {
typedef unsigned int Id; typedef unsigned int Id;
#define SPV_VERSION 0x10300 #define SPV_VERSION 0x10300
#define SPV_REVISION 1 #define SPV_REVISION 6
static const unsigned int MagicNumber = 0x07230203; static const unsigned int MagicNumber = 0x07230203;
static const unsigned int Version = 0x00010300; static const unsigned int Version = 0x00010300;
static const unsigned int Revision = 1; static const unsigned int Revision = 6;
static const unsigned int OpCodeMask = 0xffff; static const unsigned int OpCodeMask = 0xffff;
static const unsigned int WordCountShift = 16; static const unsigned int WordCountShift = 16;
@ -73,6 +76,14 @@ enum ExecutionModel {
ExecutionModelFragment = 4, ExecutionModelFragment = 4,
ExecutionModelGLCompute = 5, ExecutionModelGLCompute = 5,
ExecutionModelKernel = 6, ExecutionModelKernel = 6,
ExecutionModelTaskNV = 5267,
ExecutionModelMeshNV = 5268,
ExecutionModelRayGenerationNV = 5313,
ExecutionModelIntersectionNV = 5314,
ExecutionModelAnyHitNV = 5315,
ExecutionModelClosestHitNV = 5316,
ExecutionModelMissNV = 5317,
ExecutionModelCallableNV = 5318,
ExecutionModelMax = 0x7fffffff, ExecutionModelMax = 0x7fffffff,
}; };
@ -80,6 +91,7 @@ enum AddressingModel {
AddressingModelLogical = 0, AddressingModelLogical = 0,
AddressingModelPhysical32 = 1, AddressingModelPhysical32 = 1,
AddressingModelPhysical64 = 2, AddressingModelPhysical64 = 2,
AddressingModelPhysicalStorageBuffer64EXT = 5348,
AddressingModelMax = 0x7fffffff, AddressingModelMax = 0x7fffffff,
}; };
@ -87,6 +99,7 @@ enum MemoryModel {
MemoryModelSimple = 0, MemoryModelSimple = 0,
MemoryModelGLSL450 = 1, MemoryModelGLSL450 = 1,
MemoryModelOpenCL = 2, MemoryModelOpenCL = 2,
MemoryModelVulkanKHR = 3,
MemoryModelMax = 0x7fffffff, MemoryModelMax = 0x7fffffff,
}; };
@ -130,7 +143,17 @@ enum ExecutionMode {
ExecutionModeLocalSizeId = 38, ExecutionModeLocalSizeId = 38,
ExecutionModeLocalSizeHintId = 39, ExecutionModeLocalSizeHintId = 39,
ExecutionModePostDepthCoverage = 4446, ExecutionModePostDepthCoverage = 4446,
ExecutionModeDenormPreserve = 4459,
ExecutionModeDenormFlushToZero = 4460,
ExecutionModeSignedZeroInfNanPreserve = 4461,
ExecutionModeRoundingModeRTE = 4462,
ExecutionModeRoundingModeRTZ = 4463,
ExecutionModeStencilRefReplacingEXT = 5027, ExecutionModeStencilRefReplacingEXT = 5027,
ExecutionModeOutputLinesNV = 5269,
ExecutionModeOutputPrimitivesNV = 5270,
ExecutionModeDerivativeGroupQuadsNV = 5289,
ExecutionModeDerivativeGroupLinearNV = 5290,
ExecutionModeOutputTrianglesNV = 5298,
ExecutionModeMax = 0x7fffffff, ExecutionModeMax = 0x7fffffff,
}; };
@ -148,6 +171,13 @@ enum StorageClass {
StorageClassAtomicCounter = 10, StorageClassAtomicCounter = 10,
StorageClassImage = 11, StorageClassImage = 11,
StorageClassStorageBuffer = 12, StorageClassStorageBuffer = 12,
StorageClassCallableDataNV = 5328,
StorageClassIncomingCallableDataNV = 5329,
StorageClassRayPayloadNV = 5338,
StorageClassHitAttributeNV = 5339,
StorageClassIncomingRayPayloadNV = 5342,
StorageClassShaderRecordBufferNV = 5343,
StorageClassPhysicalStorageBufferEXT = 5349,
StorageClassMax = 0x7fffffff, StorageClassMax = 0x7fffffff,
}; };
@ -275,6 +305,10 @@ enum ImageOperandsShift {
ImageOperandsConstOffsetsShift = 5, ImageOperandsConstOffsetsShift = 5,
ImageOperandsSampleShift = 6, ImageOperandsSampleShift = 6,
ImageOperandsMinLodShift = 7, ImageOperandsMinLodShift = 7,
ImageOperandsMakeTexelAvailableKHRShift = 8,
ImageOperandsMakeTexelVisibleKHRShift = 9,
ImageOperandsNonPrivateTexelKHRShift = 10,
ImageOperandsVolatileTexelKHRShift = 11,
ImageOperandsMax = 0x7fffffff, ImageOperandsMax = 0x7fffffff,
}; };
@ -288,6 +322,10 @@ enum ImageOperandsMask {
ImageOperandsConstOffsetsMask = 0x00000020, ImageOperandsConstOffsetsMask = 0x00000020,
ImageOperandsSampleMask = 0x00000040, ImageOperandsSampleMask = 0x00000040,
ImageOperandsMinLodMask = 0x00000080, ImageOperandsMinLodMask = 0x00000080,
ImageOperandsMakeTexelAvailableKHRMask = 0x00000100,
ImageOperandsMakeTexelVisibleKHRMask = 0x00000200,
ImageOperandsNonPrivateTexelKHRMask = 0x00000400,
ImageOperandsVolatileTexelKHRMask = 0x00000800,
}; };
enum FPFastMathModeShift { enum FPFastMathModeShift {
@ -388,12 +426,20 @@ enum Decoration {
DecorationMaxByteOffset = 45, DecorationMaxByteOffset = 45,
DecorationAlignmentId = 46, DecorationAlignmentId = 46,
DecorationMaxByteOffsetId = 47, DecorationMaxByteOffsetId = 47,
DecorationNoSignedWrap = 4469,
DecorationNoUnsignedWrap = 4470,
DecorationExplicitInterpAMD = 4999, DecorationExplicitInterpAMD = 4999,
DecorationOverrideCoverageNV = 5248, DecorationOverrideCoverageNV = 5248,
DecorationPassthroughNV = 5250, DecorationPassthroughNV = 5250,
DecorationViewportRelativeNV = 5252, DecorationViewportRelativeNV = 5252,
DecorationSecondaryViewportRelativeNV = 5256, DecorationSecondaryViewportRelativeNV = 5256,
DecorationPerPrimitiveNV = 5271,
DecorationPerViewNV = 5272,
DecorationPerTaskNV = 5273,
DecorationPerVertexNV = 5285,
DecorationNonUniformEXT = 5300, DecorationNonUniformEXT = 5300,
DecorationRestrictPointerEXT = 5355,
DecorationAliasedPointerEXT = 5356,
DecorationHlslCounterBufferGOOGLE = 5634, DecorationHlslCounterBufferGOOGLE = 5634,
DecorationHlslSemanticGOOGLE = 5635, DecorationHlslSemanticGOOGLE = 5635,
DecorationMax = 0x7fffffff, DecorationMax = 0x7fffffff,
@ -470,6 +516,34 @@ enum BuiltIn {
BuiltInPositionPerViewNV = 5261, BuiltInPositionPerViewNV = 5261,
BuiltInViewportMaskPerViewNV = 5262, BuiltInViewportMaskPerViewNV = 5262,
BuiltInFullyCoveredEXT = 5264, BuiltInFullyCoveredEXT = 5264,
BuiltInTaskCountNV = 5274,
BuiltInPrimitiveCountNV = 5275,
BuiltInPrimitiveIndicesNV = 5276,
BuiltInClipDistancePerViewNV = 5277,
BuiltInCullDistancePerViewNV = 5278,
BuiltInLayerPerViewNV = 5279,
BuiltInMeshViewCountNV = 5280,
BuiltInMeshViewIndicesNV = 5281,
BuiltInBaryCoordNV = 5286,
BuiltInBaryCoordNoPerspNV = 5287,
BuiltInFragSizeEXT = 5292,
BuiltInFragmentSizeNV = 5292,
BuiltInFragInvocationCountEXT = 5293,
BuiltInInvocationsPerPixelNV = 5293,
BuiltInLaunchIdNV = 5319,
BuiltInLaunchSizeNV = 5320,
BuiltInWorldRayOriginNV = 5321,
BuiltInWorldRayDirectionNV = 5322,
BuiltInObjectRayOriginNV = 5323,
BuiltInObjectRayDirectionNV = 5324,
BuiltInRayTminNV = 5325,
BuiltInRayTmaxNV = 5326,
BuiltInInstanceCustomIndexNV = 5327,
BuiltInObjectToWorldNV = 5330,
BuiltInWorldToObjectNV = 5331,
BuiltInHitTNV = 5332,
BuiltInHitKindNV = 5333,
BuiltInIncomingRayFlagsNV = 5351,
BuiltInMax = 0x7fffffff, BuiltInMax = 0x7fffffff,
}; };
@ -528,6 +602,9 @@ enum MemorySemanticsShift {
MemorySemanticsCrossWorkgroupMemoryShift = 9, MemorySemanticsCrossWorkgroupMemoryShift = 9,
MemorySemanticsAtomicCounterMemoryShift = 10, MemorySemanticsAtomicCounterMemoryShift = 10,
MemorySemanticsImageMemoryShift = 11, MemorySemanticsImageMemoryShift = 11,
MemorySemanticsOutputMemoryKHRShift = 12,
MemorySemanticsMakeAvailableKHRShift = 13,
MemorySemanticsMakeVisibleKHRShift = 14,
MemorySemanticsMax = 0x7fffffff, MemorySemanticsMax = 0x7fffffff,
}; };
@ -543,12 +620,18 @@ enum MemorySemanticsMask {
MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200, MemorySemanticsCrossWorkgroupMemoryMask = 0x00000200,
MemorySemanticsAtomicCounterMemoryMask = 0x00000400, MemorySemanticsAtomicCounterMemoryMask = 0x00000400,
MemorySemanticsImageMemoryMask = 0x00000800, MemorySemanticsImageMemoryMask = 0x00000800,
MemorySemanticsOutputMemoryKHRMask = 0x00001000,
MemorySemanticsMakeAvailableKHRMask = 0x00002000,
MemorySemanticsMakeVisibleKHRMask = 0x00004000,
}; };
enum MemoryAccessShift { enum MemoryAccessShift {
MemoryAccessVolatileShift = 0, MemoryAccessVolatileShift = 0,
MemoryAccessAlignedShift = 1, MemoryAccessAlignedShift = 1,
MemoryAccessNontemporalShift = 2, MemoryAccessNontemporalShift = 2,
MemoryAccessMakePointerAvailableKHRShift = 3,
MemoryAccessMakePointerVisibleKHRShift = 4,
MemoryAccessNonPrivatePointerKHRShift = 5,
MemoryAccessMax = 0x7fffffff, MemoryAccessMax = 0x7fffffff,
}; };
@ -557,6 +640,9 @@ enum MemoryAccessMask {
MemoryAccessVolatileMask = 0x00000001, MemoryAccessVolatileMask = 0x00000001,
MemoryAccessAlignedMask = 0x00000002, MemoryAccessAlignedMask = 0x00000002,
MemoryAccessNontemporalMask = 0x00000004, MemoryAccessNontemporalMask = 0x00000004,
MemoryAccessMakePointerAvailableKHRMask = 0x00000008,
MemoryAccessMakePointerVisibleKHRMask = 0x00000010,
MemoryAccessNonPrivatePointerKHRMask = 0x00000020,
}; };
enum Scope { enum Scope {
@ -565,6 +651,7 @@ enum Scope {
ScopeWorkgroup = 2, ScopeWorkgroup = 2,
ScopeSubgroup = 3, ScopeSubgroup = 3,
ScopeInvocation = 4, ScopeInvocation = 4,
ScopeQueueFamilyKHR = 5,
ScopeMax = 0x7fffffff, ScopeMax = 0x7fffffff,
}; };
@ -682,6 +769,11 @@ enum Capability {
CapabilityStorageBuffer8BitAccess = 4448, CapabilityStorageBuffer8BitAccess = 4448,
CapabilityUniformAndStorageBuffer8BitAccess = 4449, CapabilityUniformAndStorageBuffer8BitAccess = 4449,
CapabilityStoragePushConstant8 = 4450, CapabilityStoragePushConstant8 = 4450,
CapabilityDenormPreserve = 4464,
CapabilityDenormFlushToZero = 4465,
CapabilitySignedZeroInfNanPreserve = 4466,
CapabilityRoundingModeRTE = 4467,
CapabilityRoundingModeRTZ = 4468,
CapabilityFloat16ImageAMD = 5008, CapabilityFloat16ImageAMD = 5008,
CapabilityImageGatherBiasLodAMD = 5009, CapabilityImageGatherBiasLodAMD = 5009,
CapabilityFragmentMaskAMD = 5010, CapabilityFragmentMaskAMD = 5010,
@ -695,6 +787,12 @@ enum Capability {
CapabilityShaderStereoViewNV = 5259, CapabilityShaderStereoViewNV = 5259,
CapabilityPerViewAttributesNV = 5260, CapabilityPerViewAttributesNV = 5260,
CapabilityFragmentFullyCoveredEXT = 5265, CapabilityFragmentFullyCoveredEXT = 5265,
CapabilityMeshShadingNV = 5266,
CapabilityImageFootprintNV = 5282,
CapabilityFragmentBarycentricNV = 5284,
CapabilityComputeDerivativeGroupQuadsNV = 5288,
CapabilityFragmentDensityEXT = 5291,
CapabilityShadingRateNV = 5291,
CapabilityGroupNonUniformPartitionedNV = 5297, CapabilityGroupNonUniformPartitionedNV = 5297,
CapabilityShaderNonUniformEXT = 5301, CapabilityShaderNonUniformEXT = 5301,
CapabilityRuntimeDescriptorArrayEXT = 5302, CapabilityRuntimeDescriptorArrayEXT = 5302,
@ -708,6 +806,11 @@ enum Capability {
CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310, CapabilityInputAttachmentArrayNonUniformIndexingEXT = 5310,
CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311, CapabilityUniformTexelBufferArrayNonUniformIndexingEXT = 5311,
CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312, CapabilityStorageTexelBufferArrayNonUniformIndexingEXT = 5312,
CapabilityRayTracingNV = 5340,
CapabilityVulkanMemoryModelKHR = 5345,
CapabilityVulkanMemoryModelDeviceScopeKHR = 5346,
CapabilityPhysicalStorageBufferAddressesEXT = 5347,
CapabilityComputeDerivativeGroupLinearNV = 5350,
CapabilitySubgroupShuffleINTEL = 5568, CapabilitySubgroupShuffleINTEL = 5568,
CapabilitySubgroupBufferBlockIOINTEL = 5569, CapabilitySubgroupBufferBlockIOINTEL = 5569,
CapabilitySubgroupImageBlockIOINTEL = 5570, CapabilitySubgroupImageBlockIOINTEL = 5570,
@ -1071,7 +1174,15 @@ enum Op {
OpGroupSMaxNonUniformAMD = 5007, OpGroupSMaxNonUniformAMD = 5007,
OpFragmentMaskFetchAMD = 5011, OpFragmentMaskFetchAMD = 5011,
OpFragmentFetchAMD = 5012, OpFragmentFetchAMD = 5012,
OpImageSampleFootprintNV = 5283,
OpGroupNonUniformPartitionNV = 5296, OpGroupNonUniformPartitionNV = 5296,
OpWritePackedPrimitiveIndices4x8NV = 5299,
OpReportIntersectionNV = 5334,
OpIgnoreIntersectionNV = 5335,
OpTerminateRayNV = 5336,
OpTraceNV = 5337,
OpTypeAccelerationStructureNV = 5341,
OpExecuteCallableNV = 5344,
OpSubgroupShuffleINTEL = 5571, OpSubgroupShuffleINTEL = 5571,
OpSubgroupShuffleDownINTEL = 5572, OpSubgroupShuffleDownINTEL = 5572,
OpSubgroupShuffleUpINTEL = 5573, OpSubgroupShuffleUpINTEL = 5573,

View file

@ -1,5 +1,6 @@
// //
// Copyright (C) 2014 LunarG, Inc. // Copyright (C) 2014 LunarG, Inc.
// Copyright (C) 2015-2018 Google, Inc.
// //
// All rights reserved. // All rights reserved.
// //
@ -79,6 +80,11 @@ const MemorySemanticsMask MemorySemanticsAllMemory =
MemorySemanticsAtomicCounterMemoryMask | MemorySemanticsAtomicCounterMemoryMask |
MemorySemanticsImageMemoryMask); MemorySemanticsImageMemoryMask);
struct IdImmediate {
bool isId; // true if word is an Id, false if word is an immediate
unsigned word;
};
// //
// SPIR-V IR instruction. // SPIR-V IR instruction.
// //
@ -88,8 +94,19 @@ public:
Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { } Instruction(Id resultId, Id typeId, Op opCode) : resultId(resultId), typeId(typeId), opCode(opCode), block(nullptr) { }
explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { } explicit Instruction(Op opCode) : resultId(NoResult), typeId(NoType), opCode(opCode), block(nullptr) { }
virtual ~Instruction() {} virtual ~Instruction() {}
void addIdOperand(Id id) { operands.push_back(id); } void addIdOperand(Id id) {
void addImmediateOperand(unsigned int immediate) { operands.push_back(immediate); } operands.push_back(id);
idOperand.push_back(true);
}
void addImmediateOperand(unsigned int immediate) {
operands.push_back(immediate);
idOperand.push_back(false);
}
void setImmediateOperand(unsigned idx, unsigned int immediate) {
assert(!idOperand[idx]);
operands[idx] = immediate;
}
void addStringOperand(const char* str) void addStringOperand(const char* str)
{ {
unsigned int word; unsigned int word;
@ -116,14 +133,25 @@ public:
addImmediateOperand(word); addImmediateOperand(word);
} }
} }
bool isIdOperand(int op) const { return idOperand[op]; }
void setBlock(Block* b) { block = b; } void setBlock(Block* b) { block = b; }
Block* getBlock() const { return block; } Block* getBlock() const { return block; }
Op getOpCode() const { return opCode; } Op getOpCode() const { return opCode; }
int getNumOperands() const { return (int)operands.size(); } int getNumOperands() const
{
assert(operands.size() == idOperand.size());
return (int)operands.size();
}
Id getResultId() const { return resultId; } Id getResultId() const { return resultId; }
Id getTypeId() const { return typeId; } Id getTypeId() const { return typeId; }
Id getIdOperand(int op) const { return operands[op]; } Id getIdOperand(int op) const {
unsigned int getImmediateOperand(int op) const { return operands[op]; } assert(idOperand[op]);
return operands[op];
}
unsigned int getImmediateOperand(int op) const {
assert(!idOperand[op]);
return operands[op];
}
// Write out the binary form. // Write out the binary form.
void dump(std::vector<unsigned int>& out) const void dump(std::vector<unsigned int>& out) const
@ -153,7 +181,8 @@ protected:
Id resultId; Id resultId;
Id typeId; Id typeId;
Op opCode; Op opCode;
std::vector<Id> operands; std::vector<Id> operands; // operands, both <id> and immediates (both are unsigned int)
std::vector<bool> idOperand; // true for operands that are <id>, false for immediates
Block* block; Block* block;
}; };
@ -179,6 +208,7 @@ public:
const std::vector<std::unique_ptr<Instruction> >& getInstructions() const { const std::vector<std::unique_ptr<Instruction> >& getInstructions() const {
return instructions; return instructions;
} }
const std::vector<std::unique_ptr<Instruction> >& getLocalVariables() const { return localVariables; }
void setUnreachable() { unreachable = true; } void setUnreachable() { unreachable = true; }
bool isUnreachable() const { return unreachable; } bool isUnreachable() const { return unreachable; }
// Returns the block's merge instruction, if one exists (otherwise null). // Returns the block's merge instruction, if one exists (otherwise null).
@ -331,7 +361,9 @@ public:
Instruction* getInstruction(Id id) const { return idToInstruction[id]; } Instruction* getInstruction(Id id) const { return idToInstruction[id]; }
const std::vector<Function*>& getFunctions() const { return functions; } const std::vector<Function*>& getFunctions() const { return functions; }
spv::Id getTypeId(Id resultId) const { return idToInstruction[resultId]->getTypeId(); } spv::Id getTypeId(Id resultId) const {
return idToInstruction[resultId] == nullptr ? NoType : idToInstruction[resultId]->getTypeId();
}
StorageClass getStorageClass(Id typeId) const StorageClass getStorageClass(Id typeId) const
{ {
assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer); assert(idToInstruction[typeId]->getOpCode() == spv::OpTypePointer);

View file

@ -89,26 +89,26 @@ static const TBuiltInResource DefaultTBuiltInResource = {
/* .MaxCullDistances = */ 8, /* .MaxCullDistances = */ 8,
/* .MaxCombinedClipAndCullDistances = */ 8, /* .MaxCombinedClipAndCullDistances = */ 8,
/* .MaxSamples = */ 4, /* .MaxSamples = */ 4,
// /* .maxMeshOutputVerticesNV = */ 256, /* .maxMeshOutputVerticesNV = */ 256,
// /* .maxMeshOutputPrimitivesNV = */ 512, /* .maxMeshOutputPrimitivesNV = */ 512,
// /* .maxMeshWorkGroupSizeX_NV = */ 32, /* .maxMeshWorkGroupSizeX_NV = */ 32,
// /* .maxMeshWorkGroupSizeY_NV = */ 1, /* .maxMeshWorkGroupSizeY_NV = */ 1,
// /* .maxMeshWorkGroupSizeZ_NV = */ 1, /* .maxMeshWorkGroupSizeZ_NV = */ 1,
// /* .maxTaskWorkGroupSizeX_NV = */ 32, /* .maxTaskWorkGroupSizeX_NV = */ 32,
// /* .maxTaskWorkGroupSizeY_NV = */ 1, /* .maxTaskWorkGroupSizeY_NV = */ 1,
// /* .maxTaskWorkGroupSizeZ_NV = */ 1, /* .maxTaskWorkGroupSizeZ_NV = */ 1,
// /* .maxMeshViewCountNV = */ 4, /* .maxMeshViewCountNV = */ 4,
/* .limits = */ { /* .limits = */ {
/* .nonInductiveForLoops = */ 1, /* .nonInductiveForLoops = */ 1,
/* .whileLoops = */ 1, /* .whileLoops = */ 1,
/* .doWhileLoops = */ 1, /* .doWhileLoops = */ 1,
/* .generalUniformIndexing = */ 1, /* .generalUniformIndexing = */ 1,
/* .generalAttributeMatrixVectorIndexing = */ 1, /* .generalAttributeMatrixVectorIndexing = */ 1,
/* .generalVaryingIndexing = */ 1, /* .generalVaryingIndexing = */ 1,
/* .generalSamplerIndexing = */ 1, /* .generalSamplerIndexing = */ 1,
/* .generalVariableIndexing = */ 1, /* .generalVariableIndexing = */ 1,
/* .generalConstantMatrixVectorIndexing = */ 1, /* .generalConstantMatrixVectorIndexing = */ 1,
} }
}; };